Webhooks voor boekingen sturen realtime events (nieuwe boeking, wijziging, annulering) als JSON-payload naar jouw HTTPS-endpoint, zodra ze gebeuren op het boekingsplatform. Je zet ze in zodra je boekingsgegevens automatisch wilt synchroniseren met een CRM, kassasysteem of eigen database, zonder dat je continu de API moet bevragen. Platforms zoals RaxBooker ondersteunen webhooks standaard, mits je endpoint klaarstaat met signature-verificatie.
Kort samengevat:
- Webhooks vereisen een publiek toegankelijke HTTPS-endpoint met een geldig TLS-certificaat en open poort 443 voor correcte werking.
- Signatures in headers beschermen tegen nepverzoeken, replay-aanvallen en vereisen verificatie van de hash en timestamp.
- Voor betrouwbare verwerking moet je een idempotentie-mechanisme gebruiken met unieke
event_id-velden en database-upserts toepassen.- Het laden van de server, firewall-instellingen en juiste logging van raw payloads zijn cruciaal om issues snel te identificeren en op te lossen.
- Het beperken van abonnements-events tot relevante type- en status-updates voorkomt onnodige load en complexiteit in je systeem.
Inhoudsopgave
- Webhook-endpoint maken: stappen en minimale vereisten
- Payload en voorbeelden: typische JSON-structuren voor boekingsevents
- Signatures, secrets en IP-restricties: zo verifieer je de bron
- Levering, retries en idempotentie: betrouwbare verwerking bouwen
- Testen en debuggen: test-events, logs en veelvoorkomende fouten
- Checklist met best practices voor productie-implementatie
- RaxBooker als praktisch voorbeeld: webhooks voor boekingen in actie
- Versiebeheer van webhook payloads en endpoints
- Gebruik van webhook management tools of platforms
- Praktische voorbeelden van implementatie in populaire boekingssystemen
- Schaalbaarheid en performance overwegingen bij gebruik van webhooks
- Wat de meeste teams over het hoofd zien bij webhooks
- RaxBooker en jouw eigen webhook-integratie
- Bronnen
- Veelgestelde vragen
Webhook-endpoint maken: stappen en minimale vereisten
Voor je een webhook kunt registreren, moet je endpoint aan een paar harde vereisten voldoen. Boekingsplatforms accepteren vrijwel nooit een callback-URL zonder geldig TLS-certificaat, en een endpoint die niet publiek bereikbaar is, krijgt gegarandeerd nul events binnen.
Zo zet je een werkend endpoint op:
- Bouw een publiek HTTPS-endpoint. Gebruik een geldig TLS-certificaat (Let's Encrypt is prima) en zorg dat de server vanaf het internet bereikbaar is, niet alleen binnen je eigen netwerk.
- Registreer de endpoint-URL in het dashboard of via de API van het boekingsplatform.
- Selecteer specifieke events waarop je wilt abonneren, zoals
booking.createdofbooking.cancelled, in plaats van alles binnen te laten stromen. - Zet testmodus aan en verstuur een test-event om te controleren of je endpoint reageert zoals verwacht.
Let bij hosting op firewall- en NAT-instellingen: een endpoint achter een restrictieve firewall of zonder poort 443 open, blokkeert inkomende webhook-calls zonder duidelijke foutmelding aan jouw kant. Retourneer bovendien altijd snel een 200 OK, en verwerk zware logica (database-updates, e-mails, synchronisatie) asynchroon in een wachtrij. Een endpoint die vijf seconden laat wachten op verwerking voordat hij antwoordt, veroorzaakt onnodige timeouts en retries.
Payload en voorbeelden: typische JSON-structuren voor boekingsevents
Elke webhook-call bevat een JSON-body met het event-type en de bijbehorende boekingsdata. De exacte veldnamen verschillen per platform, maar de kernstructuur is opvallend consistent tussen aanbieders.
Een booking.created event ziet er typisch zo uit:
{
"event": "booking.created",
"booking_id": "bk_88291",
"start": "2026-05-14T10:00:00Z",
"end": "2026-05-14T12:00:00Z",
"customer": { "name": "J. de Vries", "email": "j.devries@example.nl" },
"price": { "amount": 4500, "currency": "EUR" },
"status": "confirmed",
"metadata": { "source": "website" }
}
Bij een booking.updated event blijft de structuur gelijk, maar verandert het status-veld en verschijnt vaak een extra changed_fields-array die aangeeft welke waarden zijn aangepast. Een booking.cancelled event bevat meestal een cancelled_at timestamp en een reason-veld.
Voor reconciliatie en idempotentie moet je minstens deze velden loggen:
booking_idals unieke referentie voor upsertsevent-type en eenevent_idper verzendingstatusenupdated_atom verouderde events te herkennen
| Veld | Doel |
|---|---|
booking_id | Koppelt event aan bestaande record |
event_id | Voorkomt dubbele verwerking |
status | Bepaalt of actie nodig is |
updated_at | Filtert verouderde of out-of-order events |
Platforms zoals Bookingmood versturen op deze manier events als bookings.created en payments.paid, en raden nadrukkelijk aan om je endpoint idempotent te maken.
Signatures, secrets en IP-restricties: zo verifieer je de bron
Iedereen die je endpoint-URL kent, kan in theorie een nepverzoek sturen. Signature-verificatie is daarom geen extra beveiligingslaag, het is de basis.
De meeste platforms werken met een signing secret die je bij registratie ontvangt. Bij elke webhook-call wordt een hash (meestal HMAC-SHA256) van de payload en een timestamp meegestuurd in een header zoals X-Signature. Jouw server berekent dezelfde hash met het eigen secret en vergelijkt de uitkomst.
- Verifieer altijd de
X-Signature-header tegen een lokaal berekende hash, voordat je de payload verwerkt. - Controleer de timestamp: verzoeken ouder dan een paar minuten weiger je, dat voorkomt replay-aanvallen met onderschepte payloads.
- IP-whitelisting werkt alleen als het platform vaste, gepubliceerde IP-reeksen garandeert; bij veel SaaS-platforms wisselen die reeksen, waardoor whitelisting sneller kapot loopt dan het beveiligt.
- Roteer secrets periodiek en bewaar ze in een secrets-manager, nooit hardcoded in je codebase.
Pro-tip: Bewaar oude en nieuwe secrets tijdens een rotatieperiode van 24 tot 48 uur naast elkaar actief, zodat in-transit events met het oude secret niet alsnog worden afgewezen.
Levering, retries en idempotentie: betrouwbare verwerking bouwen
Webhook-levering is nooit gegarandeerd op de eerste poging. Netwerkstoringen, trage responses of een server die net herstart, kunnen een verzoek laten mislukken. Daarom bouwen platforms retry-logica in: bij een non-2xx statuscode proberen ze het verzoek later opnieuw, vaak meerdere keren met toenemende tussenpozen.
De praktische consequentie: jouw endpoint moet razendsnel een 200 OK teruggeven zodra de payload binnenkomt, zelfs voordat de verwerking klaar is. Doe je dat niet, dan ontvang je hetzelfde event dubbel of driedubbel.
- Gebruik een
event_idals idempotentie-key en sla verwerkte ID's op vóór je verdere logica draait. - Werk met database-upserts (
INSERT ... ON CONFLICT UPDATEof vergelijkbaar) in plaats van blinde inserts. - Retourneer
200bij succesvolle ontvangst,4xxbij een structureel foute payload (die het platform niet opnieuw moet proberen) en laat5xxalleen ontstaan bij een echte tijdelijke serverfout.
Bookingmood probeert een mislukte aflevering tot drie keer opnieuw, en de exacte volgorde waarin events aankomen is niet altijd gegarandeerd — bouw je verwerkingslogica dus zo dat een latere updated_at nooit wordt overschreven door een event dat toevallig later binnenkomt maar ouder is.
Testen en debuggen: test-events, logs en veelvoorkomende fouten
Voor je live gaat, wil je zeker weten dat elk onderdeel van de keten werkt: TLS, signature-check, verwerking en foutafhandeling.
- Gebruik de test-events die het platform aanbiedt, of maak een testboeking aan in een sandbox-omgeving en volg die door je eigen logs.
- Zet tijdens ontwikkeling een tool als ngrok of een vergelijkbare request-capturing dienst in, zodat je lokale server webhooks kan ontvangen zonder een publieke server op te tuigen.
- Controleer TLS-configuratie, CORS-instellingen, firewallregels en timeouts stuk voor stuk als events niet aankomen.
- Bewaar de volledige raw payload van elk ontvangen event, ook bij succesvolle verwerking.
Wink adviseert precies dit: log elke inkomende payload, zodat je bij een probleem exact kunt reconstrueren wat er binnenkwam. Ontbrekende logging is een van de meest onderschatte fouten in webhook-integraties; zonder de ruwe payload gok je achteraf naar wat er misging.
Pro-tip: Correleer elke gelogde payload met een intern event-ID in je eigen systeem. Dat versnelt debugging aanzienlijk zodra je een klacht krijgt over een boeking die "niet is aangekomen".
Checklist met best practices voor productie-implementatie
Voor je een webhook-integratie live zet, loop deze punten na:
- HTTPS met geldig, niet-verlopen certificaat op het endpoint.
- Signature-verificatie actief, met een redelijke timestamp-tolerantie (twee tot vijf minuten).
- Idempotentie via
event_id, met database-upserts in plaats van inserts. - Logging van raw payloads, plus monitoring en alerting op mislukte deliveries.
- Selectief abonneren op alleen de events die je systeem echt nodig heeft.
- Een escalatiematrix en rollback-plan voor als een reeks deliveries structureel faalt.
| Aandachtspunt | Waarom het telt |
|---|---|
| HTTPS + certificaat | Zonder geldig certificaat weigert het platform te leveren |
| Signature-verificatie | Voorkomt nepverzoeken en replay-aanvallen |
| Idempotentie | Voorkomt dubbele boekingen in je eigen database |
| Logging en monitoring | Maakt snelle diagnose mogelijk bij storingen |
Een abonnement op te veel events voegt onnodige complexiteit en load toe; beperk je bewust tot wat je systeem daadwerkelijk verwerkt.
RaxBooker als praktisch voorbeeld: webhooks voor boekingen in actie
Binnen RaxBooker verloopt een webhook conceptueel in drie stappen: het platform stuurt het event naar je endpoint, je endpoint zet het event in een verwerkingswachtrij, en een worker doet vervolgens de upsert naar je eigen boekingsdatabase. Die scheiding tussen ontvangen en verwerken is precies waarom snelle 200-responses zo belangrijk zijn.

