Skip to Content
Webhooks

Webhooks

Abonneer je op uitgaande events in plaats van te pollen: Kinmu stuurt een POST naar je HTTPS-endpoint zodra er iets relevants gebeurt. Elke delivery is ondertekend volgens de conventie Standard Webhooks verifieer altijd de handtekening voordat je het event verwerkt.

Het beheren van endpoints vereist de scope webhooks:manage en gebeurt via het dashboard of via de endpoints onder /v1/webhook-endpoints.

Abonneren

Maak een endpoint aan met je URL (HTTPS) en de events die je wilt ontvangen:

curl -s -X POST "https://api.kinmu.app/v1/webhook-endpoints" \ -H "Authorization: Bearer kinmu_sk_live_…" \ -H "Content-Type: application/json" \ -d '{ "url": "https://tu-app.example.com/webhooks/kinmu", "events": ["absence.approved", "checkin.created"], "description": "Sync con nuestro ERP" }'

De response bevat het signing secret (whsec_…), eenmalig zichtbaar. Bewaar het: je hebt het nodig om handtekeningen te verifiëren.

Beschikbaar beheer: GET (lijst), GET /{id}, PATCH /{id} (events/status), DELETE /{id}, POST /{id}/test (stuurt een ping), GET /{id}/deliveries (laatste deliveries) en POST /{id}/deliveries/{deliveryId}/retry (zet een specifieke delivery opnieuw in de wachtrij). Maximaal 5 actieve endpoints per bedrijf.

Events

employee.created, employee.updated, employee.terminated, checkin.created, absence.requested, absence.approved, absence.denied, absence.cancelled, vacation_balance.updated, report.completed, ping.

Event-payload

{ "id": "evt_…", "type": "absence.approved", "created_at": "…", "company_id": "…", "data": { } }

data bevat publieke ids + status (minimaal); haal de volledige resource op via GET wanneer je alle velden nodig hebt.

Handtekening verifiëren

Elke delivery komt binnen met drie headers:

HeaderInhoud
webhook-idUniek id van het event (idempotentie in je receiver).
webhook-timestampUnix-timestamp van verzending.
webhook-signaturev1,<handtekening> (er kunnen meerdere zijn, gescheiden door spaties).

Algoritme: handtekening = base64( HMAC_SHA256( key, "{webhook-id}.{webhook-timestamp}.{rauwe_body}" ) ), met prefix v1,. De key is het deel na whsec_ van het secret (eenmalig getoond bij het aanmaken van de webhook), gedecodeerd van base64 naar bytes. Onderteken de rauwe body (de exact ontvangen bytes), niet de opnieuw geserialiseerde JSON.

Verificatie (wijs af als de handtekening niet klopt of als webhook-timestamp meer dan 5 minuten van je klok afwijkt):

const crypto = require('crypto'); function verify(secret, headers, rawBody) { const id = headers['webhook-id']; const ts = headers['webhook-timestamp']; if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // ±5 min const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64'); const expected = 'v1,' + crypto .createHmac('sha256', key) .update(`${id}.${ts}.${rawBody}`) .digest('base64'); return headers['webhook-signature'] .split(' ') .some(sig => crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))); }

Verifieer en onderteken de rauwe body (de exact ontvangen bytes), niet de opnieuw geserialiseerde JSON — elke herformattering maakt de handtekening ongeldig. Gebruik het webhook-id als idempotentiesleutel in je receiver om herverzendingen te negeren.

Retries

Bij een fout (of een response ≠ 2xx) doet Kinmu retries met backoff: 1 m, 5 m, 30 m, 2 u, 12 u, 24 u. Antwoord snel met 2xx; verwerk async als het langer duurt. Een endpoint dat 7 dagen achter elkaar faalt, wordt automatisch gedeactiveerd.

Je kunt een mislukte delivery handmatig opnieuw in de wachtrij zetten met POST /v1/webhook-endpoints/{id}/deliveries/{deliveryId}/retry (gebruik het id van de delivery uit GET /{id}/deliveries).

Best practices

Antwoord snel, verwerk op de achtergrond

Verifieer de handtekening, zet het werk in een queue en antwoord direct met 2xx.

Verifieer altijd de handtekening

Verwerk geen enkele payload zonder webhook-signature te verifiëren. Behandel het secret als een credential.

Wees idempotent

Dedupliceer op webhook-id. Retries zijn normaal.

Test met ping

Gebruik POST /v1/webhook-endpoints/{id}/test om een ping-event te ontvangen en je integratie end-to-end te valideren.

Last updated on