CATALOGUES · Published 2026-10-06 · Updated 2026-10-06 · SecureSMTP

Error catalogue

Every error the API returns, what it means and what to do.

Every response has a status code and a JSON body. Read the body as well as the status: some failures of POST /mail/send come back as HTTP 200 with "ok": false.

  • POST /mail/send, GET /mail/domain-status and POST /sequences/enroll name the problem in reason, next to "ok": false.
  • The forms and sites endpoints name it in error. The blocks endpoints use error next to "ok": false.
Examples
// POST /mail/send
{ "ok": false, "sent": false, "reason": "attachments_too_large" }

// POST /forms/submit
{ "error": "no_notify_email_configured" }

// POST /blocks/lift
{ "ok": false, "error": "not_self_liftable" }

Authentication (every endpoint)

ValueHTTPMeaningWhat to do
missing_api_key401No key header was sent.Send x-securessmtp-api-key. See API conventions.
invalid_api_key401The key does not match any site. It may have been rotated.Copy the current key, or rotate it. See Sites and API keys.
site_disabled403The site is disabled. Not returned by the blocks endpoints.Check Blocks.

POST /mail/send

In the order the checks run. Values are in reason.

ValueHTTPMeaningWhat to do
invalid_json400The body is not valid JSON.Fix the body. Do not retry as is.
invalid_payload400A field failed validation. details lists which (for example a bad address, more than 50 recipients, from sent as a string).Fix the field named in details.
template_not_found400No template with that id or slug in your account, and no starter template with it.Check the name in /app/templates.
no_body400No html, no text and no template.Send html, text or a template.
invalid_attachment400An attachment’s content is not valid base64. The response includes its filename.Encode the file as base64.
attachments_too_large400Attachments add up to more than 15 MB after decoding.Send fewer or smaller files, or a link.
rate_limited200The site sent 120 emails in the last 60 seconds. Not sent.Wait a minute and send again.
content_flagged400The subject and body scored 60 or more on the spam check. Not sent.Change the content. See Spam protection.
held_as_spam200Not an error: ok and sent are true and held is true. A contact-form notification was judged spam and not sent.Nothing. Do not resend it another way.
ai_flagged400The AI check is at least 85% sure the email is spam. Not sent.Change the content. If you think it is wrong, contact support.
over_quota200The account’s monthly email count is used up (relay mode only). Not sent.Wait for the new month, send from a verified domain, or upgrade. See Plans and limits.
send_failed200The send failed. error has the cause (see below).Read error. Retry only for causes other than the two below.

Values of error with send_failed

errorMeaning
all_recipients_suppressedEvery address in to is on the suppression list. See Bounces and suppressions.
all_recipients_unsubscribedEvery address in to unsubscribed from this site. See Unsubscribe links.
Any other textA delivery error on our side. Retry after a short wait; contact support if it repeats.

A request body over 25 MB is refused by the web server with 413 before it reaches the API.

GET /mail/domain-status

Only the authentication errors above.

POST /forms/submit

ValueHTTPMeaningWhat to do
invalid_json400The body is not valid JSON.Fix the body.
invalid_payload400A field failed validation. details lists which (for example form_id missing, a field value over 10,000 characters, site_url not a full URL).Fix the field named in details.
no_notify_email_configured400No valid recipient in the request and the site has no notify email.Send notify_emails, or set the site’s notify email on the Sites page.

These are not errors, but your code should know them:

BodyMeaning
{"ok":true,"blocked":true}Dropped: rejected captcha token, blocked IP, or the IP went over the limit. Not stored.
{"ok":true,"id":"…"}Stored as spam. Not emailed.
{"ok":true,"id":"…","email_sent":false}Stored. The email failed, or the monthly form-submission count is used up.

GET /forms/render/{slug}

ValueHTTPMeaningWhat to do
invalid_slug400The slug has characters other than lowercase letters, numbers and dashes.Use the slug shown in the form builder.
site_has_no_owner403The key’s site is not linked to an account.Contact support.
form_not_found404No form with that slug in the account that owns the key.Check the slug and that the key belongs to the same account.
form_archived410The form was archived.Use another form.

GET and POST /sites/captcha

ValueHTTPMeaningWhat to do
invalid_json400The body is not valid JSON.Fix the body.
invalid_payload400provider is missing or not one of the allowed values, or a key is too long.Fix the field named in details.
site_key_required400A provider that needs keys was chosen without site_key.Send site_key.
secret_key_required_on_first_save400No secret is saved yet and none was sent.Send secret_key.
encryption_failed500The secret could not be stored.Retry later. Contact support if it repeats.

POST /sites/verify

ValueHTTPMeaningWhat to do
invalid_json400The body is not valid JSON.Fix the body.
invalid_payload400site_url is missing or not a full URL, or a version field is over 20 characters.Fix the field named in details.

POST /sequences/enroll

ValueHTTPMeaningWhat to do
invalid_payload400The body is not valid JSON, or a field failed validation. No details are given.Check sequence, email and data.
sequence_not_found404No sequence with that ID in the account that owns the key.Copy the ID from the sequence page.

Two answers have HTTP 200 and "ok": false: "result": "exists" (the address is already in the sequence) and "result": "no_steps" (the sequence has no steps). See Follow-up sequences.

GET /blocks/status and POST /blocks/lift

ValueHTTPMeaningWhat to do
bad_body400The body is not {"kind":"ip","block_id":"…"} or {"kind":"site"}.Fix the body.
not_found404No IP block with that ID.Read the IDs from GET /blocks/status.
already_lifted400The IP block was already lifted.Nothing.
not_self_liftable403The IP block’s reason is not rate_limit.Contact support.
not_owner403The IP block was set for another site.Use that site’s key, or contact support.
requires_admin_review403The site was not disabled automatically.Contact support. If you deactivated it, reactivate it on the Sites page.
already_active400The site is not disabled.Nothing.

These endpoints accept the key of a disabled site, so they never return site_disabled.

SMTP replies

Messages sent over SMTP go through the same checks as POST /mail/send. The result comes back as the SMTP reply. 4xx means try again later; your mail program does this by itself. 5xx means the message will not be sent as it is.

ReplyMeaningWhat to do
250 AcceptedAccepted. Also the answer when a contact-form notification is held as spam.Nothing.
535Login failed: the password is not a valid key, or the site is disabled.Use the site’s current API key as the password.
450 4.7.0Rate limit: 120 emails per minute per site.Your mail program retries. Send more slowly.
450 4.3.0Temporary failure.Your mail program retries.
450 4.5.3Too many recipients: every recipient after the 150th in one message is refused.Split the message.
550 5.7.0Monthly email limit reached.Wait for the new month or upgrade.
550 5.7.1Looks like spam, the site is disabled, or every recipient unsubscribed from this site.Read the text after the code.
550 5.7.8The key stopped working during the session (for example it was rotated).Use the new key.
550 5.1.1Every recipient is on the suppression list.See Bounces and suppressions.
550 5.3.4Attachments are larger than 15 MB in total.Send smaller files.
550 5.6.0The message could not be read: no body, an attachment that cannot be read, or bad recipient addresses.Fix the message.
550 5.5.1No recipients.Add a recipient.
550 5.5.3More than 50 addresses in To, Cc or Bcc.Split the message.