Ontwikkelaars die een API-koppeling met leisure-software bouwen, herkennen dit patroon: eerst de verbinding vastleggen, dan pas de bedrijfslogica erachter. RaxBooker's reserveringssysteem volgt dezelfde opzet als de voorbeelden hierboven, met events voor nieuwe boekingen, wijzigingen en annuleringen.
Versiebeheer van webhook payloads en endpoints
Payload-structuren veranderen na lancering vrijwel altijd. Een platform voegt een veld toe, hernoemt een status-waarde, of introduceert een nieuw event-type. Zonder versiebeheer breekt zo'n wijziging elke integratie die op de oude structuur vertrouwt.
De meeste volwassen platforms lossen dit op met een expliciete versie in de header (bijvoorbeeld X-Webhook-Version: 2) of in de payload zelf. Als developer moet je twee dingen doen: je parsing-logica zo bouwen dat onbekende velden genegeerd worden in plaats van een crash te veroorzaken, en nooit blind aannemen dat een veld altijd aanwezig blijft.
Praktisch betekent dit dat je defensief parseert: controleer of een veld bestaat voordat je het gebruikt, en log onverwachte structuren in plaats van de hele verwerking te laten falen. Bij een major versie-upgrade van een platform krijg je meestal een migratieperiode waarin beide versies naast elkaar draaien. Gebruik die periode om je code te testen tegen de nieuwe structuur, voordat de oude wordt uitgefaseerd.
Voor endpoint-versiebeheer geldt hetzelfde principe als bij elke API: een nieuwe, incompatibele endpoint-structuur krijgt een nieuw pad (/webhooks/v2/booking) in plaats van de oude URL stilletjes te wijzigen. Zo kunnen bestaande integraties blijven draaien terwijl je nieuwe klanten op de nieuwste versie aansluit.

