Webhooks
Houd gebeurtenissen in je Bookingmood-account in de gaten, zodat je integratie automatisch realtime reacties kan activeren.
Waarom zou je webhooks gebruiken?
Als je integraties met Bookingmood bouwt, wil je misschien dat je apps gebeurtenissen ontvangen zodra die zich in je Bookingmood-accounts voordoen, zodat je backend-systemen daarop kunnen reageren. Om webhook-gebeurtenissen in te schakelen, moet je webhook-eindpunten registreren. Nadat je deze hebt geregistreerd, kan Bookingmood realtime gebeurtenisgegevens naar het webhook-eindpunt van je app sturen wanneer er gebeurtenissen plaatsvinden in je Bookingmood-account. Bookingmood gebruikt HTTPS om webhook-gebeurtenissen als JSON-payload naar je app te sturen.
Het ontvangen van webhook-gebeurtenissen is vooral handig om op de hoogte te blijven van asynchrone gebeurtenissen, zoals wanneer er een boeking wordt geregistreerd of wanneer een betaling is voldaan.
Webhooks gebruiken
Als er een gebeurtenis plaatsvindt, maakt Bookingmood een nieuw Event-object aan. Eén enkele actie kan ertoe leiden dat er meerdere gebeurtenissen worden aangemaakt.
Als je bijvoorbeeld een boeking bevestigt, worden zowel de gebeurtenis calendar_events.updated als calendar_events.confirmed verzonden.
Event-object
Het Event-object dat we naar je webhook-eindpunt sturen, geeft een momentopname weer van het object dat is aangemaakt of gewijzigd. Het object ziet er als volgt uit.
{
"id": "00000000-0000-0000-0000-000000000000",
"date": 1680064028,
"event_type": "calendar_events.updated",
"payload": {
"new": {
"id": "00000000-0000-0000-0000-000000000000",
...
},
"old": {
"id": "00000000-0000-0000-0000-000000000000",
...
}
}
}
Het veld event_type in het Event-object geeft aan welk type gebeurtenis er heeft plaatsgevonden. Het veld payload bevat de nieuwe en oude versie van het object dat is aangemaakt of gewijzigd.
Soorten evenementen
Bookingmood stuurt deze soorten gebeurtenissen door. Gebeurtenissen die eindigen op .created en .updated worden verstuurd wanneer een record wordt aangemaakt of gewijzigd; calendar_events.confirmed en calendar_events.cancelled wanneer de status van een boeking verandert, payments.paid wanneer een betaling is ontvangen, en tasks.completed wanneer een taak als voltooid wordt gemarkeerd.
bookings.createdbookings.updatedcalendar_events.createdcalendar_events.updatedcalendar_events.confirmedcalendar_events.cancelledcontacts.createdcontacts.updatedinvoices.createdinvoices.updatedpayments.createdpayments.updatedpayments.paidtasks.createdtasks.updatedtasks.completedmembers.createdmembers.updatedproducts.createdproducts.updatedsites.createdsites.updatedwidgets.createdwidgets.updated
Hoe stel je je webhook-integratie in?
Om webhook-gebeurtenissen in je app te gaan ontvangen, kun je de onderstaande stappen volgen. Je kunt één eindpunt registreren om meerdere verschillende soorten gebeurtenissen tegelijk te verwerken, of afzonderlijke eindpunten instellen voor specifieke gebeurtenissen.
Maak een webhook-eindpunt aan om gebeurtenissen te ontvangen.
Registreer je eindpunt in Bookingmood onder Instellingen › Webhooks, of via de API.
Beveilig je webhook-eindpunt.
Bezorging en herhalingspogingen
Bookingmood stuurt binnen enkele seconden nadat een gebeurtenis plaatsvindt een melding naar je eindpunt. De verzending is geslaagd als je eindpunt binnen 10 seconden reageert met een 2xx- of 3xx-statuscode. Omleidingen worden niet gevolgd.
Als een verzending mislukt, probeert Bookingmood het opnieuw met steeds langere tussenpozen: na 1 minuut, 5 minuten, 30 minuten, 2 uur, 6 uur, 12 uur, 24 uur en nog eens 24 uur. Als alle 9 pogingen mislukken – verspreid over ongeveer 3 dagen – wordt de gebeurtenis gemarkeerd als mislukt. Je kunt de verzendingen van de afgelopen 7 dagen en de reacties van je endpoint bekijken onder Instellingen › Webhooks.
Uitgeschakelde webhooks
Als elke poging om een gebeurtenis door te sturen mislukt en er ondertussen geen andere gebeurtenis het eindpunt heeft bereikt, schakelt Bookingmood de webhook uit en stuurt het een e-mail naar de beheerders van je organisatie. Een uitgeschakelde webhook ontvangt geen nieuwe gebeurtenissen. Nadat je je eindpunt hebt gerepareerd, schakel je de webhook weer in onder Instellingen › Webhooks, of stel de disabled_at in op null via de API.
1. Maak een webhook-eindpuntfunctie aan
Stel een HTTPS-eindpunt in dat webhook-verzoeken via de POST-methode kan verwerken. Stel je eindpuntfunctie zo in dat deze:
Verwerkt POST-verzoeken met een JSON-payload die bestaat uit een gebeurtenisobject.
Geeft snel een succesvolle statuscode (
2xx) terug, nog voordat er complexe logica wordt uitgevoerd die een time-out zou kunnen veroorzaken. Bookingmood wacht maximaal 10 seconden op een reactie.
Voorbeeld van een eindpunt
Dit codefragment is een webhook-functie die zo is ingesteld dat hij controleert of het gebeurtenistype is ontvangen, de gebeurtenis afhandelt en een 200-antwoord terugstuurt.
// In dit voorbeeld wordt Express gebruikt om webhooks te ontvangen
const express = require("express");
const app = express();
// Pas de ruwe body aan het inhoudstype application/json aan
// Als je Express v4 - v4.16 gebruikt, moet je body-parser gebruiken in plaats van express om de request body op te halen
app.post(
"/webhook",
express.json({ type: "application/json" }),
(request, response) => {
const event = request.body;
// Verwerk de gebeurtenis
switch (event.event_type) {
case "calendar_events.confirmed":
const calendarEvent = event.payload.new;
// Definieer en roep vervolgens een methode aan om de bevestiging van de agenda-afspraak te verwerken.
// handleCalendarEventConfirmation(calendarEvent);
break;
case "products.created":
const product = event.payload.new;
// Definieer en roep vervolgens een methode aan om de aanmaak van het product af te handelen.
// handleProductCreated(product);
break;
// ... andere gebeurtenistypen afhandelen
default:
console.log(`Niet-afgehandeld gebeurtenistype ${event.event_type}`);
}
// Stuur een reactie terug om de ontvangst van de gebeurtenis te bevestigen
response.json({ received: true });
}
);
app.listen(8000, () => console.log("Draait op poort 8000"));2. Registreer en beheer je webhook in Bookingmood
Nadat je je webhook-eindpunt hebt aangemaakt, registreer je de openbaar toegankelijke URL van het webhook-eindpunt onder Instellingen › Webhooks of via de API, zodat Bookingmood weet waar het de gebeurtenissen naartoe moet sturen. Geregistreerde webhook-eindpunten moeten openbaar toegankelijke HTTPS-URL’s zijn. Om je webhook-eindpunt te registreren, geef je de openbaar toegankelijke HTTPS-URL van je webhook-eindpunt op en selecteer je het type gebeurtenissen dat je via je eindpunt ontvangt.
De configuratie van een webhook-eindpunt beheren
Je kunt bestaande webhook-eindpunten altijd bijwerken of verwijderen via Instellingen › Webhooks of via de API.
3. Beveilig je webhooks
Nadat je hebt gecontroleerd of de verbinding met je webhook-eindpunt naar behoren werkt, beveilig je de verbinding door de aanbevolen werkwijzen voor webhooks toe te passen.
Een heel belangrijke best practice is om webhook-handtekeningen te gebruiken om te controleren of het webhook-verzoek echt door Bookingmood is gegenereerd en niet afkomstig is van een server die zich voordoet als Bookingmood.
Volgorde van gebeurtenissen
Bookingmood verstuurt de gebeurtenissen van een webhook in de volgorde waarin ze worden gegenereerd, maar garandeert niet dat ze in die volgorde aankomen: een gebeurtenis die opnieuw wordt geprobeerd, komt pas na latere gebeurtenissen binnen. Het verwerken van een betaling kan bijvoorbeeld de volgende gebeurtenissen genereren:
payments.updatedpayments.paid
Je endpoint mag er niet vanuit gaan dat deze gebeurtenissen in deze volgorde worden geleverd, en moet de levering daarop afstemmen.
Je kunt de API ook gebruiken om ontbrekende objecten op te halen (je kunt bijvoorbeeld de bijbehorende factuur ophalen met behulp van de informatie uit payments.paid).
Omgaan met dubbele gebeurtenissen
Webhook-eindpunten kunnen af en toe dezelfde gebeurtenis meer dan eens ontvangen. Je kunt voorkomen dat gebeurtenissen dubbel worden ontvangen door je gebeurtenisverwerking idempotent te maken. Een manier om dit te doen is door de gebeurtenissen die je al hebt verwerkt te loggen, en vervolgens gebeurtenissen die al zijn gelogd niet nogmaals te verwerken.
Luister alleen naar de soorten gebeurtenissen die je integratie nodig heeft
Stel je webhook-eindpunten zo in dat ze alleen de soorten gebeurtenissen ontvangen die je integratie nodig heeft. Als je op extra gebeurtenissen (of alle gebeurtenissen) luistert, belast je je server onnodig, en dat raden we niet aan. Je kunt in het Dashboard of via de API aanpassen welke gebeurtenissen een webhook-eindpunt ontvangt.
Controleer of er gebeurtenissen worden verzonden vanuit Bookingmood
Gebruik webhook-handtekeningen om te controleren of ontvangen gebeurtenissen echt van Bookingmood komen en niet van een derde partij. Bookingmood ondertekent elke gebeurtenis volgens de Standaard Webhooks-specificatie, met deze headers:
| Koptekst | Inhoud |
|---|---|
webhook-id | Het ID van de gebeurtenis; dit is hetzelfde bij elke bezorgpoging |
webhook-timestamp | Het tijdstip waarop de gebeurtenis is verzonden, in seconden sinds het epoch |
webhook-signature | v1, gevolgd door de in base64 gecodeerde HMAC-SHA256-handtekening |
In het volgende gedeelte wordt uitgelegd hoe je webhook-handtekeningen kunt controleren:
Haal het geheim van je endpoint op.
Controleer de handtekening.
Het geheim van je endpoint ophalen
Bookingmood genereert voor elk eindpunt een unieke geheime sleutel. Om deze op te halen, ga je naar Instellingen › Webhooks en kopieer de geheime sleutel onder de eindpunt-URL, of gebruik de API. Als je meerdere eindpunten gebruikt, moet je bovendien voor elk eindpunt waarvoor je handtekeningen wilt verifiëren een geheime sleutel aanvragen.
De handtekening controleren
Volg deze stappen om de handtekening te controleren die Bookingmood bij elke gebeurtenis meestuurt:
Lees de ruwe request body. Parseer en serialiseer deze niet opnieuw: de handtekening dekt precies de bytes die zijn verzonden.
Maak de ondertekende inhoud klaar door de
webhook-id-header, dewebhook-timestamp-header en de ruwe body samen te voegen met het teken..Bereken de verwachte handtekening als de HMAC-SHA256 van de ondertekende inhoud, met je
signing_secret(als UTF-8-tekst) als sleutel, gecodeerd als base64.Vergelijk de verwachte handtekening met de handtekening na
v1,in dewebhook-signature-header, met behulp van een vergelijking in constante tijd. Als de handtekeningen overeenkomen, is de gebeurtenis geverifieerd.
De standaard webhooks-bibliotheken kunnen dit voor je regelen. Ze verwachten een in base64 gecodeerd geheim, dus geef je signing_secret door, gecodeerd als base64.
Voorbeeld van het handmatig controleren van handtekeningen
// Stel je geheime sleutel in.
const signingSecret = "...";
// Zorg ervoor dat de geheime sleutel nooit aan de client wordt blootgesteld
// In dit voorbeeld wordt Express gebruikt om webhooks te ontvangen
const express = require("express");
const crypto = require("crypto");
const app = express();
app.post(
"/webhook",
// Bewaar de ruwe body: de handtekening dekt precies de bytes die zijn verzonden
express.raw({ type: "application/json" }),
(request, response) => {
const id = request.headers["webhook-id"];
const timestamp = request.headers["webhook-timestamp"];
const body = request.body.toString("utf8");
const expectedSignature = crypto
.createHmac("sha256", signingSecret)
.update(`${id}.${timestamp}.${body}`)
.digest("base64");
const signature = (request.headers["webhook-signature"] ?? "")
.split(" ")
.find((value) => value.startsWith("v1,"))
?.slice(3);
if (
!signature ||
signature.length !== expectedSignature.length ||
!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))
) {
response.status(401).send("Ongeldige handtekening");
return;
}
// Gebeurtenissen afwijzen die ouder zijn dan 5 minuten
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
response.status(401).send("Verlopen tijdstempel");
return;
}
const event = JSON.parse(body);
// Verwerk de gebeurtenis
switch (event.event_type) {
default:
console.log(`Onverwerkte gebeurtenis ontvangen van het type: ${event.event_type}`);
}
// Stuur een reactie terug om te bevestigen dat je de gebeurtenis hebt ontvangen
response.json({ received: true });
}
);
app.listen(8000, () => console.log("Draait op poort 8000"));Oude handtekening
Gebeurtenissen bevatten ook een X-Signature-header, voor eindpunten die gebeurtenissen op dezelfde manier verifiëren als vóór de toevoeging van de Standard Webhooks-headers. Deze bestaat uit \x, gevolgd door de hexadecimale MD5-hash van je signing_secret, het teken . en de onbewerkte request body. Gebruik de webhook-signature-header voor nieuwe integraties: MD5 wordt niet langer als veilig beschouwd.
Replay-aanvallen voorkomen
Een replay-aanval is wanneer een aanvaller een geldige payload en de bijbehorende handtekening onderschept en deze vervolgens opnieuw verstuurt. Om zulke aanvallen te voorkomen, bevat elke verzending een tijdstempel in de webhook-timestamp-header en in het date-veld van de body (seconden sinds de epoch). Omdat de tijdstempel is ondertekend, kan een aanvaller deze niet wijzigen zonder de handtekening ongeldig te maken.
Als de handtekening geldig is maar de tijdstempel te oud is, kun je je app de payload laten afwijzen.
Bookingmood genereert de tijdstempel en handtekening elke keer dat we een gebeurtenis naar je eindpunt sturen.
Als Bookingmood een gebeurtenis opnieuw probeert te verzenden (bijvoorbeeld omdat je eindpunt eerder een statuscode anders dan 2xx heeft teruggestuurd), dan genereren we een nieuwe handtekening en tijdstempel voor de nieuwe verzendpoging.
Laatst gewijzigd 3 november 2026