Вебхуки

POST на ваш адрес по событиям клиентов: подпись, ретраи, журнал доставок.

Мы шлём POST на ваш эндпоинт, когда что-то происходит у ваших клиентов. Настраивается в кабинете: раздел «Вебхуки».

События

СобытиеКогда
account.createdвы завели клиента — через API или свою витрину
account.suspendedклиент отключён
account.restoredклиент включён обратно
payment.succeededподтверждённый платёж вашего клиента
payment.refundedвозврат или чарджбэк по такому платежу

Подписка — набор из этого списка. Событие вне списка при регистрации отклоняется с ошибкой: опечатка в payment.suceeded должна упасть сразу, а не превратиться в подписку, которая никогда не сработает.

Отдельно есть webhook.test — его нельзя подписать, он приходит только по кнопке «Тестовое событие» в кабинете.

Тело

POST <ваш url>
Content-Type: application/json
X-Logrus-Event: payment.succeeded
X-Logrus-Delivery: 6f1d...
X-Logrus-Idempotency-Key: payment.succeeded:6b0c...
X-Logrus-Signature: sha256=<hex>

{
  "event": "payment.succeeded",
  "idempotency_key": "payment.succeeded:6b0c...",
  "created_at": "2026-09-01T10:00:00Z",
  "data": {
    "payment_id": "6b0c...",
    "account_id": "9a1e...",
    "subscription_id": "2f77...",
    "plan_code": "base",
    "amount_cents": 29900,
    "currency": "RUB",
    "status": "succeeded",
    "occurred_at": "2026-09-01T10:00:00Z"
  }
}

amount_cents всегда в минорных единицах своей валюты, и currency всегда рядом. Никогда не читайте сумму без валюты.

Для account.* блок data содержит account_id, email, external_ref, status.

Подпись

X-Logrus-Signature — это sha256= плюс HMAC-SHA256 сырого тела запроса, в нижнем регистре hex, на секрете вашего эндпоинта. Секрет показывается один раз при создании и при смене.

Проверяйте до того, как что-то делать с событием, и сравнивайте константным по времени сравнением:

import hmac, hashlib

def verify(secret: str, raw_body: bytes, header: str) -> bool:
    mac = hmac.new(secret.encode(), raw_body, hashlib.sha256)
    return hmac.compare_digest("sha256=" + mac.hexdigest(), header)

Хешируйте именно те байты, которые получили. Если фреймворк сначала распарсил JSON, а вы сериализуете его обратно — подпись не сойдётся, и виноват будет не наш HMAC.

Идемпотентность

idempotency_key стабилен для факта, а не для попытки: ретраи и повторная отправка того же события несут тот же ключ. Сохраняйте его и пропускайте дубли — так двойного начисления не будет даже при повторе.

Ретраи

Считается успехом любой ответ 2xx. Иначе:

  • 5xx, таймаут, обрыв — повторяем: 1, 2, 4, 8, 16, 32, 64, 128 минут, восемь попыток, чуть больше четырёх часов суммарно. Дальше доставка помечается dead.
  • 4xx (кроме 408 и 429) — не повторяем. Такой ответ значит, что эндпоинт нас понял и отказал; за четыре часа это не изменится.
  • 408 и 429 повторяются как временные.

Отвечайте быстро: на ответ даётся 10 секунд. Кладите событие в свою очередь и отвечайте 200, а разбирайте потом.

Автоотключение

После 20 неудачных доставок подряд эндпоинт выключается, с причиной, видимой в кабинете. Починили — включите обратно, счётчик обнулится.

Журнал

В кабинете, под списком эндпоинтов: событие, статус, число попыток, HTTP-код ответа и время следующей попытки. Он же — единственный способ увидеть нашу сторону разговора, не спрашивая нас.

Чего вебхук не заменяет

Уведомление может опоздать или (после восьми неудач) не прийти. Если для вас важна сверка — читайте метрики и выплаты периодически. Вебхуки быстрые, опрос надёжный; серьёзные интеграции делают и то и другое.