Gebruik van webhook management tools of platforms
Handmatig elke webhook-aanroep loggen, retryen en debuggen wordt onhoudbaar zodra je meerdere boekingsplatforms of honderden events per dag verwerkt. Daar komen webhook management tools in beeld.
Diensten zoals Svix of Hookdeck zitten tussen het boekingsplatform en jouw endpoint, en nemen taken over als het bufferen van events, automatische retries met exponentiële back-off, en een dashboard waarin je elke aflevering kunt inspecteren. Dat scheelt eigen infrastructuur voor iets dat in de kern een gesolveerd probleem is.
Voor kleinere integraties is dat niet altijd nodig. Een enkele endpoint met goede logging en een idempotentie-check redt het vaak prima zonder extra laag. Zodra je meerdere boekingsbronnen combineert, of wanneer je zakelijk afhankelijk wordt van betrouwbare aflevering, wordt een management-tool waardevoller dan het eigen bouwen van retry-logica en monitoring.
Sommige boekingsplatforms bieden zelf al een vergelijkbaar dashboard aan, met inzicht in verzonden events, foutcodes per aanroep en de mogelijkheid om een mislukte aflevering handmatig opnieuw te versturen. Check dit eerst voordat je een extra tool toevoegt aan je stack: een tussenlaag toevoegen die het platform al aanbiedt, is onnodige complexiteit.
Praktische voorbeelden van implementatie in populaire boekingssystemen
Boekingsplatforms verschillen in de details, maar de kernpatronen komen sterk overeen. Bookingmood stuurt events als bookings.created en payments.paid als JSON naar je geregistreerde endpoint, met signature-verificatie en idempotentie als expliciete aanbevelingen. Wink werkt met een vergelijkbare structuur, maar legt extra nadruk op het loggen van elke payload voor debugdoeleinden.
Voor systemen die niet nativ met webhooks werken, bestaan er tussenoplossingen. Zo zijn er WordPress-integraties, zoals plugins voor edoobox, die boekingsdata doorsturen naar een website of CRM via webhook-achtige mechanismen. Dat werkt goed voor lichte integraties, maar mist vaak de robuustheid van een native webhook-systeem met retries en signature-verificatie.
Grotere platforms zoals de Bookings-API van Square documenteren expliciet hoe je een handler bouwt voor boekingsevents, inclusief voorbeeldcode voor payload-verwerking. Die documentatie is een goed referentiepunt, ook als je zelf met een ander platform werkt: de structuur van event-type, payload-body en verificatiestap is bijna universeel.
Bij een migratie van het ene boekingssysteem naar het andere raden praktijkvoorbeelden een parallelle fase van twee tot vier weken aan, waarin het nieuwe systeem via webhooks realtime meeloopt met het oude. Zo zie je verschillen tussen beide systemen voordat je volledig overschakelt.
Schaalbaarheid en performance overwegingen bij gebruik van webhooks
Eén webhook per boeking lijkt onschuldig, tot je duizenden boekingen per dag verwerkt en je endpoint een piekbelasting van honderden gelijktijdige requests krijgt. Op dat moment worden ontwerpkeuzes die eerder optioneel leken, ineens verplicht.
De eerste maatregel is het loskoppelen van ontvangst en verwerking. Je endpoint accepteert het event, zet het direct in een wachtrij (RabbitMQ, SQS, of een simpele database-queue) en geeft meteen een 200 terug. Een aparte worker verwerkt de wachtrij op zijn eigen tempo, zonder dat het platform op een trage database-transactie moet wachten.
Ten tweede: horizontale schaalbaarheid van je endpoint zelf. Als je verwacht dat het aantal boekingen groeit, zorg dan dat je endpoint achter een load balancer draait met meerdere instances, in plaats van op één server die bij een piek plat kan gaan.
Ten derde speelt database-load een rol die vaak onderschat wordt: bij duizenden upserts per uur moet je indexen op booking_id en event_id goed staan, anders wordt elke upsert langzamer naarmate de tabel groeit. Monitor de verwerkingstijd van je wachtrij continu; een groeiende achterstand is het eerste signaal dat je capaciteit tekortschiet voordat klanten er iets van merken.
Wat de meeste teams over het hoofd zien bij webhooks
De technische kant van webhooks (endpoint, signature, retry-logica) is inmiddels goed gedocumenteerd en relatief eenvoudig te implementeren. Waar het vaak misgaat, is bij de operationele kant: niemand kijkt naar de logs totdat een klant belt over een boeking die "verdwenen" is.
Conventionele adviezen focussen bijna uitsluitend op de eerste implementatie: zet HTTPS aan, verifieer de signature, retourneer 200. Terecht, maar onvolledig. Wat zelden aan bod komt, is dat een webhook-integratie na drie maanden in productie een heel ander risicoprofiel heeft dan op dag één. Payload-structuren veranderen, event-volumes groeien, en de developer die de integratie oorspronkelijk bouwde, is misschien niet meer degene die de logs bekijkt als er iets misgaat.
Mijn advies: investeer relatief meer tijd in monitoring en alerting dan in de eerste implementatie zelf. Een integratie die perfect werkt op dag één, maar zonder alerting draait, faalt op dag negentig zonder dat iemand het merkt. Dat is geen technisch probleem, het is een organisatorisch probleem dat toevallig een technische oorzaak heeft.
— Bernard
RaxBooker en jouw eigen webhook-integratie
RaxBooker biedt developers een directe route om boekingsdata automatisch te synchroniseren met eigen systemen, zonder dat je zelf een polling-mechanisme moet bouwen. Waar handmatige API-polling vertraging en onnodige serverload veroorzaakt, geeft een webhook-integratie via RaxBooker je boekingsgegevens op het moment dat ze ontstaan, direct verwerkbaar in je CRM, kassasysteem of eigen database.

