Разработка и проверка webhook

Для существующего webhook-сценария используйте HTTP-туннель либо облачный webhook inbox. Inbox выдаёт постоянный публичный HTTPS-адрес и записывает входящие события в инспектор.

Описание

Общее описание функционала

Облачный webhook inbox — постоянный публичный HTTPS-адрес для приёма вебхуков от внешних провайдеров (платёжные системы, CRM, мессенджеры и т.д.) без обязательного подключения локального клиента туннеля. Каждый inbox привязан к вашему аккаунту, имеет собственный URL и режим доставки: только сохранение с подтверждением провайдеру, пересылка на локальный сервис через подключённый клиент или пересылка на внешний HTTPS-эндпоинт (при наличии соответствующей опции тарифа).

Входящие запросы фиксируются в инспекторе HTTP-трафика с меткой webhook inbox. При сбое доставки провайдер по-прежнему получает успешное подтверждение (HTTP 200), чтобы избежать лавины повторных отправок; детали ошибки видны вам в инспекторе.

Функция доступна на тарифах с возможностью webhook-inbox. Количество inbox на аккаунт ограничено лимитом тарифа. Пересылка на удалённый HTTPS-URL требует дополнительной опции webhook-inbox-remote-forward.

Как пользователь может использовать

  • Разработчик нажимает Создать endpoint, получает публичный адрес без запущенного локального клиента и просматривает тестовые вебхуки в инспекторе.
  • Интегратор даёт провайдеру стабильный URL inbox в режиме «только хранение», пока бэкенд ещё не готов к приёму трафика.
  • Команда с подключённым клиентом туннеля пересылает вебхуки на 127.0.0.1:3000 и видит реальный HTTP-код ответа локального сервиса.
  • Пользователь с опцией удалённой пересылки направляет вебхуки на staging-сервер по HTTPS без постоянного локального туннеля.
  • QA ставит доставку на паузу, чтобы накопить события в инспекторе, не беспокоя downstream-сервис.
  • Владелец аккаунта меняет режим или адрес назначения через API или дашборд — публичный URL inbox при этом не меняется.
  • Оператор копирует public_url из раздела Туннели → Webhook inbox и вставляет его в настройки провайдера.
  • Пользователь сравнивает повторные доставки через повтор запроса (Replay) после исправления обработчика на локальной стороне.
  • Разработчик проверяет подпись или заголовки провайдера на сохранённых событиях в инспекторе до включения пересылки.
  • Команда ограничена одним inbox на бесплатном тарифе — создаёт новый только после удаления старого туннеля или смены плана с большим лимитом.
  • Разработчик открывает ссылку на /dashboard/webhook-inbox из закладки или письма без активной сессии, входит в форму на главной странице и сразу возвращается к своим endpoint.
  • Владелец больше не использует endpoint и на странице /dashboard/webhook-inbox выбирает его, нажимает Удалить endpoint и подтверждает необратимое удаление. После подтверждения endpoint исчезает из списка, а его публичный URL перестаёт принимать webhook-запросы.

Как это реализовано в сервисе

1. Вы создаёте inbox в личном кабинете или через API POST /api/webhook-inboxes. Сервис выдаёт постоянный публичный URL и сохраняет настройки режима.

2. Провайдер отправляет HTTP-запрос (любой метод и путь) на этот URL. Запрос не требует входа на платформу.

3. Сервис распознаёт трафик как inbox, записывает событие в инспектор (тело, заголовки, метаданные) и в зависимости от режима:

  • Только хранение — отвечает провайдеру HTTP 200;
  • Локальная пересылка — при подключённом клиенте передаёт запрос на указанный локальный адрес и возвращает провайдеру код ответа upstream; если клиент недоступен — сохраняет событие и отвечает HTTP 200;
  • HTTPS пересылка — при наличии опции тарифа отправляет запрос на настроенный HTTPS-URL и при успехе возвращает провайдеру код ответа удалённого сервиса; при ошибке доставки — HTTP 200 и запись об ошибке в инспекторе.

