ZitadelDocs

Complete authentication and create handoff token

Completes the authentication attempt and mints a `handoff_token`. Call this after all required factors have been verified and the attempt is in `completed` state. The handoff token is short-lived (≤60 seconds) and must be exchanged at POST /sessions/exchange to receive the final session and session_token. The handoff token is: - Single-use (atomic exchange, no retry) - Audience-bound (requires matching project key for exchange) - Idempotency-safe within a 5-minute window (see conventions)

POST
/auth_attempts/{attempt_id}/handoff

Completes the authentication attempt and mints a handoff_token.

Call this after all required factors have been verified and the attempt is in completed state. The handoff token is short-lived (≤60 seconds) and must be exchanged at POST /sessions/exchange to receive the final session and session_token.

The handoff token is:

  • Single-use (atomic exchange, no retry)
  • Audience-bound (requires matching project key for exchange)
  • Idempotency-safe within a 5-minute window (see conventions)

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_-]+$

Header Parameters

Idempotency-Key?string

Optional retry key for safe retries of the handoff creation (Category B idempotency). Retries carrying the same key within the exchange window return the same handoff token without re-completing the attempt or minting a new token.

Response Body

Handoff token created successfully

application/json
  1. response

The handoff token and metadata for session exchange.

This is a short-lived credential (TTL ≤ 60 seconds) that the client must exchange at POST /sessions/exchange to receive the final session and session_token. The handoff token is single-use and audience-bound to the project.

handoff_token*string

The short-lived handoff token for session exchange.

Exchange at: POST /sessions/exchange

Requirements:

  • Single-use (atomic GETDEL on exchange)
  • TTL ≤ 60 seconds
  • Audience-bound to project (exchange requires sk_proj_… for matching project)
  • Idempotency-safe (Category B, 5-minute window)
expires_at*string

When this handoff token expires

Formatdate-time
curl -X POST 'https://example.com/auth_attempts/string/handoff'
{  "handoff_token": "string",  "expires_at": "2019-08-24T14:15:22Z"}