Webhook per la live chat
I webhook permettono a onWebChat di inviare eventi al tuo server in tempo reale. Ogni volta che succede qualcosa (inizia una nuova chat, viene inviato un messaggio, una chat viene chiusa o valutata, un visitatore lascia un messaggio offline), inviamo una richiesta HTTP POST con un corpo JSON all'URL che scegli.
È il modo più semplice per sincronizzare le trascrizioni delle chat nel tuo CRM o CMS, inviare email di follow-up, creare report personalizzati o notificare un altro sistema, senza polling.
I webhook sono disponibili in tutti i piani a pagamento e durante la prova gratuita di 14 giorni. Ogni consegna è firmata, così puoi verificare che provenga davvero da onWebChat.
POST https://your-server.com/onwebchat-webhook
Content-Type: application/json
User-Agent: onWebChat-Webhooks/1.0
X-OWC-Event: chat.closed
X-OWC-Delivery: 9381
X-OWC-Signature: sha256=4f1c...c2a9
{ "event": "chat.closed", "siteid": 1234, ... }
Configurare i webhook
Accedi alla tua dashboard come amministratore e vai su Impostazioni → Webhooks. Clicca su «Aggiungi endpoint», incolla l'URL che deve ricevere gli eventi, scegli quali eventi desideri (o seleziona «Tutti gli eventi», che include anche gli eventi che aggiungeremo in futuro) e salva.
Quando crei un endpoint, generiamo per esso un segreto di firma (inizia con whsec_). Userai questo segreto per verificare le richieste in arrivo (vedi Verifica delle firme più avanti). Puoi rigenerarlo in qualsiasi momento: quello vecchio smette subito di funzionare.
Puoi aggiungere più endpoint per sito web e rivedere le consegne recenti, inclusi lo stato HTTP, il numero di tentativi e qualsiasi errore, direttamente nella dashboard.
/* Dashboard → Settings → Webhooks */
URL : https://your-server.com/onwebchat-webhook
Events : chat.closed, message.created
Secret : whsec_3f9a... (used to verify requests)
Status : Enabled
Tipi di evento
Puoi ricevere qualsiasi combinazione degli eventi seguenti. Ogni messaggio ha un «author»: visitor, agent o ai (più trigger, per i messaggi dei trigger nella trascrizione di chat.closed), quindi lo stesso evento message.created copre le conversazioni gestite dal tuo team e dal chatbot IA.
| Evento | Inviato quando |
|---|---|
chat.created | Inizia una nuova chat (dialogo). Il campo source indica come: visitor, trigger o agent. |
chat.assigned | Un agente assume la gestione di una chat: la prende in carico, la rileva da un altro agente o dal chatbot IA, oppure accetta un trasferimento. Il campo source vale pickup, reassign, ai_takeover o transfer. |
message.created | Un nuovo messaggio viene inviato in una chat. Include messaggi dal visitatore, da un agente e dal chatbot IA. |
chat.closed | Una chat termina. Il payload include la trascrizione completa, i dettagli del visitatore e le etichette. |
chat.rated | Un visitatore valuta una chat (da 1 a 5 stelle). |
offline_message.created | Un visitatore invia il modulo offline o di contatto mentre non ci sono agenti disponibili. |
visitor.updated | Un agente aggiorna il nome, l'email, il telefono o le note del visitatore dalla dashboard della chat. |
visitor.banned | Un agente blocca un visitatore dalla dashboard della chat. |
visitor.unbanned | Un agente sblocca un visitatore precedentemente bloccato dalla dashboard della chat. |
Formato del payload
Ogni webhook è un oggetto JSON con la stessa struttura di base: il nome dell'evento, il tuo siteid, un timestamp ISO-8601 e un oggetto dati la cui forma dipende dall'evento.
L'esempio mostra un payload chat.closed, che contiene l'intera conversazione. Gli eventi più piccoli come message.created o chat.rated includono solo i campi rilevanti.
{
"event": "chat.closed",
"siteid": 1234,
"created_at": "2026-06-22T07:40:52.322Z",
"data": {
"chat_id": 1206836,
"started_at": "22-06-2026 10:40",
"closed_at": "2026-06-22T07:40:52.322Z",
"visitor": {
"name": "Sarah Chen",
"email": "sarah@example.com",
"phone": "",
"notes": "",
"country_code": "us",
"country": "United States",
"os": "Windows 10",
"browser": "Chrome 149.0"
},
"agents": ["Alex"],
"labels": [{ "name": "sales", "color": "#4caf50" }],
"messages": [
{ "author": "visitor", "agent_name": "", "text": "pricing info please", "time": "10:40", "date": "22-06-2026" },
{ "author": "ai", "agent_name": "", "text": "Here is a quick overview...", "time": "10:40", "date": "22-06-2026" },
{ "author": "agent", "agent_name": "Alex", "text": "Hi Sarah, I can help with a quote.", "time": "10:41", "date": "22-06-2026" }
]
}
}
Verifica delle firme
Ogni richiesta include un'intestazione X-OWC-Signature contenente un hash HMAC-SHA256 del corpo grezzo esatto della richiesta, calcolato con il segreto di firma del tuo endpoint.
Per verificare una richiesta, calcola l'HMAC-SHA256 del corpo grezzo con il tuo segreto e confrontalo con il valore dell'intestazione (la parte dopo "sha256="). Usa un confronto a tempo costante e calcola sempre l'hash del corpo grezzo, non di una versione riserializzata.
Ricevi anche X-OWC-Event (il nome dell'evento) e X-OWC-Delivery (un ID di consegna univoco che resta lo stesso nei nuovi tentativi, così puoi usarlo per la deduplicazione). Le richieste vengono inviate con lo User-Agent onWebChat-Webhooks/1.0.
// Node.js / Express
const crypto = require('crypto');
app.post('/onwebchat-webhook',
express.raw({ type: '*/*' }), (req, res) => {
const secret = 'whsec_your_secret';
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(req.body) // raw Buffer
.digest('hex');
const got = req.headers['x-owc-signature'] || '';
// constant-time compare; guard length first (timingSafeEqual throws on mismatch)
const a = Buffer.from(got), b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return res.status(401).end();
const payload = JSON.parse(req.body.toString());
// ... handle payload.event ...
res.sendStatus(200);
});
Verifica in PHP
La stessa verifica in PHP: leggi il corpo grezzo della richiesta, ricalcola l'HMAC con il tuo segreto e confronta con hash_equals().
<?php
$secret = 'whsec_your_secret';
$payload = file_get_contents('php://input');
$got = $_SERVER['HTTP_X_OWC_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $got)) {
http_response_code(401);
exit;
}
$event = json_decode($payload, true);
// ... handle $event['event'] ...
http_response_code(200);
Tentativi e disattivazione automatica
Il tuo endpoint dovrebbe rispondere con uno stato 2xx il più rapidamente possibile, e comunque entro 10 secondi. Qualsiasi risposta diversa da 2xx, un timeout o un errore di connessione viene considerato un tentativo fallito.
Le consegne non riuscite vengono ritentate con un intervallo crescente: dopo 1 minuto, 5 minuti, 20 minuti, 1 ora e 2 ore (6 tentativi in totale).
Se 5 consegne di fila falliscono anche dopo tutti i tentativi, l'endpoint viene disattivato automaticamente e il titolare dell'account riceve un'email. Riattivalo dalla dashboard dopo aver risolto il problema. Una risposta HTTP 410 (Gone) lo disattiva immediatamente.
Attempt 1 → immediately
Attempt 2 → after 1 minute
Attempt 3 → after 5 minutes
Attempt 4 → after 20 minutes
Attempt 5 → after 1 hour
Attempt 6 → after 2 hours
5 failed deliveries in a row → endpoint disabled
Buone pratiche
- Verifica sempre l'intestazione X-OWC-Signature prima di fidarti di un payload.
- Rispondi subito con uno stato 2xx, poi esegui il lavoro pesante in modo asincrono (mettilo in coda) per non andare in timeout.
- Usa X-OWC-Delivery per deduplicare, perché la stessa consegna può essere ritentata dopo un errore temporaneo.
- Esponi il tuo endpoint tramite HTTPS.
- Ignora i tipi di evento sconosciuti, così i nuovi eventi che aggiungeremo in futuro non comprometteranno la tua integrazione.
Pronto a iniziare? Vedi i piani o apri Impostazioni → Webhooks nella tua dashboard.