Error Catalog
Digital ID returns errors in this form:
Code
| Field | Type | Description |
|---|---|---|
error | object | Error details. Present on each non-2xx response. |
error.code | string | Machine-readable error code, for example invalid_input. |
error.message | string | Human-readable description. Do not parse this value. Use error.code instead. |
| HTTP status | Code | Meaning |
|---|---|---|
| 400 | invalid_input | The request body or a parameter is invalid. |
| 401 | unauthorized | The API key or token is invalid. |
| 404 | not_found | The session, merchant, or exchange code was not found. |
| 409 | invalid_state | The requested action is not allowed at the current step. |
| 410 | session_expired | The verification session expired. This includes the end of the consent confirmation window. |
| 423 | session_blocked | Three liveness or face-match attempts failed. |
| 429 | rate_limited | The client sent too many requests. |
The invalid_state, session_expired, and session_blocked codes match the
conditions in Verification Flow:
invalid_state: the requested action is not allowed at the current step.session_expired: the verification session expired.session_blocked: three liveness or face-match attempts failed.
Front-channel errors
The widget reports front-channel failures with privy:error:
Code
An unverified iframe host receives the event type without the payload.
The widget sends privy:error when the session is blocked after three failed
liveness or face-match attempts. It also sends privy:error with
session_expired when the consent confirmation window ends. The widget sends
privy:cancel when the user rejects the consent request.
Camera errors
The WebView camera guard can reject a request before it accesses the camera:
camera_unsupportedwhen the OS or WebView does not support capture.camera_missing_permissionwhen the host application lacks its required camera declaration.
User permission denial and hardware failures use standard browser
DOMException values: NotAllowedError, NotFoundError, or
NotReadableError.
Recovery guide
Where the public API contract has no recovery mechanism, raise the case through your agreed Privy support process.
| Scenario | Recovery |
|---|---|
The create-session request times out, or no session_url arrives. | Create a new session. The retry can return a new session_id. The unused session expires automatically and is not charged. |
| The user closes the application during verification. | If the retained session_url has not expired, load it again. If not, create a new session. The user starts the flow again. |
The session expired: 410 session_expired or privy:error. | Create a new session. The user starts the flow again. You cannot extend or reactivate an expired session. |
The user rejects the consent request: privy:cancel. | Create a new session if the user wants to try again. The user starts again from step 1. |
The consent confirmation window ends: privy:error with session_expired. | Create a new session. The user starts again from step 1. |
| The exchange code is lost or expired: 404 or 410 on exchange. | The public API cannot issue the code again. If the server callback delivers the result, use it. If no verified result arrives through either channel, start a new session or contact Privy support. |
| Callback processing takes more than 60 seconds. | Privy can treat the delivery as timed out. Acknowledge promptly and process asynchronously. Use the exchange flow if you received the code. |
| The result arrives through both the exchange and the callback. | This is expected. Both channels deliver the same verified result. Process it one time, by session_id. |
| JWT verification fails. | Reject the result and do not use its data. Get the JWKS again and repeat the kid, aud, exp, and iss checks. If verification still fails, contact Privy support. Do not skip a check. |
| No verified result arrives on the backend. | There is no public status lookup by session_id. Treat the verification as incomplete. Start a new session, or raise the case through your agreed Privy support process. |
| The session is blocked: 423 after three failed liveness or face-match attempts. | The session cannot continue. Privy policy decides whether and when the user can try again with a new session. Raise the case through your agreed Privy support process. |
