Centro assistenza
Chat API

Webhook

Ultimo aggiornamento:

Panoramica sui webhook

I webhook consentono a ChatLab di notificare i tuoi sistemi nel momento esatto in cui accade qualcosa nei tuoi chatbot. Invece di eseguire il polling della Management API o esportare i dati manualmente, registri un endpoint HTTPS e ChatLab vi invia una richiesta HTTP POST firmata in tempo reale - quando un visitatore lascia un lead, invia un modulo di contatto, valuta una conversazione, richiede un operatore umano o quando viene eseguita un'azione AI.

Utilizzi tipici:

  • inviare nuovi lead direttamente nel tuo CRM nell'istante in cui vengono acquisiti
  • avvisare il tuo team su Slack quando un visitatore richiede la live chat
  • inserire valutazioni e riepiloghi delle conversazioni nei tuoi strumenti di analisi
  • monitorare l'esecuzione delle AI action (azioni AI) e ricevere avvisi in caso di errori

Disponibilità: il tuo account deve includere la funzionalità Webhooks (Webhook).

Dove configurare: nell'app di amministrazione, apri Account settings -> Webhooks (Impostazioni account -> Webhook, subito accanto alla sezione Management API). I webhook sono a livello di account - un singolo endpoint può ricevere eventi da tutti i tuoi bot o da un bot selezionato.

Configurazione di un endpoint

  1. Apri Account settings -> Webhooks e fai clic su Add endpoint (Aggiungi endpoint).
  2. Compila il modulo dell'endpoint:
    • Name (Nome) - un'etichetta di riferimento personale, ad es. "Sincronizzazione CRM" o "Avvisi Slack".
    • URL - l'indirizzo HTTPS a cui ChatLab invierà gli eventi tramite POST.
    • Events (Eventi) - seleziona i tipi di evento che questo endpoint deve ricevere (consulta il catalogo riportato di seguito). Seleziona solo ciò di cui hai bisogno; gli eventi ad alto volume come ai_action.executed possono generare molto traffico.
    • Bot filter (Filtro bot) (opzionale) - seleziona un singolo bot, oppure All bots (Tutti i bot) per tutti i bot del tuo account.
    • Custom form filter (Filtro modulo personalizzato) (opzionale) - indirizza gli invii di un modulo personalizzato specifico verso questo endpoint. Limita unicamente l'evento custom_form.submitted; qualsiasi altro evento a cui ti iscrivi (lead, richieste di contatto, conversazioni, live chat, azioni AI) viene recapitato indipendentemente da questa impostazione.
  3. Invia. Il secret (segreto) dell'endpoint viene mostrato una sola volta nella finestra di conferma - copialo subito e conservalo in un luogo sicuro. Ti servirà per verificare le firme (consulta la sezione Sicurezza di seguito). Il testo in chiaro non potrà essere recuperato in seguito.

Ciascun endpoint include inoltre:

  • Selettore attiva/disattiva - metti in pausa gli invii senza eliminare l'endpoint. Gli endpoint disattivati scartano gli eventi in modo invisibile (non vengono messi in coda per dopo).
  • Send sample event (Invia evento di prova) - recapita una richiesta di test firmata al tuo URL per consentirti di verificare il funzionamento del tuo ricevitore end-to-end. Puoi scegliere il tipo di evento e modificare i valori di esempio prima dell'invio, in modo che il tuo gestore visualizzi dati realistici. Il test arriva come una normale consegna con eventType corrispondente alla tua selezione (oppure come webhook.test per un semplice controllo di connettività).
  • Roll secret (Rigenera segreto) - genera un nuovo segreto e invalida quello precedente. Utilizza questa opzione se ritieni che il segreto sia stato compromesso. Anche il nuovo segreto verrà mostrato una sola volta. Per una rotazione controllata, metti in pausa l'endpoint, rigenera e copia il nuovo segreto, aggiorna il ricevitore, quindi riattiva l'endpoint e invia un evento di prova. Gli eventi generati durante la pausa non vengono messi in coda. Pianifica questa interruzione prima di procedere con la rotazione.
  • Delivery log (Registro delle consegne) - un elenco specifico per l'endpoint delle consegne recenti con timestamp, tipo di evento, codice di stato HTTP restituito dal tuo server e tempo di risposta. Le consegne non riuscite e le sospensioni dovute al circuit breaker sono visibili qui. Il registro viene conservato per 14 giorni.

Wrapper dell'evento

