Документация API

Быстрый старт

Три шага до первого уведомления.

1

1. Создайте проект

Зарегистрируйтесь через Яндекс или ВК, создайте проект в дашборде.

2

2. Получите API-ключ

В настройках проекта скопируйте API-ключ формата zn_aBcDeFgH...

3

3. Отправьте первый запрос

Используйте curl или любой HTTP-клиент:

curl -X POST https://api.zapnoty.com/v1/send
-H "Authorization: Bearer zn_aBcDeFgH..."
-H "Content-Type: application/json"
-d '{
"subscriber_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "Привет!"
}'

Аутентификация

Все запросы к API требуют Bearer-токен в заголовке Authorization.

Base URL: https://api.zapnoty.com
Content-Type: application/json для всех POST/PUT/PATCH запросов

Формат заголовка:

Authorization: Bearer zn_aBcDeFgHiJkLmNoPqRsTuVwXyZ123456

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 или в дашборде:

GET /v1/auth/link
 
// Response:
{
"telegram_link": "https://t.me/YourBot?start=auth_my-app",
"max_link": "https://max.ru/YourBot?start=auth_my-app",
"configured": true
}

API-сессии (с state)

Для передачи state (например, ID браузерной сессии) создайте сессию через API:

POST /v1/auth/session
 
{
"state": "browser_session_abc"
}
 
// Response:
{
"session_id": "aBcDeFgH12345678",
"telegram_link": "https://t.me/YourBot?start=auths_aBcDeFgH12345678",
"expires_in": 300
}

Верификация кода

После подтверждения пользователь попадает на callback_url?code=CODE. Верифицируйте код:

POST /v1/auth/verify
 
{
"code": "aBcDeFgH..."
}
 
// Response:
{
"channel": "telegram",
"first_name": "John",
"username": "johndoe",
"avatar_url": null,
"subscriber_id": "uuid-...",
"lang": "ru",
"tags": [],
"state": "browser_session_abc"
}

QR/Polling (кросс-девайс)

Для авторизации на десктопе через мобильного бота: создайте сессию, покажите QR-код со ссылкой, и поллите статус. Когда пользователь подтвердит авторизацию на телефоне, вы получите code. Интервал polling: 2-3 секунды. Код одноразовый — после получения status=completed повторный запрос вернёт expired.

GET /v1/auth/session/{session_id}/status
 
// Pending:
{ "status": "pending" }
 
// Completed:
{ "status": "completed", "code": "aBcDeFgH..." }
 
