Errors
Failures are predictable. Every error carries an HTTP status and a stable detail code — branch on the code, show the status, and you have consistent handling
across the whole API.
Error shape
Most errors return a single stable code in detail:
response · 403 Forbidden
{
"detail": "missing_scope"
}Codes are stable, messages are not
Branch your logic on the
detail code, not on human-readable text. Codes are part of
the API contract; wording may change or be localized.Validation errors
When a request body fails schema validation the status is 422 and detail is an array pinpointing each offending field:
response · 422 Unprocessable Content
{
"detail": [
{
"loc": ["body", "expires_in_days"],
"msg": "Input should be less than or equal to 365",
"type": "less_than_equal"
}
]
}Error reference
| detail | Status | Meaning |
|---|---|---|
unauthorized | 401 | Missing, malformed or invalid token. |
forbidden | 403 | Authenticated, but not allowed to perform this action. |
missing_scope | 403 | The token lacks a scope this endpoint requires. |
plan_feature_required:* | 403 | The feature (signing links, API, webhooks, SMS, bulk send, identity, white label) is not included in the current plan. |
insufficient_credits:* | 402 | The operation is valid but the balance is too low. The suffix details what is missing — amount needed vs. available and the credit type (qualified ICP-Brasil signatures draw from a separate balance). |
quota_exceeded | 402 | The plan send quota is exhausted. Buying credits unblocks it. |
not_found | 404 | Resource does not exist in your tenant (also returned instead of 403 for other tenants). |
conflict | 409 | Idempotency key reused with a different payload, or a conflicting state. |
payload_too_large | 413 | The uploaded file exceeds the size limit. |
unprocessable_pdf | 422 | The uploaded file failed validation and was quarantined. |
(validation) | 422 | Request body failed schema validation — detail is an array of field errors. |
rate_limited | 429 | Too many requests. Back off and retry. |
Retrying safely
429 and transient 5xx responses are safe to retry with exponential
backoff. To retry writes without risking duplicates, send the same Idempotency-Key you used on the first attempt — see Authentication.