4. Флаг пауза доставки останавливает пересылку, но приём и запись в инспектор продолжаются; провайдер по-прежнему получает HTTP 200.

5. Изменения режима, адреса назначения и паузы применяются через PATCH /api/webhook-inboxes или кнопки в дашборде; публичный URL остаётся прежним.

6. Когда endpoint больше не нужен, его можно удалить в дашборде. После подтверждения действие нельзя отменить: endpoint удаляется из списка, а публичный URL навсегда перестаёт принимать webhook-запросы. Дашборд показывает подтверждение успешного удаления.

Подробности API — в справочнике API. Коды ошибок — в справочнике ошибок. Ограничения — в известных ограничениях.

Справочник API

Обзор

Управление облачными webhook inbox выполняется через REST API под префиксом /api/webhook-inboxes. Все методы требуют авторизованной сессии (кука) или эквивалентной аутентификации дашборда.

Приём вебхуков от внешних провайдеров идёт на публичный URL inbox (public_url из ответа API) — без авторизации, любым HTTP-методом и с любым путём после хоста.

МетодПутьНазначение
GET/api/webhook-inboxesСписок inbox текущего пользователя
GET/api/webhook-inboxes?id=<tunnel_id>Подробности inbox, доступного пользователю
POST/api/webhook-inboxesСоздать inbox
PATCH/api/webhook-inboxes?id=<tunnel_id>Изменить режим, назначение или паузу доставки

Другие HTTP-методы на /api/webhook-inboxes возвращают 405 Method Not Allowed.

Удаление endpoint относится к общему жизненному циклу туннеля, а не к этому набору методов.

---

GET /api/webhook-inboxes

Список всех inbox, принадлежащих авторизованному пользователю.

Для чтения конкретного inbox передайте id: GET /api/webhook-inboxes?id=<tunnel_id>. После принятия приглашения редактор (editor) и наблюдатель (viewer) могут читать его подробности по этому адресу. Общий список по-прежнему содержит только собственные inbox пользователя.

Успешный ответ 200

Тело JSON:

ПолеТипОписание
inboxesмассивСписок объектов inbox (может быть пустым)

Каждый элемент массива inboxes:

ПолеТипОписание
tunnel_idстрокаИдентификатор inbox (используется в PATCH ?id=)
public_urlстрокаПубличный HTTPS-URL для провайдера
modeстрокаstore_only, forward_local или forward_remote
remote_forward_urlстрокаHTTPS-URL назначения (для forward_remote; иначе пусто)
target_addrстрокаЛокальный адрес назначения (для forward_local; иначе служебное значение)
delivery_pausedbooleantrue — пересылка отключена, приём и запись в инспектор продолжаются
created_atстрока (RFC3339)Время создания
updated_atстрока (RFC3339)Время последнего изменения

---

POST /api/webhook-inboxes

Создаёт новый inbox и выдаёт публичный URL.

Требуется возможность тарифа webhook-inbox и свободная квота max_webhook_inboxes.

Тело запроса (JSON)

ПолеОбязательностьОписание
modeнеобязательноРежим доставки. По умолчанию store_only. Допустимые значения: store_only, forward_local, forward_remote
target_addrнеобязательноДля forward_local: адрес локального сервиса, например 127.0.0.1:3000
remote_forward_urlобязательно для forward_remoteПолный HTTPS-URL внешнего эндпоинта, например https://api.example.com/hooks

Для режима forward_remote требуется опция тарифа webhook-inbox-remote-forward. URL должен использовать схему HTTPS; адреса localhost, частных и служебных сетей отклоняются при создании.

Успешный ответ 201 Created

Тело — один объект inbox (те же поля, что в списке выше).

---

PATCH /api/webhook-inboxes?id=<tunnel_id>

Частичное обновление существующего inbox. Параметр id в query обязателен и равен tunnel_id.

