Errors
One envelope for every failure, with a coarse class and a specific machine code
Every error response has the same shape, whatever went wrong.
{
"error": {
"type": "invalid_request_error",
"code": "FLOW_NOT_FOUND",
"message": "No flow with id flw_nope",
"param": "flow",
"request_id": "req_8a3f21bc"
}
}| Field | Notes |
|---|---|
type | A coarse class. Use it to decide how to react. |
code | A specific upper snake case machine code. Use it to decide what to say. |
message | Human-readable, for your logs. Do not show it to end users and do not parse it. |
param | The offending field, on validation errors. |
request_id | Also on the X-Request-Id response header. Quote it in support tickets. |
Error types
| Type | Status | What it means and what to do |
|---|---|---|
invalid_request_error | 400 | Your request was malformed or referenced something that does not exist. Fix the call. Never retry unchanged. |
authentication_error | 401 | Missing, malformed or revoked key. Check the Authorization header. |
permission_error | 403 | The key is valid but not scoped for this, or the account lacks the entitlement. |
not_found_error | 404 | No such resource for this account and environment. |
idempotency_error | 409 | The same Idempotency-Key was reused with a different body. See Idempotency. |
rate_limit_error | 429 | Too many requests. Back off and retry, see Rate limits. |
api_error | 5xx | Something failed on our side. Safe to retry with backoff. |
Which errors to retry
Retry rate_limit_error and api_error, with exponential backoff and jitter. Do not retry the 4xx
classes, since the same request will fail the same way. If you retry a create call for any reason,
send the same Idempotency-Key so you cannot accidentally create two verifications for one user.
A cross-environment call is not a 404 by accident
Sandbox and live data are separate. Reading a live verification with a test key returns
not_found_error rather than the record, which is deliberate. If a lookup that works in production
returns 404 in staging, check which environment your key belongs to before you check anything else.
Codes are additive
New code values can appear within the existing type classes. Branch on type for control flow
and treat code as a refinement, with a default branch for codes you have never seen.