Справочник API: вебхуки
Вебхуки доставляют события на ваш сервер в момент, когда они происходят. Задайте приложению Webhook URL в разделе Ещё → Merchant API — и платформа будет отправлять POST с подписанным JSON-телом на каждое событие, на которое вы подписаны.
Конверт
{
"update_id": 123,
"update_type": "invoice_paid",
"request_date": "2026-08-11T12:00:00Z",
"payload": { … }
}
update_id не меняется между повторными доставками одного события —
стройте дедупликацию на нём. request_date проставляется при каждой
попытке доставки. payload — полный объект для типа события: объект
счёта для событий счетов, объект чека или объект подписки (их состав — на
страницах справочника).
Типы событий
update_type | Когда отправляется | Payload |
|---|---|---|
invoice_paid | счёт оплачен — доставляется всегда | объект счёта |
invoice_expired | срок счёта истёк без оплаты | объект счёта |
check_activated | один из ваших чеков активирован | объект чека |
refund_completed | выполнен возврат | объект счёта с полями refunded_* |
subscription_activated | пользователь подтвердил план | объект подписки |
subscription_charged | списан период — какой именно, говорит charge.kind: initial, renewal или resubscribe | объект подписки + charge: {period_no, kind, asset, amount, fee, paid_at} |
subscription_cancelled | подписка отменена любой из сторон | объект подписки |
subscription_expired | льготный период истёк без оплаты | объект подписки |
Всё, кроме invoice_paid, включается по желанию (расширение над
Crypto Bot — обработчик, написанный строго под Crypto Bot, никогда не
встретит незнакомый update_type, если вы сами его не включили).
Включаются события на карточке приложения на экране Merchant API, в
блоке Дополнительные webhook-события: тумблеры появляются после того,
как задан Webhook URL, и названы теми же идентификаторами, что в таблице
выше.
Проверка подписи
В каждой доставке есть заголовок TgPayCrypto-API-Signature
(прежнее TgCryptoPay-API-Signature и Crypto-Pay-API-Signature — псевдонимы для совместимости, значение то
же): hex-значение HMAC-SHA256 от сырого тела запроса с ключом —
SHA-256-дайджестом основного API-токена приложения. Это схема
Crypto Bot, так что существующий код проверки работает без изменений:
import hashlib, hmac
secret = hashlib.sha256(API_TOKEN.encode()).digest()
expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, headers["TgPayCrypto-API-Signature"])
Проверяйте по сырым полученным байтам — если разобрать JSON и сериализовать его заново, байты могут отличаться, и проверка не пройдёт. Подписывает только основной токен; ограниченные токены — никогда. Обновление основного токена мгновенно меняет ключ подписи — обновите секрет на своём сервере одновременно с ним.
Доставка и повторы
- Доставка считается успешной при любом ответе 2xx в пределах 10 секунд.
- Всё остальное — статус ошибки, таймаут, обрыв соединения — повторяется с экспоненциальной задержкой: первый повтор примерно через 10 секунд, интервал удваивается до 8 часов, всего до 17 попыток на протяжении примерно 3 дней.
- После последней попытки доставка отбрасывается. Сам Webhook URL никогда не отключается автоматически — нестабильный сервер не отпишет ваше приложение от событий незаметно для вас.
- Поскольку доставки повторяются, обработчик
обязан быть идемпотентным: дедуплицируйте по
update_id, прежде чем действовать.
⚠️ Сначала проверка — потом выполнение
Отправить POST на ваш Webhook URL может кто угодно. Пока проверка
подписи не прошла, считайте тело запроса недоверенными данными: не
отгружайте заказ, ничего не начисляйте пользователю, ничего не помечайте
оплаченным.
Безопасный порядок: проверить подпись → дедуплицировать по update_id
→ действовать.
Была ли статья полезной?
Спасибо за отзыв.