API-Referenz: Webhooks
Webhooks schicken Ereignisse in dem Moment an deinen Server, in dem sie passieren. Lege die Webhook-URL deiner App unter Mehr → Händler-API fest; die Plattform sendet dann für jedes Ereignis, das du abonniert hast, per POST einen signierten JSON-Body.
Die Hülle
{
"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 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 – wird immer zugestellt | Rechnungsobjekt |
invoice_expired | eine Rechnung unbezahlt ihre Frist überschreitet | Rechnungsobjekt |
check_activated | einer deiner Schecks eingelöst wird | Scheckobjekt |
refund_completed | eine Rückerstattung ausgeführt wird | Rechnungsobjekt mit den refunded_*-Feldern |
subscription_activated | ein Nutzer einem Plan zustimmt | Abo-Objekt |
subscription_charged | ein Zeitraum abgerechnet 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 |
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 auf dem
Bildschirm Händler-API zu – die Schalter erscheinen, sobald eine Webhook-URL
gesetzt ist, und sie sind mit den rohen Bezeichnern aus der Tabelle oben
beschriftet.
Die Signatur prüfen
Jede Zustellung trägt den Header TgCryptoPay-API-Signature
(Crypto-Pay-API-Signature ist ein 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["TgCryptoPay-API-Signature"])
Prüfe über die 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 jeder 2xx-Antwort innerhalb von 10 Sekunden als erfolgreich.
- Alles andere – ein Fehlerstatus, ein Timeout, ein Verbindungsfehler – wird mit exponentiell wachsenden Abständen wiederholt: der erste Versuch nach etwa 10 Sekunden, der Abstand verdoppelt sich bis auf 8 Stunden, insgesamt bis zu 17 Versuche über rund 3 Tage verteilt.
- 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.