Изменять inbox может владелец или участник с ролью редактора (editor). Доступность режима и пересылки определяется тарифом владельца inbox; тариф редактора не расширяет и не ограничивает эти возможности. Наблюдатель (viewer), посторонний пользователь и участник с отозванным доступом получают 404 при попытке изменения. Если нужная возможность отсутствует в тарифе владельца, ответ — 403 с кодом feature_disabled и полем feature_id.

Публичный URL (public_url) не меняется при обновлении.

Тело запроса (JSON)

Все поля необязательны; передаются только изменяемые:

ПолеОписание
modeНовый режим: store_only, forward_local, forward_remote
target_addrНовый локальный адрес для forward_local
remote_forward_urlНовый HTTPS-URL для forward_remote
delivery_pausedtrue — приостановить пересылку; false — возобновить

Те же правила тарифа и валидации HTTPS-URL, что при создании, применяются при смене режима или remote_forward_url.

Успешный ответ 200

Тело — обновлённый объект inbox.

---

DELETE /api/tunnels?id=<tunnel_id>

Удаляет endpoint через общий API жизненного цикла туннелей. Используйте tunnel_id из списка inbox. После успешного удаления его публичный URL навсегда перестаёт принимать webhook-запросы, а endpoint исчезает из списка.

Успешный ответ 204 No Content

Тело ответа отсутствует.

Для работы в интерфейсе откройте /dashboard/webhook-inbox, выберите endpoint, нажмите Удалить endpoint и подтвердите действие. Удаление необратимо.

DELETE /api/webhook-inboxes не поддерживается.

---

Публичный приём вебхуков (public_url)

Внешний провайдер отправляет запросы на public_url с любым путём и query, например:

POST https://<ваш-поддомен>/hooks/payment

Авторизация на платформе не требуется.

Поведение ответа провайдеру

РежимУспешная доставкаСбой доставки или пауза
store_onlyHTTP 200, пустое тело—
forward_localHTTP-код ответа локального сервисаHTTP 200; событие в инспекторе с пометкой об ошибке доставки
forward_remoteHTTP-код ответа удалённого HTTPS-сервиса (безопасные заголовки ответа могут быть переданы провайдеру)HTTP 200; событие в инспекторе с пометкой об ошибке доставки

При delivery_paused: true пересылка не выполняется; провайдер получает HTTP 200, событие сохраняется в инспекторе.

Если возможность webhook-inbox снята с тарифа владельца, публичный URL возвращает 404 Not Found.

Состояние самого endpoint как туннеля проверяется до доставки. Если endpoint приостановлен в списке Туннели (это не пауза доставки), провайдер получает 503 Service Unavailable. Если срок жизни endpoint истёк, ответ — 410 Gone. В обоих случаях шлюз, mock-ответ и пересылка не выполняются, а подтверждение 200 не отправляется. Такой ответ совпадает с ответом обычного HTTP-туннеля в том же состоянии.

События помечаются в инспекторе тегом webhook-inbox. Подробнее о просмотре — в документации инспектора HTTP-трафика.

---

Дашборд

На странице /dashboard/webhook-inbox (видна при наличии возможности webhook-inbox):

  • Создать inbox — выбор режима и полей назначения;
  • Копировать / открыть public_url;
  • Пауза доставки / Возобновить доставку.
  • Удалить endpoint — выбрать endpoint, подтвердить необратимое удаление и получить подтверждение об успехе.

Подписи режимов в интерфейсе: Только хранение, Локальная пересылка, HTTPS пересылка.

Ошибки

401 Unauthorized

Когда: запрос к /api/webhook-inboxes без действующей сессии или с недействительными учётными данными.

Что делать: войдите в личный кабинет или передайте корректную авторизацию, как для остальных API дашборда.

---

403 Forbidden — заблокированный аккаунт

Когда: попытка создать inbox при заблокированном аккаунте (POST /api/webhook-inboxes).

Тело ответа (JSON): code: "user_suspended", сообщение «Аккаунт заблокирован».

