Перейти к содержанию

Webhooks

Отправляйте события жизненного цикла сессий из Expecto на ваш URL в момент, когда они происходят. Webhooks подходят, чтобы запускать последующие BI- конвейеры, кидать оповещения в Slack/Teams при упавшей сессии или передавать экспортированный пакет в свои системы без постоянного опроса.

Что нужно

Роль owner или admin в организации. Каждый endpoint принадлежит одной организации и, опционально, одному проекту в ней.

Что доставляется

Для каждой сессии в организации Expecto эмитит webhook на каждом переходе жизненного цикла:

Событие Когда срабатывает
session.created Создана новая сессия
session.uploaded Загружен файл для сессии
session.parsed Парсинг завершён без ошибок
session.transformed Трансформация завершена без ошибок
session.checked Бизнес-правила прошли без ошибок
session.confirmed Отправитель подтвердил данные
session.approved Финальная апрува дана (только в режиме dual — single пропускает этот шаг)
session.exported Экспортный пакет сгенерирован и загружен
session.failed Упала стадия пайплайна (parse, transform или check). В payload — stage и reason.
webhook.ping Синтетическое тестовое событие по запросу

Payload не содержит download URL для экспортного пакета — потребители скачивают его авторизованно через API со своим API key. Событие экспорта несёт имя пакета и список артефактов с sha256, row_count и size_bytes для каждого файла.

Где найти

Открой Settings → Webhooks. Вкладка показывает все видимые endpoint'ы и кнопку Create Webhook.

Settings → Webhooks tab в пустом состоянии

Создание endpoint'а

Нажми Create Webhook. В диалоге три поля:

  • Name — человекочитаемое название, чтобы различать endpoint'ы в списке и в логе доставок.
  • URL — куда Expecto будет POST'ить события. Только https://. Приватные, loopback, link-local и cloud-metadata IP-диапазоны отвергаются на этапе создания (SSRF-защита). Dev-override (webhook_allow_http) доступен только операторам инстанса Expecto, не в UI.
  • Event types — минимум одно. События сгруппированы по неймспейсу (напр. session.*) в дерево: отмечай отдельные события, переключай всю группу её чекбоксом или используй Select all / Clear. Выбор можно поменять позже через Edit.

Диалог создания с заполненными name, URL и checkbox'ами событий

После Create Expecto покажет подписной ключ ровно один раз в модалке. Скопируй его сейчас — это единственный момент, когда виден ключ в открытом виде. Expecto хранит зашифрованную форму и после этого показывает только префикс whsec_…. Если потеряешь — ротируй ключ и обнови потребителя.

Список endpoint'ов

Каждая строка показывает URL, подписанные события, префикс ключа и badges состояния:

  • Disabled — endpoint на паузе; новые события не доставляются.
  • Auto-disabled — Expecto отключил endpoint после 10 подряд dead-letter доставок (см. Обработка ошибок).

Список endpoint'ов с одним созданным

Outbound-биндинги в том же списке

Кроме webhook-endpoint'ов список показывает outbound-биндинги организации — правила уровня проекта, которые пишут события сессий прямо во внешнюю платформу через интеграционное подключение (сегодня — Salesforce). Карточка биндинга несёт бейдж Outbound binding и тип адаптера, вместо URL показывает подключение → цель (объект Salesforce), подписанные события, проект-владелец и один из бейджей состояния:

  • Active — события доставляются.
  • Inactive — биндинг на паузе.
  • Auto-disabled — Expecto поставил биндинг на паузу после серии dead-letter-доставок подряд; счётчик показан рядом с бейджем.

Биндинги редактируются в проекте, а не здесь: открой Project › Context › Outbound Bindings (действие Open in project ведёт туда). Show deliveries на карточке открывает тот же лог доставок, что и у endpoint'ов; колонка Result заполняется из ответа внешней системы.

Меню Actions

У каждой карточки endpoint'а справа есть меню Actions ▾. Пункты:

Раскрытое Actions меню на карточке endpoint'а

  • Edit — изменить имя, URL, подписанные события или кастомный auth-заголовок endpoint'а. Открывает диалог, предзаполненный текущими значениями.
  • Show deliveries / Hide deliveries — разворачивает таблицу лога доставок inline (см. ниже).
  • Send ping — отправляет синтетическое webhook.ping envelope на endpoint. Используй после создания endpoint'а, чтобы убедиться, что потребитель достижим и корректно проверяет подпись.
  • Rotate secret — генерирует новый подписной ключ, шифрует и сохраняет, показывает его в открытом виде ровно один раз в той же reveal-one модалке. Предыдущий ключ перестаёт приниматься в момент подтверждения ротации — обновляй потребителя в один шаг, иначе будут ошибки проверки подписи.
  • Disable / Enable — пауза/возобновление доставок. Пауза не удаляет endpoint и историю; ожидающие ретраи просто останавливаются.
  • Delete — удаляет endpoint и историю доставок. Необратимо.

