Skip to main content
Jede Anfrage, die wir an Ihren Server senden — Webhook-Zustellungen und Aufrufe von Tool-Endpunkten — enthält eine HMAC-SHA256-Signatur im Header X-ThunderPhone-Signature. Implementieren Sie die Verifizierung einmal korrekt und verwenden Sie denselben Helfer in jedem Handler.

Der Algorithmus

  1. Lesen Sie den rohen Anfragetextkörper — die exakten Bytes, die wir per POST an Sie gesendet haben.
  2. Berechnen Sie hmac_sha256(secret, body).hexdigest().
  3. Vergleichen Sie die Signatur in konstanter Zeit mit X-ThunderPhone-Signature. (Ein naiver Stringvergleich gibt Timing-Informationen preis.)
Wir signieren exakt die Bytes, die wir übertragen. Daher funktioniert die Verifizierung des rohen Textkörpers immer. Diese Bytes sind außerdem die kanonische JSON-Serialisierung der Nutzlast — alphabetisch sortierte Schlüssel, kompakte Trennzeichen (, und : ohne Leerzeichen), UTF-8. Das bietet Ihnen eine zweite, vollständig gleichwertige Methode, wenn Ihr Framework nur geparstes JSON bereitstellt: Serialisieren Sie kanonisch erneut und berechnen Sie dafür den HMAC.
Bevorzugen Sie den rohen Textkörper — das ist ein Schritt weniger und immun gegen Eigenheiten beim JSON-Zahlen-Roundtrip in einigen Sprachen.

Welches Secret?

Speichern Sie das Secret in Ihrem Secret Manager oder einer Umgebungsvariable — committen Sie es niemals.

Referenzimplementierungen

Alle vier verifizieren den rohen Anfragetextkörper:

Framework-spezifische Anbindung

Tool-Aufrufe verifizieren

Wenn der Agent eines Ihrer Funktionstools direkt aufruft (das Tool verfügt über einen endpoint), enthält die Anfrage neben Ihren konfigurierten endpoint.headers zwei ThunderPhone-Header:
  • X-ThunderPhone-Call-ID — die numerische ID des aktiven Anrufs.
  • X-ThunderPhone-Signature — HMAC-SHA256 mit Ihrem organisationsweiten Webhook-Secret als Schlüssel über die exakten Request-Body-Bytes.
Dieselbe Hilfsfunktion verify() funktioniert unverändert, mit zwei Besonderheiten:
  1. GET- / DELETE-Tools haben keinen Body. Argumente werden als Query- Parameter übertragen, und die Signatur wird über die leere Byte- Zeichenfolge berechnet — also verify(b"", sig, secret) (Python) oder verify(Buffer.alloc(0), sig, secret) (Node). Hashen Sie nicht die Query-Zeichenfolge.
  2. Organisationen ohne konfigurierten Legacy-Webhook haben kein Organisations-Secret. In diesem Fall enthalten Tool-Aufrufe nur X-ThunderPhone-Call-ID und keinen Signatur-Header. Konfigurieren Sie den Legacy-Webhook (PUT /v1/webhook), um ein Signatur-Secret zu erhalten, oder authentifizieren Sie Tool-Aufrufe über einen eigenen Header via endpoint.headers.
Der Tool-Versand im Webhook-Modus (Tools ohne endpoint, die über Ihren Organisations-Webhook als telephony.tool / web.tool übermittelt werden) ist ein gewöhnlicher signierter Webhook — das oben beschriebene Standardverfahren gilt. Informationen zu beiden Anfrageformaten finden Sie unter Funktionstools.

Häufige Fallstricke

Das Parsen des Bodys und erneute Ausgeben mit den Standardeinstellungen Ihrer JSON-Bibliothek (Leerzeichen nach , / :, in Einfügereihenfolge angeordnete Schlüssel) erzeugt andere Bytes und beschädigt den HMAC. Prüfen Sie den Roh-Body — oder falls Sie ihn erneut serialisieren müssen, entsprechen Sie exakt unserem kanonischen Format: sortierte Schlüssel, kompakte Trennzeichen, UTF-8.
Die Middleware express.json() von Express verbraucht den Body-Stream, wodurch Sie die Rohbytes verlieren. Verwenden Sie gezielt express.raw() für die Webhook-Route, oder puffern Sie den Roh-Body in einer vorgeschalteten Middleware. Dasselbe gilt für NestJS / Koa — lesen Sie deren Dokumentation zum „raw body“.
expected === signature in JS oder expected == signature in Python sind Vergleiche mit variabler Laufzeit. Verwenden Sie jeweils crypto.timingSafeEqual oder hmac.compare_digest. Der Leistungsunterschied ist vernachlässigbar.
Direkte Aufrufe von Tool-Endpunkten werden mit dem Webhook-Secret auf Organisationsebene (GET /v1/webhook) signiert — nicht mit einem Endpunkt-spezifischen Secret aus /v1/developer/webhook-endpoints. Verwenden Sie dieselbe Funktion verify() erneut, stellen Sie jedoch sicher, dass Sie ihr auf Tool-Routen das Organisations-Secret übergeben.
Bei Tool-Methoden ohne Body umfasst die Signatur den leeren Byte-String, wodurch ein universelles Verfahren erhalten bleibt: Bilden Sie den HMAC über den Roh-Request-Body, unabhängig davon, was er enthält. Das Hashing der URL oder des Query-Strings wird niemals übereinstimmen.
Die Rückgabe von 200 bei fehlgeschlagener Verifizierung macht den Handler zu einem Ziel für Replay-Angriffe. Antworten Sie immer mit einem Nicht-2xx-Status, wenn die Verifizierung fehlschlägt.

Nächste Schritte

Webhook-Übersicht

Zustellsemantik, Wiederholungsversuche, Quell-IP-Adressen.

Webhook-Endpunkte

Verwalten Sie mehrere URLs, rotieren Sie Secrets.

Function Tools

Die beiden Pfade für Tool-Aufrufe und ihre Request-Formate.

Tool-Integrationen

Erstellen Sie eine vollständige Tool-gestützte Integration von Anfang bis Ende.