Отримувати події Slen

Що несе доставка вебхука, як перевірити її підпис, коли її надсилають знову і про що повідомляє кожна родина подій.

6 хв читання

Вебхук надсилає події Slen на адресу вашого сервісу в міру того, як вони стаються: узято холд, бюджет майже витрачено, виклик закінчився, виконання чекає на рішення. Ця стаття — про те, що приходить на цю адресу і як це читати. Вебхуки додають і змінюють у консолі — стаття Вебхуки показує як.

Що несе доставка

Доставка — це POST із тілом JSON і заголовком Content-Type: application/json. Тіло — це подія.

JSON
{
  "id": "74443412671954944",
  "type": "operation.uncertain",
  "created_at": "2026-10-02T09:13:04+00:00",
  "data": {
    "reservation_id": "74442097331195904",
    "project_id": "74438200973594624",
    "operation_code": "generate_email",
    "external_user_id": "user_8421",
    "model": "gpt-4o-mini",
    "reason": "operation_uncertain",
    "hold_expires_at": "2026-10-02T09:27:04+00:00"
  }
}
  • id називає подію. Кожен вебхук, який чує подію, отримує той самий id.

  • type — ім’я події, а data несе те, про що подія: id, суми, статуси. Він ніколи не несе промпт або відповідь моделі.

  • created_at — мить, коли подія сталася, а не мить доставки.

Перевірте підпис

Кожну доставку підписано секретом вебхука, який показують один раз під час створення вебхука. Підпис іде в заголовку доставки поруч із типом її тіла:

HTTP
POST /webhooks/slen HTTP/1.1
Content-Type: application/json
Slen-Signature: t=1759396384,v1=5f0c8e2a…

t — час підпису в секундах від 1970 року, а v1 — підпис.

1. Зберіть підписаний текст

З’єднайте значення t, крапку й тіло точно в тому вигляді, у якому воно прийшло, байт у байт. Не розбирайте тіло й не записуйте його заново перед цим.

2. Обчисліть підпис

Обчисліть HMAC-SHA256 цього тексту із секретом у ролі ключа, записаний малими шістнадцятковими цифрами.

Terminal
printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$SECRET"

3. Порівняйте

Порівняйте результат зі значенням v1 за сталий час. Відхиліть доставку, підпис якої відрізняється, і доставку, чиє t далеке від вашого годинника, — це стара доставка, яку хтось надіслав знову.

Коли доставку надсилають знову

  • Ваш сервіс відповідає 2xx, щоб прийняти доставку. Відповідайте одразу, а роботу робіть потім: Slen чекає на відповідь 10 секунд, якщо сервіс не налаштовано інакше.

  • Відповідь 400, 401, 403, 404, 410 або 422 завершує доставку: її не надсилають знову.

  • Будь-яка інша відповідь — переспрямування, 408, 429, 5xx — або відсутність відповіді вчасно вважається збоєм, і доставку надсилають знову пізніше. Пауза починається з 30 секунд і щоразу подвоюється, до години. Після 12 спроб від доставки відмовляються. Це значення сервісу за замовчуванням.

  • Доставки йдуть раз на хвилину.

Та сама подія може прийти більше одного разу, а дві події можуть прийти не у своєму порядку. Зберігайте id кожної обробленої події й пропускайте ту, яку вже бачили.

Які вебхуки чують подію

Вебхук чує події, на які його підписано.

  • Вебхук одного проєкту чує події цього проєкту.

  • Вебхук усіх проєктів чує події кожного проєкту організації й події, які не стосуються жодного проєкту: кожне connection.cooldown_started і події підключення, бюджету чи сповіщення всієї організації.

  • Вимкнений вебхук нічого не чує. Доставка, яка вже на нього чекає, усе одно надсилається.

Події

Це події, які надсилає Slen. Форма консолі пропонує частину з них; будь-яку з них можна назвати через API.

ОбʼєктПодії
reservation
  • reservation.created

    A hold was taken

  • reservation.captured

    A hold was captured

  • reservation.released

    A hold was released

  • reservation.expired

    A hold expired

  • reservation.overrun

    A capture came out above its hold

budget
  • budget.threshold_reached

    A budget crossed a threshold

  • budget.exceeded

    A budget reached its limit