Что делать: обратитесь в поддержку для разблокировки аккаунта.

---

403 Forbidden — нет возможности на тарифе

Когда:

  • создание или изменение inbox без возможности webhook-inbox на тарифе;
  • создание или переключение в режим forward_remote без опции webhook-inbox-remote-forward;
  • превышена квота max_webhook_inboxes при создании нового inbox.

Текст ответа: содержит forbidden и имя недоступной возможности или квоты (например feature webhook-inbox, feature webhook-inbox-remote-forward, quota max_webhook_inboxes).

Что делать: проверьте тариф и лимиты в разделе оплаты или обновите план. Удалите неиспользуемый inbox, если исчерпана квота количества.

---

400 Bad Request — некорректное тело

Когда: JSON в теле запроса не разбирается.

Текст ответа: invalid body.

Что делать: проверьте синтаксис JSON и заголовок Content-Type: application/json.

---

400 Bad Request — обязательный параметр

Когда: PATCH /api/webhook-inboxes без query-параметра id.

Текст ответа: id required.

Что делать: добавьте ?id=<tunnel_id> к URL.

---

400 Bad Request — недопустимый режим

Когда: в mode передано значение вне списка store_only, forward_local, forward_remote.

Текст ответа: invalid webhook inbox mode.

Что делать: используйте одно из допустимых значений режима.

---

400 Bad Request — недопустимый URL удалённой пересылки

Когда: для forward_remote указан URL не по HTTPS, адрес localhost, частной сети или иной запрещённый адрес.

Текст ответа: invalid remote forward URL.

Что делать: укажите публичный HTTPS-URL без частных IP и localhost. Если hostname указывает на частный адрес при фактическом соединении, доставка будет заблокирована; провайдер получит HTTP 200, а ошибка отобразится в инспекторе.

---

404 Not Found — inbox не найден

Когда:

  • PATCH для чужого или несуществующего tunnel_id;
  • внешний запрос на public_url inbox, если возможность webhook-inbox снята с тарифа владельца или запись inbox отсутствует.

Текст ответа (API): not found.

Что делать: проверьте tunnel_id и владельца inbox. Для публичного URL убедитесь, что inbox активен и тариф владельца включает функцию.

---

405 Method Not Allowed

Когда: на /api/webhook-inboxes вызван метод, отличный от GET, POST, PATCH (например DELETE).

Что делать: не отправляйте DELETE /api/webhook-inboxes: этот метод не поддерживается. Чтобы удалить endpoint, выберите его на /dashboard/webhook-inbox, нажмите Удалить endpoint и подтвердите действие. Для интеграции используйте общий API жизненного цикла туннелей: DELETE /api/tunnels?id=<tunnel_id>.

---

503 Service Unavailable / 410 Gone на публичном URL

Когда: провайдер отправил запрос на public_url, а endpoint приостановлен как туннель (503) или его срок жизни истёк (410). Пауза доставки к этому не относится: при ней провайдер по-прежнему получает 200.

Что делать: при 503 возобновите endpoint на странице Туннели. При 410 создайте новый endpoint и передайте его URL провайдеру: истёкший endpoint восстановить нельзя.

---

500 Internal Server Error / 503 Service Unavailable

Когда: внутренняя ошибка сервиса при создании, обновлении или чтении списка; сервис временно недоступен.

Что делать: повторите запрос позже. Если ошибка сохраняется — обратитесь в поддержку.

---

Ошибки доставки (видны в инспекторе, не в HTTP-ответе провайдеру)

Когда: пересылка на локальный клиент или удалённый HTTPS-эндпоинт не удалась (клиент отключён, сеть, таймаут, отказ upstream, отсутствие опции удалённой пересылки после смены тарифа, пауза доставки с пересылкой и т.д.).

Поведение для провайдера: HTTP 200 (подтверждение приёма), чтобы провайдер не повторял отправку бесконечно.

