Swaloo Docs
API

Webhooks

Recevez des notifications en temps reel lors des changements de statut de vos expeditions.

Webhooks

Les webhooks envoient une requete HTTP POST vers votre serveur des qu'un evenement se produit dans Swaloo. C'est le moyen recommande de synchroniser vos systemes plutot que d'interroger l'API en boucle (polling).


Prerequis

Les webhooks font partie d'un module d'abonnement. Seuls les plans Pro, Business et Entreprise incluent les webhooks. Le plan Decouverte n'y a pas acces.

Une notification n'est envoyee que si les trois conditions sont reunies :

  1. Le forfait de l'organisation inclut les webhooks (hasWebhooks = true).
  2. Une URL de destination (webhookUrl) en HTTPS est renseignee.
  3. Le webhook est active (isWebhookEnabled = true).

Configuration

Le webhook se configure au niveau de l'organisation, via l'API ou le dashboard :

curl -X PATCH https://api.swaloo.com/api/v1/organizations/{id} \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{"webhookUrl": "https://votre-serveur.com/webhooks/swaloo", "isWebhookEnabled": true}'
ChampTypeDescription
webhookUrlstringURL HTTPS de votre endpoint. Doit etre accessible publiquement.
webhookSecretstringSecret HMAC genere automatiquement (whsec_ + 40 hex). Lecture seule.
isWebhookEnabledbooleanActive/desactive l'envoi des notifications.

Le webhookSecret est genere automatiquement a la creation de l'organisation. Il n'est pas modifiable. Conservez-le en variable d'environnement.


Evenements

Swaloo emet un seul type d'evenement : shipment.status_changed, emis a chaque transition de workflow d'une tache :

TransitionDescriptionStatut expedition
assignTache assignee a un chauffeurpending
start_approachChauffeur en route vers la collectepickup_in_progress
pick_upColis recuperepicked_up
start_delivery_approachChauffeur en route vers la livraisonin_transit
start_transitLivraison en coursin_transit
deliverColis remis au destinatairedelivered
failEchec de collecte ou de livraisondepend du contexte
cancelTache annuleecancelled
reactivateTache reactivee apres un echecpending

Une meme expedition genere plusieurs notifications au fil de son cycle de vie.


Format du payload

En-tetes : Content-Type: application/json et X-Swaloo-Signature: sha256=<hmac_hex>

ChampTypeDescription
eventstringToujours "shipment.status_changed"
shipmentIdstring (uuid)Identifiant de l'expedition
trackingNumberstringNumero de suivi (SWL-...)
externalReferencestring | nullVotre reference de commande
statusstringStatut expedition : pending_approval, pending, pickup_in_progress, picked_up, in_transit, delivered, returned, cancelled
taskTypestringType de tache : pickup, delivery, transfer, return
taskStatusstringStatut tache : waiting_for_pickup, assigned_waiting, pending, assigned, pickup_in_progress, picked_up, delivery_in_progress, in_transit, delivered, failed, cancelled
driverNamestring | nullNom du chauffeur ou null
updatedAtstring (ISO 8601)Horodatage

Exemple : colis livre

{
  "event": "shipment.status_changed",
  "shipmentId": "550e8400-e29b-41d4-a716-446655440000",
  "trackingNumber": "SWL-20260616-A1B2C3",
  "externalReference": "CMD-20260616-001",
  "status": "delivered",
  "taskType": "delivery",
  "taskStatus": "delivered",
  "driverName": "Jean Dupont",
  "updatedAt": "2026-06-16T15:02:00+00:00"
}

Cycle de vie typique

1. assign (pickup)       → status: pending,            taskStatus: assigned
2. start_approach        → status: pickup_in_progress, taskStatus: pickup_in_progress
3. pick_up               → status: picked_up,          taskStatus: picked_up
4. assign (delivery)     → status: picked_up,          taskStatus: assigned
5. start_delivery        → status: in_transit,         taskStatus: delivery_in_progress
6. deliver               → status: delivered,          taskStatus: delivered

Verifier la signature

Chaque requete inclut X-Swaloo-Signature: sha256=<hmac> — le HMAC-SHA256 du corps brut avec votre webhookSecret comme cle.

Calculez le HMAC sur le corps brut (avant parsing JSON). Re-serialiser l'objet modifierait les octets.

Node.js

const crypto = require('crypto');

app.post('/webhooks/swaloo', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.header('X-Swaloo-Signature') || '';
  const expected = 'sha256=' +
    crypto.createHmac('sha256', process.env.SWALOO_WEBHOOK_SECRET)
      .update(req.body).digest('hex');

  const valid = signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));

  if (!valid) return res.status(401).end();

  const event = JSON.parse(req.body.toString());
  // Traiter l'evenement (idempotent)...
  res.status(200).json({ received: true });
});

PHP

$payload   = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SWALOO_SIGNATURE'] ?? '';
$expected  = 'sha256=' . hash_hmac('sha256', $payload, getenv('SWALOO_WEBHOOK_SECRET'));

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

$event = json_decode($payload, true);
// Traiter selon $event['status']...
http_response_code(200);

Politique de retry

Code de reponseComportement
2xxSucces — livraison validee
4xxRejet definitif — aucune nouvelle tentative
5xx ou timeout/erreur reseauRetry avec backoff exponentiel

Strategie : jusqu'a 3 tentatives (delai : 1s, 2s, 4s). Apres epuisement, le message part en dead-letter queue. Votre endpoint a 10 secondes pour repondre.


Tester en local

# 1. Tunnel HTTPS avec ngrok
ngrok http 3000
# → https://abc123.ngrok.io

# 2. Configurer l'URL
curl -X PATCH https://api.swaloo.com/api/v1/organizations/{id} \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{"webhookUrl": "https://abc123.ngrok.io/webhooks/swaloo", "isWebhookEnabled": true}'

# 3. Simuler un webhook manuellement
SECRET="whsec_3f9a8b2c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a"
PAYLOAD='{"event":"shipment.status_changed","shipmentId":"550e8400-...","trackingNumber":"SWL-20260616-A1B2C3","externalReference":"CMD-001","status":"delivered","taskType":"delivery","taskStatus":"delivered","driverName":"Test","updatedAt":"2026-06-16T15:00:00+00:00"}'
SIGNATURE="sha256=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')"

curl -X POST http://localhost:3000/webhooks/swaloo \
  -H "Content-Type: application/json" \
  -H "X-Swaloo-Signature: $SIGNATURE" \
  -d "$PAYLOAD"

Bonnes pratiques

  • Verifiez la signature sur chaque requete avant tout traitement.
  • Idempotence : de-dupliquez sur shipmentId + taskStatus + updatedAt.
  • Repondez vite en 2xx puis traitez en arriere-plan.
  • HTTPS uniquement pour l'URL de destination.
  • Utilisez updatedAt pour ordonner les evenements (pas l'ordre d'arrivee).
  • Gerez les null : externalReference et driverName peuvent etre absents.

Erreurs courantes

ProblemeCauseSolution
Aucun webhook recuPlan sans webhooks, URL vide, ou desactiveVerifiez les 3 conditions
Signature invalideBody parse avant HMACUtilisez le corps brut
Webhooks en doubleRetry apres timeoutRendez votre handler idempotent
Pas de retry apres erreurVotre serveur repond 4xxRenvoyez 5xx pour forcer un retry

Voir aussi : API externe | Endpoints | Erreurs | Statuts

Webhooks | Documentation Swaloo