tgpay cryptoAPI
crypto-payapiwebhookssignature

Riferimento API: webhook

3 min di letturaAggiornata il 11 ago 2026

I webhook inviano gli eventi al tuo server nel momento in cui succedono. Imposta l’URL del webhook sulla tua app in Altro → Merchant API: da lì in poi la piattaforma manda in POST un corpo JSON firmato per ogni evento a cui sei iscritto.

La busta

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

update_id resta lo stesso a ogni riconsegna dello stesso evento: usa quello per deduplicare. request_date viene registrato a ogni tentativo di consegna. payload è l’oggetto completo del tipo di evento: l’oggetto fattura per gli eventi delle fatture, l’oggetto buono o l’oggetto abbonamento (le loro forme stanno nelle rispettive pagine di riferimento).

I tipi di evento

update_typeQuando partePayload
invoice_paiduna fattura viene pagata — consegnato sempreoggetto fattura
invoice_expireduna fattura supera la scadenza senza essere pagataoggetto fattura
check_activateduno dei tuoi buoni viene riscattatooggetto buono
refund_completedun rimborso viene eseguitooggetto fattura con i campi refunded_*
subscription_activatedun utente approva un pianooggetto abbonamento
subscription_chargedun periodo viene fatturato — charge.kind dice quale: initial, renewal o resubscribeoggetto abbonamento + charge: {period_no, kind, asset, amount, fee, paid_at}
subscription_cancelledun abbonamento viene disdetto da una delle due partioggetto abbonamento
subscription_expiredil periodo di tolleranza finisce senza pagamentooggetto abbonamento

Tutto tranne invoice_paid è facoltativo (è un’estensione rispetto a Crypto Bot: un consumatore fatto esattamente sulla forma di Crypto Bot non incontra mai un update_type sconosciuto, a meno che tu non l’abbia chiesto). Si attivano per app sotto Eventi webhook aggiuntivi, sulla schermata Merchant API: le opzioni compaiono una volta impostato un URL e portano gli identificativi grezzi della tabella qui sopra.

Verificare la firma

Ogni consegna porta l’intestazione TgPayCrypto-API-Signature (Crypto-Pay-API-Signature ne è un alias di compatibilità, con lo stesso valore): l’HMAC-SHA256 in esadecimale del corpo grezzo della richiesta, con chiave il digest SHA-256 del token API principale della tua app. È lo schema di Crypto Bot, quindi il codice di verifica che hai già funziona senza modifiche:

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 sui byte grezzi ricevuti: un JSON riserializzato dopo il parsing può differire byte per byte e far fallire il controllo. A firmare è solo il token principale; i token con permessi limitati non firmano mai. Rigenerare il token principale cambia all’istante la chiave di firma dei webhook, quindi aggiorna il segreto sul tuo server nello stesso momento.

Consegne e tentativi

  • Una consegna si considera riuscita con qualsiasi risposta 2xx entro 10 secondi.
  • Qualsiasi altra cosa — uno stato di errore, un timeout, una connessione caduta — viene ritentata con attese crescenti: il primo tentativo dopo circa 10 secondi, poi l’intervallo raddoppia fino a 8 ore, per un massimo di 17 tentativi distribuiti su circa 3 giorni.
  • Dopo l’ultimo tentativo la consegna viene lasciata perdere. L’URL del webhook, però, non viene mai disattivato da solo: un endpoint ballerino non ti disiscrive l’app in silenzio.
  • Siccome i tentativi si ripetono, il tuo gestore dev’essere idempotente: deduplica su update_id prima di agire.

⚠️ Verifica prima di evadere

Al tuo URL può mandare un POST chiunque. Finché il controllo della firma non passa, tratta il corpo come input non fidato: non spedire un ordine, non accreditare un utente, non segnare niente come pagato. L’ordine giusto è: verifica la firma → deduplica su update_id → agisci.