APERGREXДокументация
Разделы

Вебхуки

Push-события биллинга и задач с подписью HMAC-SHA256.

Вебхуки

Вебхуки — push-уведомления о событиях биллинга и задач. Регистрируйте HTTPS-эндпоинт, подписывайтесь на типы событий — и получайте POST-запросы с подписью HMAC-SHA256.

Быстрый старт

# зарегистрировать эндпоинт (секрет показывается один раз!)
curl -X POST -H "X-API-Key: $FRANKLAB_KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/franklab-hook","eventTypes":["billing.settled","task.succeeded"]}' \
  https://apergrex.ru/franklab/api/v1/webhooks/endpoints

# тестовая доставка
curl -X POST -H "X-API-Key: $FRANKLAB_KEY" \
  https://apergrex.ru/franklab/api/v1/webhooks/endpoints/<id>/test

Типы событий

СобытиеКогда
billing.settledподтверждено списание (с финальной суммой)
billing.refundedвозврат резерва при неудаче задачи
billing.topup.confirmedзачислено пополнение
billing.low_balanceбаланс ниже 1 000 ₣ (не чаще раза в 24 ч)
billing.invoice.status_changedсчёт юрлица сменил статус/оплачен
task.succeeded / task.failed / task.refundedтерминальный статус задачи генерации
webhook.testтестовое событие (по команде)

Формат доставки

Заголовки:

X-Franklab-Event: billing.settled
X-Franklab-Event-Id: <uuid события — ключ идемпотентности>
X-Franklab-Timestamp: <unix-секунды>
X-Franklab-Signature: sha256=<HMAC-SHA256(secret, "{timestamp}.{body}")>

Тело — общий конверт:

{
  "eventId": "…",
  "eventType": "billing.settled",
  "occurredAt": "2026-09-04T12:00:00.000Z",
  "partnerId": "…",
  "schemaVersion": 1,
  "data": { "transactionId": "…", "amountFranks": 84 }
}

Проверка подписи

const expected = crypto.createHmac('sha256', secret)
  .update(`${timestamp}.${rawBody}`)
  .digest('hex');
// сравните с X-Franklab-Signature (без префикса sha256=) и проверите,
// что timestamp не старше ~5 минут (анти-replay)

Гарантии доставки

  • At-least-once: дубликаты возможны — идемпотентируйте по eventId.
  • Дубликаты возможны и после рестарта поллера — надёжный ключ дедупликации: eventType + data.transactionId / data.taskId / data.invoiceId.
  • Задержка — до минуты (поллер).
  • Повторы при неудаче: 1 мин → 5 мин → 30 мин → 2 ч → 6 ч, затем dead-letter (виден в GET /v1/webhooks/deliveries?status=dead_lettered).
  • Статус uncertain — запрос отправлен, но исход неизвестен: такие доставки не повторяются автоматически — повторите их через POST /v1/webhooks/deliveries/{id}/replay.
  • Отвечайте 2xx быстро; таймаут — 10 секунд.

Управление

ОперацияЭндпоинт
СписокGET /v1/webhooks/endpoints
РегистрацияPOST /v1/webhooks/endpoints
УдалениеDELETE /v1/webhooks/endpoints/{id}
Ротация секретаPOST /v1/webhooks/endpoints/{id}/rotate-secret
ТестPOST /v1/webhooks/endpoints/{id}/test
История доставокGET /v1/webhooks/deliveries?endpointId=…&status=…
Повтор доставкиPOST /v1/webhooks/deliveries/{id}/replay

Ограничения: до 10 эндпоинтов на партнёра; URL — только публичный HTTPS (внутренние адреса и IP-литералы отклоняются); редиректы не следуются.

Для AI-агентов/docs/webhooks.md