Errors
Every error code of the public API with its status and meaning.
Error body
Every error answers with a stable code and an English message for logs. Branch on the code, never on the message.
{ "code": "domain_not_verified", "message": "from uses mail.acme.dev, which is not a verified sending domain of this account" }
Every answer carries an X-Request-Id header. Quote it when you write to support: letr.dev finds the request by it. Send your own X-Request-Id (at most 64 letters, digits, - or _) and letr.dev uses it; otherwise letr.dev sets one. A 401 also carries WWW-Authenticate: Bearer.
Codes
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request |
The body is not readable JSON, the Idempotency-Key is longer than 255 characters, or a query parameter (cursor, limit, status, q, range) is invalid. |
| 401 | unauthorized |
No key, or an unknown, revoked or expired key. |
| 403 | insufficient_permission |
The key's permission does not allow this request. |
| 403 | domain_not_allowed |
The from-domain is outside the domains the key is limited to. |
| 403 | account_not_active |
The account is not active: its payment is pending or it is disabled. |
| 403 | account_paused |
The account is paused. |
| 404 | not_found |
No such email, domain, webhook or address in this account. |
| 405 | method_not_allowed |
The path exists, the method does not. |
| 409 | domain_exists |
The account already has this domain. |
| 409 | not_scheduled |
The email is not waiting for its scheduled time any more, so it cannot be cancelled. |
| 409 | webhook_disabled |
The endpoint is disabled: pausing, resuming or replaying needs it enabled first. |
| 413 | import_too_large |
A suppression import has more than 10'000 lines or 1 MB. |
| 415 | unsupported_media_type |
Send Content-Type: application/json; POST /v1/suppressions/import takes text/csv. |
| 422 | domain_not_verified |
The from-domain is not a verified domain of the account. |
| 422 | recipient_suppressed |
A recipient is on the suppression list; the message names them. |
| 422 | invalid_from |
from is missing or not an address. |
| 422 | invalid_recipients |
to is empty or an address is invalid. |
| 422 | too_many_recipients |
More than 50 recipients across to, cc and bcc. |
| 422 | invalid_subject |
subject is missing, longer than 998 characters or not one line. |
| 422 | missing_content |
Neither html nor text. |
| 422 | invalid_attachment |
Missing filename, content that is not base64, or an invalid or repeated contentId. |
| 422 | message_too_large |
The email is larger than 15 MB as sent, about 10 MB of attachments. |
| 422 | invalid_headers |
Too many headers, an invalid name, a value that is too long or has a line break, or a repeated name. |
| 422 | reserved_header |
A header letr.dev sets itself. |
| 422 | invalid_tags |
More than 10 tags, an invalid name or a value over 256 characters. |
| 422 | invalid_batch |
A batch with no email or more than 100. |
| 422 | idempotency_key_reused |
The Idempotency-Key was used with a different request. |
| 422 | invalid_domain |
The name is not a domain. |
| 422 | domain_limit_reached |
The account has 20 domains; remove one first. |
| 422 | api_key_expiring |
The key is already being replaced; roll its successor instead. |
| 422 | invalid_webhook_url |
Not a public https URL. |
| 422 | invalid_webhook_events |
No event type, or an unknown one. |
| 422 | webhook_url_taken |
Another endpoint of the account has this URL. |
| 422 | webhook_limit_reached |
The account has 5 endpoints; delete one first. |
| 422 | invalid_scheduled_at |
scheduledAt is less than 1 minute or more than 7 days ahead. |
| 422 | invalid_email |
The address to suppress, or the email address at signup, is not valid. |
| 422 | invalid_customer_type |
Signup: the customer type is neither a company nor a private person. |
| 422 | invalid_use_case |
Signup: the description of what you will send is shorter than 20 or longer than 500 characters. |
| 429 | monthly_ceiling_reached |
The monthly ceiling of your account is reached. Choose a higher ceiling under Billing if one is offered, otherwise write to Support. |
| 429 | daily_limit_reached |
The daily limit of your account is used up. |
| 429 | rate_limited |
Too many requests; slow down. |
| 500 | internal_error |
Something failed at letr.dev. |
| 503 | unavailable |
letr.dev is temporarily unavailable; retry later. |
| 503 | content_busy |
Too many content reads at once; retry after the Retry-After header. |
In a batch, the message names the position of the failing email, for example [3].to.