Errors

One error envelope, one code per failure, a matching HTTP status.

Every 4xx and 5xx response uses the same envelope:

{
  "error": {
    "code": "invalid_request",
    "message": "Body must be JSON."
  }
}
  • code is stable and machine-readable — branch on it.
  • message is human-readable and may change.

Some send failures that were still logged include a message_id alongside code and message, so you can look the attempt up later.

Status codes

StatuscodeMeaning
400invalid_requestThe body failed validation (bad JSON, missing or malformed field).
401unauthorizedMissing key, invalid/revoked key, or the key lacks the required scope.
404template_not_foundNo template with that slug in this project.
404not_foundNo such message in this project.
409template_not_publishedThe template exists but has no published version.
409sends_pausedThe project's kill switch is on — no sends leave until it's cleared.
422suppressedThe recipient is on the suppression list (bounce, complaint, or manual block).
429daily_capThe project's daily send cap has been reached.
429monthly_capThe provider plan's monthly send limit has been reached.
429rate_limitedToo many requests in a short window. Retry after a short backoff.
502provider_errorThe email provider rejected the request.
500internalAn unexpected server error. Safe to retry with the same Idempotency-Key.

suppressed, sends_paused, daily_cap, and monthly_cap are policy outcomes, not bugs — the request was well-formed but the send was deliberately blocked. Handle them distinctly from invalid_request.

On this page