Тестирование интеграции
Перед боевым запуском интеграцию стоит проверить. Zapnoty даёт несколько инструментов: тестовые ключи, предпросмотр и dry-run рассылок.
Два ключа на проект
У каждого проекта два API-ключа: боевой zn_live_ и тестовый zn_test_. Это один и тот же проект — общие подписчики, шаблоны и webhook-эндпоинты, разница только в ключе. При создании проекта ответ содержит сразу оба ключа — поля api_key и test_api_key.
Что разрешено тестовому ключу
Тестовый ключ zn_test_ предназначен для проверки ОТПРАВКИ (runtime), а не для управления проектом. Поэтому он разграничен по правам:
Чтение — любые GET-запросы (шаблоны, подписчики, теги, права, вебхуки, журналы, аналитика).
Runtime-операции (замоканы в sandbox): /v1/send, /v1/send/batch, /v1/send/preview, /v1/otp/*, /v1/broadcast, /v1/auth/session, /v1/auth/verify, /v1/events/track, /v1/helpdesk/tickets/*, /v1/helpdesk/request, /v1/test/simulate-event.
Изменение настроек проекта — любой мутирующий запрос (POST/PUT/PATCH/DELETE) к шаблонам, правам, тегам, вебхукам, sender, авто-сообщениям, формам, helpdesk-конфигу (settings/SLA/типы обращений/готовые ответы/правила маршрутизации), custom-bots, планировщику (scheduled/drip/recurring), ротации ключей, удалению подписчиков → 403.
Запрос на изменение настроек с тестовым ключом возвращает 403 со стандартным конвертом ошибки. Так тест-ключ нельзя случайно использовать для порчи проекта: настройка проекта — разовое действие, и его выполняют боевым ключом zn_live_ один раз при настройке.
Песочница: что такое sandbox-режим
Запрос с тестовым ключом zn_test_ проходит всю API-логику (валидация, rate-limit, журнал доставок, вебхуки) и отвечает точно так же, как боевой — те же ответы и коды ошибок, — но реальное сообщение в Telegram/Max НЕ отправляется (mock-доставка). Sandbox покрывает /v1/send, /v1/send/batch, /v1/otp/send и /v1/broadcast. Записи в журнале доставок помечаются is_test=true и не учитываются в боевой статистике проекта.
Симуляция исхода доставки
В sandbox-режиме в тело /v1/send можно добавить _test_directives, чтобы воспроизвести нужный исход. delivery_outcome: "failed" уводит доставку по failure-пути: запись в журнале со статусом failed и вебхук delivery.failed с reason из failure_reason. Допустимые failure_reason: user_blocked_bot, chat_not_found, bot_banned, invalid_message, rate_limited, platform_unavailable, unknown. Для боевого ключа _test_directives молча игнорируется.
OTP в песочнице
При вызове /v1/otp/send с тестовым ключом ответ содержит дополнительное поле sandbox_code — реальный сгенерированный код в открытом виде. CI/тест может сразу передать его в /v1/otp/verify без доступа к мессенджеру. Для боевого ключа поле sandbox_code отсутствует.
Предпросмотр сообщения
POST /v1/send/preview рендерит сообщение (шаблон, переменные, подпись) и возвращает итоговый текст без отправки. Удобно проверить, как подставятся vars и какой формат применится.
Dry-run рассылки
Параметр dry_run: true в /v1/broadcast не создаёт рассылку — возвращает размер аудитории под фильтрами, оценку списания кредитов и пример отрендеренного сообщения. Так проверяют фильтры (теги, разрешения) перед реальной отправкой.
Проверка вебхуков
Чтобы проверить приём событий, временно укажите в webhook-эндпоинте URL тестового приёмника (webhook.site, ngrok на localhost). Подпись X-Zapnoty-Signature считается так же — проверьте валидацию HMAC. Журнал доставок вебхуков виден в кабинете. Доставки от sandbox-запросов помечаются is_test=true.
В sandbox вебхуки delivery.success / delivery.failed диспатчатся с задержкой ~2 секунды — это имитирует реальную асинхронность (боевые вебхуки приходят уже после ответа API).
Ручной триггер событий
POST /v1/test/simulate-event доступен только с тестовым ключом zn_test_. Эндпоинт реально доставляет произвольное событие на webhook-эндпоинты проекта с HMAC-подписью и пометкой is_test=true — удобно отлаживать обработчик любого события без воспроизведения сценария. Тело: event (имя из списка известных событий) и data (произвольный JSON-объект). Невалидное событие или data не-объект → 400. Если у проекта нет webhook-эндпоинтов — ответ dispatched: true, endpoints: 0.
Тестовый ключ для старого проекта
Проекты, созданные до появления sandbox, не имеют тестового ключа. Сгенерируйте его кнопкой в кабинете: настройки проекта → блок «Тестовый ключ». То же делает запрос POST /api/projects/{id}/test-key — он создаёт ключ либо перевыпускает существующий (повторный вызов ротирует ключ). Ответ содержит test_api_key — он показывается один раз, сохраните его сразу.