API Documentation
Webhooks clients
ONESSTA envoie une requête HTTP POST à votre URL de callback lorsqu'un statut de colis change. Une modification de la situation de paiement seule déclenche aussi un webhook. Il s'agit d'une notification sortante d'ONESSTA vers votre serveur, et non d'un endpoint de l'API à appeler.
Configuration
- Dans votre compte
onessta.com, ouvrez Profil → Webhook Config. - Renseignez votre Webhook URL (une URL HTTPS publique) et une Secret Key que vous conservez côté serveur.
- Enregistrez la configuration. ONESSTA envoie les événements uniquement aux endpoints actifs liés au compte du client.
- Utilisez Tester le Webhook dans le profil : un événement
webhook.testest envoyé sans modifier de colis.
La API-Key utilisée pour appeler l'API ONESSTA n'est pas envoyée dans les webhooks clients.
Utilisez X-Signature et votre Secret Key pour authentifier la notification.
Événements
parcel.status_updated: changement du statut principalstatusou secondairestatus_second.parcel.situation_updated: changement desituationsans changement de statut, par exempleNOT_PAID→PAID.webhook.test: test manuel sans colis ;data.testvauttrue.
Si le statut et la situation changent dans la même mise à jour, un seul événement parcel.status_updated est envoyé ; le champ data.parcel.situation contient déjà la nouvelle valeur.
Une modification des seules coordonnées du destinataire ne déclenche pas actuellement un webhook client.
La création d'un colis ne déclenche pas cet événement de changement de statut.
Requête envoyée
POST https://votre-domaine.example/webhooks/onessta
Content-Type: application/json
User-Agent: Onessta-Webhook/1.0
X-Webhook-Event: parcel.status_updated
X-Webhook-Delivery: {event_id UUID}
X-Signature: {HMAC-SHA256 du payload avec votre Secret Key}
La structure est event_id (UUID stable lors des retries), event_type, timestamp, puis data.parcel et data.additional_data.
Tous les événements utilisent les mêmes champs data.parcel ; seules les valeurs de additional_data dépendent du changement.
Champs du colis
code: code du colis chez ONESSTA.status: statut envoyé au client. Si le statut principal interne vautIN_PROGRESS, ce champ reprendstatus_second(et peut donc êtrenull).status_second: statut secondaire du colis, ounull.situation: situation de paiement du colis, par exempleNOT_PAID,INVOICEDouPAID.comment: dernier commentaire de statut (last_statut_commentdans ONESSTA), éventuellementnull.receiver,phone,address: coordonnées du destinataire.city_id,city_name,district: localisation du destinataire ; certains champs peuvent êtrenull.total_fees: frais du colis, avec0par défaut si la valeur est absente.reported_date: date reportée au formatYYYY-MM-DD HH:MM:SS, ounull.created_at,updated_at: dates ISO 8601, ounull.
data.additional_data.delivery_man contient les informations du livreur si elles sont disponibles (sinon un tableau vide).
data.additional_data.reported_date reprend aussi la date reportée.
Le webhook client n'envoie pas de champ external_id ni de header X-API-Key.
Exemple : changement du statut principal
{
"event_id": "8d46bb4c-9fae-48bd-a5ac-48b267093df4",
"event_type": "parcel.status_updated",
"timestamp": "2026-10-20T09:00:00+00:00",
"data": {
"parcel": {
"code": "ABC123",
"status": "DELIVERED",
"status_second": null,
"situation": "NOT_PAID",
"comment": "Livré avec succès",
"receiver": "Client Exemple",
"phone": "0600000000",
"address": "Casablanca",
"city_id": 97,
"city_name": "Casablanca",
"district": null,
"total_fees": 50,
"reported_date": null,
"created_at": "2026-10-18T08:00:00+00:00",
"updated_at": "2026-10-20T09:00:00+00:00"
},
"additional_data": {
"old_status": "DISTRIBUTION",
"new_status": "DELIVERED",
"status_second": null,
"delivery_man": [],
"reported_date": null
}
}
}
Exemple : changement du statut secondaire
L'event_type reste parcel.status_updated. Dans cet exemple, status dans data.parcel vaut PROGRAMED parce que le statut principal interne est IN_PROGRESS ; le statut principal reste visible dans additional_data.status.
{
"event_id": "eeea9616-d650-4165-94aa-58ce6bd794aa",
"event_type": "parcel.status_updated",
"timestamp": "2026-10-20T09:30:00+00:00",
"data": {
"parcel": {
"code": "ABC123",
"status": "PROGRAMED",
"status_second": "PROGRAMED",
"situation": "NOT_PAID",
"comment": null,
"receiver": "Client Exemple",
"phone": "0600000000",
"address": "Casablanca",
"city_id": 97,
"city_name": "Casablanca",
"district": null,
"total_fees": 50,
"reported_date": null,
"created_at": "2026-10-18T08:00:00+00:00",
"updated_at": "2026-10-20T09:30:00+00:00"
},
"additional_data": {
"status": "IN_PROGRESS",
"old_status_second": null,
"new_status_second": "PROGRAMED",
"delivery_man": [],
"reported_date": null
}
}
}
Exemple : changement de situation
{
"event_id": "f51aa46a-f952-40c1-8be8-359ae80b3063",
"event_type": "parcel.situation_updated",
"timestamp": "2026-10-20T10:30:00+00:00",
"data": {
"parcel": {
"code": "ABC123",
"status": "DELIVERED",
"status_second": null,
"situation": "PAID",
"comment": null,
"receiver": "Client Exemple",
"phone": "0600000000",
"address": "Casablanca",
"city_id": 97,
"city_name": "Casablanca",
"district": null,
"total_fees": 50,
"reported_date": null,
"created_at": "2026-10-18T08:00:00+00:00",
"updated_at": "2026-10-20T10:30:00+00:00"
},
"additional_data": {
"old_situation": "NOT_PAID",
"new_situation": "PAID",
"delivery_man": [],
"reported_date": null
}
}
}
Les exemples montrent les trois cas de notification. Les valeurs du colis et les dates sont illustratives ; les champs optionnels peuvent être vides ou null.
Signature, réponse et erreurs
X-Signature est un HMAC-SHA256 hexadécimal calculé avec votre Secret Key sur les octets exacts du corps HTTP reçu.
Ne réencodez pas le JSON avant la vérification. Comparez la signature en temps constant, puis parsez le JSON.
Les webhooks clients n'envoient pas de X-API-Key ; ne les confondez pas avec les webhooks partenaires.
Exemple PHP
$rawBody = file_get_contents('php://input');
$expected = hash_hmac('sha256', $rawBody, $secretKey);
$received = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
if (!hash_equals($expected, $received)) {
http_response_code(401);
exit;
}
$payload = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
// Dédupliquez par event_id avant de traiter le colis.
http_response_code(200);
Exemple Node.js (Express)
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/webhooks/onessta', express.raw({ type: 'application/json' }), (req, res) => {
const received = req.get('X-Signature') ?? '';
const expected = crypto.createHmac('sha256', process.env.ONESSTA_WEBHOOK_SECRET)
.update(req.body).digest('hex');
const valid = /^[a-f0-9]{64}$/i.test(received) &&
crypto.timingSafeEqual(Buffer.from(received, 'hex'), Buffer.from(expected, 'hex'));
if (!valid) return res.sendStatus(401);
const event = JSON.parse(req.body.toString('utf8'));
// Dédupliquez par event.event_id et traitez en arrière-plan.
return res.sendStatus(200);
});
Répondez rapidement avec un code 2xx et traitez l'événement de manière asynchrone.
Le délai maximal de la requête est de 60 secondes (connexion : 5 secondes).
Toute erreur réseau ou réponse HTTP non-2xx est réessayée automatiquement par la queue, jusqu'à 3 tentatives au total (délais de 10 puis 30 secondes).
Le profil client affiche les 20 derniers envois, leurs statuts, le code HTTP et le nombre d'essais. Un envoi échoué peut être relancé manuellement avec le même event_id.
Une erreur 401 indique généralement une signature ou une Secret Key incorrecte : corrigez la configuration avant de relancer.
Les retries peuvent produire des doublons ; utilisez event_id comme clé d'idempotence.