Webhooks
Webhooks bieden een manier om automatisch notificaties te ontvangen wanneer bepaalde gegevens toegevoegd, gewijzigd of verwijderd zijn. Dit maakt het mogelijk om systemen up-to-date te houden zonder handmatige polling.
Het instellen van webhooks begint met het aanmaken van een subscriptie via ds_wm_webhook_subscriptie.
Bij het aanmaken van een subscriptie, kan bepaald worden welke dataservice gegevens wel of geen webhooks moeten versturen. De webhooks worden dan verstuurd naar het opgegeven url telkens wanneer de gegevens veranderen.
Deze handleiding beschrijft:
- Het proces voor het beheren van subscripties
- De structuur van de verzonden webhook-berichten
- De verwerking van webhooks
- De lijst van beschikbare eventtypes
Subscripties beheren
Subscriptie aanzetten
Een nieuwe subscriptie kan aangezet worden door minstens 1 eventtype aan te zetten met een nieuwe unieke URL. Voor het aanmaken van een subscriptie is een URL nodig, waar de webhooks naartoe gestuurd worden.
Notitie
Het maximum aantal subscripties per werkmaatschappij is 5.
Subscriptie uitzetten
Een subscriptie wordt automatisch uitgezet wanneer alle eventtypes uit staan. Dit kan ook eenvoudig door parameter stopsubscriptie mee te sturen met true als waarde.
Waarschuwing
Zodra wij detecteren dat een URL (afkomstig van een test website) is verlopen, zullen wij deze verwijderen.
Webhook structuur
Bij een wijziging in de gegevens wordt een HTTP POST-request verstuurd naar het opgegeven url. De payload bevat informatie over het eventtype en de bijbehorende gegevens in JSON format.
Voorbeeld webhook:
Header:
| connection | keep-alive |
|---|---|
| x-signature | SHA1-base64 khldRWN+Gz4yPIOAuQG0jMCc4LYXZh7rgrS7Bm1i7/NT7p+J+a4mpLC2efOFuGCbO2oBtFRtAJDLHmk1MscTTs85TqiAv6QHveqXTTOpLlKpeMpL3+CQVs0iqPI8Tdx7yFai1kDqghRmwVwHkw24yN629GTtmwRM/R37TQubkMY7UNLl22j98s1c/k2BpBLm7Cm9wsKpxK5YlK85fKXZBd7ZSakYXqZfDi4460OQUmNXP+JFvfwsU0tyrNag8w/jpqetmmG6qA0JkwAl+oN0fzeejA1mYEy77coxULfeaafSqM7WijYgQEbpY43/lcKEcwchqgp4wPq7Jm6cLICZApxDoYuahSoluMZJBD+yvibsk0Rk8Z3h1IZfRtEmG30hRnfYnSQ1tYezfWkQJb37U8CisyAaN47lH+jwWYjEtspJaTkqXIo2kDF3dShcP5s6RcBvuwb+NQ3VtKJB3NirJGx4a57eG/xzeIqnSHr2p4BSMlXnKORXdxGr18SOgThR3LVncHrO1Sa6OQ+K/hgJZE0yk3VZbCRrB3b2XA8qDbh70jLtb/9N7P1apF3mmZxe8PJsYUIdlutMsz8nW0gkoz9Q+18WcxV/CsQ23/Ikf3qyCoqPN1NgVq7C8nBomDSiS0Mzve6UutPHLdV6KWn0MM/ZekOyqjHqU5gcaxiSS4E= |
| content-type | application/json |
| content-length | 717 |
| user-agent | Trinc-Prolog |
| accept | */* |
Request body:
{
"wmnr": 9999,
"timestamp": "2025-07-01T09:09:09",
"events": [
{
"type": "ds_fw_loonkostenvoordeel",
"actie": 27490,
"data": [
{
"field": "registratienummer",
"value": 999
},
{
"field": "datumingang",
"value": "2025-07-01"
},
{
"field": "regeling",
"value": 999
}
],
"timestamp": "2025-07-01T09:09:09"
},
{
"type": "ds_fw_loonkostenvoordeel",
"actie": 27491,
"data": [
{
"field": "registratienummer",
"value": 999
},
{
"field": "datumingang",
"value": "2025-07-01"
},
{
"field": "regeling",
"value": 999
}
],
"timestamp": "2025-07-01T09:09:09"
},
{
"type": "ds_fw_loonkostenvoordeel",
"actie": 27492,
"data": [
{
"field": "registratienummer",
"value": 999
},
{
"field": "datumingang",
"value": "2025-07-01"
},
{
"field": "regeling",
"value": 999
}
],
"timestamp": "2025-07-01T09:09:09"
}
],
"test_webhook": true
}
Webhook object:
| Attribuut | Type | Omschrijving |
|---|---|---|
| wmnr | integer | Nummer van de werkmaatschappij. |
| timestamp | datetime | Datumtijd webhook verwerking. |
| events | array | Event objecten van de gewijzigde gegevens. |
| test_webhook | boolean | Indicator of het een test webhook is. |
Event object:
| Attribuut | Type | Omschrijving |
|---|---|---|
| type | string | Eventtype van de webhook. |
| actie | integer | Code van uitgevoerde actie: 27490 Insert 27491 Update 27492 Delete |
| data | array | Data objecten van het event object. Dit zijn de benodigde parameters en hun value voor het ophalen van het gewijzigde object via de dataservice. |
Data object:
| Attribuut | Type | Omschrijving |
|---|---|---|
| field | string | Naam van de field. |
| value | field afhankelijk | De waarde van de field. |
Webhook verwerking
Een webhook wordt maximaal 5 seconden na een wijziging verstuurd. Bij wijzigingen van meerdere eventtypes, worden de gegevens gegroepeerd tot 1 webhook request. De event objecten zijn gesorteerd op type en actie. Een webhook request bevat maximaal 1000 event objecten.
Validatie
De webhook requests bevatten een X-Signature header voor verificatie van de afzender. De signature wordt gegenereerd door een SHA1-hash van de request body te ondertekenen met een RSA-private key. De public key voor het verifiëren is:
MIICCgKCAgEAl2oGoJZH7pSrD8ZlgXMHSSFDjifc+LqCrJhzoSdIK/iTYPmj4p/Ccam4XE7v/kkCVmEM3UjRu
BTfGwwsbak8JOuHjEIqhtWf+AP0xHIdfilvdPpDOmN3Mt88nKTyfRs4I62wcu9WCzL9Lt+81dXMfiH5MDshJa
NLq5WWFNmbrPPGK5VhcejEdpR5tdIgf4yxBvl4FyAJkvZlDZZslOIWVbqJE2ntXgUarloPza+whyI3h0xX2Bj
IU6Fygw4eWfsS003MwsOIv4eKhzk3u5h3IEkXzMl4TF57y5fIrnim/aUT5PgU6EHy4x840fCmQW/XQQ5VExCD
DU8lpN1WFE4qyYcRzFJALa78t2oaiFz2BPlartyfLwDwD0bd1mLp7MwS3InOp/olfJHViRPCc56nR7+Rycyhj
oibOWYbGBLX0c0RlqB4P1W0gkwnFivXms52rR2u6YE5jjjxwYRVxYPWMfNrBlzRbqL4V0hAPtVUewDRU/MV+j
m0iO9RPDraOolXnFXL/so6OYHjrT2ZEgaL1iGw1cq10tAAg6Fde2YXsl7ZydhWfqLKMC2graWIRCA5UdDQy9D
19zBZ5lYdQ5bzdcddUwZDKLGEPYQzLQqUOd5JO0sQrsnHU7j7PSEa4ONfF3TI/vM1bC1DhTiXdcGuvS1wLC0B
TKeibhoZcbtUk10CAwEAAQ==
Retry
Wanneer een webhook niet succesvol is afgeleverd, wordt automatisch een retry gestart. De retry heeft een exponentiële backoff met een maximale wachttijd van 120 minuten tussen de pogingen. Hieronder alle kenmerken op een rij:
- Maximaal aantal retries: 100
- Initiële wachttijd: 2 minuten
- Backoff-strategie: wachttijd verdubbelt na elke mislukte poging
- Maximale wachttijd: zodra 120 minuten is bereikt, blijft de wachttijd gelijk voor alle volgende retries
- Retry's stoppen na 100 mislukte pogingen of een succesvolle aflevering
Wachttijd per poging:
| Poging | Wachttijd sinds vorige poging |
|---|---|
| 1 | 2 minuten |
| 2 | 4 minuten |
| 3 | 8 minuten |
| 4 | 16 minuten |
| 5 | 32 minuten |
| 6 | 64 minuten |
| 7 | 120 minuten (limiet bereikt) |
| 8–100 | 120 minuten |
Totale duur
- Poging 1 t/m 6 = 2 + 4 + 8 + 16 + 32 + 64 = 126 minuten
- Poging 7 t/m 100 = 94 pogingen × 120 minuten = 11.280 minuten
- Totale duur retry-proces ≈ 11.406 minuten ≈ 7 dagen en 22 uur
Waarschuwing
Dit betekent dat het systeem maximaal ongeveer 8 dagen blijft proberen de webhook opnieuw te versturen. Wanneer de 100ste poging is bereikt, zal contact opgenomen worden met desbetreffende werkmaatschappij.
Twee weken na de 100ste poging zal de subscriptie uitgezet worden.
Eventtypes
Elk eventtype heeft eigen set data fields voor het ophalen van de gewijzigde gegevens. Hieronder is een overzicht van beschikbare eventtypes en hun parameters.
| Eventtypes | Data fields (parameter) |
|---|---|
| ds_fw_apg_inkomstenverhouding | registratienummer numiv |
| ds_fw_arbeidscontract | contractnummer |
| ds_fw_factuurgegevens | factuuridnummer |
| ds_fw_fases | fasenummer |
| ds_fw_inkomstenverhoudingen | fwregistratienummer plaatsingnummer lhregistratienummer numiv srtiv |
| ds_fw_jaaropgavegegevens | jaaropgavenummer |
| ds_fw_loonkostenvoordeel | registratienummer datumingang regeling |
| ds_fw_loonopgave | registratienummer ingangsdatum |
| ds_fw_loonspecificatiegegevens | loonspecificatienummer |
| ds_fw_opleidingen | opleidingnummer |
| ds_fw_persoonsgegevens_all | registratienummer |
| ds_fw_profielfoto | fwregistratienummer |
| ds_fw_reserveringen | reserveringnummer |
| ds_fw_tijdvoortijd_plaatsing | plaatsingnummer sectorrisicogroep |
| ds_fw_timecards | registratienummer |
| ds_fw_vaste_beloningen | beloningsnummer |
| ds_fw_werkervaringen | werkervaringnummer |
| ds_fw_wwpremie | registratienummer datumgeldigheid |
| ds_rf_declaraties_all | rf_decl_declnr |
| ds_rf_documentgegevens | documentnummer |
| ds_rf_loon_tarieven | lotanr |
| ds_rf_sollicitaties | sollicitatienummer |
| ds_rf_uitsluitingen | fwregistratienummer rlregistratienummer |
| ds_rl_aanvragen | aanvraagnummer |
| ds_rl_bedrijfsgegevens | registratienummer |
| ds_rl_contactpersonen | contactpersoonsnummer |
| ds_rl_factuurgegevens | factuuridnummer |
| ds_rl_ilb_functies_beroepsgroepen | registratienummer |
| ds_rl_journaalposten | jpdnr |
| ds_rl_kostenplaatsen | kostenplaatsnummer |
| ds_rl_loonschemas | loonschemanummer |
| ds_rl_meld_werkadressen | nummer |
| ds_rl_plaatsingen | plaatsingnummer |
| ds_rl_reserveringsschemas | rlregistratienummer schemanummer |
| ds_rl_sectoren | rlregistratienummer sectornummer |
| ds_rl_tariefschemas | tariefschemanummer |
| ds_wm_administratie | Voor deze service keert er geen data terug. |
| ds_wm_businessunits | bunr |
| ds_wm_document_folders | foldernummer |
| ds_wm_document_types | documentnummer |
| ds_wm_eigenaarsrechten | medewerkernummer |
| ds_wm_financiele_administratie | loonjaar |
| ds_wm_ilb_inleners | inlenerid |
| ds_wm_ilb_versie | registratienummer |
| ds_wm_inlenersbeloningen | inlenersbeloningnummer |
| ds_wm_locaties | locatienummer |
| ds_wm_loonbelasting | lhnr |
| ds_wm_looncomponenten | lcnr |
| ds_wm_loonjaren | loonjaar |
| ds_wm_loonschemas | registratienummer |
| ds_wm_medewerkers | medewerkernummer |
| ds_wm_notificaties | notitienummer |
| ds_wm_rekeningschema | rekeningschemanummer |
| ds_wm_reserveringsschemas | reserveringsschemanr |
| ds_wm_sectoren | sectornummer |
| ds_wm_tariefschema_artiest | registratienummer ingangsdatum |
| ds_wm_tariefschemas | registratienummer |
| ds_wm_vertalingen | taalnummer |
| ds_wr_loonschema_spec | loonschemanummer |
| ds_wr_tariefschema_spec | tariefschemanummer |