Ogni invio è una richiesta HTTP POST con Content-Type: application/json. Il corpo presenta sempre la stessa struttura di base (envelope); l'oggetto data è specifico per il tipo di evento:

{
  "eventId": "9f1c1c8e-6a2b-4b9e-9d2f-3f8a1e2b4c5d",
  "eventType": "lead.created",
  "timestamp": "2026-08-13T14:22:31Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": { }
}
  • eventId - univoco per ciascun evento. Usalo per la deduplicazione se l'elaborazione deve essere idempotente.
  • eventType - uno dei tipi documentati di seguito; viene inviato anche nell'header X-ChatLab-Event.
  • timestamp - orario UTC in formato ISO 8601 in cui è stato preparato il wrapper di consegna.
  • botId / botName - il bot a cui appartiene l'evento.
  • conversationId / sessionId - il contesto della conversazione, quando applicabile.

Catalogo degli eventi

lead.created

Viene attivato quando un visitatore invia i propri dati di contatto - tramite il modulo di acquisizione lead, il modulo preliminare di live chat o un modulo personalizzato utilizzato per l'acquisizione di lead.

{
  "eventId": "9f1c1c8e-6a2b-4b9e-9d2f-3f8a1e2b4c5d",
  "eventType": "lead.created",
  "timestamp": "2026-08-13T14:22:31Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "email": "jane.doe@example.com",
    "name": "Jane Doe",
    "phone": "+1 555 0123",
    "source": "LEAD_COLLECTION_FORM",
    "formCodeName": "lead_form",
    "formName": "Lead form",
    "fields": [
      {"name": "email", "value": "jane.doe@example.com", "type": "email"},
      {"name": "company", "value": "Acme Inc.", "type": "text"},
      {"name": "topics", "value": ["Billing", "Delivery"], "type": "multichoice"},
      {"name": "attachment", "value": "https://api.chatlab.com/aichat/customform/download?key=...&token=...", "type": "file"}
    ],
    "pageUrl": "https://acme.com/pricing"
  }
}
  • source - come sono stati acquisiti i dati di contatto: LEAD_COLLECTION_FORM (modulo di acquisizione lead), LIVE_CHAT_FORM (modulo preliminare di live chat), CONVERSATION (l'IA ha raccolto i dati durante la chat), ADMIN_DATA_UPDATE o UPDATE_CLIENT_CONTEXT (modificati sul lato ChatLab). Gli invii del modulo di supporto umano non attivano mai questo evento - attivano invece contact_form.submitted.
  • email, name, phone - i dati di contatto mappati sul record del lead.
  • Quando viene utilizzato un modulo personalizzato per l'acquisizione di lead, ogni campo definito su quel modulo viene incluso in fields, nell'ordine del modulo, e formCodeName / formName identificano il modulo. Con il modulo lead classico entrambi sono null e fields è un array vuoto.
  • Ciascuna voce in fields è {name, value, type}. name è il nome tecnico del campo, stabile rispetto alle modifiche delle etichette - usalo per la mappatura nel tuo CRM.
  • Per i campi multichoice value è un array delle opzioni selezionate. I campi casella di controllo sono voci individuali con valori "true" / "false".
  • Per i campi file value è un link di download al file caricato; il webhook non trasporta mai il contenuto dei file.
  • pageUrl - la pagina su cui si trovava il visitatore al momento dell'invio.

contact_form.submitted

Viene attivato quando un visitatore invia il modulo di contatto per il supporto umano o un modulo personalizzato utilizzato per il contatto umano.

{
  "eventId": "3a7b9c2d-1e4f-4a6b-8c0d-5e2f7a9b1c3d",
  "eventType": "contact_form.submitted",
  "timestamp": "2026-08-13T14:25:02Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "email": "jane.doe@example.com",
    "message": "I need help with my last invoice.",
    "source": "CUSTOM_FORM",
    "formCodeName": "contact_form",
    "formName": "Contact form",
    "fields": [
      {"name": "email", "value": "jane.doe@example.com", "type": "email"},
      {"name": "order_number", "value": "A-10293", "type": "text"},
      {"name": "message", "value": "I need help with my last invoice.", "type": "textarea"}
    ]
  }
}
  • email - l'indirizzo lasciato dal visitatore, e quello a cui il tuo team di supporto deve rispondere.
  • source - CUSTOM_FORM quando il modulo di contatto si basa su un modulo personalizzato, CONTACT_FORM per quello integrato.
  • formCodeName / formName - identificano il modulo personalizzato alla base della richiesta; entrambi sono null per il modulo integrato.
  • Quando viene utilizzato un modulo personalizzato, ogni campo definito su quel modulo viene incluso in fields (stesso formato {name, value, type} di lead.created). Con il modulo di contatto integrato vengono compilati solo email e message, fields è un array vuoto e gli identificatori del modulo sono null.
  • message - il campo del messaggio mappato, oppure tutti i valori compilati uniti insieme quando il modulo non definisce alcun campo messaggio.

