POST /v1/send
Отправка персонального уведомления конкретному подписчику.
Параметры
subscriber_id string (UUID) UUID подписчика (из списка подписчиков)
text string Текст сообщения (до 4000 символов). Обязателен, если не указан template
format string Формат текста: plain (по умолчанию), markdown или html. Взаимоисключающее с entities — если переданы entities, format должен быть пустым.
entities array Структурированное форматирование (рекомендуемый формат). Массив [{type, offset, length, ...}], offset/length в UTF-16 единицах. Типы: bold, italic, underline, strikethrough, code, pre, blockquote, spoiler, mention, text_link (с полем url). Защищает от HTML/Markdown injection.
external_id string Альтернатива subscriber_id: свой ID клиента в его системе. Резолвит все активные подписки этого клиента (multi-channel one-shot отправка). Mutually exclusive с subscriber_id.
channels array Фильтр каналов при resolve по external_id, массив строк (например, ["telegram","max"]). Если не задан — все active подписки.
channel string Одиночный канал доставки (telegram/max) — legacy-альтернатива массиву channels, действует как channels: [channel].
media object Объект медиа: {type, url}. Типы: photo, video, document
buttons array Массив рядов кнопок: [[{text, url}]] или [[{text, callback_data}]]
template string Slug шаблона вместо text
vars object Переменные для шаблона: {key: value}
permission string Фильтр по разрешению: отправить только подписчикам с этим ключом
Пример запроса
Ответ
Ответ — агрегированный: sent / failed — счётчики, details — массив по каждому получателю. Поле delivery_id — id записи в журнале доставок проекта (для ссылки в саппорт / аудита, виден в дашборде → Доставки); есть и у успешных, и у неуспешных. Статус всегда 200, даже если часть отправок failed — смотрите на details.
Идемпотентность
Чтобы повторный запрос (ретрай при таймауте) не создал дубль, передавайте заголовок Idempotency-Key — строка 8–128 символов [A-Za-z0-9_-], уникальная на каждую операцию.
- Тот же ключ + то же тело → возвращается тот же ответ (статус 200) с заголовком X-Zapnoty-Idempotent-Replay: true. Повторная отправка не выполняется.
- Тот же ключ + другое тело → 409 idempotency_conflict.
- Запрос с тем же ключом ещё обрабатывается → 425 idempotency_in_progress, повторите чуть позже.
Entities — структурированное форматирование
Рекомендуемая замена format=html/markdown. Вместо парсинга разметки клиент передаёт массив диапазонов: позиция, длина и тип форматирования. Защищает от HTML/Markdown injection — текст никогда не интерпретируется, ставится «как есть».
offset и length считаются в UTF-16 code units (как Telegram). Для большинства языков 1 символ = 1 единица; emoji (👋) занимает 2 единицы. Entities должны быть отсортированы по offset и не пересекаться.
Типы: bold, italic, underline, strikethrough, code, pre, blockquote, spoiler, mention, text_link (с полем url, проходит SSRF-проверку приватных IP). Spoiler и mention в Max игнорируются (нет аналога).
Шаблоны
Шаблоны позволяют переиспользовать текст с переменными. Создаются в дашборде или через API.
Использование: передайте template и vars вместо text в /v1/send.
Переменные в шаблоне обозначаются {{имя}}. Например: «Заказ {{order_id}} доставлен».
Медиа и кнопки
К уведомлениям можно прикрепить медиа-файлы и inline-кнопки.
Типы медиа: photo, video, document. Передайте URL файла.
Кнопки — двумерный массив: внешний массив — ряды, внутренний — кнопки в ряду.
- Кнопка с URL: {"text": "Открыть", "url": "https://..."}
- Кнопка с callback: {"text": "Да", "callback_data": "confirm_123"}
1 медиа + кнопки — поддерживается. Несколько медиа + кнопки — не поддерживается (ограничение Telegram). Caption с медиа: до 1024 символов (Telegram) / до 4000 (Max). Текст без медиа — до 4000 символов.