---
title: "Send a batch"
description: "Up to 100 at once."
url: "https://openemail.uk/docs/api/emails/batch"
area: "API"
category: "Emails"
---

# Send a batch

Up to 100 at once.

`POST /emails/batch`

## Per item, never all-or-nothing

Each message is accepted or refused on its own and the response reports both. A batch that rolled back on one bad address would turn your retry into a question of which messages had already gone, which is what you used a batch to avoid tracking.

## Send a batch

The body is an array, or `{ "emails": [...] }`. Every message takes the same fields as a single send.

**curl**

```
curl -X POST "$OE/emails/batch" -H "$AUTH" -H "Content-Type: application/json" \
  -d '{
    "emails": [
      { "from": "billing@acme.com", "to": ["ada@example.com"],   "subject": "Invoice",  "html": "<p>1</p>" },
      { "from": "nope@other.com",   "to": ["grace@example.com"], "subject": "Invoice",  "html": "<p>2</p>" },
      { "from": "billing@acme.com", "to": ["broken@"],           "subject": "Invoice",  "html": "<p>3</p>" }
    ]
  }'
```

**Response**

```
HTTP/1.1 207 Multi-Status

{
  "object": "list",
  "sent": 1,
  "failed": 2,
  "data": [
    { "index": 0, "status": "ok", "email": { "id": "msg_e7e468…", "status": "sent" } },
    {
      "index": 1,
      "status": "error",
      "error": { "type": "permission_error", "code": "from_address_forbidden", "param": "from" }
    },
    {
      "index": 2,
      "status": "error",
      "error": { "type": "validation_error", "code": "invalid_email_address", "param": "to.0" }
    }
  ]
}
```

> `207`, not `200`: some of it worked. Read `data[].status` per item rather than branching on the status code.

> An `Idempotency-Key` on a batch is extended per item internally, so one key on a hundred messages does not collapse them into the first.