Лог доставок

Выбери Show deliveries, чтобы увидеть последние 50 доставок к endpoint'у, начиная с самой свежей.

Лог доставок с одним успешным webhook.ping

Колонки:

  • Event — тип события (например session.exported, webhook.ping).
  • Status — pending, in_progress, succeeded или failed.
  • Attempts — текущая попытка из максимума (по умолчанию 6).
  • Code — последний HTTP-статус, который вернул твой endpoint.
  • Result — что вернулось: для успешной доставки outbound-биндинга — id записи, созданной во внешней системе (например, id записи Salesforce), для неудачной — фрагмент ошибки (полный текст по наведению), для ожидающего ретрая — время следующей попытки.
  • When — время последней попытки.
  • Actions — кнопка Replay (см. ниже).

Replay доставки

Replay переотправляет тот же payload, но генерирует новый webhook-id и перепподписывает body, чтобы проверка подписи всё ещё прошла. Используй, если потребитель пропустил доставку или нужно переслать что-то, что попало в failed после починки приёмника. Новая доставка связана с оригиналом — твоя целевая система может дедуплицировать по исходному event id, если нужна exactly-once семантика, или обрабатывать replay как свежее событие.

Обработка ошибок

Если потребитель возвращает что-то вне 2xx, Expecto делает retry с экспоненциальным backoff (по умолчанию: база 30 с, cap 1 ч, 6 попыток всего) и per-delivery jitter, чтобы retry'и с разных endpoint'ов не синхронизировались.

Когда у доставки закончились попытки, она уходит в dead-letter, а счётчик consecutive_failures endpoint'а увеличивается. После 10 подряд dead-letter доставок endpoint автоматически отключается — Expecto ставит disabled_reason = "consecutive_failures" и перестаёт эмитить новые события.

Чтобы вернуть auto-disabled endpoint, почини потребителя и нажми Enable в Actions меню. Счётчик сбрасывается, и Expecto начинает эмитить новые события сразу, как они появляются (события, которые уже ушли в dead-letter, автоматически не реэмитятся — нажми Replay вручную, если нужны).

Одной успешной доставки достаточно, чтобы сбросить счётчик — нестабильный потребитель, который чинится в пределах девяти ошибок, не дотянет до auto-disable.

Скоупинг endpoint'а на проект

Endpoint'ы без проекта — org-level: получают каждое подходящее событие сессий организации, независимо от проекта сессии. Endpoint'ы, привязанные к проекту, получают только события сессий этого проекта. Используй project-scope, когда у разных команд разные BI- потребители, или когда контрактору не нужно видеть сессии других проектов.

Project scope ставится программно (через API или MCP) — в текущем UI- диалоге он не открыт. Фильтр в списке endpoint'ов уважает твой проектный доступ — контракторы видят только endpoint'ы своих проектов.

Кастомный auth header

Некоторые приёмники стоят за reverse proxy или API Gateway, который требует от отправителя (нас) авторизоваться — например Authorization: Bearer <token> против OAuth2-прокси или X-API-Key: <key> против собственного шлюза. В диалоге создания поставь галочку Add a custom auth header, чтобы добавить такой заголовок. Введи имя (например Authorization) и значение (Bearer eyJ…); значение шифруется тем же Fernet-ключом, что и подписной секрет, и расшифровывается только в момент отправки запроса.

Значение заголовка — write-only: после сохранения UI показывает только имя, но не значение. Чтобы ротировать значение, открой endpoint на редактирование и введи новое; чтобы полностью убрать заголовок — через API (UI для очистки будет в следующей итерации).

Это дополняет, не заменяет HMAC-подпись. Подпись аутентифицирует отправителя (Expecto). Кастомный заголовок позволяет твоей инфраструктуре решить — принимать ли запрос вообще.

Безопасность и проверка подписи

Каждый request на твой URL несёт три заголовка:

  • webhook-id — UUID этой доставки. Стабилен на retry; меняется на replay.
  • webhook-timestamp — Unix-секунды на момент подписания.
  • webhook-signature — v1,<base64-HMAC-SHA256> от webhook-id.timestamp.body.

Проверяй, пересчитывая HMAC с подписным ключом endpoint'а и сравнивая constant-time. Отвергай request старше 5 минут (webhook_signature_tolerance_seconds).

Примеры проверки на Python и Node и полное описание envelope — в референсе разработчика For Developers → Webhooks.