Errors
Nani uses standard HTTP status codes. Unsuccessful responses return a JSON body with an error object you can handle programmatically.
Use error.code for branching in your integration. The error.message field is safe to log but may change wording between releases.
Response shape
All error responses follow this structure:
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"error"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"code"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"BAD_REQUEST"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"message"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"country is required"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>Some errors include a details object (for example rate limits).
Status codes
- Name
2xx- Description
Success — the request completed as expected.
- Name
4xx- Description
Client error — check your API key, request body, or resource IDs.
- Name
5xx- Description
Server error — retry with backoff and contact support if it persists.
Common errors
Error codes
- Name
BAD_REQUEST- Type
- 400
- Description
Invalid or missing parameters.
- Name
UNAUTHORIZED- Type
- 401
- Description
Missing or invalid API key or Bearer token.
- Name
PAYMENT_REQUIRED- Type
- 402
- Description
Insufficient credits on the tenant account.
- Name
NOT_FOUND- Type
- 404
- Description
Session, identity, or other resource does not exist.
- Name
CONFLICT- Type
- 409
- Description
State conflict (for example duplicate or invalid transition).
- Name
GONE- Type
- 410
- Description
Resource expired or is no longer available.
- Name
UNPROCESSABLE_ENTITY- Type
- 422
- Description
Semantically invalid request (valid JSON but not allowed).
- Name
RATE_LIMITED- Type
- 429
- Description
Too many requests — back off using
details.retry_after.
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid credentials"
}
}
Example on an endpoint
When creating a session, you may see:
{
"session_id": "ses_01hzabc123",
"verify_url": "http://localhost:3005/verify/tok_xyz",
"status": "created",
"required_steps": ["consent", "id_document", "liveness"],
"expires_at": "2026-06-01T12:00:00Z"
}