Вебхуки

Уведомления о статусах

При смене статуса платежа, выплаты или подписки Cashera отправляет POST-запрос на ваш callback_url

Как это работает

  • Событие приходит POST-запросом на callback_url (платежа/выплаты или из настроек мерчанта)
  • Тело - JSON с типом события и объектом
  • Запрос содержит заголовки X-Api-Key и X-Secret - обязательно проверяйте их подлинность
  • Ответьте 2xx. Иначе доставка повторяется
Требования к callback_url

URL должен использовать HTTPS (порт 443) и указывать на публичный хост. Адреса вида localhost, *.local, *.internal и приватные IP отклоняются. Вебхуки уходят, только если в кабинете включены уведомления и задан секрет мерчанта.

Заголовки и аутентификация

Каждый вебхук содержит статические заголовки с вашими учётными данными:

ПолеТипОписание
Content-Typestringapplication/json
X-Api-KeystringПубличный ключ мерчанта (pk_…)
X-SecretstringСекрет мерчанта (sk_…). Сравните со своим сохранённым секретом
Не логируйте X-Secret

Сравнивайте X-Api-Key и X-Secret с вашими значениями в постоянном времени и никогда не пишите секрет в логи, APM или трекеры ошибок. Подробно - на странице проверки подлинности.

Событие transaction.status_updated

{
"event": "transaction.status_updated",
"transaction": {
"uuid": "9b1f2c4e-7a01-4b9d-8f1c-2eab57d90c11",
"external_id": "order-10428",
"status": "paid",
"type": "deposit",
"amount": 49900,
"gross_amount": 49900,
"net_amount": 48403,
"currency": "RUB",
"payment_method": "sbp",
"paid_at": "2026-06-02T18:11:42+00:00"
}
}

Событие payout.status_updated

{
"event": "payout.status_updated",
"payout": {
"uuid": "7c2e5b91-0a44-4d12-9f3a-1be64c0d2255",
"external_id": "withdraw-001",
"status": "completed",
"amount": 2500000,
"currency": "RUB",
"destination": { "type": "card", "number": "2200000000000000" },
"metadata": null,
"failure_reason": null,
"completed_at": "2026-06-02T18:34:11+00:00",
"failed_at": null
}
}

Событие subscription.status_updated

При изменении состояния рекуррентной подписки приходит отдельное событие. Значения поля status описаны в справочнике статусов подписки.

{
"event": "subscription.status_updated",
"subscription": {
"uuid": "31dc7faa-c380-4ec7-a258-3202a2211e76",
"external_id": "subscription-pro-10428",
"status": "active",
"amount": 10000,
"gross_amount": 10000,
"net_amount": 9500,
"currency": "RUB",
"interval": "monthly",
"next_charge_at": "2026-09-24T13:02:00+00:00",
"last_charge_at": "2026-08-24T13:02:00+00:00",
"activated_at": "2026-08-24T13:01:00+00:00",
"cancelled_at": null,
"failed_at": null
}
}

Событие рекуррентного списания

Каждое списание приходит стандартным событием transaction.status_updated. Отличительный признак - payment_method = sbp_recurring и дополнительный объект subscription в корне payload.

{
"event": "transaction.status_updated",
"transaction": {
"uuid": "ace5700c-839a-4b95-92a5-e93132c0b32e",
"external_id": "recurring.31dc7faa-c380-4ec7-a258-3202a2211e76.20d8754b-b834-4940-826c-65f07fe29d21",
"status": "paid",
"type": "deposit",
"amount": 10000,
"gross_amount": 10000,
"net_amount": 9500,
"currency": "RUB",
"payment_method": "sbp_recurring",
"paid_at": "2026-08-24T13:02:00+00:00"
},
"subscription": {
"uuid": "31dc7faa-c380-4ec7-a258-3202a2211e76",
"external_id": "subscription-pro-10428"
}
}

Событие webhook.test

Когда в кабинете мерчант нажимает «тест вебхука», Cashera отправляет на тот жеcallback_url с теми же заголовками X-Api-Key и X-Secret проверочное событие webhook.test. Оно служит только для проверки доставки и не относится ни к одному заказу.

{
"event": "webhook.test",
"test": {
"sent_at": "2026-06-02T18:00:00+00:00"
}
}
Допускайте неизвестные события

Не отклоняйте вебхук по жёсткому списку разрешённых типов. Обрабатывайте интересующие вас события (transaction.status_updated, payout.status_updated,subscription.status_updated), а на неизвестные и наwebhook.test просто отвечайте 2xx - список событий может расширяться.

Доставка и повторы

  • Вебхук отправляется только при реальной смене статуса (дубли провайдера не пересылаются)
  • При неуспехе доставка повторяется до 3 раз с интервалом около 5 минут
  • Ответ 4xx считается ошибкой конфигурации - повторов не будет, доставка фиксируется как неуспешная
  • Ответы 5xx и сетевые сбои - повторяются

Если доставка так и не удалась, состояние всегда можно получить запросом. По платежам - статус транзакции или поиск по external_id. По выплатам - статус выплаты, если вы сохранили uuid при создании, либо история выплат за нужный период, если не сохранили. По подпискам - получение состояния и история списаний.

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

Эндпоинт должен быть идемпотентным: один и тот же статус может прийти повторно. Используйте ключuuid + status (для платежей - transaction.uuid + transaction.status, для выплат -payout.uuid + payout.status, для подписок -subscription.uuid + subscription.status) и пропускайте уже обработанные события, возвращая 200.

Что считать подтверждением

Заказ оплачен только при transaction.status = paid; выплата исполнена только приpayout.status = completed. Перед зачислением сверяйте сумму и валюту с вашими данными.