custom_form.submitted

Viene attivato per ogni invio di un modulo personalizzato, indipendentemente dallo scopo del modulo. Tieni presente che i moduli il cui scopo è l'acquisizione di lead o il contatto umano attivano anche il rispettivo evento dedicato lead.created / contact_form.submitted - iscriviti all'uno o all'altro a seconda che tu voglia la vista generica o quella specializzata, invece di creare azioni aziendali duplicate. Le due famiglie di eventi hanno ID evento diversi; conversationId insieme a timestamp non costituisce un identificatore univoco affidabile per l'invio.

{
  "eventId": "6c1d8e3f-2a5b-4c7d-9e0f-1a4b6c8d0e2f",
  "eventType": "custom_form.submitted",
  "timestamp": "2026-08-13T14:27:45Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "formCodeName": "warranty_claim",
    "formName": "Warranty claim",
    "fields": [
      {"name": "order_number", "value": "A-10293", "type": "text"},
      {"name": "issue", "value": "Damaged on arrival", "type": "textarea"},
      {"name": "photo", "value": "https://api.chatlab.com/aichat/customform/download?key=...&token=...", "type": "file"}
    ],
    "purpose": "STANDALONE"
  }
}
  • formCodeName - il nome tecnico stabile del modulo, che non cambia quando rinomini il modulo; usalo per instradare gli invii nel tuo sistema. formName è l'etichetta visibile mostrata ai visitatori.
  • fields utilizza le stesse voci {name, value, type} di lead.created: i valori a scelta multipla sono array, i valori dei file sono link di download.
  • purpose - STANDALONE, LEAD_COLLECTION o HUMAN_CONTACT, a seconda di come il modulo è collegato al chatbot.

conversation.started

Viene attivato quando un visitatore invia il primo messaggio di una nuova conversazione.

{
  "eventId": "8e2f0a4b-3c6d-4e8f-a1b2-2c5d7e9f1a3b",
  "eventType": "conversation.started",
  "timestamp": "2026-08-13T14:20:11Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "firstMessage": "Do you ship to Canada?",
    "chatSource": "WIDGET",
    "byAdmin": false,
    "countryCode": "PL",
    "ipAddress": "83.12.44.7"
  }
}
  • firstMessage - il testo esatto del messaggio di apertura del visitatore. null se la conversazione è stata aperta senza contenuto del messaggio.
  • chatSource - il canale da cui è arrivata la conversazione: WIDGET, WHATSAPP, MESSENGER, VOICE, VOICE_PHONE, API, BOOKING, AIRBNB o IDOBOOKING.
  • byAdmin - true quando la conversazione proviene dall'anteprima del chatbot all'interno del pannello di amministrazione di ChatLab anziché da un visitatore reale. Usalo per escludere le tue chat di prova dal tuo CRM.
  • countryCode - codice paese ISO rilevato dall'indirizzo IP del visitatore, null quando non è stato possibile determinarlo.
  • ipAddress - l'indirizzo IP del visitatore rilevato da ChatLab, null quando non disponibile. Trattalo come dato personale ai sensi del GDPR e conservalo solo se disponi di una base giuridica valida.

conversation.rated

Viene attivato quando un visitatore invia una valutazione positiva o negativa della conversazione (vedi Valutazione della conversazione).

{
  "eventId": "1b4c6d8e-5f0a-4b2c-8d3e-4f7a9b1c3d5e",
  "eventType": "conversation.rated",
  "timestamp": "2026-08-13T14:31:09Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "rating": "POSITIVE"
  }
}
  • rating - POSITIVE o NEGATIVE. La cancellazione di una valutazione non attiva l'evento, quindi non riceverai mai un valore neutro.

conversation.summarized

Viene attivato quando ChatLab genera un riepilogo di una conversazione terminata.

