Отправка писем через Stream API
Stream API (Потоковое API) — специализированный интерфейс для отправки больших объёмов писем по одному в одном запросе. Подходит для систем, которые генерируют письма поштучно и не могут заранее сформировать полный список получателей.
Когда использовать Stream API
- Ваша система формирует письма по одному (например, поштучная генерация из CRM).
- Если вам требуется отправлять более 10 писем в секунду на постоянной основе.
- Вы отправляете одновременно и транзакционные, и массовые письма потоком.
Альтернативы в Sendsay API
-
Для массовых рассылок с готовым списком получателей быстрее и удобнее использовать экспресс-выпуск (
issue.sendсusers.list). -
Для транзакционных писем, где не важна максимальная скорость, подойдёт персональный выпуск (
issue.sendсgroup: "personal"). Для него доступны почти все настройки Sendsay APIissue.send(ленты новостей, расширенная персонализация и другие).
Требования для отправки
- API-ключ.
- Доступ к Stream API — для подключения .
- Черновик письма или содержимое письма, передаваемое прямо в запросе.
Адрес API
Вызовы Stream API отправляются методом POST на:
https://trapi.sendsay.ru/tranz/api/v2/account/json/issue.send/personal
Где account — код вашего аккаунта.
Требования к соединению:
- Транспорт: HTTP 1.0/1.1 over TLSv1.2.
- Content-Type: application/json.
- Максимальный размер запроса: 25 МБ.
- Для лучшей пропускной способности используйте Keep-Alive.
- Хост
trapi.sendsay.ruимеет несколько IP-адресов — при недоступности одного переключайтесь на другой.
Авторизация
По API-ключу
В теле запроса:
{
"apikey": "ваш-api-ключ",
...
}
Или в HTTP-заголовке:
Authorization: sendsay apikey=url-кодированный-ключ
По JWT-токену
В теле запроса:
{
"apikey": "jwt:ваш-токен",
...
}
Или в HTTP-заголовке:
Authorization: sendsay apikey=jwt:url-кодированн ый-токен
Для настройки JWT .
Отправка одного письма
С черновиком
{
"apikey": "ваш-api-ключ",
"action": "issue.send",
"group": "personal",
"email": "test@test.com",
"uuid": "order-confirm-20260217-001",
"letter": {
"draft.id": "order_confirmation"
},
"extra": {
"anketa": {
"order_id": "A-12345",
"total": "4 500 ₽"
}
}
}
Без черновика
{
"apikey": "ваш-api-ключ",
"action": "issue.send",
"group": "personal",
"email": "test@test.com",
"uuid": "welcome-20260217-002",
"letter": {
"subject": "Добро пожаловать!",
"from.name": "Мой магазин",
"from.email": "info@myshop.ru",
"message": {
"html": "<h1>Добро пожаловать!</h1><p>Рады видеть вас.</p>",
"text": "Добро пожаловать! Рады видеть вас."
}
}
}
Параметры запроса
| Параметр | Обязательный | Описание |
|---|---|---|
action | ✓ | Всегда issue.send |
group | ✓ | Всегда personal |
email | ✓ | Адрес получателя |
uuid | — | Уникальный идентификатор письма (до 240 символов, A-Za-z0-9=_-). Если не указан — назначается автоматически. Используется для идентификации в статистике. В callback передаётся как gate.uniq. Хранится 30 дней |
letter.draft.id | — | ID или алиас черновика |
letter.subject | — | Тема письма (обязательно, если нет черновика) |
letter.from.email | — | Адрес отправителя (обязательно, если нет черновика) |
letter.from.name | — | Имя отправителя |
letter.reply.email | — | Адрес для ответов |
letter.to.name | — | Имя получателя |
letter.message.html | — | HTML-версия |
letter.message.text | — | Текстовая версия |
letter.message.amp | — | AMP-версия |
letter.attaches | — | Массив прикреплённых файлов |
extra.anketa | — | Данные персонализации конкретного получателя. В Stream API индивидуальные данные передаются именно в extra.anketa (в отличие от основного API, где anketa подтягивается из базы автоматически) |
label | — | Метка или массив меток (до 3 штук, до 32 байт) для группировки в статистике |
dkim.id | — | DKIM-ключ для подписи |
customer.id | — | Ваш внутренний ID получателя (до 255 байт). В callback — customer.id |
ttl | — | Время попыток доставки в секундах (по умолчанию — 4 дня) |
relink | — | 1 — отслеживать клики, 0 — нет (по умолчанию — 0) |
weak_draft | — | 1 — параметры запроса приоритетнее черновика |
care_vars | — | Массив обязательных переменных персонализа ции |
ignore_stoplist | — | 1 — отправить, даже если адрес в стоп-листе (дополнительная функция, для подключения ) |
email.fake | — | Подменный адрес для статистики (реальный адрес не сохраняется в системе) |
lbac.id | — | ID политики доступа LBAC |
Должна быть заполнена хотя бы одна версия — HTML или text.
Ответ
Успешный ответ:
{
"uuid": "order-confirm-20260217-001"
}
Ответ с ошибкой:
{
"errors": [
{
"id": "wrong_email",
"explain": "invalid email format"
}
]
}
Персонализация — отличие от основного API
В Stream API индивидуальные данные получателя передаются в extra.anketa. Это ключевое отличие от Sendsay API, где anketa — зарезервированное имя, и данные контакта подтягиваются автоматически из базы.
{
"extra": {
"anketa": {
"name": "Анна",
"order_id": "A-12345",
"total": "4 500 ₽"
}
}
}
В шаблоне черновика обращение остаётся одинаковым:
[% anketa.name %],
[% anketa.order_id %]
В Stream API не работают функции шаблонизатора:
countup,countdown,draw_graph,lenta_get,geturl.
Прикреплённые файлы
{
"letter": {
"attaches": [
{
"name": "invoice.pdf",
"content": "JVBERi0xLjQK...",
"encoding": "base64"
},
{
"name": "readme.txt",
"content": "Текстовый файл в UTF-8"
}
]
}
}
Для двоичных файлов используйте encoding: "base64". Для текстовых файлов кодирование не обязательно — содержимое передаётся как есть.
Отправка нескольких писем (batch)
Если ваша система накапливает письма небольшими группами, можно отправить 50–100 писем за один HTTP-вызов.
Адрес:
POST https://trapi.sendsay.ru/tranz/api/v2/account/json.batch/issue.send/personal
Запрос
{
"apikey": "ваш-api-ключ",
"action": "batch",
"do": [
{
"action": "issue.send",
"group": "personal",
"email": "user1@test.com",
"uuid": "batch-001",
"letter": { "draft.id": "welcome" }
},
{
"action": "issue.send",
"group": "personal",
"email": "user2@test.com",
"uuid": "batch-002",
"letter": { "draft.id": "welcome" }
}
]
}
API-ключ указывается один раз на уровне всего запроса, а не в каждом задании.
Ответ
{
"result": [{ "uuid": "batch-001" }, { "uuid": "batch-002" }]
}
Ошибка одного задания не влияет на остальные — каждое обрабатывается независимо.
Отложенная отпра вка
Письмо можно передать сейчас, а отправить в указанное время.
Время можно передать в URL с адресом:
POST https://trapi.sendsay.ru/tranz/api/v2/account/json/issue.send/personal/later/2026-03-01T10:00
или в теле запроса:
{
"later.time": "2026-03-01 10:00",
...
}
Указывайте московское время, или используйте суффикс Z для UTC. Допустимые форматы:
YYYY-MM-DDThh:mmYYYY-MM-DD hh:mm
Дополнительно можете указать секунды. Время приводится к ближайшему меньшему значению, кратному 5 минутам (например: 12:03 → 12:00, 12:09 → 12:05).
Черновик и API-ключ (или JWT-токен) должны быть валидны на момент отправки, а не на момент передачи письма.
Группировка писем в выпуски
Письма в Stream API автоматически группируются в выпуски для статистики:
-
С черновиком — группировка по номеру черновика +
dkim.id. Название черновика = название выпуска. -
Без черновика — группировка по меткам (
label) +dkim.id. Метки через пробел = название выпуска. -
Дополнительно учитываются: день, саблогин, наличие AMP-версии, номер LBAC.
ВажноЕсли вы одновременно отправляете через Stream API массовые и транзакционные письма, массовые могут замедлять транзакционные. Для настройки разделения .
Коды ошибок
Ошибки, возвращаемые сразу
| Код | Описание |
|---|---|
cant_decode | Невалидный JSON или не объект |
wrong_letter | letter не является объектом |
wrong_uuid | UUID длиннее 255 символов или содержит недопустимые символы |
wrong_apikey | Пустой API-ключ |
wrong_credentials | Ошибка в заголовке Authorization |
internal_write | Внутренние проблемы |
Ошибки, возвращаемые после обработки
| Код ESMTP | Описание |
|---|---|
5.0.0 | Адрес имеет постоянные ошибки доставки или в стоп-листе |
6.6.5 wrong_email | Ошибка в адресе получателя |
6.6.5 wrong_letter.* | Ошибка в параметрах письма |
6.7.0 | Исчерпан месячный лимит писем |
6.7.8 gate is disabled | Stream API не подключено |
6.7.8 authorization failed | Невалидный API-ключ |
6.7.8 error/account/blocked | Аккаунт заблокирован |
6.7.8 error/sender/unknown | Неизвестный адрес отправителя |
6.7.8 error/sender/prohibited | Недопустимый адрес отправителя |
6.7.8 error/issue/blocked | Выпуски заблокированы |
6.7.8 error/issue/blocked_personal | Транзакционные выпуски заблокированы |
6.7.8 unknown_draft | Неизвестн ый черновик |
Получение статистики
Статистику по выпускам через Stream API можно посмотреть:
- в разделе Статистика личного кабинета.
- используя метод
stat.uniSendsay API. - через колбеки — Sendsay может отправлять уведомления о событиях доставки (доставлено, открыто, клик, ошибка и др.) на ваш URL по мере их возникновения.
Особенности отправки через Stream API
- Скорость приёма запросов зависит от индивидуальных настроек аккаунта.
- При успешной обработке HTTP-код ответа всегда 200. Ошибки API передаются в
errors, а не в HTTP-статусах. - При получении кода 502, 503, 504 или таймаут а — повторите запрос.
- Ошибка
rate_limitуказывает на превышение лимита коннектов. - Назначайте
uuidсамостоятельно для надёжной идентификации писем в статистике. Если у вас нет возможности создать уникальныйuuid, не указывайте его, и система назначит его автоматически. relinkпо умолчанию0. Измените эту настройку, если вам нужно отслеживание кликов.