Поведение для вас: событие в инспекторе HTTP-трафика с тегами webhook-inbox и при необходимости delivery_error или capture_error; в заметках события — текст причины (например «локальный клиент не подключён»).

Что делать: проверьте подключение клиента, URL назначения, опцию тарифа, снимите паузу доставки; при необходимости повторите обработку через Replay.

Ограничения

  • Подтверждение провайдеру при сбое доставки. В режимах с пересылкой при недоступности назначения, паузе доставки или отсутствии опции удалённой пересылки внешний провайдер всё равно получает HTTP 200. Это сделано намеренно, чтобы остановить повторные отправки со стороны провайдера. Факт сбоя смотрите в инспекторе трафика.
  • Режим «только хранение». Провайдер всегда получает HTTP 200 с пустым телом; код ответа вашего приложения не формируется.
  • Локальная пересылка требует клиента. Без подключённого клиента туннеля запрос сохраняется в инспекторе, пересылка не выполняется, провайдер получает HTTP 200.
  • Удалённая пересылка — только HTTPS. HTTP-URL, localhost, частные и служебные адреса отклоняются при настройке; hostname, резолвящийся в частный IP при соединении, блокируется при доставке.
  • Опция удалённой пересылки. Режим forward_remote и поле remote_forward_url доступны только с опцией тарифа webhook-inbox-remote-forward. После снятия опции существующий inbox в этом режиме продолжает принимать вебхуки, но пересылка не выполняется до восстановления опции или смены режима.
  • Квота количества inbox. Лимит max_webhook_inboxes задаётся тарифом (на бесплатном плане по умолчанию — один inbox). Превышение блокирует только создание новых; существующие продолжают работать.
  • Публичный URL неизменен. Смена режима, адреса назначения или паузы не меняет выданный public_url; провайдеру не нужно обновлять endpoint.
  • Удаление необратимо. Endpoint можно удалить в /dashboard/webhook-inbox: выберите его, нажмите Удалить endpoint и подтвердите действие. После этого endpoint исчезает из списка, а его публичный URL навсегда перестаёт принимать webhook-запросы. Для интеграций доступен общий API жизненного цикла туннелей DELETE /api/tunnels?id=<tunnel_id>; отдельный DELETE /api/webhook-inboxes не поддерживается.
  • Трафик inbox и лимиты тарифа. Входящие запросы на публичный URL inbox не расходуют те же лимиты HTTP RPM и исходящего трафика, что обычный прокси-туннель; это не отменяет общие правила тарифа для остального трафика аккаунта.
  • Гостевые и закрытые туннели. Публичный URL inbox доступен внешним провайдерам без входа на платформу и не блокируется теми же правилами гостевого доступа, что приватные туннели.
  • Захват в инспекторе. Размер и полнота тела запроса зависят от настроек инспектора HTTP-трафика и тарифа; при ошибке подготовки захвата провайдер всё равно получает HTTP 200, в событии может быть тег capture_error.
  • Заголовки при удалённой пересылке. На внешний HTTPS-эндпоинт не пересылаются служебные hop-by-hop заголовки; в ответ провайдеру из upstream передаётся ограниченный набор безопасных заголовков.
  • Снятие возможности с тарифа. Если у владельца inbox больше нет webhook-inbox, публичный URL отвечает 404 Not Found; API создания и изменения также возвращает отказ.
  • Панель дашборда. Секция Webhook inbox скрыта, если возможность webhook-inbox недоступна на тарифе, даже если старые записи существуют в системе.
  • Пауза туннеля и пауза доставки — разные действия. Пауза доставки на странице endpoint продолжает принимать вебхуки и отвечает провайдеру 200. Приостановка endpoint в списке туннелей или истечение его срока жизни полностью останавливает приём: провайдер получает 503 или 410 и может начать повторные отправки по своим правилам.
  • Вход по прямой ссылке. Если открыть /dashboard/webhook-inbox без входа, сервис откроет форму входа на главной странице, а после входа вернёт на страницу endpoint. Для других разделов дашборда после входа открывается список туннелей.