Исходящие webhook
Если канал входящих webhook принимает внешние события для обработки, то исходящие webhook делают обратное: они уведомляют ваши системы, когда в betool происходит значимое событие.
Зачем
У вас, вероятно, уже есть:
- Система оповещений (PagerDuty, Opsgenie, Slack).
- ITSM-инструмент (Jira, ServiceNow) для управления тикетами.
- Кастомный дашборд, агрегирующий состояние ваших операций.
Вместо того чтобы заставлять эти системы опрашивать API betool, подпишите их на исходящие webhook: они получают уведомление мгновенно, как только что-то происходит.
Настройка
- Администрирование → Исходящие webhook → Новая подписка.
- Выберите:
- Целевой URL — эндпоинт, который будет получать POST-запросы.
- События для прослушивания — см. список ниже.
- HMAC-секрет — генерируется автоматически; используйте его на стороне вашего приёмника для проверки подписей.
- (Опционально) Фильтры — ограничение выполнениями конкретного pipeline, уровнем серьёзности и т. д.
Доступные события
| Событие | Когда срабатывает |
|---|---|
execution.failed | Выполнение pipeline завершилось неудачей |
execution.requires_human | Узел confirmation ожидает проверки |
execution.cost_threshold | Выполнение превысило порог стоимости |
billing.low_balance | Баланс кредитов опустился ниже заданного порога |
billing.out_of_credits | Баланс равен нулю (активны отказы до вызова) |
audit.cross_tenant_read | Внешний agent прочитал контент этой организации |
webhook.delivery_failed | Предыдущий исходящий webhook не удался 3 раза |
Формат POST
POST /your/endpoint HTTP/1.1
Content-Type: application/json
X-Betool-Event: execution.failed
X-Betool-Signature: sha256=...
X-Betool-Delivery: dlv_01HXYZ...
{
"event": "execution.failed",
"delivered_at": "2026-05-24T10:42:13Z",
"org_id": "org_...",
"data": {
"execution_id": "exec_...",
"pipeline_id": "pip_...",
"pipeline_name": "support email triage",
"failed_node": "agent: classifier",
"error_kind": "llm_timeout",
"error_message": "Provider responded after 30s timeout"
}
}
HMAC-подпись
Заголовок X-Betool-Signature содержит sha256=<hmac>, где hmac = HMAC-SHA256(secret, body). Проверяйте его при получении, чтобы убедиться, что запрос действительно исходит от betool:
import hmac, hashlib
def verify(body: bytes, signature: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(),
body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
Повторные попытки и идемпотентность
- Если ваш эндпоинт отвечает 2xx, событие помечается как доставленное.
- При ответе не-2xx или тайм-ауте betool повторяет попытку с экспоненциальной задержкой (1 мин, 5 мин, 30 мин, 2 ч, 12 ч, 24 ч — максимум 6 попыток).
- После 6 неудач событие помечается как dead-letter, и генерируется
webhook.delivery_failed(для ваших других активных подписок).
Каждый POST несёт уникальный идентификатор X-Betool-Delivery. Если ваш эндпоинт получает одну и ту же доставку дважды (граничный случай сети), обрабатывайте её идемпотентно.
Безопасность
- Требуется HTTPS — подписки на обычный HTTP отклоняются.
- Ротируемый секрет — вы можете перегенерировать секрет в любой момент; POST-запросы «в полёте», использующие старый секрет, всё ещё будут приниматься до истечения срока (5 мин).
- Исходные IP — betool публикует свои исходящие IP на status.betool.fr, чтобы вы могли добавить их в allow-list на вашем межсетевом экране.