Skip to content

Batch sending

POST /v1/emails/batch takes a list of up to 100 send requests, each the same shape as a single send.

POST /emails/batch
[
{ "from": "Kedai <resit@kedai.my>", "to": "siti@example.com", "subject": "Resit #1042", "text": "Terima kasih." },
{ "from": "Kedai <resit@kedai.my>", "to": "ahmad@example.com", "subject": "Resit #1043", "text": "Terima kasih." }
]

Duta answers 200 OK:

{ "data": [{ "id": "msg_...", "status": "queued" }, { "id": "msg_...", "status": "queued" }] }

By default a batch is strict: Duta checks every email before sending any, and one invalid email means none are sent. The error names the first failing index and lists every failure in detail.errors.

Send the header x-batch-validation: permissive to send the valid emails anyway. The response then lists the rest by index:

{
"data": [{ "id": "msg_...", "status": "queued" }],
"errors": [{ "index": 1, "code": "validation_failed", "name": "validation_error", "message": "to: Required" }]
}

Either way, an email refused at the moment of sending, for a rate or quota limit, is reported in errors by index. A batch where nothing was sent answers with an error rather than an empty success.

  • Attachments must be inline content. path is refused in a batch.
  • A batch counts as one request for idempotency: an Idempotency-Key covers the whole batch.