tgpay cryptoAPI
crypto-payapiwebhookssignature

Referência da API: webhooks

4 min de leituraAtualizado em 9 de out. de 2026

Os webhooks enviam eventos ao seu servidor depois que eles acontecem. Defina a URL de webhook (opcional) do seu app em Mais → API para comerciantes; a plataforma então faz POST de um corpo JSON assinado para cada evento que você assinou.

O envelope

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

O update_id é estável entre as reentregas do mesmo evento — baseie sua deduplicação nele. O request_date registra a data e a hora de cada tentativa de entrega. O payload é o objeto completo daquele tipo de evento: o objeto de fatura nos eventos de fatura, o objeto de cheque, de transferência ou de assinatura (os formatos estão nas páginas de referência de cada um).

Tipos de evento

update_typeQuando disparaPayload
invoice_paiduma fatura é paga — não exige ativação separadaobjeto de fatura
invoice_expireduma fatura passa do prazo sem ser pagaobjeto de fatura
check_activatedum cheque ou a parte de um destinatário é resgatadaobjeto de cheque; no resgate de uma lista de destinatários, inclui também activated_slot
check_expiredum cheque com lista de destinatários expira e as partes não resgatadas voltam ao appobjeto de cheque com recipients e seus valores de claimed_at
transfer_completeduma transferência é concluída ou um pagamento on-chain é confirmadoobjeto de transferência ou de saque
transfer_returneduma transferência pendente não recebida volta ao app, ou um pagamento on-chain falha e o valor reservado é devolvidoobjeto de transferência ou de saque
refund_completedum reembolso é executadoobjeto de fatura com os campos refunded_*
subscription_activatedum usuário aprova um planoobjeto de assinatura
subscription_chargedum período é cobrado — o charge.kind diz qual: initial, renewal ou resubscribeobjeto de assinatura + charge: {period_no, kind, asset, amount, fee, paid_at}
subscription_cancelleduma assinatura é cancelada por qualquer um dos ladosobjeto de assinatura
subscription_expiredo período de carência acaba sem pagamentoobjeto de assinatura

Pagamentos on-chain criados no app usam esses mesmos eventos de transferência. O payload tem kind: "withdrawal", campos da blockchain como network, address e txid, e status completed ou failed. Seu transfer_id pertence a uma sequência de IDs separada; diferencie os payloads por kind antes de usá-lo. A referência OpenAPI para download descreve as duas variantes.

Tudo, menos o invoice_paid, é opcional (uma extensão sobre o Crypto Bot — um consumidor estritamente no formato do Crypto Bot nunca encontra um update_type desconhecido, a não ser que você peça). Ative por app, em Eventos extras de webhook, na seção Webhook do app. As opções usam os identificadores da tabela acima. Salve uma URL de webhook para receber os eventos.

Verificando a assinatura

Toda entrega traz o cabeçalho TgPayCrypto-API-Signature (TgCryptoPay-API-Signature e Crypto-Pay-API-Signature são aliases de compatibilidade com o mesmo valor): o HMAC-SHA256 em hexadecimal do corpo bruto da requisição, com chave igual ao digest SHA-256 do token de API principal do seu app. É o esquema do Crypto Bot, então o código de verificação existente funciona sem mudança:

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

Verifique sobre os bytes brutos recebidos — interpretar o JSON e serializá-lo novamente pode alterar os bytes e fazer a verificação falhar. Só o token principal assina; os tokens restritos nunca assinam. Rotacionar o token principal troca a chave da assinatura de webhook na hora, então atualize o segredo no seu servidor ao mesmo tempo.

Entrega e novas tentativas

  • Uma entrega conta como bem-sucedida quando uma resposta 2xx chega antes do timeout. Responda rapidamente e processe tarefas demoradas separadamente.
  • Um status de erro, timeout ou falha de conexão provoca novas tentativas com intervalos crescentes, até o limite de tentativas da plataforma. A entrega não é garantida; use getInvoices para conferir os pagamentos após uma indisponibilidade.
  • Depois da última tentativa, a entrega é descartada. A URL de webhook em si nunca é desativada automaticamente — um endpoint instável não cancela a inscrição do seu app em silêncio.
  • Como as novas tentativas acontecem, seu handler precisa ser idempotente: deduplique pelo update_id antes de agir.

⚠️ Verifique antes de entregar

Qualquer um pode fazer POST na sua URL de webhook. Até a checagem de assinatura passar, trate o corpo como entrada não confiável: não envie um pedido, não credite um usuário, não marque nada como pago. A ordem segura é: verificar a assinatura → deduplicar pelo update_id → agir.