Reference
Errors
Every error returns a stable machine-readable code, a human-readable message, and a request_id for support. Build retry logic against code, not the message.
Error shape
{ "error": { "type": "invalid_request_error", "code": "identity_not_found", "message": "No identity with id 'person_xxx' in test mode.", "param": "person", "doc_url": "https://docs.valyd.id/errors#identity_not_found", "request_id": "req_8YQzL2pMxV1nRk" } }
HTTP status codes
| Status | Meaning |
|---|---|
200 | OK — request succeeded. |
201 | Created — resource created. |
400 | Bad request — malformed or missing parameter. |
401 | Unauthorized — missing, invalid, or revoked API key. |
402 | Payment required — plan limit reached. |
403 | Forbidden — key lacks scope for this resource. |
404 | Not found — resource does not exist (or wrong mode). |
409 | Conflict — idempotency key reused with different body. |
429 | Too many requests — see Retry-After. |
5xx | Server error — safe to retry with backoff. |
Retry guidance
Exponential backoff with jitter
Retry on 429 and 5xx with exponential backoff (start 250ms, cap 30s) plus ±20% jitter. Always include the original Idempotency-Key on retries.
Never retry 400, 401, 403, or 404 — these indicate a logic bug, not a transient failure.
Error codes
| Code | Status | What happened |
|---|---|---|
identity_not_found | 404 | The person ID doesn't exist in this mode (test vs live). |
identity_already_verified | 409 | Already passed this check within the dedupe window. |
face_match_failed | 200 | Returned in the body — request succeeded, check failed. |
liveness_failed | 200 | The capture didn't pass liveness; prompt the user to retry. |
license_expired | 200 | Credential found but past expiry. Includes expired_at. |
license_unknown_jurisdiction | 400 | Pass an ISO 3166-2 region code (e.g. US-CA). |
scope_insufficient | 403 | Token is missing the requested scope (e.g. license:nurse). |
agent_not_authorized | 403 | The agent's policy doesn't permit this action. |
agent_approval_required | 202 | Action queued pending human approval. |
webhook_signature_invalid | 401 | Signature header failed verification — reject the event. |
idempotency_conflict | 409 | Same key, different body within 24h. |
rate_limited | 429 | Slow down. See Retry-After. |
api_key_invalid | 401 | Key revoked, malformed, or wrong mode prefix. |
internal_error | 500 | Our problem. Retry with backoff and contact support with the request_id. |
