Skip to main content
Two ways to send beyond a single message: a batch of up to 100 in one round trip, and a future-dated send that the platform queues until its scheduledAt time.

Batch sends

POST /v1/emails/batch Wrap up to 100 messages in an emails array. Each item is exactly the same shape as a single send — the same from, to, body, attachments, headers, and tags described in Send email. The batch is not all-or-nothing: each message is validated and queued independently.
sendMany shorthand. When you already have an array of messages, emails.sendMany([…]) wraps it in the { emails } envelope for you — same result as sendBatch.
sendMany

The 207 multi-status response

A batch returns HTTP 207 Multi-Status, never a single success or failure. The body carries a results array with one entry per submitted message, in order, each tagged with its index:
  • Queued{ index, id, status } where status is queued (or scheduled if that item carried a scheduledAt).
  • Failed{ index, error } with a typed error (e.g. a validation_error for a bad recipient). Other items in the same batch still succeed.
207 Multi-Status
Always inspect every result. A 207 is not an all-success signal. Walk the results array and branch on whether each entry has an id or an error; don’t assume the call either fully succeeded or fully failed.

Idempotency on batches

A batch is one HTTP request, so an Idempotency-Key covers the whole array. Replaying the same key within the window returns the original results instead of re-sending all 100 messages — which is exactly what you want when a network blip leaves you unsure whether the batch landed.
The key is per request, not per message. One key guards the entire batch as a unit; you can’t idempotency-key individual items inside it. To dedupe at the message level, send those messages one at a time, each with its own key. Full rules are in Idempotency & retries.

Scheduled sends

POST /v1/emails To send in the future, add scheduledAt — an ISO-8601 timestamp — to any single send. The message is accepted immediately and comes back with status: "scheduled" instead of queued; the platform holds it and queues it for delivery at that time.
string
ISO-8601 timestamp for the future send (e.g. 2026-07-01T09:00:00Z). Use UTC, or include an explicit offset. A time in the past sends right away.
Schedule inside a batch too. scheduledAt is a per-message field, so items in a batch can each have their own send time — schedule some for later and queue others immediately, all in one request.
Suppression is checked at send time. Recipients are screened against your suppression list when a scheduled message actually goes out, not when you schedule it — so an address that bounces in the meantime is still protected.

Next

Idempotency & retries

Make batches and single sends safe to retry.

Templates

Reuse one body across every message in a batch.

Send batch API

The full POST /v1/emails/batch contract.

Metrics

Watch a batch’s delivery, bounce, and open rates.