Aller au contenu

Webhooks

Les webhooks permettent à Logistall de pousser les changements de statut d’expédition vers votre propre point de terminaison au lieu que vous interrogiez /v1/shipments. C’est distinct de l’API de lecture /v1/* — les abonnements se gèrent dans l’application web Logistall, pas via un appel d’API public.

Les abonnements webhook se créent depuis la section Webhooks de la page Clés API (la même page où vous créez les clés API — voir Authentification et la FAQ du Guide utilisateur). L’ajout d’un abonnement demande :

  • URL du point de terminaison — où Logistall enverra la charge utile de l’événement en POST.
  • Événement — il n’existe actuellement qu’un seul type d’événement : shipment.status_changed.
  • Secret (facultatif) — sert à signer les livraisons pour que vous puissiez vérifier qu’elles proviennent bien de Logistall. Fortement recommandé ; sans secret, les livraisons sont envoyées non signées.

Les abonnements peuvent être supprimés depuis la même page, ce qui arrête les livraisons futures vers cette URL.

shipment.status_changed se déclenche chaque fois que le champ status d’une expédition change via l’application (par exemple, un répartiteur ou un chauffeur qui fait passer une expédition de pickup_scheduled à in_transit).

{
"event": "shipment.status_changed",
"tenantId": "7f2a1c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"shipmentId": "3f1c9c2a-6b3e-4b3a-9b2d-1a2b3c4d5e6f",
"shipmentNumber": "SHP-00482",
"oldStatus": "pickup_scheduled",
"newStatus": "in_transit",
"at": "2026-07-13T09:15:00.000Z"
}

Le Content-Type est application/json.

Si votre abonnement a un secret configuré, chaque livraison inclut :

X-Logistall-Signature: sha256=<hex-encoded HMAC-SHA256>

La signature est un HMAC-SHA256 du corps brut exact de la requête (le texte JSON tel qu’envoyé, pas une version resérialisée), avec le secret de votre webhook comme clé. Calculez le même HMAC de votre côté et comparez.

// Node.js (Express) example. Requires the RAW request body as a string/Buffer —
// re-stringifying a parsed JSON object can reorder keys and break the comparison.
const crypto = require('crypto');
function verifyLogistallSignature(rawBody, signatureHeader, secret) {
if (!signatureHeader || !signatureHeader.startsWith('sha256=')) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const provided = signatureHeader.slice('sha256='.length);
const a = Buffer.from(expected, 'hex');
const b = Buffer.from(provided, 'hex');
if (a.length !== b.length) return false;
return crypto.timingSafeEqual(a, b);
}
// Express route — use express.raw() (not express.json()) so req.body is a Buffer.
app.post(
'/webhooks/logistall',
express.raw({ type: 'application/json' }),
(req, res) => {
const ok = verifyLogistallSignature(
req.body,
req.header('X-Logistall-Signature'),
process.env.LOGISTALL_WEBHOOK_SECRET
);
if (!ok) return res.status(401).send('Invalid signature');
const event = JSON.parse(req.body.toString('utf8'));
// ... handle event ...
res.status(200).end();
}
);

Si votre abonnement n’a pas de secret défini, les livraisons sont envoyées sans l’en-tête X-Logistall-Signature — il n’y a rien à vérifier.

Chaque tentative de livraison a un délai d’expiration de 5 secondes. En cas d’échec (erreur réseau, expiration du délai ou réponse non-2xx), Logistall réessaie jusqu’à 3 tentatives au total pour cette livraison, avec un court délai avant les 2e et 3e tentatives (environ 200 ms, puis 800 ms). Si les 3 tentatives échouent, la livraison est marquée comme non aboutie et n’est plus retentée — il n’y a pas de nouvelle livraison planifiée après cette fenêtre.

Votre point de terminaison doit répondre rapidement avec un statut 2xx dès qu’il a durablement accepté l’événement ; effectuez les traitements plus lourds de manière asynchrone plutôt que dans le gestionnaire de requête, pour ne pas dépasser le délai de 5 secondes.

Chaque tentative de livraison (URL, code de statut reçu, nombre de tentatives, succès/échec et la dernière erreur le cas échéant) est enregistrée en interne au niveau de l’abonnement. À ce jour, il n’existe ni page dans l’application ni point de terminaison API pour consulter cet historique vous-même — si une livraison semble échouer, vérifiez les journaux de votre propre point de terminaison, ou communiquez l’URL de l’abonnement et l’heure approximative pour qu’une vérification puisse être faite côté serveur.