Webhooks
Des événements envoyés à votre serveur dès qu’ils arrivent : un livreur devant la porte, une livraison faite, un véhicule qui ne bouge plus.
Sur cette page
Les webhooks sont fournis avec le suivi de flotte. Référence des webhooks
Événements
| Événement | Quand | data |
|---|---|---|
task.created | Une livraison a été créée | task |
task.assigned | La livraison a été confiée à un véhicule (ou un autre l’a reprise) | task |
task.arriving | Le livreur est à moins de arrivingS de la tâche (3 minutes par défaut) ou à moins de 250 m du point de livraison | task |
task.completed | Marquée comme livrée | task |
task.failed | Marquée comme échouée | task |
vehicle.offline | Un véhicule n’a rien envoyé pendant offlineAfterS (10 minutes par défaut), une fois par silence | vehicle |
task.updated | Vous avez modifié la livraison (PATCH /tasks/{id}) ; changed liste les champs | task, changed |
task.started | Un chauffeur N-Ways a commencé la livraison (connexion de chauffeurs) | task |
delivery.rated | Le client a noté la livraison (1 à 5 étoiles, visible seulement par votre entreprise) | task, rating |
zone.entered, zone.exited | Un véhicule est entré dans l’une de vos zones ou en est sorti | vehicle, zone |
connection.approved, connection.declined | Un chauffeur N-Ways a accepté ou refusé votre invitation | connection ou invite |
connection.revoked, connection.ended | Le chauffeur a arrêté le partage, ou votre entreprise a mis fin à la connexion | connection |
driver.availability_changed | Un chauffeur connecté s’est mis disponible pour vous, ou ne l’est plus | connection |
dispatch.offered, .accepted, .declined, .expired, .withdrawn | Une demande de livraison à un chauffeur N-Ways, et ce qu’elle est devenue | offer, task |
Équipes ERP (SAP, Odoo, Microsoft Dynamics) : voyez Connecter votre ERP pour la correspondance des champs, la vérification des signatures en C#, Groovy et Python, et le rapprochement avec l’API d’export.
Les alertes (zone quittée, zone franchie, véhicule silencieux ou arrêté) arrivent aussi en événements asset.*, et peuvent partir par e-mail, notification, Google Sheets, Telegram ou Excel : voir Alertes et transmission.
Ajouter un point de réception
Indiquez une adresse HTTPS sur votre serveur, et les événements qu’elle veut recevoir (aucun dans la liste veut dire tous). La réponse contient le secret de signature du point de réception : il n’est affiché que cette fois, alors conservez-le.
curl -X POST "https://nways.ng/maps/v1/fleet/webhooks" \
-H "X-NWays-Api-Key: VOTRE_CLE_SERVEUR" -H "Content-Type: application/json" \
-d '{"url": "https://example.com/nways/events", "events": ["task.arriving", "task.completed", "task.failed"]}'POST /webhooks/{id}/test envoie un événement ping pour vérifier que tout marche ; GET /webhooks/{id}/deliveries montre ce qui a été envoyé, les réponses de votre serveur et la prochaine nouvelle tentative.
Ce qui arrive, et vérifier que ça vient de nous
Chaque événement est un POST avec un corps JSON (id, type, createdAt, data) et ces en-têtes :
| En-tête | Valeur |
|---|---|
X-NWays-Event | Le type d’événement |
X-NWays-Delivery | L’identifiant de cet envoi (dlv_…), le même à chaque nouvelle tentative |
X-NWays-Signature | t=<unix seconds>,v1=<hex>, où v1 est le HMAC-SHA256 de "<t>.<raw body>" avec le secret de votre point de réception |
Vérifiez la signature sur le corps brut, avant de l’analyser, et refusez un horodatage décalé de plus de 5 minutes :
import { createHmac, timingSafeEqual } from 'node:crypto'
import { createServer } from 'node:http'
const SECRET = process.env.NWAYS_WEBHOOK_SECRET
function verified(raw, header) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false
const want = createHmac('sha256', SECRET).update(`${parts.t}.${raw}`).digest('hex')
return want.length === parts.v1?.length && timingSafeEqual(Buffer.from(want), Buffer.from(parts.v1))
}
createServer((req, res) => {
let raw = ''
req.on('data', (c) => (raw += c))
req.on('end', () => {
if (!verified(raw, req.headers['x-nways-signature'] ?? '')) return res.writeHead(401).end()
const event = JSON.parse(raw)
if (event.type === 'task.arriving') console.log(`Commande ${event.data.task.id} : le livreur arrive`)
res.writeHead(204).end() // répondez vite ; faites le travail lent ensuite
})
}).listen(8080)import hashlib
import hmac
import os
import time
SECRET = os.environ["NWAYS_WEBHOOK_SECRET"].encode()
def verified(raw: bytes, header: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
if abs(time.time() - int(parts.get("t", 0))) > 300:
return False
want = hmac.new(SECRET, parts["t"].encode() + b"." + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(want, parts.get("v1", ""))Nouvelles tentatives et ordre
- Répondez par n’importe quel code 2xx en moins de 10 secondes. Toute autre réponse donne lieu à une nouvelle tentative après 30 secondes, 2 minutes, 10 minutes, 30 minutes, 1, 3, 6 et 12 heures, puis l’envoi est marqué comme échoué.
- Un événement peut arriver plusieurs fois ou dans le désordre : gardez les
iddes événements déjà traités, et fiez-vous austatusde la tâche plutôt qu’à l’ordre d’arrivée des événements. - Les redirections ne sont pas suivies, et l’adresse doit être publique.
- Un secret a fuité ?
POST /webhooks/{id}/rotate-secreten donne un nouveau immédiatement.