Документация API
Быстрый старт
Три шага до первого уведомления.
1. Создайте проект
Зарегистрируйтесь через Яндекс или ВК, создайте проект в дашборде.
2. Получите API-ключ
В настройках проекта скопируйте API-ключ формата zn_aBcDeFgH...
3. Отправьте первый запрос
Используйте curl или любой HTTP-клиент:
Аутентификация
Все запросы к API требуют Bearer-токен в заголовке Authorization.
Base URL: https://api.zapnoty.comContent-Type: application/json для всех POST/PUT/PATCH запросовФормат заголовка:
API-ключ имеет формат zn_ + 32 символа. Ключ создаётся в дашборде проекта.
Не передавайте ключ в URL или query-параметрах. Используйте только заголовок Authorization.
Auth через ботов
Авторизация пользователей вашего сайта через ботов Telegram/Max. Пользователь кликает ссылку, подтверждает в боте, автоматически подписывается на уведомления, и вы получаете его данные.
Как это работает
1. Пользователь кликает ссылку бота
2. Бот показывает запрос авторизации с кнопками "Войти" / "Отмена"
3. Пользователь нажимает "Войти" → автоматическая подписка на уведомления + генерация кода
4. Бот отправляет кнопку "Перейти на сайт" → callback_url?code=CODE
5. Ваш сервер вызывает POST /v1/auth/verify → получает данные
Настройка
В дашборде проекта перейдите в Settings → Auth и задайте Callback URL и Origin URL.
Статические ссылки
Простой вариант — постоянная ссылка. Получите через API или в дашборде:
API-сессии (с state)
Для передачи state (например, ID браузерной сессии) создайте сессию через API:
Верификация кода
После подтверждения пользователь попадает на callback_url?code=CODE. Верифицируйте код:
QR/Polling (кросс-девайс)
Для авторизации на десктопе через мобильного бота: создайте сессию, покажите QR-код со ссылкой, и поллите статус. Когда пользователь подтвердит авторизацию на телефоне, вы получите code. Интервал polling: 2-3 секунды. Код одноразовый — после получения status=completed повторный запрос вернёт expired.
POST /v1/send
Отправка персонального уведомления конкретному подписчику.
Параметры
subscriber_id string (UUID) UUID подписчика (из списка подписчиков)
text string Текст сообщения (до 4000 символов). Обязателен, если не указан template
format string Формат текста: plain (по умолчанию), markdown или html
media object Объект медиа: {type, url}. Типы: photo, video, document
buttons array Массив рядов кнопок: [[{text, url}]] или [[{text, callback_data}]]
template string Slug шаблона вместо text
vars object Переменные для шаблона: {key: value}
permission string Фильтр по разрешению: отправить только подписчикам с этим ключом
segment string Фильтр по сегменту (тегу)
Пример запроса
Ответ
OTP (одноразовые коды)
Отправка и проверка кодов подтверждения через мессенджер.
POST /v1/otp/send
Генерирует 6-значный код и отправляет подписчику.
subscriber_id string (UUID) обязательныйUUID подписчика
Ответ
POST /v1/otp/verify
Проверяет введённый код.
subscriber_id string (UUID) обязательныйUUID подписчика
code string обязательный6-значный код от пользователя
Ответ
✓ Код верный
✗ Код неверный
Лимиты OTP: макс. 5 попыток проверки, TTL кода — 5 минут, 1 активный код на подписчика.
Broadcast (массовая рассылка)
Отправка сообщения всем подписчикам или сегменту.
POST /v1/broadcast
Создаёт задачу рассылки. Сообщения отправляются через очередь.
text string обязательныйТекст сообщения
format string Формат текста: plain (по умолчанию), markdown или html
media object Объект медиа: {type, url}. Типы: photo, video, document
buttons array Массив рядов кнопок: [[{text, url}]] или [[{text, callback_data}]]
permission string Фильтр по permission
tags array Фильтр по тегам: ["vip", "beta"]
Ответ
GET /v1/broadcast/:job_id
Получение статуса рассылки.
Поля ответа: status (pending/processing/completed/failed), total, sent, failed.
Подписчики
Управление списком подписчиков и их тегами.
GET /v1/subscribers
Список подписчиков проекта. Пагинация через query-параметры.
limit number Кол-во записей (по умолчанию 50, макс. 200)
offset number Смещение от начала списка (по умолчанию 0)
channel string Фильтр по каналу: telegram или max
Ответ
PUT /v1/subscribers/:id/tags
Обновление тегов подписчика. Передайте полный массив тегов. Теги должны быть предварительно созданы в настройках проекта или через API. Несуществующие теги будут автоматически созданы (если не достигнут лимит 20).
Ответ
Шаблоны
Шаблоны позволяют переиспользовать текст с переменными. Создаются в дашборде или через 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 символов.
Управление через API
API для управления шаблонами, разрешениями, тегами и вебхуком проекта. Все эндпоинты требуют Bearer-токен.
Шаблоны
GET /v1/templates — список шаблоновPOST /v1/templates — создать шаблон (key, text, format?)PUT /v1/templates/{key} — обновить шаблон (text?, format?)DELETE /v1/templates/{key} — удалить шаблонРазрешения
GET /v1/permissions — список разрешенийPOST /v1/permissions — создать (key, title, description?, required?)PUT /v1/permissions/{key} — обновить (title?, description?, required?)Удаление разрешений доступно только в дашборде.
Теги
GET /v1/tags — список тегов проектаPOST /v1/tags — создать тег (name)PUT /v1/tags/{name} — переименовать тег (new_name)DELETE /v1/tags/{name} — удалить тег (удаляется и у всех подписчиков)Допустимые символы: буквы, цифры, - и _. Максимум 20 тегов.
Подпись отправителя
Каждое сообщение может содержать подпись — имя отправителя и описание. Настраивается в дашборде (Overview → Уведомления или Settings → Notifications).
Формат подписи: текст\n\n— Имя\nОписание
Логотип: загружается через дашборд, сжимается до 256×256 PNG.
Автосообщения
Управляйте автосообщениями при подписке/отписке через API. Каждое сообщение включается отдельным флагом и поддерживает два языка (RU/EN). Подпись проекта добавляется автоматически.
GET /v1/auto-messages — получить настройкиPUT /v1/auto-messages — обновить настройкиПоля: subscribe_message_enabled, unsubscribe_message_enabled (boolean), subscribe_message, unsubscribe_message ({"ru":"...","en":"..."}). Если флаг выключен — стандартный текст.
OTP-шаблон
Кастомный шаблон OTP-сообщения. Должен содержать {{code}}. Можно использовать {{minutes}} для срока действия.
Пример: Ваш код подтверждения: {{code}}. Действует {{minutes}} мин.
Вебхук
GET /v1/webhook — получить текущий вебхукPUT /v1/webhook — установить вебхук (url, events?[])DELETE /v1/webhook — удалить вебхукЕсли events не указан — будут отправляться все события. Secret генерируется автоматически.
Вебхуки
Zapnoty отправляет HTTP POST на ваш URL при наступлении событий. Один вебхук на проект. Настраивается в дашборде или через API.
События: subscription.created, subscription.deleted, delivery.success, delivery.failed, broadcast.completed, button.clicked, auth.completed, ticket.created, ticket.replied, ticket.status_changed, ticket.assigned, ticket.closed.
Подпись: заголовок X-Zapnoty-Signature содержит HMAC-SHA256 от тела запроса с вашим webhook secret.
Проверка подписи:
Формат payload:
Политика ретраев
При ошибке доставки webhook автоматически повторяется до 3 раз с exponential backoff (1с → 2с → 4с). Таймаут каждой попытки — 10 секунд. При 4xx от вашего сервера повторы не выполняются. Рекомендуем реализовать идемпотентную обработку на своей стороне.
Расписание
Отложенные сообщения, цепочки и повторяющиеся рассылки
Отложенная отправка
Отправка сообщения в заданное время. Поддерживает форматирование (html/markdown), медиа-вложения и inline-кнопки.
subscriber_id string (UUID) обязательныйUUID подписчика
text string обязательныйТекст сообщения
scheduled_at string (ISO 8601) обязательныйДата и время отправки (ISO 8601 UTC)
name string Название (для кабинета)
Цепочки (Drip)
Автоматическая последовательность сообщений при подписке или событии. Каждый шаг поддерживает форматирование, медиа и кнопки.
name string обязательныйНазвание (для кабинета)
trigger string обязательныйТриггер: subscription, segment, permission
trigger_value string Значение триггера (тег или ключ разрешения)
steps[].text string обязательныйТекст сообщения
steps[].delay_minutes number обязательныйЗадержка от момента триггера (минуты)
Повторяющиеся
Регулярная рассылка с заданным интервалом. Поддерживает форматирование, медиа, кнопки и фильтры (channel, segment, permission).
name string обязательныйНазвание (для кабинета)
text string обязательныйТекст сообщения
interval_hours number обязательныйИнтервал повторения (часы)
Helpdesk API
Система тикетов поддержки. Позволяет создавать тикеты от клиентов, отвечать на них и управлять статусами. При обращении в поддержку пользователь автоматически подписывается на уведомления. Включите Helpdesk в настройках проекта.
POST /v1/helpdesk/tickets — создание тикета
Создаёт тикет от имени клиента. Номер тикета генерируется автоматически.
text string обязательныйТекст первого сообщения
subject string Тема обращения (необязательно)
channel string Канал: telegram, max или virtual. По умолчанию virtual
chat_id number Chat ID в мессенджере. Обязателен для telegram/max
first_name string Имя клиента
username string Username клиента
ticket_type_id string UUID типа обращения (из GET /v1/helpdesk/ticket-types). Необязательный.
Ответ
GET /v1/helpdesk/tickets — список тикетов
Возвращает список тикетов проекта. Фильтрация по статусу: ?status=new|in_progress|waiting|closed.
GET /v1/helpdesk/tickets/{id} — детали тикета
Возвращает полную информацию о тикете по ID, включая все сообщения.
POST /v1/helpdesk/tickets/{id}/reply — ответ на тикет
Отправляет ответ агента на тикет. Клиент получит уведомление в мессенджер.
POST /v1/helpdesk/tickets/{id}/customer-reply — ответ виртуального клиента
Отправляет ответ от имени виртуального клиента (channel=virtual). Только для тикетов с каналом virtual. Агенты получат уведомление, а webhook ticket.replied будет отправлен.
text string обязательныйТекст первого сообщения
PATCH /v1/helpdesk/tickets/{id}/status — смена статуса
Изменяет статус тикета. Допустимые значения: open, in_progress, closed.
PATCH /v1/helpdesk/tickets/{id}/assign — назначить агента
Назначает тикет на агента поддержки.
user_id string обязательныйID пользователя-агента
PATCH /v1/helpdesk/tickets/{id}/priority — приоритет тикета
Изменяет приоритет тикета. Допустимые значения: low, normal, high, urgent.
priority string обязательныйПриоритет: low, normal, high, urgent
GET /v1/helpdesk/ticket-types — типы обращений
Возвращает список активных типов обращений проекта. Каждый тип содержит id, name, description. Используйте ticket_type_id при создании тикета для классификации обращений. Типы настраиваются в дашборде (Settings → Поддержка).
Webhook-события
ticket.created — создан тикет, ticket.replied — ответ на тикет, ticket.status_changed — смена статуса, ticket.assigned — назначен агент, ticket.closed — тикет закрыт.
Формы
Публичный endpoint для приёма заявок с сайтов. Не требует API-ключа — безопасен для использования в клиентском JavaScript.
POST /f/{form_id}
body object обязательныйПроизвольный JSON — любые поля формы
Пример запроса
Ответ
Поля формы
Принимаются произвольные поля. Стандартные поля выделяются в уведомлениях и будут использоваться в будущих интеграциях (CRM, Google Sheets).
name string Имя отправителя
email string Email отправителя
phone string Телефон
subject string Тема обращения
company string Компания
city string Город
url string Ссылка на сайт
message string Текст сообщения
* any Любые другие поля — передаются как есть
Формат allowed_origins
Разрешённые источники указываются как домены. Схема (http/https), www и слеши нормализуются автоматически — достаточно написать example.com, все варианты (https://example.com, www.example.com, example.com/) будут приняты.
example.com — принимает заявки с https://example.com, http://example.com, https://www.example.com
*.example.com — любой поддомен и сам example.com (требуется минимум второй уровень, *.com запрещено)
Запрещены локальные хосты (localhost, 127.0.0.1), приватные IP и зарезервированные TLD (.local, .test, .example) — сервер вернёт ошибку при сохранении
Безопасность
Проверка Origin — только разрешённые домены
Rate limit — 30 заявок/мин на форму
Honeypot — скрытое поле _honey для защиты от ботов
Санитизация — автоматическое удаление HTML-тегов и опасного контента
Time-to-submit — заявки быстрее 3 сек отклоняются (настраивается)
Блоклист одноразовых email-сервисов (mailinator, tempmail и т.д.) — помечаются как спам
Спам-папка и фильтры
Спам-заявки не удаляются — сохраняются отдельно для ревью. Вебхуки и email-уведомления для спама не отправляются.
Вкладка «Спам» в кабинете — отдельный список заявок, помеченных фильтрами
Honeypot — скрытое поле с уникальным именем per-form. Если бот его заполнит — заявка тихо отклоняется
Keyword blocklist — настраиваемый список слов. Заявки с ними помечаются как спам
Timestamp проверка — `_submit_time` при загрузке формы, сервер сверяет с моментом отправки
Можно вручную помечать заявки как спам/не-спам в дашборде
Маршруты заявок (Form Routes)
Единая модель: маршрут = триггер + действие. Триггер — «всегда» (базовый получатель) или «по условию». Действия: доставить получателю / пометить как спам / заблокировать. До 40 маршрутов на форму.
Операторы условия: `contains` (подстрока), `equals` (точное равенство). Поле условия — имя поля или `*` для любого строкового поля
`mark_spam` — сохранить, но пометить как спам (не отправлять получателям, не слать webhook)
`block` — не сохранять вообще (тихий 200 OK)
`deliver` — доставить получателю (email/messenger/subscriber/team). Условный маршрут добавляется к основным «всегда» по умолчанию
Флаг `replace_defaults` на условном deliver-маршруте заменяет все «всегда»-маршруты при срабатывании — используется для перенаправления (например, «только для продаж — на sales@»)
Redirect после отправки
Если в настройках формы задан `redirect_url` и запрос пришёл как `application/x-www-form-urlencoded` (HTML-форма без JS), сервер отвечает `303 See Other` с `Location: <redirect_url>`. JSON-запросы (fetch/AJAX) продолжают получать `{ok:true}`.
Получатели: мессенджеры (Telegram/Max), email, подписчики проекта
Пример интеграции
Лимиты
Rate limits и ограничения на размеры полей.
Rate limit: 300 запросов/мин на проект. При превышении — 429 Too Many Requests.
Текст сообщения: до 4 096 символов.
Кнопки: до 3 рядов, до 3 кнопок в ряду.
Медиа: до 20 МБ (photo), 50 МБ (video/document).
Broadcast: до 100 000 подписчиков за одну рассылку.
OTP: TTL 5 мин, макс. 5 попыток, 1 активный код на subscriber_id.
Теги: до 20 тегов на проект, длина тега до 64 символов.
Разрешения: до 20 на проект.
Шаблоны: до 100 на проект.
Заголовки X-RateLimit-* не возвращаются. При превышении лимита API возвращает только HTTP 429 с телом ошибки. Рекомендуем реализовать экспоненциальный backoff на своей стороне.
Коды ошибок
API возвращает стандартные HTTP-коды с JSON-телом ошибки. Поле retryable указывает, стоит ли повторить запрос.
Формат ошибки:
400 — Невалидный запрос (отсутствуют обязательные поля, неверный формат)
401 — Неверный или отсутствующий API-ключ
403 — Нет доступа к ресурсу
404 — Подписчик или ресурс не найден
409 — Конфликт (например, OTP уже отправлен)
422 — Ошибка валидации (текст слишком длинный, невалидный URL)
429 — Превышен rate limit (retryable: true, заголовок Retry-After)
500 — Внутренняя ошибка сервера (retryable: true)
Обработка ошибок и retry
Рекомендации по обработке ошибок API и стратегии повторных запросов.
retryable: true — ошибку можно повторить (429, 500). Используйте exponential backoff: 1с → 2с → 4с, максимум 3 попытки.
retryable: false — повторять бессмысленно (400, 401, 403, 404, 409). Исправьте запрос перед повторной отправкой.
Retry-After — при 429 заголовок указывает сколько секунд ждать перед повторным запросом. Rate limit: 300 запросов в минуту на проект.
Exponential backoff — увеличивайте задержку между попытками: 1с, 2с, 4с. Не повторяйте POST-запросы (send, broadcast) автоматически — используйте поле retryable для принятия решения.
Playground
Соберите запрос к API и скопируйте готовую curl-команду.
{
"subscriber_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "Привет от Zapnoty!"
}curl -X POST https://api.zapnoty.com/v1/send \
-H "Authorization: Bearer zn_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subscriber_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "Привет от Zapnoty!"
}'API vs Дашборд
Что можно автоматизировать через REST API, а что доступно только в дашборде.
Доступно через API
Отправка уведомлений — POST /v1/send (персональные, по subscriber_id, с медиа, кнопками, шаблонами)
OTP-коды — POST /v1/otp/send и /v1/otp/verify
Массовые рассылки — POST /v1/broadcast, GET /v1/broadcast/:job_id
Подписчики — GET /v1/subscribers, PUT /v1/subscribers/:id/tags
Шаблоны — полный CRUD: GET/POST /v1/templates, PUT/DELETE /v1/templates/{key}
Разрешения — GET/POST /v1/permissions, PUT /v1/permissions/{key}
Теги — полный CRUD: GET/POST /v1/tags, PUT/DELETE /v1/tags/{name}
Вебхук — GET/PUT/DELETE /v1/webhook
Auth через ботов — GET /v1/auth/link, POST /v1/auth/session, POST /v1/auth/verify, GET статус сессии
Helpdesk — создание тикетов, ответы, смена статуса, назначение, приоритет, типы обращений
Автосообщения — GET/PUT /v1/auto-messages (включение/выключение, тексты на двух языках)
Аналитика — GET /api/projects/:id/analytics (через JWT-сессию кабинета)
Только через дашборд
Создание проекта — регистрация и создание проектов только через UI
API-ключ — генерация и перегенерация ключа (требует OTP-подтверждение)
Удаление проекта — с OTP-подтверждением через мессенджер
Подпись отправителя — настройка имени и описания (Settings → Notifications)
Логотип — загрузка и удаление логотипа проекта
OTP-шаблон — мультиязычный шаблон с HTML-форматированием и превью
Настройки Auth — callback URL, origin URL, текст кнопки авторизации
Включение Helpdesk — активация модуля тикетов в настройках проекта
SLA-таймеры — настройка сроков первого ответа и закрытия тикетов
Удаление разрешений — DELETE permissions доступен только в дашборде
QR-коды — генерация QR-кодов для подписки со стилями и логотипом
API-ключ (Bearer zn_...) используется для всех /v1/* эндпоинтов. Дашборд работает через JWT-сессию после OAuth авторизации (Яндекс/VK).