Mailgentic

Errors, retries and limits

Error envelope

Every non-2xx JSON response has the same shape:

{
  "error": {
    "code": "quota_exceeded",
    "message": "daily quota of 5000 recipients exceeded"
  }
}

code is stable and meant for programs; message is for humans and may change.

Status codes

Status Meaning What to do
400 Malformed request, invalid parameter or unsupported operation Fix the request
401 Missing, invalid, expired or revoked credential Check the key; rotate if leaked
403 Missing scope, suspended scope, recipient not on the inbox allowlist, free-trial restriction, or submission refused by a reject pause Do not retry blindly; inspect code
413 Request body or attachments too large Reduce the payload
404 Unknown resource, or one outside your tenant / inbox scope Treat as not found
409 State conflict (inbox_paused, approval already decided, duplicate folder…) Read current state and reconcile
422 Valid JSON but invalid send data (bad address, missing body, oversize attachment) Fix the message
429 Quota or rate limit exceeded Wait for Retry-After seconds, then retry
451 Request hit the wrong data-region endpoint Use the region your account is pinned to
503 Temporary unavailability or a delivery dependency is down Retry with back-off; honour Retry-After if present

Common error codes

Code Status Notes
invalid_request 400 Parameter or body problem; message names the field
invalid_folder 400 Folder name violates the naming rules
unauthorized, key_expired, invalid_credentials 401 Bad, missing or expired bearer / login
forbidden 403 Key lacks the scope, or the resource is not manageable by this key
ip_not_allowed 403 Request source is outside the key’s allowed_cidrs
account_suspended, tenant_disabled, sending_suspended 403 A pause or disablement covers this submission
recipient_not_allowed 403 Inbox allow_recipients policy
trial_domain, trial_recipient 403 Free-trial account used a non-shared domain or a recipient other than its own verified address
not_found 404 Unknown or out-of-scope resource
inbox_paused 409 Inbox status is paused
already_decided 409 Approval was already approved or rejected
mx_unverified, inbound_disabled 409 Domain cannot receive yet
folder_not_empty 409 Delete a non-empty custom folder without ?move_to=
unsafe_content 409 Outbound body failed a hard Shield block
too_large 413 Request or attachments exceed 25 MiB
too_many_recipients, invalid 422 Send data rejected by the submission pipeline
folder_limit 422 More than 100 custom folders
quota_exceeded, rate_limited, throttled 429 Tenant quota or rate; Retry-After is set
trial_daily_cap 429 Free trial: 50 sends/day
too_many_streams 429 More than 5 concurrent WebSocket streams on one key
wrong_region 451 Account is pinned to another data region
unavailable, spool_unavailable, approval_unavailable, payments_unavailable, ai_unavailable 503 Temporary; retry with back-off

Retrying safely

Limits

Limit Value
Attachments per message 25 MiB total after base64 decoding
Recipients per message Tenant max_recipients_per_message
Daily / monthly recipients, per-minute / per-hour rates Tenant quotas; 429 + Retry-After when exceeded
List page size default 50, maximum 200 (events: default 100, max 200)
Custom folders per inbox 100; names 1–64 characters
Batch mailbox action 1–200 message IDs
Concurrent WebSocket streams 5 per key
Webhook timestamp tolerance 5 minutes
AI extraction Monthly token cap per account
Free-trial accounts 50 sends/day, own verified address only, shared domain

Data regions

Accounts are pinned to a data region at signup. Requests sent to another region’s endpoint receive 451 and are not processed. Enterprise customers can choose the region; others are placed in the default region.

Health endpoints

GET /healthz returns 200 while the process is up; GET /readyz returns 503 when the database or pause cache is unavailable. Current status for the hosted service is published on the status page linked from the console.