Webhook
TapToChat può inviare una richiesta HTTPS al tuo server ogni volta che succede qualcosa: una nuova conversazione, un messaggio, un’assegnazione. Ogni richiesta è firmata, così puoi verificare che arrivi da noi.
Configurare un webhook
I webhook fanno parte del piano Pro. Owner e admin li gestiscono in Impostazioni.
- Apri Impostazioni → Webhook e scegli Aggiungi webhook.
- Assegnagli un nome e l’URL https che deve ricevere gli eventi.
- Scegli gli eventi da inviare.
- Copia il segreto di firma. Viene mostrato una sola volta; potrai rigenerarlo in seguito.
Eventi
Ogni webhook riceve solo gli eventi a cui è iscritto.
| Evento | Inviato quando |
|---|---|
conversation.created | Un visitatore avvia una conversazione, su qualsiasi canale. |
conversation.assigned | Una conversazione viene assegnata a un agente. |
conversation.closed | Una conversazione viene chiusa. |
message.created | Viene salvato un messaggio: di un visitatore, di un agente o una risposta automatica. |
tag.added | Viene aggiunto un tag a una conversazione. |
note.created | Un agente aggiunge una nota interna o esegue un comando come /summary, il cui risultato viene salvato come nota (kind command_result). |
integration.connected | Viene collegata un’integrazione. |
integration.disconnected | Viene scollegata un’integrazione. |
integration.error | La sincronizzazione di un’integrazione non riesce. |
webhook.test | Scegli Invia evento di prova in Impostazioni. Non viene mai inviato in altri casi. |
Payload
Ogni richiesta è una POST con un corpo JSON, sempre nello stesso formato:
{
"id": "6f1c2b0e-8a7d-4c1e-9b3a-2d5e7f9a1c4b",
"event": "message.created",
"created_at": "2026-10-01T09:30:00.000Z",
"organization_id": "0c9a1f4e-3b2d-4e5f-8a6b-7c8d9e0f1a2b",
"data": {
"message": {
"id": "a1b2c3d4-…",
"conversation_id": "e5f6a7b8-…",
"sender_type": "visitor",
"sender_id": null,
"content": "Hello, is anyone there?",
"channel": "web",
"created_at": "2026-10-01T09:30:00.000Z"
},
"conversation": { "id": "e5f6a7b8-…", "status": "open", "visitor_name": "Ada", "…": "…" }
}
}id: l’id dell’evento. Una consegna ritentata ha lo stesso id, quindi usalo per ignorare i duplicati.event: il nome dell’evento, come nella tabella qui sopra.data: cosa è successo. I campi dipendono dall’evento; un evento di messaggio contiene il messaggio e la relativa conversazione.
Header
X-TapToChat-Signature: la firma: v1= seguito da un HMAC-SHA256 in esadecimale.X-TapToChat-Timestamp: quando la richiesta è stata firmata, in secondi Unix.X-TapToChat-Event: il nome dell’evento.X-TapToChat-Delivery-Id: questa consegna. Ogni nuovo tentativo ha lo stesso id.
Verificare la firma
Calcola un HMAC-SHA256 del timestamp, di un punto e del corpo grezzo della richiesta, usando come chiave il tuo segreto di firma, e confrontalo con l’header della firma in tempo costante. Rifiuta le richieste il cui timestamp si discosta di più di 5 minuti dal tuo orologio, così una richiesta intercettata non può essere riprodotta.
Usa come chiave l’intero segreto, compreso il prefisso whsec_. Verifica il corpo grezzo prima di analizzarlo: un JSON serializzato di nuovo non corrisponderà.
import crypto from 'node:crypto'
// The raw request body, exactly as received: verify before parsing JSON.
export function verifyTapToChat(rawBody, headers, secret) {
const timestamp = headers['x-taptochat-timestamp']
const signature = headers['x-taptochat-signature']
if (!timestamp || !signature) return false
// Refuse old requests, so a captured one cannot be replayed later.
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false
const expected =
'v1=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
const a = Buffer.from(signature)
const b = Buffer.from(expected)
return a.length === b.length && crypto.timingSafeEqual(a, b)
}Nuovi tentativi
Rispondi con un qualsiasi stato 2xx entro 10 secondi per confermare una consegna. In caso contrario viene ritentata, fino a 6 tentativi in tutto.
Le attese tra un tentativo e l’altro sono 30s, 60s, 120s, 240s, 480s.
Una risposta 4xx diversa da 408 o 429 interrompe subito i nuovi tentativi, e lo stesso vale per un redirect: i redirect non vengono seguiti, quindi indica l’URL finale.
Occasionalmente una consegna può arrivare più di una volta. Usa l’id nel corpo per elaborare ogni evento una sola volta.
Disattivazione automatica
Dopo 20 consegne consecutive non riuscite, il webhook viene disattivato e le Impostazioni ne mostrano il motivo. Correggi il ricevitore, poi riattivalo; il conteggio riparte da zero.
Da sapere
- L’URL deve usare https e puntare a un indirizzo pubblico.
- I messaggi che gli agenti inviano dall’app mobile di TapToChat non generano ancora message.created. Quelli inviati dalla dashboard web e da tutti i canali sì.
Qualcosa non funziona come descritto? Contattaci.