{
  "eventId": "4d7e9f1a-6b2c-4d4e-9f0a-5b8c0d2e4f6a",
  "eventType": "conversation.summarized",
  "timestamp": "2026-08-13T14:45:00Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "summary": "Visitor asked about shipping to Canada and delivery times. The bot confirmed availability and quoted 5-7 business days. Visitor left satisfied.",
    "language": "en_US"
  }
}
  • summary - il testo del riepilogo generato. La generazione del riepilogo è asincrona e dipende dalla configurazione del riepilogo del bot e dalla pianificazione dell'elaborazione; non dare per scontato un ritardo di consegna fisso.
  • language - il locale interno del bot passato alla generazione del riepilogo, ad esempio en_US; non dare per scontato che corrisponda alla lingua della conversazione del visitatore.

client.summarized

Viene attivato quando ChatLab aggiorna il profilo IA di un cliente. Il profilo viene ricostruito a partire dal profilo precedente più il riepilogo della conversazione appena terminata, e potrebbe essere generato dopo conversation.summarized. L'ordine di consegna non è garantito. Il payload include un indirizzo e-mail quando è noto, ma ChatLab può gestire anche clienti senza un'e-mail.

{
  "eventId": "b5d8f1a3-7c2e-4d9b-a6f0-1e3c5a7b9d2f",
  "eventType": "client.summarized",
  "timestamp": "2026-08-18T09:12:04Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "clientEmail": "jane.doe@example.com",
    "client": {
      "email": "jane.doe@example.com",
      "name": "Jane Doe",
      "phone": "+1 555 0123",
      "countryCode": "PL",
      "ipAddress": "83.12.44.7"
    },
    "clientSummary": "Returning customer interested in international shipping. Asked about delivery times to Canada twice and about return costs once."
  }
}
  • clientEmail - l'identificatore per associare il cliente al tuo CRM. È null per i visitatori anonimi che non hanno mai lasciato un indirizzo, e l'evento viene comunque attivato anche per loro - ignora queste consegne se la tua integrazione è basata sull'e-mail.
  • client - la scheda di contatto memorizzata da ChatLab per questa persona: email, name, phone, countryCode e ipAddress. Ogni chiave è sempre presente; i valori sconosciuti sono null.
  • clientSummary - il testo completo del profilo in testo semplice, non un diff. Sostituisce qualsiasi riepilogo precedente, quindi memorizzalo sovrascrivendo invece di aggiungerlo in coda.
  • Il profilo viene ricostruito solo per i bot con la memoria della chat abilitata, e solo per le conversazioni rimaste inattive abbastanza a lungo da essere riepilogate - aspettati questo evento alcuni minuti dopo la fine della conversazione, non immediatamente.

live_chat.requested

Viene attivato quando l'IA trasferisce la conversazione alla live chat, sia perché il visitatore ha richiesto un operatore umano sia perché il bot ha stabilito che fosse necessario un intervento umano.

{
  "eventId": "7a0b2c4d-8e3f-4a5b-b0c1-6d9e1f3a5b7c",
  "eventType": "live_chat.requested",
  "timestamp": "2026-08-13T14:33:20Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "requestedBy": "AI"
  }
}
  • requestedBy - attualmente sempre AI, poiché il passaggio viene sempre avviato dall'azione di live chat del bot, anche quando il visitatore lo richiede esplicitamente. Trattalo come un enum aperto: gestisci i valori sconosciuti invece di verificare rigidamente la presenza di AI.
  • Questo evento copre l'azione dell'IA che richiede il passaggio, non tutti i modi in cui un visitatore può aprire la live chat. Non prova che un operatore sia effettivamente entrato nella chat.

live_chat.started

Viene attivato quando la sessione di live chat viene creata dopo l'invio del modulo di passaggio da parte del visitatore. Questo avviene prima che un operatore entri o risponda necessariamente; non considerarlo una prova dell'intervento umano.

{
  "eventId": "0c3d5e7f-9a4b-4c6d-a1b2-7e0f2a4b6c8d",
  "eventType": "live_chat.started",
  "timestamp": "2026-08-13T14:33:55Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {}
}
  • data è intenzionalmente vuoto. Tutto ciò di cui hai bisogno si trova nella busta: botId identifica il chatbot e conversationId / sessionId collegano l'evento alla conversazione. Potresti riceverlo senza un precedente live_chat.requested, ad esempio quando il visitatore ha utilizzato il comando di live chat del widget.

live_chat.ended

Viene attivato quando la sessione di live chat termina.

{
  "eventId": "2e5f7a9b-0c5d-4e7f-b2c3-8f1a3b5c7d9e",
  "eventType": "live_chat.ended",
  "timestamp": "2026-08-13T14:52:41Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "durationSeconds": 1126
  }
}
  • durationSeconds - durata trascorsa della sessione di live chat, calcolata a partire dalla creazione della sessione, compreso il tempo di attesa di un operatore. Il campo viene omesso nel raro caso in cui una sessione termini senza essere mai stata avviata.

