Errors
Every error response uses the same envelope, with a stable, machine-readable code and the request_id of the call. The HTTP status tells you the class of problem; code tells you exactly what went wrong. The message text follows Accept-Language (pt-BR, en-US, es-ES, fr-FR, defaulting to en-US); code never changes.
{
"error": {
"code": "validation_failed",
"message": "The request has invalid fields.",
"request_id": "01J8Z3ZQ4H8K2M0T1S9P7YQF5C",
"details": [
{ "field": "name", "code": "required", "message": "Name is required." }
]
}
}codeis the only field your integration should branch on. Handle any code you do not recognize by its HTTP status.detailsis always present. It lists the individual problems, typically on400and422, and is an empty array when there is nothing to itemize. Each item carriesfield(request body field) orparameter(query parameter),code(the rule that was violated), andmessage. Business rule rejections addreasonwith the specific cause.request_idmatches theX-Request-Idresponse header and the entry in the audit trail (GET /requests/{request_id}). Include this value when you contact support.- A resource outside the scope of the current credentials returns
404, exactly like a resource that does not exist. The API never confirms the existence of something you cannot see. - The API fails closed: if the credential state, its permissions, or the rate limiter cannot be verified, the response is
503, never access. - A validation error executes nothing and does not consume the
Idempotency-Key. A429response does not count against the rate limit window.
Codes
| Code | HTTP | When |
|---|---|---|
unauthenticated | 401 | The credential is missing, has an unrecognized format, or does not exist. |
credential_revoked | 401 or 422 | The credential has been revoked. Credential management operations return 422 instead. |
credential_suspended | 401 | The credential has been suspended by Cademí. |
credential_expired | 401 | The credential has expired. |
ambiguous_credentials | 401 | The call uses two authentication modes at once, or sends an ID token instead of an access token. |
human_context_required | 401 | The credential requires human mode, but the call sent only the API key. |
invalid_access_token | 401 | The administrator's access token is invalid, expired, or revoked. |
instance_blocked | 403 | The account is blocked or has been removed. |
instance_unavailable | 403 | The credential's account is not available to the API. |
credential_state_unverifiable | 503 | The credential state could not be verified, so the API fails closed. |
permission_denied | 403 | The credential lacks the permission required by the operation. |
not_found | 404 | The resource does not exist, has been deleted, or is not accessible with the current credentials. |
operation_not_catalogued | 503 | The route is not a recognized public operation, so the request is rejected as a safety measure. |
not_acceptable | 406 | The request's Accept header does not allow application/json. |
unsupported_media_type | 415 | The Content-Type is not application/json. |
payload_too_large | 413 | The request body exceeds 1 MiB. |
malformed_json | 400 | The request body is not valid JSON. |
json_too_deep | 400 | The JSON is nested more than 16 levels deep. |
invalid_utf8 | 400 | The request body contains bytes that are not valid UTF-8. |
validation_failed | 422 | A required field is missing or a value was rejected. details lists each field and rule. |
unknown_field | 422 | The request body contains a field that is not in the schema. |
unknown_parameter | 400 | The query string contains a parameter that is not in the schema. |
invalid_cursor | 400 | The cursor was altered, belongs to a different sort order, or has expired (24 hours). |
method_not_allowed | 405 | The HTTP method is not supported by the route. |
revision_mismatch | 412 | The If-Match value does not match the current revision of the resource. |
invalid_transition | 422 | The requested state change is not available for the resource. |
credential_not_removable | 422 | The credential has usage history and can only be revoked. |
delegation_limit_exceeded | 403 | The delegated policy tried to grant more than the issuing credential has. |
idempotency_key_required | 422 | A state-changing POST request was sent without an Idempotency-Key. |
idempotency_key_invalid | 422 | The Idempotency-Key is malformed (it must be 1 to 128 characters). |
idempotency_key_reused | 422 | The same key was already used with a different body or route. |
idempotency_in_progress | 409 | A request with the same key is still being processed. |
result_uncertain | 409 | The first attempt did not reach a recorded result. Retry the call. |
secret_not_replayable | 409 | A replay does not return a secret that is shown only once. |
result_not_replayable | 409 | The recorded result cannot be replayed for this call. |
operation_type_unknown | 422 | The batch type is not a supported operation type. |
duplicate_item_key | 422 | Two items in the batch share the same key. |
operation_backlog_exceeded | 422 | The account already has too many open operations. |
operation_not_cancelable | 422 | The operation has already finished. |
operation_not_resumable | 422 | The operation has not failed or has no recoverable items. |
item_invalid | 422 | The payload of a batch item does not have the shape its type requires. |
too_many_items | 422 | An array exceeds the maximum size. For operation batches, the limit depends on the operation type (up to 1,000 items). |
operation_ownership_lost | 409 | Another attempt took over the operation, and this attempt was discarded. |
domain_rule_violation | 422 | A business rule was violated that has no dedicated public code. |
http_error | Same as the response | Generic HTTP error. The response status is the status of the failure. |
internal_error | 500 | An unexpected failure occurred. No further detail is provided. |
audit_unavailable | 503 | The audit trail could not be recorded, so the call is not confirmed. |
rate_limit_exceeded | 429 | The per-minute limit for the source, the account, or the credential was reached. |
rate_limiter_unavailable | 503 | The rate limiter did not respond, so the API fails closed. |
state_conflict | 409 | The resource is in a state that does not allow this call. |
upload_integrity_mismatch | 422 | The uploaded bytes do not match the declared size, checksum, or type. |
storage_unavailable | 503 | The file storage service did not respond. |
sandbox_only | 403 | The operation is available only in sandbox accounts. |
production_only | 403 | The operation is available only in production accounts. |
replica_readonly | 403 | The record is a replica copied from another account and is read-only, except for status. Other edits, publishing, and deletion are rejected. |
order_set_mismatch | 422 | The reorder request does not contain exactly the set of IDs in scope. |
hierarchy_violation | 422 | The target would break the hierarchy (a parent inside its own child, or an invalid level). |
banner_type_unavailable | 422 | The banner type is not available for the account. |
already_exists | 409 | A resource with the supplied identifier (external_id, slug) already exists. |
plan_limit_reached | 409 | The account's plan does not allow another resource of this type. |
email_recently_sent | 409 | The same email was sent recently. Wait for the window to pass. |
feature_disabled | 409 | The feature is turned off in the account settings. |
tag_in_use | 409 | The tag is in use and cannot be deleted. |
template_not_previewable | 409 | The template has nothing to preview. |
format_unsupported | 409 | The requested format is not supported by the resource. |
human_mode_not_allowed | 403 | The credential does not allow human mode. |
admin_not_eligible | 403 | The administrator of the access token is not linked to the credential. |
tenant_mismatch | 403 | The administrator of the access token belongs to another account. |
too_many_streams | 429 | The limit of event streams per credential (5) or per account (20) was reached. |
stream_busy | 409 | The event stream already has an open connection. |
cursor_expired | 410 | The cursor points to an event that is no longer retained (30-day retention). |
sandbox_required | 409 | The test scenario runs only in a sandbox account. |
unsupported_resource | 422 | The resource type is not accepted by this operation. |
plan_invalid | 422 | The declarative manifest failed validation. |
plan_stale | 409 | The plan was computed against a state that has since changed. |
plan_expired | 409 | The plan has expired and must be computed again. |
What to do for each class
| Status | Action |
|---|---|
400, 404, 405, 406, 409, 412, 413, 415, 422 | Client error. Retrying without changes produces the same result. |
401, 403 | Credential or permissions. Review the credential and its permissions before retrying. |
429 | Wait for retry_after_seconds (or the Retry-After header) and retry. See Limits, quotas, and retention. |
500, 503 | Server failure or unavailability. Retry with exponential backoff; for state-changing requests, use the same Idempotency-Key. |
If a state-changing request returns 500, 503, or times out, the outcome is uncertain: retry with the same Idempotency-Key. If the first attempt was recorded, the retry returns the same response with Idempotent-Replayed: true and creates nothing new.