Helpcentrum
Chat API

Webhooks

Laatst bijgewerkt:

Webhooks overzicht

Met webhooks kan ChatLab je systemen op de hoogte stellen op het moment dat er iets gebeurt in je chatbots. In plaats van de Management API te pollen of handmatig gegevens te exporteren, registreer je een HTTPS-endpoint waarna ChatLab er in realtime een ondertekende HTTP POST naartoe stuurt - wanneer een bezoeker een lead achterlaat, een contactformulier verzendt, een gesprek beoordeelt, om een mens vraagt of wanneer er een AI-actie wordt uitgevoerd.

Typische use-cases:

  • nieuwe leads direct naar je CRM sturen zodra ze worden vastgelegd
  • je team op Slack waarschuwen wanneer een bezoeker om Live Chat (live chat) vraagt
  • gespreksbeoordelingen en samenvattingen doorsturen naar je eigen analysesysteem
  • uitvoeringen van AI-acties monitoren en waarschuwingen ontvangen bij fouten

Beschikbaarheid: webhooks zijn beschikbaar vanaf het STANDARD-plan (functie: Webhooks).

Waar te configureren: open in de beheeromgeving Account settings -> Webhooks (Accountinstellingen -> Webhooks, direct naast het onderdeel Management API). Webhooks werken op accountniveau - één endpoint kan events ontvangen van al je bots of van een gefilterde selectie.

Een endpoint instellen

  1. Open Account settings -> Webhooks (Accountinstellingen -> Webhooks) en klik op Create endpoint (Endpoint aanmaken).
  2. Vul het formulier voor het endpoint in:
    • Name (Naam) - een label voor eigen gebruik, bijvoorbeeld "CRM sync" of "Slack alerts".
    • URL - het HTTPS-adres waar ChatLab events naartoe zal posten via POST.
    • Events (Gebeurtenissen) - selecteer welke eventtypen dit endpoint ontvangt (zie het onderstaande overzicht). Kies alleen wat je nodig hebt; events met een hoog volume zoals ai_action.executed kunnen veel dataverkeer genereren.
    • Bot filter (optioneel) - beperk het endpoint tot specifieke bots. Laat dit leeg om events van alle bots in je account te ontvangen.
    • Custom form filter (optioneel) - stuurt inzendingen van één aangepast formulier naar dit endpoint. Dit filtert uitsluitend het event custom_form.submitted; alle andere events waarop je bent geabonneerd (leads, contactaanvragen, gesprekken, live chat, AI-acties) worden ongeacht deze instelling afgeleverd.
  3. Klik op verzenden. Het secret (geheime sleutel) van het endpoint wordt precies één keer getoond in het bevestigingsvenster - kopieer het direct en bewaar het op een veilige plek. Je hebt het nodig om handtekeningen te verifiëren (zie Beveiliging hieronder). De tekst kan later niet meer worden opgevraagd.

Elk endpoint beschikt daarnaast over:

  • Enable/disable toggle (Schakelaar voor inschakelen/uitschakelen) - onderbreek afleveringen zonder het endpoint te verwijderen. Uitgeschakelde endpoints negeren events geruisloos (ze worden niet in een wachtrij geplaatst voor later).
  • Send sample event (Voorbeeldgebeurtenis verzenden) - stuurt een ondertekend testverzoek naar je URL, zodat je je ontvanger van begin tot eind kunt controleren. Je kunt het eventtype kiezen en de voorbeeldwaarden bewerken voordat je verzendt, zodat je handler realistische data te zien krijgt. De test komt binnen als een normale aflevering waarbij het eventType overeenkomt met je selectie (of als webhook.test voor een eenvoudige connectiviteitscontrole).
  • Roll secret (Secret vernieuwen) - genereert een nieuw secret en maakt het oude ongeldig. Gebruik dit als het secret mogelijk is gelekt. Het nieuwe secret wordt opnieuw slechts één keer getoond. Werk je ontvanger bij voordat je het secret vernieuwt, anders mislukt de handtekeningverificatie aan jouw kant.
  • Delivery log (Afleveringslogboek) - een lijst met recente afleveringen per endpoint, inclusief tijdstempel, eventtype, de door je server geretourneerde HTTP-status en responstijd. Mislukte afleveringen en onderbrekingen door de circuit breaker zijn hier zichtbaar. Het logboek wordt 14 dagen bewaard.

Event-envelope

Elke aflevering is een HTTP POST met Content-Type: application/json. De body heeft altijd dezelfde envelope; het object data verschilt per eventtype:

{
  "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 - uniek per event. Gebruik dit voor ontdubbeling als je verwerking idempotent moet zijn.
  • eventType - een van de hieronder beschreven typen; wordt ook meegestuurd in de header X-ChatLab-Event.
  • timestamp - ISO 8601 UTC-tijdstip waarop het event plaatsvond.
  • botId / botName - de bot waar het event bij hoort.
  • conversationId / sessionId - de gesprekscontext, indien van toepassing.

Eventcatalogus

lead.created

Wordt geactiveerd wanneer een bezoeker contactgegevens achterlaat - via het formulier voor leadverzameling, het voorloopformulier van live chat of een aangepast formulier dat voor leadverzameling wordt gebruikt.

{
  "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 - hoe de contactgegevens zijn vastgelegd: LEAD_COLLECTION_FORM (formulier voor leadverzameling), LIVE_CHAT_FORM (voorloopformulier van live chat), CONVERSATION (de AI heeft de gegevens tijdens het gesprek opgevangen), ADMIN_DATA_UPDATE of UPDATE_CLIENT_CONTEXT (bewerkt aan de kant van ChatLab). Inzendingen van het formulier voor menselijke ondersteuning activeren dit event nooit - deze activeren in plaats daarvan contact_form.submitted.
  • email, name, phone - de contactgegevens die zijn toegewezen aan het leadrecord.
  • Wanneer een aangepast formulier wordt gebruikt voor leadverzameling, wordt elk veld dat op dat formulier is gedefinieerd opgenomen in fields, in de volgorde van het formulier, en identificeren formCodeName / formName het formulier. Bij het klassieke leadformulier zijn beide null en is fields een lege array.
  • Elk element in fields bestaat uit {name, value, type}. name is de technische naam van het veld, die gelijk blijft wanneer labels worden bewerkt - gebruik deze voor de koppeling met je CRM.
  • Voor velden van het type multichoice is value een array met de geselecteerde opties. Selectievakjes zijn afzonderlijke elementen met de waarden "true" / "false".
  • Voor velden van het type file is value een downloadlink naar het geüploade bestand; de webhook bevat nooit de inhoud van het bestand zelf.
  • pageUrl - de pagina waarop de bezoeker zich bevond tijdens het verzenden.

contact_form.submitted

Wordt geactiveerd wanneer een bezoeker het contactformulier voor menselijke ondersteuning verzendt of een aangepast formulier gebruikt voor menselijk contact.

{
  "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 - het adres dat de bezoeker heeft achtergelaten en waar je ondersteuningsteam op moet antwoorden.
  • source - CUSTOM_FORM wanneer een aangepast formulier achter het contactformulier zit, CONTACT_FORM voor het ingebouwde formulier.
  • formCodeName / formName - identificeren het aangepaste formulier achter het verzoek; beide zijn null voor het ingebouwde formulier.
  • Wanneer een aangepast formulier wordt gebruikt, wordt elk veld dat op dat formulier is gedefinieerd opgenomen in fields (dezelfde {name, value, type}-structuur als bij lead.created). Bij het ingebouwde contactformulier worden alleen email en message gevuld, is fields een lege array en zijn de formulieridentificatoren null.
  • message - het gekoppelde berichtveld, of alle ingevulde waarden samengevoegd als het formulier geen specifiek berichtveld heeft.

custom_form.submitted

Wordt geactiveerd voor elke inzending van een aangepast formulier, ongeacht het doel van het formulier. Let op: formulieren die bedoeld zijn voor leadverzameling of menselijk contact activeren ook hun specifieke lead.created / contact_form.submitted-event - abonneer je op de een of de ander, afhankelijk van of je de algemene of de gespecialiseerde weergave wilt, en ontdubbel op conversationId + timestamp als je je op beide abonneert.

{
  "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 - de vaste technische naam van het formulier, die ongewijzigd blijft als je het formulier hernoemt; gebruik deze om inzendingen in je eigen systeem te routeren. formName is het weergavelabel dat bezoekers te zien krijgen.
  • fields gebruikt dezelfde {name, value, type}-elementen als lead.created: meerkeuzewaarden zijn arrays, bestandswaarden zijn downloadlinks.
  • purpose - STANDALONE, LEAD_COLLECTION of HUMAN_CONTACT, afhankelijk van hoe het formulier aan de chatbot is gekoppeld.

conversation.started

Wordt geactiveerd wanneer een bezoeker het eerste bericht van een nieuw gesprek verstuurt.

{
  "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 - de exacte tekst van het openingsbericht van de bezoeker. null als het gesprek werd geopend zonder berichtinhoud.
  • chatSource - het kanaal waar het gesprek vandaan kwam: WIDGET, WHATSAPP, MESSENGER, VOICE, VOICE_PHONE, API, BOOKING, AIRBNB of IDOBOOKING.
  • byAdmin - true wanneer het gesprek afkomstig is uit het chatbotvoorbeeld in het ChatLab-beheerpaneel in plaats van van een echte bezoeker. Gebruik dit om je eigen testgesprekken buiten je CRM te houden.
  • countryCode - de ISO-landcode herleid uit het IP-adres van de bezoeker, null als dit niet kon worden vastgesteld.
  • ipAddress - het IP-adres van de bezoeker zoals gezien door ChatLab, null wanneer niet beschikbaar. Behandel dit als persoonsgegevens onder de AVG/GDPR en sla het alleen op als je hiervoor een wettelijke grondslag hebt.

conversation.rated

Wordt geactiveerd wanneer een bezoeker een antwoord van de bot beoordeelt met een duim omhoog of omlaag (zie Gespreksbeoordeling).

{
  "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 of NEGATIVE. Het wissen van een beoordeling triggert het event niet, waardoor je nooit een neutrale waarde ontvangt.

conversation.summarized

Wordt geactiveerd wanneer ChatLab een samenvatting genereert van een afgerond gesprek.

{
  "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"
  }
}
  • summary - de gegenereerde samenvattingstekst. Samenvattingen worden enkele minuten nadat het gesprek inactief is geworden aangemaakt; dit event arriveert daardoor later dan de rest van de gespreksevents.
  • language - de ISO-code van de taal waarin de samenvatting is opgesteld, gebaseerd op de taal van het gesprek.

client.summarized

Wordt geactiveerd wanneer ChatLab het AI-profiel van een klant vernieuwt. Het profiel wordt opnieuw opgebouwd op basis van het vorige profiel en de samenvatting van het zojuist beëindigde gesprek. Dit event volgt dus op conversation.summarized van hetzelfde gesprek. Klanten worden geïdentificeerd op basis van e-mailadres, vandaar dat het adres op het hoogste niveau van data wordt herhaald.

{
  "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 - de identificator om de klant te koppelen aan je eigen CRM. Dit is null voor anonieme bezoekers die nooit een adres hebben achtergelaten; het event wordt echter ook voor hen geactiveerd - negeer deze afleveringen als je integratie gebaseerd is op e-mailadressen.
  • client - het contactrecord dat ChatLab van deze persoon heeft: email, name, phone, countryCode en ipAddress. Elke sleutel is altijd aanwezig; onbekende waarden zijn null.
  • clientSummary - de volledige profieltekst als platte tekst, geen diff. Dit overschrijft de vorige samenvatting volledig, dus sla het op als overschrijving in plaats van als toevoeging.
  • Het profiel wordt alleen opnieuw opgebouwd voor bots met geactiveerd chat memory (chatgeheugen), en alleen voor gesprekken die lang genoeg inactief waren om te worden samengevat - verwacht dit event enkele minuten nadat het gesprek is beëindigd, niet direct.

live_chat.requested

Wordt geactiveerd wanneer de AI het gesprek overdraagt aan Live Chat (live chat), hetzij omdat de bezoeker om een mens vroeg, hetzij omdat de bot vaststelde dat er een mens nodig was.

{
  "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 - momenteel altijd AI, omdat de overdracht altijd wordt geïnitieerd door de live chat-actie van de bot, ook wanneer de bezoeker er zelf om vraagt. Behandel dit als een open enum: vang onbekende waarden netjes op in plaats van strikt op AI te controleren.
  • Het event geeft aan dat er om een overdracht is gevraagd, niet dat een medewerker deze al heeft aangenomen. Wacht daarvoor op live_chat.started.

live_chat.started

Wordt geactiveerd wanneer een medewerker deelneemt en de live chatsessie daadwerkelijk van start gaat.

{
  "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 is opzettelijk leeg. Alles wat je nodig hebt staat in de envelope: botId identificeert de chatbot en conversationId / sessionId koppelen het event aan het gesprek waarvoor je eerder al live_chat.requested hebt ontvangen.

live_chat.ended

Wordt geactiveerd wanneer de live chatsessie wordt beëindigd.

{
  "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 - hoe lang de medewerker in het gesprek aanwezig was, gerekend vanaf het moment dat de sessie begon. Het veld wordt weggelaten in het zeldzame geval dat een sessie wordt beëindigd zonder ooit te zijn gestart.

ai_action.executed

Wordt geactiveerd telkens wanneer de bot een AI-actie uitvoert - een beheerde integratieaanroep of een aangepaste API-functie. Dit is een event met een hoog volume: een actieve e-commercebot kan honderden acties per dag uitvoeren, en één enkel bericht van een bezoeker kan er meerdere triggeren. Abonneer je hierop via een specifiek endpoint, of zorg ervoor dat je ontvanger deze hoeveelheid verkeer aankan.

{
  "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 - de naam van de uitgevoerde actie zoals de AI deze ziet, bijvoorbeeld search_products voor een beheerde integratie of de naam die je aan een aangepaste API-actie hebt gegeven.
  • status - SUCCESS of ERROR.
  • durationMs - hoe lang de actie duurde, in milliseconden. Handig om trage integraties op te sporen voordat bezoekers erover klagen.
  • errorMessage - de reden van de fout, alleen gevuld wanneer status gelijk is aan ERROR; anders null.

webhook.test

Wordt verzonden via de knop Send sample event (Voorbeeldgebeurtenis verzenden) wanneer je een eenvoudige connectiviteitscontrole uitvoert. Op precies dezelfde manier ondertekend als een echt event.

{
  "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 - vaste tekst, altijd identiek. De envelope-velden bevatten voorbeeldwaarden; behandel een webhook.test-aflevering dus nooit als echte data.
  • Dit is het enige eventtype waarop je je bij een endpoint niet kunt abonneren: het wordt op verzoek vanuit het beheerpaneel verzonden en bereikt altijd het endpoint waarop je hebt geklikt, ongeacht naar welke events het luistert.

Beveiliging: afleveringen verifiëren

Elke aflevering bevat vier headers:

Header Waarde
X-ChatLab-Signature sha256=<hex hmac> - HMAC-SHA256-handtekening van de payload
X-ChatLab-Timestamp Unix-tijdstip in seconden waarop de aflevering is ondertekend
X-ChatLab-Event Het type gebeurtenis, bijv. lead.created
X-ChatLab-Delivery Unieke leverings-id, gelijk aan de eventId van de body

De handtekening wordt berekend als HMAC-SHA256 over de string {timestamp}.{rawBody} met behulp van je endpoint-secret, waarbij {timestamp} de waarde is van X-ChatLab-Timestamp en {rawBody} de ruwe, niet-geparseerde request-body is. Verifieer altijd op basis van de ruwe bytes - het opnieuw serialiseren van geparseerde JSON verandert de bytevolgorde en maakt de handtekening ongeldig.

Om je te beveiligen tegen replay-aanvallen weiger je afleveringen waarvan de X-ChatLab-Timestamp ouder is dan 5 minuten.

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 (!signature || !timestamp) 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 + '.' + 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 === '') {
        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);
}

Mocht de verificatie mislukken, reageer dan met 401 en negeer de payload. Verwerk nooit niet-geverifieerde afleveringen - iedereen die jouw URL achterhaalt, kan er willekeurige JSON naartoe posten.

Aflevergedrag

Zorg dat je deze garanties begrijpt voordat je verder bouwt op webhooks:

  • Reageer snel. Je endpoint moet binnen 3 seconden reageren, anders geldt de aflevering als mislukt. Reageer direct met 2xx en verwerk de payload asynchroon (plaats deze in een wachtrij en bevestig daarna pas) - voer geen CRM-aanroepen of databasewijzigingen uit voordat je antwoordt.
  • Fire-and-forget, hoogstens één keer. Elke gebeurtenis krijgt precies één afleverpoging - er zijn geen nieuwe pogingen (retries). Als je endpoint offline is, een time-out geeft of een niet-2xx-status retourneert, is die gebeurtenis verloren en wordt deze niet opnieuw verzonden. Webhooks zijn meldingen, geen gerepliceerde gegevensopslag: wanneer je gegarandeerde volledigheid nodig hebt, stem je gegevens dan af met de Management API of je lead-exports.
  • Circuit breaker. Na 5 opeenvolgende mislukte afleveringen voor een bot worden afleveringen voor die bot gedurende 5 minuten gepauzeerd. Gebeurtenissen die tijdens deze pauze plaatsvinden, worden genegeerd en in het afleverlogboek verschijnen CIRCUIT_OPEN-vermeldingen, zodat je precies kunt zien wanneer en waarom het verkeer is onderbroken. Afleveringen die door een open circuit zijn overgeslagen, tellen niet mee voor automatisch uitschakelen.
  • Automatisch uitschakelen. Deze controle wordt uitgevoerd op het moment dat een aflevering mislukt, nooit via een timer. Als een aflevering mislukt en er gedurende 7 dagen geen enkele succesvolle aflevering is geweest - geteld vanaf het laatste succes, of vanaf de aanmaakdatum van het endpoint als er nog nooit een succes is geweest - wordt het endpoint uitgeschakeld en ontvang je een e-mailmelding. Eén enkele 2xx op elk willekeurig moment reset die teller. Een endpoint dat geen verkeer ontvangt, wordt nooit uitgeschakeld, omdat er niets mislukt. Schakel het endpoint weer in via de Account settings (Accountinstellingen) zodra je ontvanger is gerepareerd; de foutenteller en de stempel voor automatisch uitschakelen worden gereset zodra je het weer aanzet, en gebeurtenissen die gemist zijn toen het endpoint uitstond, worden niet met terugwerkende kracht verzonden.
  • 410 Gone. Als je endpoint reageert met HTTP 410 Gone, schakelt ChatLab dit direct uit. Gebruik dit om een endpoint programmatisch buiten gebruik te stellen vanaf de ontvangende kant.
  • Idempotentie. Dubbele afleveringen worden bij normaal gebruik niet verwacht, maar als je verwerking strikt idempotent moet zijn, ontdubbel dan op basis van eventId (ook beschikbaar in de header X-ChatLab-Delivery).

Limieten

  • Maximaal 10 webhook-endpoints per account.
  • Bewaartermijn afleverlogboek: 14 dagen. Oudere vermeldingen worden automatisch verwijderd.

Gerelateerde artikelen