Wat is een webhook? Hoe apps elkaar op de hoogte brengen
Een webhook is een automatisch bericht dat een dienst naar je app stuurt op het moment dat er iets gebeurt. Wanneer de betaling van een klant slaagt, stuurt Stripe een webhook naar een adres in je app met de melding ‘betaling geslaagd, hier zijn de details’, en je app reageert — markeert de bestelling als betaald, stuurt een bon, of activeert het account. Kort gezegd: een API is je app die een andere dienst een vraag stelt; een webhook is de andere dienst die je app belt om iets te melden.
Waarom het ertoe doet als je met AI bouwt
Zodra je app betalingen aanneemt, formulierinzendingen van een andere tool ontvangt, of verbinding maakt met diensten als GitHub, Shopify of een agenda, kom je webhooks tegen. Ze zijn meestal de juiste manier om te weten dat er iets gebeurd is — maar ook daar zitten AI-gebouwde apps het vaakst subtiel fout:
- Het eindpunt accepteert elk verzoek, dus iedereen kan een nep-‘betaling geslaagd’-gebeurtenis versturen.
- De app verleent toegang op de checkout-terugkeerpagina in plaats van via de webhook, dus mensen die het tabblad vroeg sluiten krijgen nooit wat ze hebben betaald, en mensen die de succes-URL vinden krijgen het gratis.
- Dezelfde gebeurtenis komt twee keer binnen en de klant krijgt twee bestellingen of twee e-mails.
Weten hoe webhooks werken, helpt je om de beveiliging vooraf te vragen.
Een alledaagse vergelijking: een bezorgsms
Je kunt op twee manieren weten of je pakket is aangekomen. Je kunt elke tien minuten naar de voordeur lopen om te kijken (dat is pollen — je app die steeds een API aanroept om te vragen ‘is er iets nieuws?’). Of de koerier kan je een sms sturen zodra het bezorgd is (dat is een webhook).
De sms is duidelijk beter — zolang je hem kunt vertrouwen. Als iedereen je een bericht ‘pakket bezorgd’ zou kunnen sturen, wil je iets hebben waarmee je kunt controleren of het echt van de koerier komt. En als je telefoon uit stond toen de sms binnenkwam, wil je dat de koerier het later opnieuw probeert. Die twee zorgen — verificatie en nieuwe pogingen — vormen het grootste deel van wat webhooks lastig maakt.
Hoe een webhook werkt, stap voor stap
- Je maakt een eindpunt in de backend van je app: een URL zoals
https://yourapp.com/webhooks/stripediePOST-verzoeken accepteert. - Je registreert die URL bij de provider en kiest welke gebeurtenissen je wilt (bijvoorbeeld ‘checkout voltooid’ en ‘abonnement opgezegd’).
- De provider geeft je een ondertekeningsgeheim. Je slaat het op als secret op je server — zie omgevingsvariabelen en secrets.
- Er gebeurt iets. De provider stuurt een HTTP-verzoek naar je URL met een JSON-body die de gebeurtenis beschrijft, plus een handtekeningheader.
- Je app verifieert de handtekening, slaat het gebeurtenis-ID op, antwoordt snel met een succescode (
200) en voert dan het werk uit. - Als je app geen succes teruggeeft, proberen veel providers het later opnieuw.
Handtekeningen
Een handtekening bewijst dat het verzoek van de provider komt en niet is gewijzigd. Stripe berekent bijvoorbeeld een HMAC (een soort gesleutelde vingerafdruk) met SHA-256 over de requestbody en een tijdstempel, met het ondertekeningsgeheim, en stuurt die in een Stripe-Signature-header. Je app doet dezelfde berekening met zijn eigen kopie van het geheim; als de uitkomsten overeenkomen, is het verzoek echt. Omdat het tijdstempel ook ondertekend is, kun je oude verzoeken afwijzen die iemand heeft opgenomen en later opnieuw afspeelt — de bibliotheken van Stripe gebruiken volgens hun documentatie per september 2026 standaard een tolerantie van vijf minuten.
Een praktisch detail: de handtekening wordt berekend over de ruwe requestbody. Als je framework de JSON parseert en opnieuw opmaakt voordat je verifieert, mislukt de controle. Dit is een zeer veelvoorkomende bug.
Nieuwe pogingen, duplicaten en volgorde
Providers verschillen, dus controleer de documentatie van elke provider. Per september 2026:
| Gedrag | Stripe | GitHub |
|---|---|---|
| Automatische nieuwe pogingen | Ja, tot drie dagen met oplopende tussenpozen in de livemodus | Nee; mislukte leveringen lever je handmatig of via een script opnieuw |
| Reactietijd | Antwoord snel met een 2xx, vóór elk traag werk | Een levering die er langer dan 10 seconden over doet om te antwoorden, telt als mislukt |
De documentatie van Stripe zegt ook dat gebeurtenissen niet gegarandeerd in de volgorde van hun optreden aankomen, en dat dezelfde gebeurtenis af en toe meer dan één keer kan binnenkomen. Daarom raadt Stripe aan gebeurtenis-ID’s bij te houden.
De algemene les geldt voor elke provider: gebeurtenissen kunnen laat, meer dan één keer en in de verkeerde volgorde aankomen. Je handler moet idempotent zijn — dezelfde gebeurtenis twee keer verwerken heeft hetzelfde effect als één keer.
Een uitgewerkt voorbeeld: een betaalde cursus ontgrendelen
Je verkoopt een online cursus. Een student klikt op Kopen, betaalt op de gehoste checkoutpagina van Stripe en wordt teruggestuurd naar je site.
De kwetsbare manier: de pagina ‘bedankt’ ontgrendelt de cursus. Als de student de browser sluit tijdens de doorverwijzing, heeft hij betaald maar geen toegang. Als iemand de bedank-URL raadt, krijgt hij toegang zonder te betalen.
De webhookmanier:
- Zodra Stripe de betaling bevestigt, stuurt het een
checkout.session.completed-gebeurtenis naar/webhooks/stripe. - Je backend verifieert de handtekening met het ondertekeningsgeheim. Als dat mislukt, antwoordt hij
400en doet verder niets. - Hij controleert of dat gebeurtenis-ID al is verwerkt. Zo ja, antwoordt hij
200en stopt. - Hij slaat het gebeurtenis-ID op, antwoordt
200, en verleent daarna de student toegang en stuurt een welkomstmail. - De pagina ‘bedankt’ zegt alleen ‘Betaling ontvangen — je cursus verschijnt zo’ en controleert de toegangsstatus van de student.
Als later een abonnement wordt opgezegd of een kaart wordt geweigerd, vertellen andere webhookgebeurtenissen je app om de toegang te verwijderen of te pauzeren. Zo blijven abonnementsproducten in sync met de facturatie — zie wat SaaS is en hoe je betalingen aan je app toevoegt.
Kernbegrippen
- Eindpunt: de URL in je app die webhooks ontvangt.
- Gebeurtenis / payload: wat er is gebeurd, en de data die het beschrijft (meestal JSON).
- Ondertekeningsgeheim: het gedeelde geheim waarmee handtekeningen worden gecontroleerd.
- Idempotent: veilig om meer dan één keer uit te voeren met hetzelfde resultaat.
- Pollen: steeds een API vragen om wijzigingen, in plaats van op een webhook te wachten.
- Tunnel: een hulpmiddel dat een laptop tijdelijk een publieke URL geeft, zodat webhooks tijdens de ontwikkeling kunnen aankomen.
Veelgemaakte fouten en misverstanden
- Handtekeningen niet verifiëren. De eindpunt-URL is geen geheim. Verificatie is wat het verzoek betrouwbaar maakt.
- Traag werk doen voordat je antwoordt. E-mails sturen of PDF’s genereren vóór je reageert kan time-outs veroorzaken, die nieuwe pogingen veroorzaken, die duplicaten veroorzaken.
- Aannemen dat iets precies één keer en in volgorde komt. Sla gebeurtenis-ID’s op en vertrouw niet op de aankomstvolgorde.
- Een preview-URL gebruiken. Webhooks hebben een stabiel, publiek adres nodig. Privépreviews en
localhostzijn niet bereikbaar vanaf internet; gebruik je gepubliceerde URL (of een tunnel tijdens het testen). - Test- en live-geheimen door elkaar halen. Providers geven vaak verschillende ondertekeningsgeheimen uit voor de test- en livemodus. Bewaar beide en gebruik het juiste.
- De payload blind vertrouwen bij belangrijke beslissingen. Voor acties met veel op het spel is het verstandig de laatste status op te halen via de API van de provider nadat je de gebeurtenis hebt ontvangen.
Wat je aan je AI-builder kunt vragen
Voeg een
POST /webhooks/stripe-eindpunt toe op de server. Verifieer de Stripe-handtekening met de ruwe requestbody en het geheimSTRIPE_WEBHOOK_SECRET. Wijs ongeldige handtekeningen af met 400. Sla elk gebeurtenis-ID op en sla gebeurtenissen over die al zijn verwerkt. Antwoord snel met 200, en verwerk daarnacheckout.session.completeddoor de bestelling als betaald te markeren en de bon te sturen. Log het gebeurtenistype. Verleen geen toegang vanaf de succespagina van de checkout.
Test het daarna: stuur een testgebeurtenis vanuit het dashboard van de provider, stuur dezelfde nogmaals, en stuur een verzoek met een verkeerde handtekening. Alleen de eerste mag iets veranderen.
Webhooks op Mythex
Mythex draait geen aparte webhookdienst; je vraagt de agent om een webhookeindpunt toe te voegen in de eigen backend van je app, en laat de provider naar je gepubliceerde URL wijzen, omdat webhooks een publiek adres nodig hebben. Het ondertekeningsgeheim gaat in de secrets van je project, en als je het op een live app wijzigt, publiceer je opnieuw. Het docs-recept over webhooks afhandelen bevat een startprompt, en store-templates zijn een goed startpunt voor apps die betalingen aannemen.
Veelgestelde vragen
Wat is een webhook in eenvoudige woorden?
Een webhook is een automatisch bericht dat een dienst naar een webadres in je app stuurt op het moment dat er iets gebeurt, zoals een geslaagde betaling of een verzonden formulier. In plaats van dat je app steeds vraagt of er iets is veranderd, vertelt de andere dienst het zelf.
Wat is het verschil tussen een webhook en een API?
Met een API-aanroep vraagt je app een andere dienst om iets en krijgt het een antwoord. Met een webhook roept de andere dienst je app aan wanneer er een gebeurtenis plaatsvindt. Veel integraties gebruiken beide: webhooks om gebeurtenissen door te krijgen, API-aanroepen om details op te halen of een actie uit te voeren.
Zijn webhooks veilig?
Dat kunnen ze zijn, als je ze verifieert. Goed opgezette providers ondertekenen elke webhook met een geheim dat alleen met jou wordt gedeeld, en je app moet elk verzoek weigeren waarvan de handtekening niet klopt. Zonder die controle kan iedereen die de URL vindt nep-gebeurtenissen sturen.
Wat gebeurt er als mijn app offline is op het moment dat een webhook wordt verzonden?
Dat hangt af van de provider. Stripe probeert mislukte leveringen bijvoorbeeld tot drie dagen lang opnieuw in de livemodus, terwijl GitHub niet automatisch opnieuw probeert en verwacht dat je opnieuw levert. Controleer de documentatie van elke provider, en ontwerp je handler zo dat hij met late of herhaalde gebeurtenissen overweg kan.