Sending API
One endpoint sends your mail: POST /v1/emails. Bearer-key auth, JSON in, a message id out, and webhooks for everything that happens next.
Authentication
Create an API key in Dashboard → Developers → API keys and pass it as a bearer token. Keys are shown once at creation. Test keys (am_test_…) accept requests but deliver to a sandbox; live keys (am_live_…) deliver for real and only from domains you have verified.
export ATRIX_MAIL_KEY="am_live_..." # from the dashboard, shown once
Send an email
curl -X POST https://api.mail.atrix.dev/v1/emails \ -H "Authorization: Bearer $ATRIX_MAIL_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "Yourco Billing <billing@yourco.com>", "to": ["ava@client.io"], "subject": "Your March invoice", "html": "<p>Invoice attached. Thanks!</p>", "text": "Invoice attached. Thanks!", "reply_to": "support@yourco.com" }'
Successful requests return 200 with the message id:
{ "id": "em_9f2c4a7b", "status": "queued" }
queued means we accepted the message; delivery is asynchronous. Track it via webhooks or GET /v1/emails/:id.
Request fields
| Field | Type | Notes |
|---|---|---|
| from | string | Required. Address on a verified domain; Name <addr> form allowed. |
| to | string[] | Required. Up to 50 recipients per request. |
| subject | string | Required. |
| html | string | At least one of html / text is required. |
| text | string | Plain-text body; strongly recommended alongside html. |
| cc | string[] | Optional. |
| bcc | string[] | Optional. |
| reply_to | string | Optional. |
| headers | object | Optional custom headers (X-* only). |
| attachments | object[] | { filename, content } with base64 content; 25 MB total. |
| scheduled_at | string | Optional ISO 8601 timestamp up to 72h ahead. |
Idempotency
Network timeouts happen mid-request. To retry safely, send an Idempotency-Key header — any unique string per logical message. If we already accepted a request with that key in the last 24 hours, we return the original result instead of sending twice.
curl -X POST https://api.mail.atrix.dev/v1/emails \ -H "Authorization: Bearer $ATRIX_MAIL_KEY" \ -H "Idempotency-Key: invoice-1042-attempt" \ -H "Content-Type: application/json" \ -d '{ "from": "billing@yourco.com", "to": ["ava@client.io"], "subject": "Your March invoice", "text": "Attached." }'
Errors
Errors are JSON with a stable machine-readable code and a human message:
{ "error": { "code": "domain_not_verified", "message": "yourco.com has no verified DKIM record." } }
| Status | Code | Meaning |
|---|---|---|
| 400 | validation_failed | Request body failed schema validation; details lists the fields. |
| 401 | invalid_api_key | Missing, malformed, or revoked key. |
| 403 | domain_not_verified | The from domain isn't verified on your account. |
| 404 | not_found | Unknown message id. |
| 409 | idempotency_conflict | Same Idempotency-Key reused with a different body. |
| 422 | recipient_suppressed | Recipient previously hard-bounced or complained; delivery refused. |
| 429 | rate_limited | Over your plan's send rate. Honor Retry-After. |
| 500 | internal_error | Our fault. Safe to retry with the same Idempotency-Key. |
429 and 500 as retryable with exponential backoff; treat every 4xx except 429 as a bug in the request, not something to retry.