RefreshDocsConsole →

API reference

Errors

One JSON error shape and every code the API returns.

Every non-2xx response has this body:

{ "error": { "code": "domain_not_verified", "message": "Domain example.com is pending" } }

code is stable and meant for programs. message is for humans and can change.

Codes

Status Code Meaning
400 invalid_json Body is not valid JSON.
401 unauthorized Missing, malformed, unknown, revoked or expired API key.
403 forbidden_domain The key is restricted to other domains than the from domain.
403 forbidden The endpoint needs a FULL key (DELETE /contacts/:id, DELETE /suppressions/:id).
403 sending_paused An admin or an alert rule paused sending for the organization (also on POST /broadcasts/:id/send). An admin resumes it in Settings → Organization.
403 test_key_not_allowed A f5_test_ key called an endpoint that sends live mail from the worker (POST /broadcasts, POST /broadcasts/:id/send, POST /broadcasts/:id/decide, POST /broadcasts/:id/resend, POST /events, POST /contacts, POST /contacts/:id/subscriptions, DELETE /contacts/:id, POST/DELETE /suppressions). Test keys simulate POST /emails only.
404 not_found No such email / contact / broadcast in this organization.
409 not_cancelable Email is no longer queued (or is being sent right now); broadcast is already sent or canceled.
409 not_schedulable Broadcast is not draft or scheduled.
409 not_testing POST /broadcasts/:id/decide: the broadcast is not testing.
409 not_resendable POST /broadcasts/:id/resend: the parent is not sent, or is itself a resend.
409 resend_exists POST /broadcasts/:id/resend: a child that is not canceled already exists.
409 resend_too_early A resend cannot send until 24 hours after the parent finished. The message names the earliest time.
422 subject_from_template POST /broadcasts/:id/resend: the parent uses a template, so subject is not accepted.
409 suppression_conflict POST /suppressions: the address already has a complaint, hard_bounce or unsubscribe entry at that scope. A manual entry cannot replace it or give it an expiry.
422 validation_error Schema validation failed; the message lists each field, e.g. to: Invalid email; subject: subject is required.
422 invalid_from from is not email or Name <email>.
422 unknown_domain The from domain is not registered in this organization.
422 domain_not_verified The from domain is pending, failed or disabled.
422 bulk_single_recipient A bulk kind (bulk.*, broadcast.*, digest.*, sequence.*) was sent to more than one recipient.
422 template_not_found No template with that id/slug, it is archived, or it has no published version (or not that version).
422 template_variables Template data invalid — message lists missing:, unknown: and mistyped: variables.
422 invalid_subject Rendered subject is empty, over 998 characters or contains line breaks.
422 unknown_topic The topic slug is not valid, or POST /contacts/{id}/subscriptions named a slug that does not exist.
422 unknown_segment segment_id is not one of the segments of the organization.
422 invalid_segment The stored filter of the segment no longer parses.
422 invalid_cursor The cursor on a list endpoint is not one the platform issued.
422 attachments_not_in_batch A POST /emails/batch item carried attachments. Send those messages one at a time.
422 stream_mismatch A bulk kind was sent from a domain whose stream is Transactional (also POST /broadcasts). Send bulk mail from a Bulk domain such as news.<domain>.
422 reserved_header headers names a header the platform sets (Message-ID, Feedback-ID, Return-Path, DKIM-Signature, From, To, Cc, Bcc, Reply-To, Sender, Subject, Date, MIME-Version, Content-Type, Content-Transfer-Encoding, Content-ID, Content-Disposition).
429 rate_limited Over the per-key requests-per-second cap (default 10; the key's own limit or API_RATE_LIMIT_PER_SEC). The response carries Retry-After: 1.
429 quota_exceeded The organization reached its monthly limit. Each recipient counts as one email. On Free the limit is the allowance. On a paid plan, mail past the allowance is sent and billed as overage, up to twice the allowance. Live sends are refused until the next UTC month; Retry-After carries the seconds until then. Test keys are never counted.
429 contact_quota_exceeded POST /events would create more new contacts than the daily quota. The response carries Retry-After in seconds until the next UTC day.
429 run_quota_exceeded POST /events would start more automation runs than the daily quota. The response carries Retry-After in seconds until the next UTC day.
500 internal_error Unexpected failure; safe to retry with the same Idempotency-Key.

Management endpoints

These come only from the management endpoints, which need an ADMIN key.

Status error.code Meaning
403 admin_key_not_mintable POST /keys will not create an ADMIN key, and POST /keys/{id}/rotate will not rotate one. Mint and rotate ADMIN keys in the console, so a key can never clone its own authority.
409 already_revoked The key is already revoked.
409 already_rotated The key has a replacement already. Rotate the replacement instead.
403 plan_limit The plan's contact or webhook endpoint limit is reached. Updates to existing contacts still work. Upgrade in Settings → Billing, or delete an endpoint.
409 domain_taken The domain belongs to this organization or to another one.
422 manual_dns The domain uses manual DNS. Read records from GET /domains/{id} and publish them yourself.
422 cloudflare_unconfigured The server has no Cloudflare token, so it cannot publish for you.
422 publish_failed Cloudflare refused one or more records. The message carries the provider error.
422 unsupported_transport Only SES domains register a sending identity.
422 identity_registration_failed SES refused the identity, a DKIM selector or the custom MAIL FROM. The message carries the provider error.
409 topic_exists A topic with that slug is already in the organization.
409 topic_in_use A broadcast references the topic. Delete the broadcast first.

POST /emails/batch never fails as a whole for per-item problems. Each item is { "id" } or { "error": { "code", "message" } } with the same codes.

SMTP replies

The SMTP relay maps each API answer to one SMTP reply:

API SMTP reply
2xx (queued or replayed) 250 2.0.0 queued as <id>
401 unauthorized 535 5.7.8 Authentication credentials invalid
429 rate_limited 451 4.7.1 rate limited, retry later
403 sending_paused 451 4.7.1 sending paused
403 forbidden_domain, 422 unknown_domain, any other 403 553 5.7.1 <code>
422 invalid_from, 422 domain_not_verified 553 5.6.0 <code>
413, or a code that names a size 552 5.3.4 <code>
Any other 422 or 400 550 5.6.0 <code>
5xx, or no answer 451 4.4.1 Temporary system problem, try again later

The full table, with the replies that the relay decides on its own, is on the SMTP relay page.