Send Email
POST /v1/send
Send one email. Runs the full pipeline: validation → rate-limit → suppression check → activation gate → from-address authorization → sandbox recipient check → moderation → SES dispatch.
Auth
Authorization: Bearer finn_sk_…
Request
{
"from": "[email protected]",
"to": "[email protected]",
"subject": "hello",
"text": "plain text body",
"html": "<p>optional html body</p>"
}
| Field | Required | Notes |
|---|---|---|
from |
yes | Must match a verified domain or a verified single sender |
to |
yes | Single recipient. Multi-recipient is a separate phase |
subject |
yes | Max 998 chars (RFC 5322) |
html |
— | Required if text not provided |
text |
— | Required if html not provided |
Headers
Idempotency-Key: <your-value>— optional. If a request with the same key + tenant has already succeeded, the cached 202 response replays withX-Idempotent-Replay: true. Max length 256 chars.
Response — 202 Accepted
{
"message_id": "01J…",
"status": "sent"
}
Query progress later via GET /v1/messages/{message_id}.
Errors
invalid_input/invalid_email— check request shapeactivation_pending— follow the signup email link firstdomain_unverified— register a domain or add a single sendersandbox_recipient_not_allowed— new recipients need explicit consent in sandbox tierrecipient_suppressed— recipient is on the suppression list (prior bounce/complaint)content_blocked— moderation rejected the content. Seereasoninmessagerate_limited— 429 withretry_after(seconds)send_failed— upstream SES error (502)
See error codes for the full list.