operation
  • operation.authorized

    A gateway call was authorized

  • operation.denied

    A gateway call was refused

  • operation.started

    A gateway call went out

  • operation.completed

    A gateway call completed

  • operation.failed

    A gateway call failed

  • operation.uncertain

    A gateway call has no known outcome

flow
  • flow.published

    A flow version was published

  • flow.rolled_back

    A flow was rolled back

connection
  • connection.cooldown_started

    A provider connection cooled down

  • connection.health_changed

    A provider connection changed health

approval
  • approval.requested

    An execution waits for an approval

  • approval.decided

    An approval got its verdict

execution
  • execution.finished

    A flow execution reached its final status

alert
  • alert.opened

    An alert rule fired

  • alert.resolved

    An alert cleared

overrun
  • overrun.decided

    An overrun was decided

customer
  • customer.balance_low

    An end customer's credits ran low

ledger
  • ledger.degraded

    The ledger went degraded

  • ledger.restored

    The ledger is back

РодинаПро що повідомляють її події
reservation.Холд узято, списано, звільнено або він сплив; reservation.overrun — списання виявилося більшим за холд
operation.Виклик моделі у флоу: холд, який він узяв (operation.authorized), відмова бюджету, політики чи блокування клієнта до виклику (operation.denied), початок виклику в провайдера і його кінець — operation.completed, operation.failed або operation.uncertain
budget.Холд довів використання бюджету до 50 % або 80 % його ліміту (budget.threshold_reached) або до всього ліміту (budget.exceeded)
flow.Опубліковано версію флоу, або флоу відкотили до ранішої версії
execution.Виконання закінчилося, з його status і error_code (execution.finished)
approval.Виконання чекає на рішення (approval.requested), і саме рішення: схвалено, відхилено або строк минув (approval.decided)
overrun.Вузол моделі виявив, що виклик коштуватиме більше за свій холд, і його політика перевитрати вирішила, що робити (overrun.decided)
connection.Підключення провайдера на якийсь час виведено з роботи (connection.cooldown_started), або змінився його status (connection.health_changed)
alert.Сповіщення відкрилося або розв’язалося
customer.Доступні клієнтові кредити опустилися нижче рівня, заданого для його рахунку (customer.balance_low)
ledger.Slen почав пропускати виклики без свого реєстру (ledger.degraded), і цей час закінчився (ledger.restored)

Бюджет повідомляє про кожен рівень не частіше одного разу за вікно — стаття Бюджети каже коли. Сповіщення повідомляє про своє відкриття й розв’язання, а не про кожне оновлення, — Сповіщення.

Події виклику моделі

Події родин reservation. і operation., а також overrun.decided, приходять від викликів моделі у флоу. Кінець виклику моделі — одна з трьох подій, і кожна каже про гроші своє.

  • operation.completed — провайдер відповів.

  • operation.failed — виклик не відбувся, і його холд повернули. Один виняток: виклик, який провайдер виконував у фоні й чий холд закрило інше списання, поки він чекав, закінчується з reason, що дорівнює background_hold_expired. Нічого не повертається, і провайдер усе ще може виставити рахунок за виклик.

  • operation.uncertain — ніхто не знає, чим закінчився виклик: втрачено відповідь вузла моделі, провайдер не відповів на початок фонового виклику, або про фоновий виклик більше не можна було запитати. Холд лишається до hold_expires_at, бо провайдерові могли заплатити. Не повторюйте такий виклик, наче він не вдався, — стаття Коли результат невідомий каже, що робити.

Виклик, який провайдер виконує у фоні, повідомляє про свій початок, як будь-який виклик, а про свій кінець — коли він настає, однією з трьох подій.

Що читати далі

  • Вебхуки — додайте вебхук, виберіть його події й збережіть його секрет.

  • Коли результат невідомий — що робити з викликом, який закінчився зі статусом uncertain.

  • Погодження — вирішіть долю виконання, про яке повідомило approval.requested.

  • Операції — запис виклику моделі, про який повідомляють події родини operation..

  • Вебхуки — перевірте підпис доставки й прочитайте її подію в SDK.

Зібрано з openapi b070e1f, sdk contract 5cc7055, php ae4a53b, node 84bc62d