Challenge API
A challenge binds an explicit approval step to the immutable original request. The supported canonical methods are action-bound passkey confirmation and a clearly labeled sandbox-only simulation when allowed by policy. Use the confirmation for this specific action in addition to the account's sign-in controls.
Browser workflow
Use the scoped browser token and SDK to retrieve challenge details, display them, obtain explicit confirmation, and complete the supported ceremony. Passkey registration is a separate process using a one-time grant issued by the authenticated backend.
Registration options are a WebAuthn creation-options object with graypass_registration_id added. Preserve that value as registration_id for registration completion. Action confirmation uses the separate challenge passkey-options operation and an authentication assertion. Keep registration, sign-in, and action-confirmation assertions associated with their respective ceremonies.
For browser callers, completion returns a receipt identifying the resulting authorization. Execution belongs to the backend verification flow. Send that ID to your backend; resolve it through the authenticated API, associate it with the original pending request, and verify its proof against the original locally computed action hash.
Response handling and lifecycle
Respect the challenge's expiry and status. Cancellation, expiry, duplicate or mismatched completion, denied confirmation, and unsupported methods preserve non-execution. If the business request changes, request a new authorization rather than reusing an old challenge.
Completing a challenge reevaluates the original request, including any active detector hold. Inspect the resulting child decision. Use the sandbox simulation to test lifecycle and binding, and the passkey ceremony for action-bound user confirmation.
See Decisions and challenges for UI and review guidance. The operation contracts below describe challenge retrieval, cancellation, passkey options, and completion.
GET /api/v1/challenges/{challenge_id}
Retrieve a challenge’s current state, permitted methods, expiry and action display for explicit confirmation.
Credential: Scoped browser token or server credential.
Inputs: Use the challenge id from the original authorization; browser scope must match its subject and origin.
Effect and retry behavior: Read-only. Show the requesting application, action and consequence together with the exact business details saved by your backend. Use those details to display the destination associated with the returned digest.
Parameters
| Name / location | Required | Meaning, type and constraints |
|---|---|---|
challenge_id (path) | Yes | Challenge identifier tied to the original pending authorization. string |
Responses
| HTTP status | Meaning | Body |
|---|---|---|
200 | Current challenge state, available methods, expiry and browser-safe action display. | application/json: ChallengePublicView |
422 | The canonical handler returns a Problem for invalid input; correct the request before retrying. | application/problem+json: Problem |
Response handling: 404 or scope refusal for an unavailable challenge. Start a fresh authorization when the intended request requires a new approval after expiry, cancellation or completion.
Example
GET /api/v1/challenges/ch_example{
"id": "ch_example",
"status": "pending",
"methods": [
"passkey"
],
"expires_at": "2026-10-01T12:05:00Z",
"display": {
"action_key": "payout.destination.change",
"action": "Change payout destination",
"consequence": "Future payouts may be sent to a different destination.",
"audience": "merchant-api"
}
}POST /api/v1/challenges/{challenge_id}/cancel
Refuse the offered action confirmation and stop that pending challenge from completing.
Credential: Scoped browser token or server credential.
Inputs: Challenge id only; no body.
Effect and retry behavior: Marks the challenge cancelled. It never grants a proof or executes the underlying action.
Parameters
| Name / location | Required | Meaning, type and constraints |
|---|---|---|
challenge_id (path) | Yes | Challenge identifier tied to the original pending authorization. string |
Responses
| HTTP status | Meaning | Body |
|---|---|---|
200 | Challenge id and cancelled status. | application/json: ChallengeCancelled |
422 | The canonical handler returns a Problem for invalid input; correct the request before retrying. | application/problem+json: Problem |
Response handling: Unavailable or invalid challenge lifecycle states are refused; keep the associated business request unexecuted.
Example
POST /api/v1/challenges/ch_example/cancel{
"id": "ch_example",
"status": "cancelled"
}POST /api/v1/challenges/{challenge_id}/complete
Verify an offered challenge method and reevaluate the immutable original request into a child authorization.
Credential: Scoped browser token or server credential.
Inputs: For passkey, supply the browser’s assertion for this challenge. sandbox_confirm is simulation only and must be permitted in a sandbox policy.
Effect and retry behavior: Consumes the pending challenge. Browser callers receive a child-authorization receipt; server callers receive the decision. The backend must retrieve/bind/verify/consume before any mutation.
Parameters
| Name / location | Required | Meaning, type and constraints |
|---|---|---|
challenge_id (path) | Yes | Challenge identifier tied to the original pending authorization. string |
Request body
application/json; required. ChallengeCompleteRequest.
Responses
| HTTP status | Meaning | Body |
|---|---|---|
200 | Scoped browser callers receive ChallengeCompletionReceipt; server callers receive AuthorizeResponse. | application/json: AuthorizeResponse or ChallengeCompletionReceipt |
422 | The canonical handler returns a Problem for invalid input; correct the request before retrying. | application/problem+json: Problem |
Response handling: Expired, repeated, mismatched or unoffered methods and invalid assertions fail. Successful completion can still yield hold or deny if policy or attack signals require it.
Example
POST /api/v1/challenges/ch_example/complete{
"method": "sandbox_confirm"
}{
"challenge": "ch_example",
"status": "completed",
"authorization": "az_child_example",
"method": "sandbox_confirm"
}POST /api/v1/challenges/{challenge_id}/passkey/options
Obtain WebAuthn authentication options bound to this challenge’s immutable request digest.
Credential: Scoped browser token or server credential.
Inputs: Challenge id and correct browser origin. At least one active passkey must be registered for the subject.
Effect and retry behavior: Prepares the ceremony and records its RP/origin binding. Complete the ceremony and resolve the resulting authorization to obtain the action decision.
Parameters
| Name / location | Required | Meaning, type and constraints |
|---|---|---|
challenge_id (path) | Yes | Challenge identifier tied to the original pending authorization. string |
Responses
| HTTP status | Meaning | Body |
|---|---|---|
200 | WebAuthn request options with action-bound challenge bytes, RP id, eligible credentials and required user verification. | application/json: object |
422 | The canonical handler returns a Problem for invalid input; correct the request before retrying. | application/problem+json: Problem |
Response handling: 409 for a nonpending challenge or no eligible registered passkey; scope/origin mismatches are refused.
Example
POST /api/v1/challenges/ch_example/passkey/options{
"timeout": 60000,
"userVerification": "required"
}