ai_action.executed

Viene attivato ogni volta che il bot esegue un'azione IA - una chiamata di integrazione gestita o una funzione API personalizzata. Si tratta di un evento ad alto volume: un bot di e-commerce attivo può eseguire centinaia di azioni al giorno, e un singolo turno del visitatore può attivarne diverse. Iscriviti a questo evento su un endpoint dedicato, oppure assicurati che il tuo ricevitore sia in grado di gestire il volume.

{
  "eventId": "5f8a0b2c-1d6e-4f8a-c3d4-9a2b4c6d8e0f",
  "eventType": "ai_action.executed",
  "timestamp": "2026-08-13T14:21:03Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "actionName": "search_products",
    "status": "SUCCESS",
    "durationMs": 842,
    "errorMessage": null
  }
}
  • actionName - il nome dell'azione eseguita così come viene visto dall'IA, ad esempio search_products per un'integrazione gestita o il nome assegnato a un'azione API personalizzata.
  • status - SUCCESS o ERROR.
  • durationMs - quanto tempo ha richiesto l'azione, in millisecondi. Utile per individuare un'integrazione lenta prima che i visitatori se ne lamentino.
  • errorMessage - il motivo dell'errore, compilato solo quando status è ERROR; null in caso contrario.

webhook.test

Inviato dal pulsante Send sample event (Invia evento di esempio) quando esegui una semplice verifica di connettività. Firmato esattamente come un evento reale.

{
  "eventId": "9b2c4d6e-3f8a-4b0c-d5e6-0b3c5d7e9f1a",
  "eventType": "webhook.test",
  "timestamp": "2026-08-13T14:10:00Z",
  "botId": 1234,
  "botName": "Support Bot",
  "conversationId": "conv_a1b2c3",
  "sessionId": "sess_x9y8z7",
  "data": {
    "message": "Test delivery from ChatLab"
  }
}
  • message - testo fisso, sempre identico. I campi della busta contengono valori di esempio, quindi non trattare mai una consegna di webhook.test come dati reali.
  • Questo è l'unico tipo di evento a cui non puoi iscriverti su un endpoint: viene inviato su richiesta dal pannello di amministrazione e raggiunge sempre l'endpoint su cui hai fatto clic, indipendentemente dagli eventi su cui è in ascolto.

Sicurezza: verifica delle consegne

Ogni consegna include quattro intestazioni:

Intestazione Valore
X-ChatLab-Signature sha256=<hex hmac> - firma HMAC-SHA256 del payload
X-ChatLab-Timestamp Ora Unix in secondi in cui la consegna è stata firmata
X-ChatLab-Event Il tipo di evento, ad es. lead.created
X-ChatLab-Delivery ID univoco di consegna, uguale a eventId nel corpo

La firma viene calcolata come HMAC-SHA256 sulla stringa {timestamp}.{rawBody} utilizzando il secret del tuo endpoint, dove {timestamp} è il valore di X-ChatLab-Timestamp e {rawBody} è il corpo non elaborato e non analizzato della richiesta. Esegui sempre la verifica sui byte grezzi - la rieserializzazione del JSON analizzato modificherà la sequenza di byte e invaliderà la firma.

Per proteggerti da attacchi di tipo replay, rifiuta le consegne in cui X-ChatLab-Timestamp è più vecchio di 5 minuti.

Node.js

const crypto = require('crypto');

function verifyChatLabSignature(req, secret) {
    const signature = req.headers['x-chatlab-signature'];
    const timestamp = req.headers['x-chatlab-timestamp'];
    if (typeof signature !== 'string' || typeof timestamp !== 'string') return false;
    if (!/^\d+$/.test(timestamp) || !Number.isSafeInteger(Number(timestamp))) return false;
    if (!Buffer.isBuffer(req.rawBody)) return false;

    // Reject stale deliveries (older than 5 minutes)
    const ageSeconds = Math.abs(Date.now() / 1000 - Number(timestamp));
    if (ageSeconds > 300) return false;

    // rawBody must be the raw request body bytes, not re-serialized JSON.
    // With Express: app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; } }))
    const expected = 'sha256=' + crypto
        .createHmac('sha256', secret)
        .update(timestamp + '.')
        .update(req.rawBody)
        .digest('hex');

    const a = Buffer.from(signature);
    const b = Buffer.from(expected);
    return a.length === b.length && crypto.timingSafeEqual(a, b);
}

