Errors
All error responses share a consistent envelope. The HTTP status code matches the error type.
Error envelope
{
"error": {
"type": "validation_error",
"message": "At least one of html or text is required.",
"request_id": "req_abc123",
"details": [
{ "field": "", "message": "At least one of html or text is required." }
]
}
}The details array is present only on validation errors and contains per-field messages. The retry_after field is present only on rate limit errors and contains the number of seconds to wait.
Error types
| Type | Status | Description |
|---|---|---|
| validation_error | 422 | Invalid request body or parameters. |
| authentication_error | 401 | Missing or invalid API key. |
| authorization_error | 403 | Key lacks required scope. |
| quota_exceeded | 403 | Plan quota exceeded (mailboxes, sends, or team members). |
| not_found | 404 | Resource does not exist. |
| conflict | 409 | Idempotency key reused with different body. |
| rate_limit_error | 429 | Rate limit exceeded, or sending limit reached (daily ramp-up, per-mailbox, or throttle). |
| internal_error | 500 | Unexpected server error. |
Quota exceeded error
A 403 response with type quota_exceeded is returned when a plan limit is reached. The message includes the current usage and limit.
{
"error": {
"type": "quota_exceeded",
"message": "Mailbox limit reached (3/3). Your Solo plan includes 3 mailboxes.",
"request_id": "req_abc123"
}
}See Plan limits for quotas by plan.
Rate limit error
A 429 response includes a Retry-After header and a retry_after field in the error body:
{
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded. Try again later.",
"request_id": "req_abc123",
"retry_after": 12
}
}