All docs Referentie

API + Webhooks

Ontvang realtime HTTPS POSTs naar je CRM, Slack, Zapier, n8n of een ander systeem wanneer er gebeurtenissen plaatsvinden op je chatbots.

Uitgaande webhooks

HMAC SHA-256 ondertekend

Tot 5 nieuwe pogingen met backoff

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:

EvenementWanneer het wordt geactiveerd
lead.capturedEen bezoeker verstuurt het pre-chat-formulier, OF een inkomend WhatsApp-bericht start een gesprek (we hebben altijd hun telefoonnummer). Aanbevolen voor CRM-koppeling.
conversation.startedEr begint een nieuw gesprek. Handig voor marketinganalyses of om direct opvolgworkflows te starten.
conversation.endedBezoeker sluit de chat, of deze is 5+ minuten inactief. Handig om follow-up-e-mails te triggeren.
message.receivedBezoeker heeft een bericht gestuurd. Hoog volume — abonneer je alleen als je een specifieke behoefte hebt.
message.sentAI 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/json
  • User-Agent: DBestChatBot-Webhook/1.0
  • X-DBestChatBot-Event: lead.captured — de naam van de gebeurtenis
  • X-DBestChatBot-Delivery: evt_abc123 — unieke leverings-ID, gebruik voor deduplicatie
  • X-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:

  1. Extraheren t and v1 vanuit de header
  2. Reject if t ligt meer dan 5 minuten van de huidige tijd (replay-beveiliging)
  3. Berekenen expected = HMAC_SHA256(signing_secret, "t.raw_request_body")
  4. Vergelijking in constante tijd expected with v1
  5. 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:

PogingVertraging na vorige
1immediate
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

  1. Ga naar Webhooks in je dashboard
  2. Klik Endpoint toevoegen — plak je URL, kies gebeurtenissen
  3. Kopieer de ondertekeningsgeheim getoond na aanmaken
  4. Stuur een testevent om te controleren of je endpoint het ontvangt en valideert
  5. 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:

  1. 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/
  2. Ga in DBestChatBot naar Webhooks → Endpoint toevoegen. Paste the Zapier URL, name it "HubSpot via Zapier," subscribe to lead.captured, opslaan.
  3. 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.
  4. Voeg in Zapier een Actie → HubSpot → event Contact aanmaken of bijwerken. Autoriseer je HubSpot-account.
  5. Koppel de velden:
    • HubSpot email ← Zapier data.visitor.email
    • HubSpot firstname ← Zapier data.visitor.name (splits voor-/achternaam indien nodig)
    • HubSpot phone ← Zapier data.visitor.phone
    • HubSpot company ← Zapier data.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 ← Zapier data.source_url
  6. Optional but recommended: voeg een tweede actie toe → HubSpot → Notitie aanmaken op dat contact met de URL van het chattranscript data.transcript_url als de notitie-inhoud. Je salesteam klikt op de link en ziet het volledige gesprek dat tot de capture leidde.
  7. Zet de Zap aan. Elke toekomstige lead.captured evenement 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.

Klaar om het aan te sluiten?

Webhooks-dashboard openen