All sending goes through one endpoint, POST https://api.email/v1/emails. This page describes every field and the behaviours worth knowing in production.
Request fields
| Field | Type | Notes |
|---|---|---|
from |
string | Required. An address on a verified domain, optionally with a name: Acme <[email protected]>. |
to |
string or string[] | Required. Up to 50 recipients. |
subject |
string | Required. |
text |
string | Plain-text body. Send it together with html. |
html |
string | HTML body. At least one of text and html is required. |
cc, bcc |
string or string[] | Optional additional recipients. |
reply_to |
string | Where replies go, if not to from. |
headers |
object | Custom headers, for example {"X-Entity-Ref-ID": "1042"}. |
attachments |
array | [{filename, content, content_type}], content base64-encoded. |
tags |
string[] | Labels for filtering logs and webhooks. |
scheduled_at |
string | ISO 8601 time to send later, up to 30 days ahead. |
track_opens, track_clicks |
boolean | Off by default. Enable to receive email.opened and email.clicked events. |
Example
curl https://api.email/v1/emails \
-H "Authorization: Bearer $API_EMAIL_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: receipt-1042" \
-d '{
"from": "Acme Billing <[email protected]>",
"to": ["[email protected]"],
"reply_to": "[email protected]",
"subject": "Your receipt for order 1042",
"text": "Thanks for your order. Your receipt is attached.",
"html": "<p>Thanks for your order. Your receipt is attached.</p>",
"attachments": [{"filename": "receipt-1042.pdf", "content": "JVBERi0x…", "content_type": "application/pdf"}],
"tags": ["receipt"]
}'
The response is {"id": "em_…", "status": "queued"}, or "scheduled" when scheduled_at is set.
Idempotency keys
Send an Idempotency-Key header that identifies the logical email, such as receipt-1042. If the same key arrives again within 24 hours, api.email returns the first response and does not send another copy. Use stable keys derived from your own data, never a random value per attempt.
Size limits
A message, including attachments after base64 decoding, can be up to 10 MB. For larger files, send a link to your own storage.
Scheduled emails
With scheduled_at the email waits in the queue until that time. Cancel it before then with DELETE /v1/emails/{id}; after it is sent, cancelling is no longer possible.
Text and HTML
Always include a plain-text version. It is what screen readers and plain-text clients show, and spam filters treat HTML-only messages with more suspicion. Keep transactional messages focused on their purpose: marketing content in a password reset hurts the delivery of every reset that follows.