// Expired:
{ "status": "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

Фильтр по сегменту (тегу)

Пример запроса

POST /v1/send
 
{
"subscriber_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "Заказ #1042 отправлен!",
"format": "markdown",
"buttons": [[{
"text": "Отследить",
"url": "https://example.com/track/1042"
}]]
}

Ответ

{
"ok": true,
"message_id": "msg_abc123"
}

OTP (одноразовые коды)

Отправка и проверка кодов подтверждения через мессенджер.

POST /v1/otp/send

Генерирует 6-значный код и отправляет подписчику.

subscriber_id string (UUID) обязательный

UUID подписчика

POST /v1/otp/send
 
{
"subscriber_id": "550e8400-e29b-..."
}

Ответ

{
"sent": true,
"expires_in_seconds": 300
}

POST /v1/otp/verify

Проверяет введённый код.

subscriber_id string (UUID) обязательный

UUID подписчика

code string обязательный

6-значный код от пользователя

POST /v1/otp/verify
 
{
"subscriber_id": "550e8400-e29b-...",
"code": "482916"
}

Ответ

✓ Код верный

{
"verified": true
}

✗ Код неверный

{
"verified": false
}

Лимиты 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"]

POST /v1/broadcast
 
{
"text": "Версия 2.0 доступна!",
"permission": "updates",
"tags": ["beta"]
}

Ответ

{
"job_id": "a1b2c3d4-e5f6-...",
"status": "pending",
"total_subscribers": 1500
}

GET /v1/broadcast/:job_id

Получение статуса рассылки.

Поля ответа: status (pending/processing/completed/failed), total, sent, failed.

{
"job_id": "b7f3...",
"status": "completed",
"total": 2847,
"sent": 2835,
"failed": 12
}

Подписчики

Управление списком подписчиков и их тегами.

GET /v1/subscribers

Список подписчиков проекта. Пагинация через query-параметры.

limit number

Кол-во записей (по умолчанию 50, макс. 200)

offset number

Смещение от начала списка (по умолчанию 0)

channel string

Фильтр по каналу: telegram или max

Ответ

{
"subscribers": [
{
"id": "550e8400-...",
"channel": "telegram",
"first_name": "John",
"username": "johndoe",
"lang": "ru",
"tags": ["vip"],
"created_at": "2026-03-05T12:00:00Z"
}
],
"total": 150
}

PUT /v1/subscribers/:id/tags

Обновление тегов подписчика. Передайте полный массив тегов. Теги должны быть предварительно созданы в настройках проекта или через API. Несуществующие теги будут автоматически созданы (если не достигнут лимит 20).

PUT /v1/subscribers/sub_abc/tags
 
{
"tags": ["vip", "beta"]
}

Ответ

{
"updated": true
}

Шаблоны

Шаблоны позволяют переиспользовать текст с переменными. Создаются в дашборде или через API.

Использование: передайте template и vars вместо text в /v1/send.

Переменные в шаблоне обозначаются {{имя}}. Например: «Заказ {{order_id}} доставлен».

Пример

POST /v1/send
 
{
"subscriber_id": "550e8400-e29b-41d4-a716-446655440000",
"template": "order_delivered",
"vars": {
"order_id": "1042",
"customer": "Иван"
}
}

Медиа и кнопки

К уведомлениям можно прикрепить медиа-файлы и inline-кнопки.

Типы медиа: photo, video, document. Передайте URL файла.

Кнопки — двумерный массив: внешний массив — ряды, внутренний — кнопки в ряду.

  • Кнопка с URL: {"text": "Открыть", "url": "https://..."}
  • Кнопка с callback: {"text": "Да", "callback_data": "confirm_123"}

Пример с медиа и кнопками

POST /v1/send
 
{
"subscriber_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "Ваш заказ готов",
"media": {
"type": "photo",
"url": "https://example.com/photo.jpg"
},
"buttons": [[
{"text": "Подробнее", "url": "https://..."},
{"text": "Отмена", "callback_data": "cancel_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.

Проверка подписи:

// Node.js
const crypto = require('crypto');
 
const signature = req.headers['x-zapnoty-signature'];
const expected = crypto
.createHmac('sha256', webhookSecret)
.update(JSON.stringify(req.body))
.digest('hex');
 
if (signature !== expected) // отклонить запрос

Формат payload:

{
"event": "subscription.created",
"timestamp": "2026-03-05T12:00:00Z",
"data": {
"subscriber_id": "sub_abc",
"channel": "telegram"
}
}

Политика ретраев

При ошибке доставки 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

Название (для кабинета)

POST /v1/scheduled
 
{
"subscriber_id": "550e8400-...",
"text": "Напоминание о встрече",
"format": "html",
"scheduled_at": "2026-03-25T10:00:00Z",
"buttons": [[{"text": "Подробнее", "url": "https://..."}]]
}

Цепочки (Drip)

Автоматическая последовательность сообщений при подписке или событии. Каждый шаг поддерживает форматирование, медиа и кнопки.

name string обязательный

Название (для кабинета)

trigger string обязательный

Триггер: subscription, segment, permission

trigger_value string

Значение триггера (тег или ключ разрешения)

steps[].text string обязательный

Текст сообщения

steps[].delay_minutes number обязательный

Задержка от момента триггера (минуты)

POST /v1/drip-chains
 
{
"name": "Онбординг",
"trigger": "subscription",
"steps": [
{"text": "Добро пожаловать!", "format": "html", "delay_minutes": 0},
{"text": "Совет дня", "delay_minutes": 1440,
"buttons": [[{"text": "Читать", "url": "https://..."}]]}
]
}

Повторяющиеся

Регулярная рассылка с заданным интервалом. Поддерживает форматирование, медиа, кнопки и фильтры (channel, segment, permission).

name string обязательный

Название (для кабинета)

text string обязательный

Текст сообщения

interval_hours number обязательный

Интервал повторения (часы)

POST /v1/recurring
 
{
"name": "Еженедельный дайджест",
"text": "<b>Итоги недели</b>",
"format": "html",
"interval_hours": 168,
"media": {"media_type": "image", "url": "https://..."}
}

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). Необязательный.

Ответ

{
"id": "550e8400-...",
"ticket_number": 42,
"status": "new",
"priority": "normal",
"channel": "virtual",
"ticket_type_id": "uuid-or-null",
"ticket_type_name": "Баг",
"created_at": "2026-03-05T12:00:00Z"
}

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 — любые поля формы

Пример запроса

POST /f/{form_id}
 
{
"name": "John",
"email": "john@example.com",
"message": "Хочу узнать подробнее"
}

Ответ

{
"ok": true
}

Поля формы

Принимаются произвольные поля. Стандартные поля выделяются в уведомлениях и будут использоваться в будущих интеграциях (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, подписчики проекта

Пример интеграции

fetch('https://api.zapnoty.com/f/form_abc123', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: form.name,
email: form.email,
message: form.message
})
})

Лимиты

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 указывает, стоит ли повторить запрос.

Формат ошибки:

{
"error": "text is required",
"retryable": false
}

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-команда
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).