Skip to Content
Webhooks

Webhooks

Plutôt que de faire du polling, abonnez-vous aux événements sortants : Kinmu envoie un POST à votre endpoint HTTPS quand un événement pertinent se produit. Chaque livraison est signée selon la convention Standard Webhooks  — vérifiez toujours la signature avant de traiter l’événement.

La gestion des endpoints requiert le scope webhooks:manage et s’effectue depuis le dashboard ou via les endpoints /v1/webhook-endpoints.

Abonnement

Créez un endpoint en indiquant votre URL (HTTPS) et les événements qui vous intéressent :

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" }'

La réponse inclut le secret de signature (whsec_…), visible une seule fois. Conservez-le : il vous servira à vérifier les signatures.

Gestion disponible : GET (liste), GET /{id}, PATCH /{id} (événements/état), DELETE /{id}, POST /{id}/test (envoie un ping), GET /{id}/deliveries (dernières livraisons) et POST /{id}/deliveries/{deliveryId}/retry (remet en file une livraison précise). 5 endpoints actifs maximum par entreprise.

Événements

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

Payload de l’événement

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

data contient les ids publics + un état minimal ; réhydratez la ressource complète via GET quand vous avez besoin de tous les champs.

Vérification de la signature

Chaque livraison arrive avec trois headers :

HeaderContenu
webhook-idId unique de l’événement (idempotence côté récepteur).
webhook-timestampTimestamp Unix de l’envoi.
webhook-signaturev1,<signature> (plusieurs signatures possibles, séparées par des espaces).

Algorithme : signature = base64( HMAC_SHA256( key, "{webhook-id}.{webhook-timestamp}.{corps_brut}" ) ), préfixée par v1,. La key est la partie après whsec_ du secret (affiché une seule fois à la création du webhook), décodée de base64 en bytes. Signez le corps brut (les bytes exacts reçus), pas le JSON re-sérialisé.

Vérification (rejetez si la signature ne correspond pas ou si webhook-timestamp s’écarte de plus de 5 min de votre horloge) :

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))); }

Vérifiez et signez sur le corps brut (les bytes exacts reçus), pas sur le JSON re-sérialisé — tout reformatage invalide la signature. Utilisez le webhook-id comme clé d’idempotence côté récepteur pour écarter les renvois.

Nouvelles tentatives

En cas d’échec (ou de réponse ≠ 2xx), Kinmu réessaie avec un backoff : 1 min, 5 min, 30 min, 2 h, 12 h, 24 h. Répondez 2xx rapidement ; traitez en asynchrone si le traitement est long. Un endpoint en échec pendant 7 jours consécutifs est désactivé automatiquement.

Vous pouvez remettre en file manuellement une livraison échouée avec POST /v1/webhook-endpoints/{id}/deliveries/{deliveryId}/retry (utilisez l’id de la livraison visible dans GET /{id}/deliveries).

Bonnes pratiques

Répondez vite, traitez en arrière-plan

Vérifiez la signature, mettez le travail en file d’attente et répondez 2xx immédiatement.

Vérifiez toujours la signature

Ne traitez aucun payload sans vérifier webhook-signature. Traitez le secret comme un identifiant sensible.

Soyez idempotent

Dédupliquez par webhook-id. Les renvois sont normaux.

Testez avec ping

Utilisez POST /v1/webhook-endpoints/{id}/test pour recevoir un événement ping et valider votre intégration de bout en bout.

Last updated on