Tổng Kho eSIM
Ausgehende Webhooks · 8 Ereignisse

Webhooks

URL mit POST /v1/webhooks registrieren und mit PUT /v1/webhooks/{id} ändern. CHECK_HEALTH muss bei Erstellung 2xx liefern. Ereignisse werden mit einem eigenen, vom API-Schlüssel getrennten Geheimnis signiert.

REST bleibt die maßgebliche Quelle. Fehlende Ereignisse lassen sich mit GET /v1/orders?updated_since=… abgleichen. Planen Sie diesen Abgleich ein.

webhook-events.de.json

Ereigniskatalog

event_typeAuslöserWichtige Datenfelder
order.completedBestellung bestätigt, eSIMs bereit
order_idexternal_refitems[] (order_item_id, iccid)
order.failedBestellung nicht abgeschlossen (Bereitstellung fehlgeschlagen usw.)
order_idexternal_refreason
esim.deliveredEine eSIM wurde mit Installationsdaten bereitgestellt

Zuordnung über `order_id` und `external_ref`. `lpa` wird erst unmittelbar vor POST entschlüsselt und nie im Zustellprotokoll unverschlüsselt gespeichert. Keine QR-Bild-URL: QR aus `lpa` erzeugen oder `qr_code_base64` über `GET /v1/esims/{id}` abrufen.

order_item_idorder_idexternal_reficcidlpa
esim.activatedDie eSIM wurde installiert und aktiviert (smdp enabled/in_use)

Mit `order_id` und `external_ref` (Ihrer beim Kauf gesendeten Referenz) ordnen Sie die eSIM Ihrer Bestellung zu.

order_item_idorder_idexternal_reficcidactivated_at
esim.usage_thresholdVerbrauch hat 75 % / 90 % erreicht

Ordnen Sie die eSIM mit `order_id` und `external_ref` zu. Nur die höchste neu überschrittene Schwelle wird gemeldet (0→95 % sendet nur 90). `threshold` bedeutet mindestens diese Schwelle überschritten.

order_item_idorder_idexternal_refthreshold (75/90)used_bytesdata_bytes
esim.expiring3 Tage / 1 Tag vor Ablauf

Mit `order_id` und `external_ref` (Ihrer beim Kauf gesendeten Referenz) ordnen Sie die eSIM Ihrer Bestellung zu.

order_item_idorder_idexternal_refdays_remaining (3/1)expires_at
wallet.low_balanceWallet hat die Warnschwelle von 25 % / 10 % erreicht

`threshold` ist ein Prozentwert (25/10), nur bei bekannter Prozentzahl enthalten, sonst weggelassen (`balance` selbst vergleichen). Kein VND-Betrag unter `threshold`.

threshold (25/10)balancecurrency
catalog.updatedKatalog geändert: Paket hinzugefügt, geändert, ausgeblendet, Basispreis geändert oder ausverkauft

Keine Preise enthalten, da sie je Organisation variieren. Rufen Sie `GET /v1/catalog/packages` ab. Änderungen im kurzen Zeitfenster (Standard 10 Minuten) werden in einem `changes[]`-Webhook zusammengefasst, je Paket einmal. Hunderte synchronisierte Pakete erzeugen nicht Hunderte Webhooks. Gilt im Test- und Livebetrieb.

changes[] (package_code, change: price|availability|package, occurred_at)change_count
json
{
  "event_id": "018f3c00-0000-7000-8000-0000000000c1",
  "event_type": "ping",
  "occurred_at": "2026-07-11T07:29:00Z",
  "is_testmode": true,
  "data": {
    "message": "TongKho eSIM webhook health check"
  }
}

Payload und Signatur-Header

Alle Webhooks nutzen dieselbe Hülle. Signatur `HMAC-SHA256(webhook_secret, timestamp\nraw_body)` in `X-TKE-Webhook-Signature` (Hex-Kleinbuchstaben). Im 24-Stunden-Rotationsfenster zusätzlich `X-TKE-Webhook-Signature-Old`. Mindestens einmal zugestellt; anhand `event_id` deduplizieren.

