Des signaux fiables pour le travail qui prend du temps
Des requêtes HTTPS signées quand tâches, domaines, publications ou approbations changent, livrées au moins une fois.
Enregistrer un point d’accès
Ajoutez un point d’accès dans Développeurs, ou avec la portée webhooks:write :
curl -s -X POST "$BASE/workspaces/$WS/webhooks" \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $(openssl rand -hex 16)" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.example.com/mini-casa","events":["job.updated","publication.updated"]}'La réponse contient signing_secret (whsec_...), affiché une seule fois. L’URL doit utiliser HTTPS sur le port 443 et ne résoudre que vers des adresses publiques. Les cibles privées, de bouclage et internes sont refusées, le contrôle est répété avant chaque livraison et les redirections ne sont jamais suivies. Un espace accepte jusqu’à 10 points d’accès actifs.
Prouver que vous le contrôlez
Les nouveaux points d’accès commencent à l’état pending_verification. Le bouton Vérifier (ou POST /webhooks/{id}/verify) envoie un seul webhook.challenge signé. Répondez 2xx avec {"challenge": "<data.challenge>"} et le point d’accès devient active.
Événements
job.updated: une tâche ou un lot change d’état.job.item.updated: un élément de lot change d’état.domain.updated: un domaine personnalisé avance dans ses contrôles.publication.updated: une construction démarre, réussit, échoue ou est remplacée.approval.updated: une approbation est décidée, expire ou est utilisée.billing.entitlement.updated: le forfait ou les droits d’accès changent.
Les corps ne portent que des identifiants et un état, jamais des identifiants secrets, du contenu ou des données personnelles. Lisez l’état actuel avec l’API.
Vérifier chaque requête
Chaque requête comporte SmallWorld-Webhook-Id, SmallWorld-Webhook-Timestamp (secondes Unix) et SmallWorld-Webhook-Signature (v1=<hex>,kid=<key id>). La signature est le HMAC-SHA256 de <timestamp>.<raw body> avec votre secret. Utilisez le corps brut avant toute analyse JSON, comparez en temps constant et refusez les horodatages écartés de plus de cinq minutes de votre horloge.
import crypto from "node:crypto";
export function verify(secret, timestamp, rawBody, header) {
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
const given = /v1=([a-f0-9]+)/.exec(header)?.[1] ?? "";
const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
return fresh && given.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}Garanties de livraison
- Au moins une fois. Une requête se répète jusqu’à une réponse
2xx. L’identifiant d’événement reste identique à chaque tentative et relivraison : stockez-le et ignorez ceux déjà vus. - Les nouvelles tentatives s’espacent d’une minute à une journée, pendant 72 heures au total. Ensuite, la livraison est en échec définitif et peut être renvoyée depuis Développeurs ou avec
redeliver_webhook. - Un point d’accès ayant 10 événements en échec définitif d’affilée est suspendu jusqu’à sa reprise.
- L’ordre n’est pas garanti : considérez l’état comme un indice et relisez la ressource.