De technische documentatie beschrijft hoe je een endpoint registreert, welke events beschikbaar zijn en hoe signature-verificatie werkt binnen het platform. Voor leisurebedrijven die activiteitenbeheer, offertes en realtime beschikbaarheid al via RaxBooker regelen, is een webhook-koppeling de logische volgende stap richting volledige automatisering van boekingen. Bekijk de mogelijkheden op de pagina over reserveringssoftware voor de leisure en vraag integratiehulp aan om je eerste webhook-endpoint binnen een dag operationeel te krijgen.
Bronnen
- Webhooks | Bookingmood docs
- Webhook-integratie | Wink
- Handle Bookings Webhook Events — Square Developer
Veelgestelde vragen
Wat is het verschil tussen een API en een webhook?
Een API vereist dat jij actief data ophaalt via herhaalde requests (polling), terwijl een webhook andersom werkt: het platform stuurt zelf een HTTP POST naar jouw endpoint zodra er iets gebeurt. Webhooks zijn daardoor sneller en efficiënter voor realtime boekingsevents dan continu pollen.
Hoe werkt een webhook precies?
Een webhook registreer je als URL bij het boekingsplatform; zodra een event optreedt (zoals een nieuwe boeking), stuurt het platform een JSON-payload naar die URL via een HTTP POST-verzoek. Jouw endpoint verwerkt de payload en stuurt een statuscode terug om ontvangst te bevestigen.
Waarom krijgt mijn endpoint geen webhooks binnen?
De meest voorkomende oorzaken zijn een ontbrekend of ongeldig TLS-certificaat, een firewall die inkomende verzoeken blokkeert, of een endpoint die niet publiek bereikbaar is vanaf het internet. Controleer eerst of de URL van buiten je netwerk te bereiken is.
Hoe voorkom je dubbele boekingen bij webhook-retries?
Gebruik een unieke event_id uit elke payload als idempotentie-key en sla verwerkte ID's op voordat je verdere logica uitvoert; combineer dit met database-upserts in plaats van blinde inserts.
Ondersteunt RaxBooker webhooks voor boekingen?
RaxBooker ondersteunt webhook-events voor nieuwe, gewijzigde en geannuleerde boekingen, zodat leisurebedrijven boekingsdata automatisch kunnen doorsturen naar een eigen CRM of kassasysteem.