PHP

<?php
function verifyChatLabSignature(string $secret): bool
{
    $signature = $_SERVER['HTTP_X_CHATLAB_SIGNATURE'] ?? '';
    $timestamp = $_SERVER['HTTP_X_CHATLAB_TIMESTAMP'] ?? '';
    if ($signature === '' || $timestamp === '' || !ctype_digit($timestamp)) {
        return false;
    }

    // Reject stale deliveries (older than 5 minutes)
    if (abs(time() - (int) $timestamp) > 300) {
        return false;
    }

    $rawBody = file_get_contents('php://input');
    $expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);

    return hash_equals($expected, $signature);
}

Se la verifica fallisce, rispondi con 401 e scarta il payload. Non elaborare mai consegne non verificate: chiunque scopra il tuo URL può inviargli del JSON arbitrario tramite POST.

Comportamento di recapito

Comprendi queste regole di recapito prima di iniziare a sviluppare con i webhook:

  • Rispondi rapidamente. Il tuo endpoint deve rispondere entro 3 secondi, altrimenti il recapito viene considerato fallito. Verifica la firma, accoda l'evento in modo persistente e conferma la ricezione con un codice 2xx entro tale intervallo. Esegui le chiamate CRM più lente e l'elaborazione aziendale in modo asincrono.
  • Fire-and-forget, al massimo una volta. Gli endpoint abilitati e corrispondenti ricevono al massimo un tentativo di recapito - non sono previsti nuovi tentativi. Gli endpoint in pausa e i circuit breaker aperti possono bloccare anche quel singolo tentativo. Se il tuo endpoint è offline, va in timeout o restituisce uno stato diverso da 2xx, l'evento va perso e non verrà recapitato nuovamente. I webhook sono notifiche, non un archivio dati replicato: usa gli endpoint per le conversazioni della Bot Talk API o le esportazioni dei lead per riconciliare i dati conservati, ove supportato. La Management API copre le impostazioni del bot e i dati di utilizzo, non un archivio eventi completo. Alcuni eventi non possono essere ricostruiti tramite queste interfacce.
  • Circuit breaker. Dopo 5 recapiti falliti consecutivi per una coppia endpoint/bot, i recapiti per quella coppia vengono sospesi per 5 minuti. Gli eventi che si verificano durante la pausa vengono ignorati e il registro dei recapiti mostra voci CIRCUIT_OPEN per identificare i tentativi bloccati. I recapiti saltati a causa di un circuito aperto non vengono conteggiati ai fini della disattivazione automatica.
  • Disattivazione automatica. Il controllo viene eseguito nel momento in cui un recapito fallisce, mai tramite timer. Se un recapito fallisce e non c'è stato alcun recapito riuscito per 7 giorni - conteggiati dall'ultimo successo, o dalla data di creazione dell'endpoint se non ha mai avuto successo - l'endpoint viene disattivato e ricevi una notifica via e-mail. Un singolo 2xx in qualsiasi momento reimposta il conteggio. Un endpoint che non riceve traffico non viene mai disattivato, poiché nulla fallisce. Riabilitalo da Account settings (Impostazioni account) una volta corretto il tuo ricevitore; il contatore degli errori e la data di disattivazione automatica vengono azzerati quando lo riattivi, e gli eventi persi mentre era disattivato non vengono recuperati.
  • 410 Gone. Se il tuo endpoint risponde con HTTP 410 Gone, ChatLab lo disattiva immediatamente. Usa questo codice per dismettere a livello programmatico un endpoint dal lato ricevente.
  • Idempotenza. L'invio di duplicati non è previsto durante il normale funzionamento, ma se la tua elaborazione deve essere rigorosamente idempotente, deduplica tramite eventId (disponibile anche nell'header X-ChatLab-Delivery).

L'ordine di recapito non è garantito. Memorizza l'ID dell'evento e rendi l'elaborazione aziendale idempotente. Mantieni i tuoi criteri di conservazione e controllo degli accessi per i payload dei webhook, che potrebbero contenere dati personali e link per il download di file.

Gli esempi di firma utilizzano Node.js crypto e hash_equals di PHP. Acquisisci il body non elaborato della richiesta prima di effettuarne il parsing.

Limiti

  • Fino a 10 webhook endpoint per account.
  • Conservazione del registro dei recapiti: 14 giorni. Le voci più vecchie vengono rimosse automaticamente.

Articoli correlati