Один запрос заменяет сотни одиночных отправок. Письма в пакете проверяются независимо: ошибка в одном письме не мешает отправке остальных. У каждого письма в пакете свои получатели, тема и содержимое, поэтому пакет подходит и для персональных уведомлений, и для рассылок.

## Ограничения

| Параметр                    | Значение                         |
| --------------------------- | -------------------------------- |
| Писем в одном запросе       | от 1 до 500                      |
| Размер запроса              | до 50 МБ, включая вложения       |
| Получателей в одном письме  | до 50, включая Cc и Bcc          |
| Метод для обычных писем     | `POST /email/batch`              |
| Метод для писем по шаблонам | `POST /email/batchWithTemplates` |

Если писем больше 500, разделите их на несколько запросов.

## Как отправить пакет писем

1. Соберите письма в JSON-массив. Каждый элемент массива описывается так же, как при одиночной отправке: From, To, Subject, HtmlBody и/или TextBody.

2. Отправьте массив на `/email/batch` с серверным API-ключом в заголовке `X-Haskimail-Server-Token`.

3. Проверьте результат каждого письма в ответе.

Пример запроса c URL:

```
curl "https://api.haskimail.ru/email/batch" \
  -X POST \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Haskimail-Server-Token: ваш_токен_сервера" \
  -d '[
    {
      "From": "Магазин <shop@example.com>",
      "To": "ivan@example.com",
      "Subject": "Ваш заказ отправлен",
      "TextBody": "Здравствуйте, Иван! Заказ №1042 передан в доставку."
    },
    {
      "From": "Магазин <shop@example.com>",
      "To": "anna@example.com",
      "Subject": "Ваш заказ отправлен",
      "TextBody": "Здравствуйте, Анна! Заказ №1043 передан в доставку."
    }
  ]'
```

Чтобы отправить письма через определённый канал, добавьте каждому письму параметр MessageStream с ID канала. Без него письма уходят через транзакционный канал сервера по умолчанию.

В пакет `/email/batch` можно добавлять и письма по шаблону: укажите в письме TemplateId или TemplateAlias и TemplateModel так же, как при отправке письма с шаблоном.

## Как отправить пакет писем по шаблонам

Для писем по сохранённым шаблонам используйте метод `/email/batchWithTemplates`. Письма передаются в поле Messages. У каждого письма указывается шаблон — его ID в TemplateId или название в TemplateAlias — и подстановки в TemplateModel.

Подстановка в шаблонах буквальная: ключ TemplateModel — это фрагмент текста шаблона вместе со скобками. Например, `{"{{name}}": "Иван"}` заменит в шаблоне `{{name}}` на «Иван».

```
curl "https://api.haskimail.ru/email/batchWithTemplates" \
  -X POST \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Haskimail-Server-Token: ваш_токен_сервера" \
  -d '{
    "Messages": [
      {
        "TemplateId": 4521,
        "TemplateModel": { "{{name}}": "Иван", "{{order}}": "1042" },
        "From": "Магазин <shop@example.com>",
        "To": "ivan@example.com"
      },
      {
        "TemplateId": 4521,
        "TemplateModel": { "{{name}}": "Анна", "{{order}}": "1043" },
        "From": "Магазин <shop@example.com>",
        "To": "anna@example.com"
      }
    ]
  }'
```

**Важно:** шаблон каждого письма должен принадлежать серверу, чей ключ указан в запросе. Иначе это письмо получит ошибку 1101, а остальные письма пакета будут отправлены.

## Как читать ответ

API возвращает HTTP 200 и массив результатов. Результаты идут в том же порядке, что и письма в запросе: первый результат относится к первому письму, второй ко второму и так далее.

HTTP 200 означает, что пакет принят, но не означает, что принято каждое письмо. Результат каждого письма смотрите в его поле ErrorCode:

* **ErrorCode = 0** — письмо принято и поставлено в очередь, в поле MessageID его идентификатор. Если у письма несколько получателей, идентификаторы перечислены через запятую.

* **ErrorCode не 0** — письмо отклонено, причина в поле Message, а MessageID равен null. Остальные письма пакета это не затрагивает.

Если элемент массива — не JSON-объект, пакет всё равно принимается: этот элемент получает в ответе ErrorCode 300 с сообщением «Письмо должно быть JSON-объектом», а остальные письма обрабатываются как обычно.

Пример ответа, где у второго письма неверный адрес получателя:

```
[
  {
    "To": "ivan@example.com",
    "SubmittedAt": "2026-10-13 14:30:12",
    "MessageID": "6f1c0b2d9e8a4f7b3c5d2e1a0b9c8d7e",
    "ErrorCode": 0,
    "Message": "OK"
  },
  {
    "To": "anna.example.com",
    "SubmittedAt": "2026-10-13 14:30:12",
    "MessageID": null,
    "ErrorCode": 6,
    "Message": "Некорректный email-адрес получателя"
  }
]
```

Время в SubmittedAt указывается по Москве в формате `ГГГГ-ММ-ДД ЧЧ:ММ:СС`.

**Важно:** не проверяйте успех пакета только по HTTP 200. Обходите массив результатов и обрабатывайте отклонённые письма отдельно, например исправьте данные и отправьте их повторно.

## Когда не отправляется весь пакет

В некоторых случаях API отклоняет пакет целиком, и ни одно письмо не уходит:

| Ответ                   | Причина                                                                                     |
| ----------------------- | ------------------------------------------------------------------------------------------- |
| HTTP 422, ErrorCode 300 | тело запроса не в том формате, в пакете нет писем или их больше 500                         |
| HTTP 413                | размер запроса больше 50 МБ                                                                 |
| HTTP 403                | в настройках аккаунта задан список разрешённых IP-адресов, а запрос пришёл с другого адреса |

## Тестирование

Тестовый ключ `HASKIMAIL_API_TEST` работает и для пакетной отправки. Передайте его в заголовке `X-Haskimail-Server-Token` вместо серверного ключа: API проверит каждое письмо пакета и вернёт результаты в обычном формате, но письма не создаются — их не будет ни в активности, ни в статистике.

Тестовый ключ проверяет только сам запрос: обязательные поля, адреса и вложения. Канал отправки и другие настройки сервера он не проверяет. Поэтому письмо, принятое с тестовым ключом, при боевой отправке всё равно может получить ошибку — например, 1226, если указан канал другого сервера.

Также для тестов подойдёт [сервер «Песочница»](https://help.haskimail.ru/hc/haskimail/articles/1790635507-server-pesochnica-rukovodstvo-po-ispolzovaniyu). Полное описание методов — в документации: [пакетная отправка](https://haskimail.ru/developer/api/email-api#batch-emails) и [пакетная отправка с шаблонами](https://haskimail.ru/developer/api/templates-api#batch-with-templates).