Errors
Every error is JSON with the same three fields, and the HTTP status matches statusCode:
{ "name": "validation_error", "message": "from and to are required", "statusCode": 400}name is the stable machine-readable identifier; branch on it, not on message.
Common errors
Section titled “Common errors”| Status | name |
Meaning |
|---|---|---|
| 400 | validation_error |
A request field is missing or malformed; message says which |
| 401 | missing_api_key |
No Authorization: Bearer ss_… header |
| 403 | invalid_api_key |
The key is wrong or revoked |
| 403 | domain_not_verified |
Sending from an unverified domain outside test mode |
| 403 | domain_not_owned |
The from-domain is verified by another team; claim it |
| 403 | sending_paused_reputation |
Bounce/complaint rates tripped the safety hold; contact support |
| 404 | not_found |
No such resource on your team |
| 409 | idempotency_in_progress |
A request with this Idempotency-Key is still in flight; retry shortly |
| 429 | rate_limit_exceeded |
Over the rate limit; back off and retry |
| 429 | quota_exceeded |
Monthly sending quota reached; sending is paused until next month or an upgrade |
| 500 | internal_error |
Something broke on our side; the X-Request-Id response header identifies the request for support |
Internal detail (SQL, provider errors) never appears in message; it’s logged server-side
against the request id.