Skip to main content
Ogni richiesta che inviamo al tuo server — consegne webhook e invocazioni degli endpoint degli strumenti — contiene una firma HMAC-SHA256 nell’header X-ThunderPhone-Signature. Implementa correttamente la verifica una volta e integra lo stesso helper in ogni handler.

L’algoritmo

  1. Leggi il corpo raw della richiesta — gli esatti byte che ti abbiamo inviato tramite POST.
  2. Calcola hmac_sha256(secret, body).hexdigest().
  3. Confrontalo in tempo costante con X-ThunderPhone-Signature. (Un confronto ingenuo tra stringhe espone informazioni di timing.)
Firmiamo esattamente i byte che trasmettiamo, quindi la verifica del corpo raw funziona sempre. Quei byte sono anche la serializzazione JSON canonica del payload — chiavi ordinate alfabeticamente, separatori compatti (, e : senza spazi), UTF-8. Questo ti offre una seconda procedura, del tutto equivalente, quando il framework espone solo JSON già analizzato: serializzalo nuovamente in modo canonico e calcola l’HMAC su quello.
Preferisci il corpo raw: è un passaggio in meno ed evita le anomalie di conversione dei numeri JSON in alcuni linguaggi.

Quale secret?

Conserva il secret nel tuo gestore di segreti o in una variabile d’ambiente — non eseguire mai il commit.

Implementazioni di riferimento

Tutte e quattro verificano il corpo raw della richiesta:

Configurazione specifica per framework

Verifica delle chiamate degli strumenti

Quando l’agente richiama direttamente uno dei tuoi strumenti funzione (lo strumento dispone di un endpoint), la richiesta include due intestazioni ThunderPhone oltre alle endpoint.headers configurate:
  • X-ThunderPhone-Call-ID — l’ID numerico della chiamata in corso.
  • X-ThunderPhone-Signature — HMAC-SHA256, con chiave costituita dal tuo segreto webhook a livello di organizzazione, calcolato sui byte esatti del corpo della richiesta.
Lo stesso helper verify() funziona senza modifiche, con due particolarità:
  1. Gli strumenti GET / DELETE non hanno corpo. Gli argomenti vengono passati come parametri di query e la firma viene calcolata sulla stringa di byte vuota — quindi verify(b"", sig, secret) (Python) oppure verify(Buffer.alloc(0), sig, secret) (Node). Non calcolare l’hash della stringa di query.
  2. Le organizzazioni senza un webhook legacy configurato non hanno un segreto dell’organizzazione. In questo caso, le chiamate degli strumenti includono solo X-ThunderPhone-Call-ID e nessuna intestazione della firma. Configura il webhook legacy (PUT /v1/webhook) per ottenere un segreto di firma, oppure autentica le chiamate degli strumenti con una tua intestazione tramite endpoint.headers.
L’inoltro degli strumenti in modalità webhook (strumenti senza un endpoint, inviati al webhook della tua organizzazione come telephony.tool / web.tool) è un normale webhook firmato: si applica la procedura standard descritta sopra. Consulta Strumenti funzione per entrambi i formati di richiesta.

Problemi comuni

Analizzare il body e riesportarlo con le impostazioni predefinite della libreria JSON (spazi dopo , / :, chiavi ordinate per inserimento) produce byte diversi e compromette l’HMAC. Verifica il body grezzo oppure, se devi ri-serializzarlo, usa esattamente la nostra forma canonica: chiavi ordinate, separatori compatti, UTF-8.
Il middleware express.json() di Express consuma lo stream del body e perdi i byte grezzi. Usa express.raw() specificamente sulla route webhook oppure memorizza nel buffer il body grezzo in un pre-middleware. Lo stesso vale per NestJS / Koa: consulta la loro documentazione sul “raw body”.
expected === signature in JS o expected == signature in Python sono confronti con tempi variabili. Usa crypto.timingSafeEqual o hmac.compare_digest rispettivamente. La differenza di prestazioni è nulla.
Le chiamate dirette agli endpoint degli strumenti sono firmate con il secret webhook a livello di organizzazione (GET /v1/webhook), non con alcun secret per endpoint da /v1/developer/webhook-endpoints. Riutilizza la stessa funzione verify(), ma assicurati di fornirle il secret dell’organizzazione nelle route degli strumenti.
Per i metodi degli strumenti senza body, la firma copre la stringa di byte vuota, mantenendo un’unica procedura universale: calcola l’HMAC del body grezzo della richiesta, qualunque esso sia. L’hash dell’URL o della stringa di query non corrisponderà mai.
Restituire 200 quando la verifica fallisce rende l’handler un bersaglio per replay. Rispondi sempre con un codice diverso da 2xx se la verifica fallisce.

Passaggi successivi

Panoramica dei webhook

Semantica di consegna, tentativi, IP di origine.

Endpoint webhook

Gestisci più URL, ruota i secret.

Function Tools

I due percorsi di invocazione degli strumenti e le relative strutture delle richieste.

Integrazioni degli strumenti

Crea un’integrazione completa supportata da strumenti, dall’inizio alla fine.