Errors
The error envelope, every error code the API returns, and what each one means.
A refused request answers with an HTTP status and a JSON envelope. The envelope carries a stable code and a sentence for people. Branch on the code. Show or log the message.
The error envelope
{
"error": {
"code": "SCOPE_DENIED",
"message": "This API key can only send email."
}
}
Some refusals add fields beside error. A RISK_REFUSED answer carries the risk reasons, and an APPROVAL_REQUIRED answer carries the draft card and an approvalId. A refusal that tells you to wait also sends a Retry-After header in seconds.
Error codes
| Status | Code | Meaning |
|---|---|---|
| 400 | BAD_REQUEST | The request is invalid. The message names the field. |
| 401 | UNAUTHORIZED | The API key is missing or not valid. |
| 402 | INSUFFICIENT_BALANCE | The wallet cannot cover an SMS or SMS code. Nothing was sent. |
| 403 | FORBIDDEN | The call is not allowed for this team or key, for example a key's approval policy that only saves drafts. |
| 403 | SCOPE_DENIED | The key's permission (full, sending or read only) does not reach this call. |
| 403 | KEY_PAUSED | The key is paused by the account owner. Nothing runs until it is resumed. |
| 403 | FORBIDDEN, details.reason DOMAIN_BULK_NOT_READY | A broadcast, automation or MARKETING send from a new domain whose DNS is not finished. The message names the record to fix. Transactional email still sends. |
| 403 | DOMAIN_PINNED | The key is restricted to one domain, and this call is not tied to it. |
| 404 | NOT_FOUND | Nothing with that id belongs to the key's team. |
| 405 | METHOD_NOT_ALLOWED | The path exists, but not with this HTTP method. |
| 409 | NOT_UNIQUE | An idempotency key was reused with a different body, or is still in flight. |
| 409 | CONFLICT | The thing changed under you, for example a broadcast that is no longer a draft. Nothing was written. |
| 409 | NOT_IN_SEGMENT | The automation is limited to a segment, and the contact does not match it. |
| 409 | APPROVAL_REQUIRED | The key's approval policy needs a person's yes for a broadcast this large. The body carries the draft card and an approvalId. Nothing was sent. |
| 409 | PARTIAL_COMPLETION | An earlier request with this idempotency key stopped part way. The body lists the email ids it sent. Nothing was sent again. |
| 422 | UNPROCESSABLE_ENTITY | Well formed but not processable, such as more than 50 recipients. |
| 422 | RISK_REFUSED | Risk scoring refused a one-time code or SMS. The body carries the reasons. |
| 429 | RATE_LIMITED | The per second rate limit or a send limit was reached. |
| 429 | RATE_LIMITED, details.reason DOMAIN_WARMUP_LIMIT | The domain is warming up or on probation and has used today's limit. See Warm-up. |
| 429 | RATE_LIMITED, details.reason SCHEDULED_BACKLOG_LIMIT | You already have 7 days of your daily limit scheduled for later. Wait for some to send, or cancel some, then schedule more. |
| 429 | LIMIT_EXCEEDED | A limit the owner set on this key (requests per minute, daily or monthly sends, SMS per day) was reached. |
| 500 | INTERNAL_SERVER_ERROR | Something went wrong on our side. Retry with backoff. |
| 503 | SERVICE_UNAVAILABLE | A dependency is briefly unavailable. Retry with backoff. |
Validation errors
A request body that fails validation answers 400 with the validation issues. Each issue names the field path and what was wrong.
Which errors to retry
- Retry transport errors, 429, 500 and 503 with backoff. On a 429, wait for
Retry-Afterfirst. - Do not retry other 4xx answers as they are. Fix the request first.
- Send an
Idempotency-Keyon sends, so a retry never sends twice. See Idempotency.