Skip to main content
Elk verzoek dat we naar je server sturen — webhookleveringen en aanroepen van tool-eindpoints — bevat een HMAC-SHA256-handtekening in de header X-ThunderPhone-Signature. Implementeer de verificatie één keer correct en gebruik dezelfde helper in elke handler.

Het algoritme

  1. Lees de onbewerkte requestbody — de exacte bytes die we naar je POSTen.
  2. Bereken hmac_sha256(secret, body).hexdigest().
  3. Vergelijk in constante tijd met X-ThunderPhone-Signature. (Een naïeve tekenreeksvergelijking lekt timinginformatie.)
We ondertekenen exact de bytes die we verzenden, dus het verifiëren van de onbewerkte body werkt altijd. Die bytes zijn ook de canonieke JSON-serialisatie van de payload — sleutels alfabetisch gesorteerd, compacte scheidingstekens (, en : zonder spaties), UTF-8. Dit biedt je een tweede, volledig gelijkwaardige aanpak wanneer je framework alleen geparseerde JSON beschikbaar maakt: serialiseer canoniek opnieuw en bereken daarover de HMAC.
Geef de voorkeur aan de onbewerkte body — dat is één stap minder en voorkomt problemen met JSON-getallen die in sommige talen opnieuw worden omgezet.

Welk secret?

Sla het secret op in je secretmanager of omgevingsvariabele — commit het nooit.

Referentie-implementaties

Alle vier verifiëren de onbewerkte requestbody:

Frameworkspecifieke integratie

Toolaanroepen verifiëren

Wanneer de spraakagent rechtstreeks een van je functietools aanroept (de tool heeft een endpoint), bevat het verzoek naast je geconfigureerde endpoint.headers twee ThunderPhone-headers:
  • X-ThunderPhone-Call-ID — de numerieke id van het actieve gesprek.
  • X-ThunderPhone-Signature — HMAC-SHA256, met je webhookgeheim op organisatieniveau als sleutel, over de exacte bytes van de aanvraagbody.
Dezelfde verify()-helper werkt ongewijzigd, met twee nuances:
  1. GET- / DELETE-tools hebben geen body. Argumenten worden als queryparameters doorgegeven en de handtekening wordt berekend over de lege bytestring — dus verify(b"", sig, secret) (Python) of verify(Buffer.alloc(0), sig, secret) (Node). Hash de querystring niet.
  2. Organisaties zonder geconfigureerde verouderde webhook hebben geen organisatiegeheim. In dat geval bevatten toolaanroepen alleen X-ThunderPhone-Call-ID en geen handtekeningheader. Configureer de verouderde webhook (PUT /v1/webhook) om een ondertekeningsgeheim te krijgen, of verifieer toolaanroepen met je eigen header via endpoint.headers.
Tooldispatch in webhook-modus (tools zonder een endpoint, geleverd aan je organisatiewebhook als telephony.tool / web.tool) is een gewone ondertekende webhook — het standaardrecept hierboven is van toepassing. Zie Functietools voor beide aanvraagvormen.

Veelvoorkomende valkuilen

De body parsen en opnieuw dumpen met de standaardinstellingen van je JSON-bibliotheek (spaties na , / :, sleutels in invoegvolgorde) produceert andere bytes en breekt de HMAC. Verifieer de onbewerkte body — of als je opnieuw moet serialiseren, volg dan exact onze canonieke vorm: gesorteerde sleutels, compacte scheidingstekens, UTF-8.
De express.json()-middleware van Express verbruikt de bodystream en je verliest de onbewerkte bytes. Gebruik specifiek express.raw() op de webhookroute, of buffer de onbewerkte body in een pre-middleware. Hetzelfde geldt voor NestJS / Koa — bekijk hun documentatie over de “raw body”.
expected === signature in JS of expected == signature in Python zijn vergelijkingen met variabele timing. Gebruik respectievelijk crypto.timingSafeEqual of hmac.compare_digest. Het prestatieverschil is nihil.
Rechtstreekse aanroepen van tool-endpoints worden ondertekend met het webhooksecret op organisatieniveau (GET /v1/webhook) — niet met een secret per eindpunt uit /v1/developer/webhook-endpoints. Hergebruik dezelfde verify() functie, maar zorg dat je deze op toolroutes het organisatiesecret geeft.
Voor toolmethoden zonder body omvat de handtekening de lege bytestring, waardoor je één universele werkwijze behoudt: HMAC de onbewerkte requestbody, wat die ook is. De URL of querystring hashen komt nooit overeen.
Een 200 retourneren bij mislukte verificatie maakt de handler een doelwit voor replayaanvallen. Geef altijd een niet-2xx-status terug als verificatie mislukt.

Volgende stappen

Webhookoverzicht

Leveringssemantiek, retries, bron-IP’s.

Webhook-eindpunten

Beheer meerdere URL’s, roteer secrets.

Functietools

De twee paden voor toolaanroepen en hun requeststructuren.

Toolintegraties

Bouw een complete integratie met tools van begin tot eind.