Docs/Sending email

Send a single email

POST /v1/email sends one message. It can go to a single recipient or to several who all share one envelope.

The request

curl https://api.anypost.com/v1/email \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <[email protected]>",
    "to": ["[email protected]"],
    "reply_to": "[email protected]",
    "subject": "Welcome to Acme",
    "html": "<p>Glad you are here.</p>",
    "text": "Glad you are here."
  }'

A 202 response means the message was accepted.

Fields

FieldRequiredDescription
fromYesSender address, on a verified domain.
toYesArray of recipient addresses, 1 to 50.
ccNoArray of copied recipients. Counts toward the 50-recipient total.
bccNoArray of blind-copied recipients. Counts toward the 50-recipient total.
reply_toNoOne address, or an array of up to 10, that replies are directed to.
subjectYesSubject line, 1 to 998 characters.
textOne ofPlain-text body, up to 1,000,000 characters.
htmlOne ofHTML body, up to 1,000,000 characters.

Provide subject and at least one of text or html. Sending with a template can supply all three instead; see Sending with templates.

Address format

from and every recipient field accept two forms:

A display name appears in the message headers only. The delivery envelope always uses the bare address. CR and LF characters are stripped from addresses before the message is built.

The domain in from must be verified for your team. A send from an unverified domain is rejected. See Domains & DNS setup.

Recipients

to, cc, and bcc together may name at most 50 recipients. Everyone in to and cc is visible to the others in the message headers; bcc recipients are not.

All recipients of one POST /v1/email share a single envelope: one message, delivered to each address. To send distinct messages, with different subjects or bodies, in one request, use Batch sending instead.

The response

{
  "id": "email_018f4f3e-7b2c-7c80-8e21-1a3a4f5b6c7d",
  "created_at": "2026-04-30T12:00:00.123000Z"
}

The 202 and this id mean Anypost accepted the message, not that it was delivered. Delivery, bounces, and engagement arrive later as events; see Webhooks. Use the id to correlate every event to this message.

An invalid request returns 400 or 422 with a validation_error naming the fields at fault. See API conventions for the error shape.

Idempotency

A retry is made safe by an Idempotency-Key header. If the first request already reached Anypost, the replay returns that original response verbatim and the message is not sent again. A network failure that leaves the 202 in doubt costs you nothing to retry.

curl https://api.anypost.com/v1/email \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9f8c2b1e-4a6d-4f1e-8c3a-2b1e4a6d4f1e" \
  -d '{ "from": "Acme <[email protected]>", "to": ["[email protected]"], "subject": "Welcome to Acme", "html": "<p>Glad you are here.</p>" }'

The SDK generates a key for any send when you omit one, so its built-in retries cannot send twice; pass idempotencyKey to set your own.

A stored response is kept for 24 hours. Reusing a key with a different body is rejected with 422 idempotency_mismatch. See API conventions for the full key rules.

Going further

A send can carry much more than a subject and body: