Overzicht
DBestChatBot verstuurt outbound webhooks wanneer er belangrijke gebeurtenissen plaatsvinden in je chatbots (een lead wordt vastgelegd, een gesprek begint of eindigt, een bericht wordt verzonden of ontvangen). Je stelt een bestemmings-URL in het dashboard in en wij POSTen binnen enkele seconden na elke gebeurtenis een JSON-envelope ernaartoe.
Webhooks zijn een Pro / Agency-functie. Free-tier accounts can still view conversations and leads in the dashboard but can't pipe them to external systems.
Evenementen
Elke webhook abonneert zich op een of meer van deze gebeurtenistypen:
| Evenement | Wanneer het wordt geactiveerd |
|---|---|
lead.captured | Een bezoeker verstuurt het pre-chat-formulier, OF een inkomend WhatsApp-bericht start een gesprek (we hebben altijd hun telefoonnummer). Aanbevolen voor CRM-koppeling. |
conversation.started | Er begint een nieuw gesprek. Handig voor marketinganalyses of om direct opvolgworkflows te starten. |
conversation.ended | Bezoeker sluit de chat, of deze is 5+ minuten inactief. Handig om follow-up-e-mails te triggeren. |
message.received | Bezoeker heeft een bericht gestuurd. Hoog volume — abonneer je alleen als je een specifieke behoefte hebt. |
message.sent | AI heeft een bezoeker beantwoord. Hoog volume — abonneer je alleen als je een specifieke behoefte hebt. |
Payload-formaat
Elke webhook verstuurt een JSON-envelope met dezelfde velden op het hoogste niveau. De data object verschilt per gebeurtenistype. Voorbeeld voor lead.captured:
{
"event": "lead.captured",
"id": "evt_abc123def456",
"created_at": "2026-05-17T15:30:00+00:00",
"data": {
"conversation_id": "conv_xyz789",
"chatbot": {
"id": 42,
"name": "Acme Support"
},
"visitor": {
"name": "Jane Doe",
"email": "jane@acme.com",
"phone": "+15551234567"
},
"source_url": "https://acme.com/pricing",
"message_count": 4,
"transcript_url": "https://dbestchatbot.com/app/conversations/conv_xyz789",
"capture_method": "prechat_form"
}
}Request headers
Elk verzoek bevat:
Content-Type: application/jsonUser-Agent: DBestChatBot-Webhook/1.0X-DBestChatBot-Event: lead.captured— de naam van de gebeurtenisX-DBestChatBot-Delivery: evt_abc123— unieke leverings-ID, gebruik voor deduplicatieX-DBestChatBot-Signature: t=1747490400,v1=<hex_hmac>— verificatiesignatuur
Handtekeningen verifiëren (aanbevolen)
Verifieer webhook-payloads altijd om er zeker van te zijn dat ze echt van DBestChatBot afkomstig zijn. Het handtekeningformaat is Stripe-compatibel: een Unix-timestamp t en een HMAC-SHA-256 hex-digest v1, samengevoegd met een komma.
Algoritme:
- Extraheren
tandv1vanuit de header - Reject if
tligt meer dan 5 minuten van de huidige tijd (replay-beveiliging) - Berekenen
expected = HMAC_SHA256(signing_secret, "t.raw_request_body") - Vergelijking in constante tijd
expectedwithv1 - Als ze overeenkomen, is de payload authentiek. Zo niet, afwijzen.
Node.js / Express
// Node.js / Express example — verify the signature header
import express from 'express';
import crypto from 'crypto';
const app = express();
const SIGNING_SECRET = process.env.DBESTCHATBOT_SIGNING_SECRET;
// IMPORTANT: use raw body, not parsed JSON, for signature verification
app.post('/webhooks/dbestchatbot',
express.raw({ type: 'application/json' }),
(req, res) => {
const header = req.header('X-DBestChatBot-Signature') || '';
const match = header.match(/t=(\d+),v1=([a-f0-9]+)/);
if (!match) return res.status(400).send('bad signature header');
const [, ts, signature] = match;
// 5-minute replay window
if (Math.abs(Date.now() / 1000 - parseInt(ts)) > 300) {
return res.status(400).send('stale timestamp');
}
const expected = crypto
.createHmac('sha256', SIGNING_SECRET)
.update(`${ts}.${req.body}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.status(401).send('signature mismatch');
}
const event = JSON.parse(req.body.toString());
console.log('Verified event:', event.event, event.data);
// Always respond 2xx quickly — we'll retry up to 5x with backoff if you don't
res.status(200).send('ok');
},
);PHP
<?php
// PHP example — verify the signature header
$signingSecret = getenv('DBESTCHATBOT_SIGNING_SECRET');
$rawBody = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_DBESTCHATBOT_SIGNATURE'] ?? '';
if (! preg_match('/t=(\d+),v1=([a-f0-9]+)/', $header, $m)) {
http_response_code(400); exit('bad signature header');
}
[, $ts, $signature] = $m;
if (abs(time() - (int) $ts) > 300) {
http_response_code(400); exit('stale timestamp');
}
$expected = hash_hmac('sha256', "{$ts}.{$rawBody}", $signingSecret);
if (! hash_equals($expected, $signature)) {
http_response_code(401); exit('signature mismatch');
}
$event = json_decode($rawBody, true);
// process $event['event'], $event['data'] ...
http_response_code(200);
echo 'ok';Nieuwe pogingen en leveringsgaranties
We proberen het opnieuw tot 5 keer with exponential backoff if your endpoint doesn't return a 2xx response within 30 seconds:
| Poging | Vertraging na vorige |
|---|---|
| 1 | immediate |
| 2 | +1 minuut |
| 3 | +5 minuten |
| 4 | +30 minuten |
| 5 | +2 uur |
Na de 5e mislukte poging wordt de levering gemarkeerd als failed en stoppen we met opnieuw proberen. Je ziet het volledige leveringslogboek (inclusief HTTP-status, foutmelding en aantal pogingen) op de detailpagina van de webhook in je dashboard.
Retourneer altijd snel een 2xx-status. Als je zware verwerking nodig hebt, bevestig eerst met 200 en verwerk asynchroon.
Idempotentie
Elke levering heeft een unieke id veld (ook verzonden als X-DBestChatBot-Delivery). Because we retry on failure, your endpoint may receive the same event more than once. Store the IDs you've already processed and skip duplicates.
IP-allowlisting
Uitgaande webhooks komen van onze productieservers op 15.204.199.41. Als je op IP whitelist, sta dit adres dan toe. Handtekeningen zijn echter het betrouwbaardere verificatiepad — IP kan worden vervalst, HMAC niet (zonder het geheim).
Aan de slag
- Ga naar Webhooks in je dashboard
- Klik Endpoint toevoegen — plak je URL, kies gebeurtenissen
- Kopieer de ondertekeningsgeheim getoond na aanmaken
- Stuur een testevent om te controleren of je endpoint het ontvangt en valideert
- Zie echte gebeurtenissen binnenkomen terwijl bezoekers je chatbots gebruiken
Verbinden met Zapier / Make / n8n
All three tools have a generic "Catch Hook" or "Webhook Trigger" action — paste the URL they generate into a new endpoint here, subscribe to the events you want, done. Map fields from data.visitor naar je CRM, Sheets of waar je maar wilt vanaf daar.
HubSpot — volledige uitleg
Dit is de meest voorkomende opzet. Legt elke chatbot-lead vast als HubSpot-contact:
- Klik in Zapier op Zap aanmaken → Trigger: Webhooks by Zapier → event Catch Hook → ga verder. Zapier toont je een aangepaste URL zoals
https://hooks.zapier.com/hooks/catch/12345/abc/ - Ga in DBestChatBot naar Webhooks → Endpoint toevoegen. Paste the Zapier URL, name it "HubSpot via Zapier," subscribe to
lead.captured, opslaan. - Terug in Zapier: klik op Testtrigger. Klik vervolgens op je DBestChatBot-webhookpagina op Testgebeurtenis versturen. Zapier zou een voorbeeldpayload moeten ontvangen — het voorbeeld bevat
data.visitor.name,data.visitor.email,data.visitor.phone, en alle aangepaste pre-chatvelden die je hebt gedefinieerd. - Voeg in Zapier een Actie → HubSpot → event Contact aanmaken of bijwerken. Autoriseer je HubSpot-account.
- Koppel de velden:
- HubSpot
email← Zapierdata.visitor.email - HubSpot
firstname← Zapierdata.visitor.name(splits voor-/achternaam indien nodig) - HubSpot
phone← Zapierdata.visitor.phone - HubSpot
company← Zapierdata.visitor.company(if you added a custom "Company" field in your chatbot's pre-chat form) - HubSpot
lifecycle_stage→ hardcode naar Lead or Abonnee - HubSpot
website← Zapierdata.source_url
- HubSpot
- Optional but recommended: voeg een tweede actie toe → HubSpot → Notitie aanmaken op dat contact met de URL van het chattranscript
data.transcript_urlals de notitie-inhoud. Je salesteam klikt op de link en ziet het volledige gesprek dat tot de capture leidde. - Zet de Zap aan. Elke toekomstige
lead.capturedevenement maakt automatisch binnen enkele seconden een HubSpot-contact aan of werkt dit bij.
Pro-tip: if you want to route HIGH-VALUE leads differently (e.g. enterprise pricing inquiries) from FAQ-style chats, add a custom field to your pre-chat form like "What are you looking to do?" with options "Just browsing / Buying / Sales question." Then in Zapier add a Filter step that only continues to HubSpot if the answer is "Sales question" — your CRM stays clean.
Other CRMs: hetzelfde patroon werkt voor Pipedrive (actie: Create Deal), Salesforce (actie: Create/Update Lead), Close (actie: Create Lead), monday.com (actie: Create Item) en Airtable (actie: Create Record). De DBestChatBot-kant is identiek — wijs gewoon een andere Zap naar dezelfde webhook-URL.
FAQ
Why isn't my endpoint receiving events?
- Controleer of de webhook active in het dashboard
- Check you're subscribed to the right event type
- Controleer het afleveringslog op de detailpagina van de webhook op HTTP-fouten
- Gebruik de Testgebeurtenis versturen button to bypass real-world triggers
Hoe stop ik tijdelijk met het ontvangen van events?
Toggle the webhook off — no events are queued or buffered, they're simply dropped.
Kan ik oudere gebeurtenissen ophalen die al hebben plaatsgevonden?
Nee, webhooks zijn fire-and-forget. Gebruik het dashboard voor historische gegevens Gesprekken export (CSV) of neem contact met ons op voor een eenmalige backfill.