Errors
Every error carries an HTTP status and a stable code in detail: 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:
{
"detail": "envelopes:send"
}Codes are stable, messages are not
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:
{
"detail": [
{
"loc": ["body", "expires_in_days"],
"msg": "Input should be less than or equal to 365",
"type": "less_than_equal"
}
]
}Error reference
Some codes carry a suffix after a colon with the specifics (which feature, how many credits). Match on the part before the colon.
| Code | Status | Meaning |
|---|---|---|
| not_authenticated | 401 | No Authorization header was sent. |
| invalid_api_token | 401 | The token is malformed, unknown, revoked or expired. |
| <scope> | 403 | The token lacks a scope this endpoint requires. detail is the scope’s name, for example envelopes:send. |
| plan_feature_required:<feature> | 403 | The feature (api, webhooks, bulk_send, embedded_signing, auth_otp_sms…) 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). |
| free_plan_send_limit_reached | 402 | The free plan send quota is exhausted. Buying credits unblocks it. |
| <resource>_not_found | 404 | The resource does not exist in your organization: envelope_not_found, document_not_found, participant_not_found, proof_not_found… Also returned instead of 403 for another organization’s resources. |
| idempotency_key_reused_with_different_payload | 409 | The Idempotency-Key was already used with a different payload. |
| envelope_not_editable_in_status_<status> | 409 | The envelope can no longer be changed in its current status — for example, after it was sent. Other state conflicts have codes of their own, such as fields_not_allowed_in_report_placement. |
| too_large | 413 | The uploaded file exceeds the size limit. |
| not_a_pdf · password_protected · corrupt · … | 422 | The uploaded file failed validation and was rejected or quarantined; detail names the reason. No document is created and no credit is consumed. |
| (validation) | 422 | The request body failed schema validation — detail is an array of field errors. |
| rate_limited | 429 | Too many requests. Wait for the seconds in Retry-After 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.