tgpay cryptoAPI
crypto-payapiwebhookssignature

API-Referenz: Webhooks

4 Min. LesezeitAktualisiert 2. Nov. 2026

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:00.123456Z",
  "payload": { … }
}

update_id bleibt über alle erneuten Zustellungen desselben Ereignisses stabil – nutze es als Schlüssel für deine Deduplizierung. request_date (UTC, ISO 8601 mit Mikrosekunden) 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 Seiten der Methoden: Rechnungen, Überweisungen und Schecks, Abos).

Ereignistypen

update_typeWird ausgelöst, wennPayload
invoice_paideine Rechnung bezahlt wird – keine gesonderte Aktivierung nötigRechnungsobjekt
invoice_expiredeine Rechnung unbezahlt ihre Frist überschreitetRechnungsobjekt
check_activatedein Scheck oder der Anteil eines Empfängers eingelöst wirdScheckobjekt; bei einer Empfängerliste zusätzlich activated_slot
check_expiredein Scheck mit Empfängerliste abläuft und nicht eingelöste Anteile zur App zurückkehrenScheckobjekt mit status: "expired", recipients und deren claimed_at-Werten
transfer_completedeine Überweisung abgeschlossen oder eine On-Chain-Auszahlung bestätigt wirdÜberweisungs- oder Auszahlungsobjekt
transfer_returnedeine 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_completedeine Rückerstattung ausgeführt wirdRechnungsobjekt mit den refunded_*-Feldern
subscription_activatedein Nutzer einem Plan zustimmtAbo-Objekt
subscription_chargeddie Zahlung für einen Zeitraum eingezogen wird – charge.kind sagt, welcher: initial, renewal oder resubscribeAbo-Objekt + charge: {period_no, kind, asset, amount, fee, paid_at}
subscription_cancelledein Abo von einer der beiden Seiten gekündigt wirdAbo-Objekt
subscription_expireddie Kulanzfrist unbezahlt abläuftAbo-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. kind gibt es nur in dieser Variante: Der Payload einer gewöhnlichen Überweisung hat gar kein Feld kind. Behandle einen Payload mit kind: "withdrawal" also als Auszahlung und einen ohne kind als Überweisung. 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 als erfolgreich, wenn innerhalb von 10 Sekunden eine 2xx-Antwort eintrifft. Antworte zügig und verarbeite längere Aufgaben separat. Weiterleitungen werden nicht verfolgt: Ein 3xx zählt als Fehler, hinterlege also die endgültige URL.
  • Ein Fehlerstatus, Timeout oder Verbindungsfehler führt zu Wiederholungen: bis zu 17 Versuche, der Abstand beginnt bei 10 Sekunden und verdoppelt sich bis auf 8 Stunden (mit etwas Zufallsstreuung), insgesamt etwa 3 Tage. Die Zustellung ist nicht garantiert; gleiche Zahlungen nach einem Ausfall mit getInvoices ab.
  • Jeder Versuch geht an die Webhook-URL, die in diesem Moment gespeichert ist: Eine geänderte URL erhält die ausstehenden Wiederholungen, wird die URL entfernt, entfallen sie.
  • 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.