json
{
  "event_id": "018f3c00-0000-7000-8000-0000000000b0",
  "event_type": "order.completed",
  "occurred_at": "2026-07-11T07:30:00Z",
  "is_testmode": false,
  "data": {
    "order_id": "018f2b00-0000-7000-8000-00000000009a",
    "external_ref": "partner-cart-9931",
    "items": [
      {
        "order_item_id": "018f2b00-0000-7000-8000-000000000001",
        "iccid": "8984012345678901234"
      }
    ]
  }
}
FeldBeschreibung
dataNutzlast je Ereignistyp (siehe unten).
event_idStabile, je Ereignis eindeutige UUID (Deduplizierung).
event_typeEreignistyp.
is_testmodetrue bei Erzeugung durch einen Testschlüssel.
occurred_atISO-8601 UTC.

Katalogabgleich: catalog.updated

Bei neuen, geänderten, verborgenen Tarifen, Basispreis- oder Bestandsänderung. Änderungen stehen gesammelt in changes[] : Hunderte Änderungen ergeben eine einzige Zustellung je Endpunkt.

json
{
  "event_id": "018f3c00-0000-7000-8000-0000000000c1",
  "event_type": "catalog.updated",
  "occurred_at": "2026-07-11T08:10:00Z",
  "is_testmode": false,
  "data": {
    "changes": [
      {
        "package_code": "THAY-BANG-MA-GOI-CUA-BAN",
        "change": "price",
        "occurred_at": "2026-07-11T08:02:11Z"
      },
      {
        "package_code": "VN_10GB_30D",
        "change": "availability",
        "occurred_at": "2026-07-11T08:04:52Z"
      },
      {
        "package_code": "JP_3GB_7D",
        "change": "package",
        "occurred_at": "2026-07-11T08:09:30Z"
      }
    ],
    "change_count": 3
  }
}
Keine Preise: beabsichtigt

Verkaufspreise sind organisationsabhängig . Ein einheitlicher Preis wäre falsch und vertraulich. Das Ereignis ist ein Auslöser : Rufen Sie GET /v1/catalog/packages?market=… zum Aktualisieren Ihrer Preise auf.

change akzeptiert drei Werte: price (Basispreis geändert), availability (auf Lager/ausverkauft), package (neu/geändert/verborgen). Auch unbekannte Werte als Anlass zum Abgleich behandeln.

Signatur, Wiederholung und Deduplizierung per event_id folgen Standardereignissen, in Test und Live getrennt nach is_testmode.

Webhook-Signaturen prüfen

X-TKE-Signature enthält HMAC-SHA256 aus webhook_secret und den rohen Body-Bytes.

text
signing_string = timestamp + "\n" + raw_body   # timestamp = header X-TKE-Webhook-Timestamp
signature      = HMAC_SHA256(webhook_secret, signing_string)   → hex lowercase

# Zeitfenster (±300 s) gegen Replay prüfen.
# Exakte empfangene Bytes signieren, JSON nicht erneut serialisieren.

Wiederholungsstrategie

1 phút→5 phút→30 phút→2 giờ→6 giờ

Bei Nicht-2xx oder 5 s Timeout: exponentielle Wiederholungen über 24 giờ: 1 phút → 5 phút → 30 phút → 2 giờ → 6 giờ.

4 wichtige Webhook-Regeln

1. Asynchron verarbeiten und sofort 200 senden
Payload einreihen und 200 in unter 1 Sekunde zurückgeben. Keine aufwendige Verarbeitung; Timeout nach 5 Sekunden.
2. Idempotenz und Deduplizierung
Mindestens einmalige Zustellung: mit event_id oder data.order_id / data.order_item_id deduplizieren.
3. Live und Test trennen
Die Konfiguration gilt pro Schlüssel. Getrennte URLs verhindern Testdaten in Produktionsdatenbanken.
4. Regelmäßiger REST-Abgleich
Lange Ausfälle können Ereignisse verlieren. Regelmäßig GET /v1/orders?updated_since=… zum Abgleich abrufen.

Hinweise zu Feldern

esim.delivered.lpa wird unmittelbar vor POST entschlüsselt, nicht im Klartext gespeichert. QR aus LPA oder GET /v1/esims/{id} erzeugen.

esim.usage_threshold: sendet nur die höchste neu überschrittene Schwelle (0→95 %: threshold=90).

wallet.low_balance.threshold ist ein Prozentsatz (25/10), kein VND-Betrag.

catalog.updated enthält keine Preise oder Bestandsdetails, nur Tarifcode und Änderungstyp.