API-Referenz: Webhooks
Webhooks schicken Ereignisse an deinen Server, nachdem sie eingetreten sind. Trage unter Mehr → Händler-API im Feld Webhook-URL (optional) die URL deiner App ein; die Plattform sendet dann für jedes Ereignis, das du abonniert hast, per POST einen signierten JSON-Body.
Nachrichtenformat
{
"update_id": 123,
"update_type": "invoice_paid",
"request_date": "2026-08-11T12:00:00Z",
"payload": { … }
}
update_id bleibt über alle erneuten Zustellungen desselben Ereignisses
stabil – nutze es als Schlüssel für deine Deduplizierung. request_date wird
pro Zustellversuch gesetzt. payload ist das vollständige Objekt zum
jeweiligen Ereignistyp: das Rechnungsobjekt bei Rechnungsereignissen, das
Scheckobjekt, das Überweisungsobjekt oder das Abo-Objekt (die Formate stehen auf den jeweiligen
Referenzseiten).
Ereignistypen
update_type | Wird ausgelöst, wenn | Payload |
|---|---|---|
invoice_paid | eine Rechnung bezahlt wird – keine gesonderte Aktivierung nötig | Rechnungsobjekt |
invoice_expired | eine Rechnung unbezahlt ihre Frist überschreitet | Rechnungsobjekt |
check_activated | ein Scheck oder der Anteil eines Empfängers eingelöst wird | Scheckobjekt; bei einer Empfängerliste zusätzlich activated_slot |
check_expired | ein Scheck mit Empfängerliste abläuft und nicht eingelöste Anteile zur App zurückkehren | Scheckobjekt mit recipients und deren claimed_at-Werten |
transfer_completed | eine Überweisung abgeschlossen oder eine On-Chain-Auszahlung bestätigt wird | Überweisungs- oder Auszahlungsobjekt |
transfer_returned | eine nicht eingelöste ausstehende Überweisung zur App zurückkehrt oder eine On-Chain-Auszahlung fehlschlägt und der einbehaltene Betrag zurückgegeben wird | Überweisungs- oder Auszahlungsobjekt |
refund_completed | eine Rückerstattung ausgeführt wird | Rechnungsobjekt mit den refunded_*-Feldern |
subscription_activated | ein Nutzer einem Plan zustimmt | Abo-Objekt |
subscription_charged | die Zahlung für einen Zeitraum eingezogen wird – charge.kind sagt, welcher: initial, renewal oder resubscribe | Abo-Objekt + charge: {period_no, kind, asset, amount, fee, paid_at} |
subscription_cancelled | ein Abo von einer der beiden Seiten gekündigt wird | Abo-Objekt |
subscription_expired | die Kulanzfrist unbezahlt abläuft | Abo-Objekt |
In der App erstellte On-Chain-Auszahlungen verwenden dieselben
Überweisungsereignisse. Ihr Payload enthält kind: "withdrawal",
Blockchain-Felder wie network, address und txid sowie den Status
completed oder failed. Ihre transfer_id gehört zu einer separaten
ID-Folge. Unterscheide deshalb anhand von kind, bevor du die ID verwendest.
Die herunterladbare OpenAPI-Referenz beschreibt beide Payload-Varianten.
Alles außer invoice_paid ist optional zuschaltbar (eine Erweiterung
gegenüber Crypto Bot – ein streng auf Crypto Bot zugeschnittener Empfänger
begegnet nie einem unbekannten update_type, solange du ihn nicht angefordert
hast). Schalte sie pro App unter Zusätzliche Webhook-Events im Bereich
Webhook zu. Die Schalter tragen die Bezeichner aus der Tabelle oben. Speichere
eine Webhook-URL, damit Ereignisse zugestellt werden können.
Die Signatur prüfen
Jede Zustellung trägt den Header TgPayCrypto-API-Signature
(TgCryptoPay-API-Signature und Crypto-Pay-API-Signature gelten als
Kompatibilitäts-Alias mit demselben Wert):
den HMAC-SHA256 des rohen Anfrage-Bodys in Hex, mit dem SHA-256-Digest des
Haupt-API-Tokens deiner App als Schlüssel. Es ist das Verfahren von
Crypto Bot, bestehender Prüfcode funktioniert also unverändert:
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"])
Berechne die Signatur aus den roh empfangenen Bytes – eine neu serialisierte Fassung kann sich Byte für Byte unterscheiden und die Prüfung scheitern lassen. Nur der Haupt-Token signiert; eingeschränkte Token tun das nie. Den Haupt-Token zu erneuern wechselt sofort den Schlüssel der Webhook-Signatur – aktualisiere das Geheimnis auf deinem Server also im selben Zug.
Zustellung und Wiederholungen
- Eine Zustellung gilt bei einer 2xx-Antwort vor Ablauf des Zustellversuchs als erfolgreich. Antworte zügig und verarbeite längere Aufgaben separat.
- Ein Fehlerstatus, Timeout oder Verbindungsfehler führt zu Wiederholungen
mit wachsenden Abständen, bis zum Versuchslimit der Plattform. Die
Zustellung ist nicht garantiert; gleiche Zahlungen nach einem Ausfall mit
getInvoicesab. - Nach dem letzten Versuch wird die Zustellung verworfen. Die Webhook-URL selbst wird nie automatisch deaktiviert – ein unzuverlässiger Endpunkt meldet deine App nicht stillschweigend ab.
- Weil es Wiederholungen gibt, muss dein Handler idempotent sein:
dedupliziere anhand von
update_id, bevor du handelst.
⚠️ Prüfe, bevor du lieferst
Jeder kann per POST an deine Webhook-URL senden. Solange die Signaturprüfung
nicht bestanden ist, behandle den Body als nicht vertrauenswürdige Eingabe:
Versende keine Bestellung, schreibe keinem Nutzer etwas gut, markiere nichts
als bezahlt. Die sichere Reihenfolge ist: Signatur prüfen → anhand von
update_id deduplizieren → handeln.
War dieser Artikel hilfreich?
Danke für dein Feedback.