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 :
| Header | Contenu |
|---|---|
webhook-id | Id unique de l’événement (idempotence côté récepteur). |
webhook-timestamp | Timestamp Unix de l’envoi. |
webhook-signature | v1,<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) :
Node.js
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.