For agents

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 / locationRequiredMeaning, type and constraints
challenge_id (path)YesChallenge identifier tied to the original pending authorization.
string

Responses

HTTP statusMeaningBody
200Current challenge state, available methods, expiry and browser-safe action display.application/json: ChallengePublicView
422The 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

HTTP
GET /api/v1/challenges/ch_example
Response excerpt (selected fields) - HTTP 200:
{
  "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 / locationRequiredMeaning, type and constraints
challenge_id (path)YesChallenge identifier tied to the original pending authorization.
string

Responses

HTTP statusMeaningBody
200Challenge id and cancelled status.application/json: ChallengeCancelled
422The 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

HTTP
POST /api/v1/challenges/ch_example/cancel
Response - HTTP 200:
{
  "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 / locationRequiredMeaning, type and constraints
challenge_id (path)YesChallenge identifier tied to the original pending authorization.
string

Request body

application/json; required. ChallengeCompleteRequest.

Responses

HTTP statusMeaningBody
200Scoped browser callers receive ChallengeCompletionReceipt; server callers receive AuthorizeResponse.application/json: AuthorizeResponse or ChallengeCompletionReceipt
422The 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

HTTP
POST /api/v1/challenges/ch_example/complete
JSON request
{
  "method": "sandbox_confirm"
}
Response - HTTP 200:
{
  "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 / locationRequiredMeaning, type and constraints
challenge_id (path)YesChallenge identifier tied to the original pending authorization.
string

Responses

HTTP statusMeaningBody
200WebAuthn request options with action-bound challenge bytes, RP id, eligible credentials and required user verification.application/json: object
422The 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

HTTP
POST /api/v1/challenges/ch_example/passkey/options
Response excerpt (selected fields) - HTTP 200:
{
  "timeout": 60000,
  "userVerification": "required"
}