tgpay cryptoAPI
crypto-payapiwebhookssignature

Referencia de la API: webhooks

4 min de lecturaActualizado el 9 oct 2026

Los webhooks envían eventos a tu servidor después de que ocurren. Pon la URL del webhook (opcional) en tu app, en Más → API para comerciantes; a partir de ahí la plataforma hace POST de un cuerpo JSON firmado por cada evento al que estés suscrito.

La estructura del mensaje

{
  "update_id": 123,
  "update_type": "invoice_paid",
  "request_date": "2026-08-11T12:00:00Z",
  "payload": { … }
}

update_id se mantiene estable entre reenvíos del mismo evento: basa tu deduplicación en él. request_date se registra en cada intento de entrega. payload es el objeto completo del tipo de evento: el objeto de factura para los eventos de facturas, el objeto de cheque, de transferencia o de suscripción (las estructuras están en las páginas de referencia correspondientes).

Tipos de eventos

update_typeSe dispara cuandoPayload
invoice_paidse paga una factura — no requiere activación adicionalobjeto de factura
invoice_expireduna factura pasa su fecha límite sin pagarseobjeto de factura
check_activatedse canjea un cheque o la parte de un destinatarioobjeto de cheque; el canje de una parte de un cheque con lista de destinatarios también incluye activated_slot
check_expiredexpira un cheque con lista de destinatarios y las partes sin canjear se devuelven a la appobjeto de cheque con recipients y sus valores claimed_at
transfer_completedse completa una transferencia o se confirma un pago on-chainobjeto de transferencia o de retiro
transfer_returneduna transferencia pendiente sin reclamar se devuelve a la app, o un pago on-chain falla y se libera el monto retenidoobjeto de transferencia o de retiro
refund_completedse ejecuta un reembolsoobjeto de factura con los campos refunded_*
subscription_activatedun usuario aprueba un planobjeto de suscripción
subscription_chargedse cobra un período — charge.kind dice cuál: initial, renewal o resubscribeobjeto de suscripción + charge: {period_no, kind, asset, amount, fee, paid_at}
subscription_cancelleduna suscripción se cancela por cualquiera de los dos ladosobjeto de suscripción
subscription_expiredel período de gracia se agota sin pagoobjeto de suscripción

Los pagos on-chain creados en la app usan estos mismos eventos de transferencia. Su payload incluye kind: "withdrawal", campos de la blockchain como network, address y txid, y el estado completed o failed. Su transfer_id pertenece a una secuencia de ID independiente; distingue los payloads por kind antes de usarlo. La referencia OpenAPI descargable describe ambas variantes.

Todo salvo invoice_paid es opcional (una extensión sobre Crypto Bot: una integración que solo admite los eventos de Crypto Bot no recibe un update_type desconocido a menos que lo actives). Actívalos por app en Eventos de webhook adicionales, dentro de la sección Webhook de la app. Los interruptores usan los identificadores de la tabla anterior. Guarda una URL de webhook para recibir los eventos.

Verificar la firma

Cada entrega lleva la cabecera TgPayCrypto-API-Signature (TgCryptoPay-API-Signature y Crypto-Pay-API-Signature son alias de compatibilidad con el mismo valor): el HMAC-SHA256 en hexadecimal del cuerpo original de la petición, sin modificar, con clave el resumen SHA-256 del token de API principal de tu app. Es el esquema de Crypto Bot, así que el código de verificación que ya tengas funciona sin cambios:

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"])

Verifica sobre los bytes originales recibidos: si analizas el JSON y vuelves a serializarlo, los bytes pueden cambiar y hacer fallar la comprobación. Solo firma el token principal; los tokens restringidos nunca firman. Renovar el token principal vuelve a fijar al instante la clave de firma de los webhooks, así que actualiza el secreto en tu servidor al mismo tiempo.

Entrega y reintentos

  • Una entrega se considera exitosa si recibe una respuesta 2xx antes de agotar el tiempo de espera. Responde pronto y procesa las tareas largas por separado.
  • Un estado de error, un tiempo de espera agotado o un fallo de conexión provoca reintentos con intervalos cada vez mayores, hasta el límite de intentos de la plataforma. La entrega no está garantizada; usa getInvoices para comprobar los pagos después de una interrupción del servicio.
  • Después del último intento se descarta la entrega. La URL del webhook no se desactiva automáticamente: los fallos de un endpoint no cancelan la suscripción a los eventos.
  • Como hay reintentos, tu manejador tiene que ser idempotente: deduplica por update_id antes de actuar.

⚠️ Verifica antes de despachar

Cualquiera puede hacer POST a tu URL de webhook. Hasta que la comprobación de la firma pase, trata el cuerpo como entrada no confiable: no despaches un pedido, no le acredites nada a un usuario, no marques nada como pagado. El orden seguro es: verificar la firma → deduplicar por update_id → actuar.