ZitadelDocs

Issue a factor challenge

Issues a single-factor verification challenge within an auth attempt. This advances the authentication state machine by requesting a specific factor method (password, passkey, TOTP, OTP via SMS, etc.). The server responds with challenge details including method, metadata, and any UI hints. The client then verifies the proof by calling POST /auth_attempts/{attempt_id}/challenges/{challenge_id}/verify.

POST
/auth_attempts/{attempt_id}/challenges

Issues a single-factor verification challenge within an auth attempt.

This advances the authentication state machine by requesting a specific factor method (password, passkey, TOTP, OTP via SMS, etc.). The server responds with challenge details including method, metadata, and any UI hints. The client then verifies the proof by calling POST /auth_attempts/{attempt_id}/challenges/{challenge_id}/verify.

Authorization

oauth2 auth_attempt.write
headerAuthorizationBearer <token>

Scope: auth_attempt.write

Path Parameters

attempt_id*string

The unique identifier of the authentication attempt

Match^att_[a-zA-Z0-9_-]+$

Request Body

application/json
  1. body

Request to issue a factor challenge.

The method field selects which factor to challenge. Additional fields are only relevant for specific methods:

  • passkey_options is optional and only used when method is passkey.
  • idp_provider is required when method is idp and must be omitted otherwise. This conditional requirement is enforced server-side.
method*challenge-method

The authentication factor method to challenge.

Value in"identifier""password""passkey"
passkey_options?

Optional WebAuthn ceremony options. Only relevant when method is passkey.

Response Body

Challenge issued successfully

application/json
  1. response

A factor challenge issued within an authentication attempt.

A challenge presents a single-factor verification prompt (password entry, TOTP code, passkey assertion, etc.). The client verifies the proof by POST /auth_attempts/{attempt_id}/challenges/{challenge_id}/verify.

challenge_id*challenge-id

Unique identifier for this challenge (dialect-minted prefixed opaque string).

Match^ch_[a-zA-Z0-9_-]+$
method*challenge-method

The authentication method this challenge represents. Determines which proof is expected in verify.

Value in"identifier""password""passkey"
state*string

Current state of this challenge:

  • pending: awaiting proof submission
  • failed: proof rejected (invalid credential, wrong code, etc.)
  • expired: challenge TTL exceeded without verification
Value in"pending""failed""expired"
created_at*string

When this challenge was issued

Formatdate-time
expires_at?|

When this challenge expires

payload?||

Method-specific challenge data. Structure depends on the method field.

  • identifier, password: null (no additional data needed)
  • passkey: WebAuthn challenge and credential options
  • idp: Authorization URL and provider information
curl -X POST 'https://example.com/auth_attempts/string/challenges' \  -H 'Content-Type: application/json' \  -d '{  "method": "identifier"}'
{  "challenge_id": "string",  "method": "identifier",  "state": "pending",  "created_at": "2019-08-24T14:15:22Z",  "expires_at": "2019-08-24T14:15:22Z",  "payload": {}}