Errors always return the same shape, with a machine-readable code and a human message. Database errors, stack traces and SQL are never surfaced; anything unexpected becomes internal_error and the detail is logged against the request id you received.
Codes by status
401 — unauthorized, invalid_api_key, api_key_revoked, api_key_expired
403 — insufficient_scope, forbidden
404 — not_found, campaign_not_found, contact_not_found, mailbox_not_found, reply_not_found, webhook_not_found, job_not_found
405 — method_not_allowed
409 — conflict, idempotency_conflict, idempotency_in_progress
413 — payload_too_large
415 — unsupported_media_type
422 — invalid_request (validation failed; the details list the offending fields)
429 — rate_limited
500 — internal_error
How to handle them
- Retry only
429,500and network failures. Everything else is a bug in the request. - Log the request id from the response with your error so support can trace it.
- Treat
422details as the source of truth for what to fix.
Was this article helpful?
