API Webhooks
Les webhooks permettent à votre application de recevoir des notifications HTTP en temps réel lorsque des événements se produisent dans votre boutique Mercozy. Au lieu d'interroger l'API, enregistrez une URL et Mercozy enverra automatiquement les données de l'événement.
Démarrage rapide
Commencez en 3 étapes :
Étape 1 : Enregistrez votre endpoint
Obtenez votre clé API depuis Paramètres > Intégration > Clés API. Autorisation admin requise. Le secret de signature du webhook (whsec_xxx) est généré automatiquement lors de la création d'un endpoint et affiché une seule fois.
curl -X POST "https://api.mercozy.com/api/v1/external/webhooks" \
-H "X-API-Key: mk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "My ERP Integration",
"url": "https://your-app.com/webhooks/mercozy",
"events": ["order.created", "order.cancelled", "payment.received"]
}'Étape 2 : Traitez les événements entrants
app.post('/webhooks/mercozy', (req, res) => {
// 1. Verify signature (see below)
const signature = req.headers['x-webhook-signature'];
if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// 2. Process the event
const { type, data } = req.body;
switch (type) {
case 'order.created':
syncOrderToERP(data);
break;
case 'payment.received':
updateAccountingSystem(data);
break;
}
// 3. Respond quickly with 200
res.status(200).json({ received: true });
});Étape 3 : Testez votre endpoint
curl -X POST "https://api.mercozy.com/api/v1/external/webhooks/{id}/test" \
-H "X-API-Key: mk_live_your_key_here"Endpoints
/webhooks
Listez tous les endpoints de webhook enregistres.
/webhooks
Enregistrez un nouveau endpoint de webhook pour recevoir les notifications d'evenements.
/webhooks/:id
Mettez a jour un endpoint de webhook existant (URL, evenements ou statut actif).
/webhooks/:id
Supprimez un endpoint de webhook. Les evenements ne seront plus livres.
Reference des Champs
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
id | string | Non | Identifiant unique du webhook (lecture seule) |
name | string | Oui | Un nom descriptif pour cet endpoint |
url | string | Oui | URL du endpoint HTTPS pour recevoir les evenements de webhook |
events | string[] | Oui | Tableau de types d'evenements a souscrire |
secret | string | Non | Secret de signature pour la verification du payload (lecture seule, genere a la creation) |
isActive | boolean | Non | Si le webhook est actif (defaut : true) |
createdAt | datetime | Non | Horodatage ISO 8601 (lecture seule) |
Types d'Evenements Disponibles
Mercozy prend en charge 18 types d'événements webhook dans 6 catégories. Abonnez-vous uniquement aux événements dont vous avez besoin.
Commandes
- order.created
Déclenché lors de la création d'une commande
- order.updated
Déclenché lors de la modification d'une commande
- order.cancelled
Déclenché lors de l'annulation d'une commande
- order.completed
Déclenché lorsqu'une commande est marquée comme terminée
- order.status_changed
Déclenché lors de tout changement de statut de commande
Paiements
- payment.received
Déclenché lors de la capture du paiement ou du paiement à la livraison
- payment.refunded
Déclenché lors d'un remboursement ou d'une annulation de paiement
Produits
- product.created
Déclenché lors de l'ajout d'un nouveau produit
- product.updated
Déclenché lors de la modification des détails du produit
- product.deleted
Déclenché lors de la suppression d'un produit
Inventaire
- stock.low
Déclenché lorsque le stock passe sous le seuil
- stock.updated
Déclenché lors du changement de quantité en stock
Clients
- customer.created
Déclenché lors de l'inscription d'un nouveau client
- customer.updated
Déclenché lors de la mise à jour des informations client
Livraisons
- delivery.batch_started
Déclenché lors du départ d'un lot de livraisons
- delivery.batch_completed
Déclenché lorsque tous les arrêts du lot sont terminés
- delivery.completed
Déclenché lorsqu'une livraison individuelle est terminée
- delivery.failed
Déclenché lors de l'échec d'une tentative de livraison
Payload du Webhook
Chaque livraison de webhook inclut le type d'evenement, l'horodatage et les donnees de la ressource concernee.
Données de l'événement de commande
{
"id": "evt_clx1abc2def3",
"type": "order.created",
"timestamp": "2026-03-19T10:30:00Z",
"data": {
"id": "clx9order123",
"orderNumber": "ORD-1042",
"status": "PENDING",
"total": 4999,
"currency": "USD"
}
}Données de l'événement de paiement
{
"id": "evt_clx2pay4ghi5",
"type": "payment.received",
"timestamp": "2026-03-19T10:35:00Z",
"data": {
"orderId": "clx9order123",
"orderNumber": "ORD-1042",
"amount": 4999,
"currency": "USD",
"paymentMethod": "CARD",
"status": "CAPTURED"
}
}Données de l'événement de produit
{
"id": "evt_clx3prod6jkl",
"type": "product.created",
"timestamp": "2026-03-19T11:00:00Z",
"data": {
"id": "clx9prod789",
"name": "Organic Coffee Beans",
"sku": "COF-001",
"price": 1299,
"status": "ACTIVE"
}
}Données de l'événement de livraison
{
"id": "evt_clx4del7mno",
"type": "delivery.completed",
"timestamp": "2026-03-19T14:22:00Z",
"data": {
"orderId": "clx9order123",
"orderNumber": "ORD-1042"
}
}En-têtes HTTP
Chaque requête webhook inclut les en-têtes suivants :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
Content-Type | string | Oui | application/json |
X-Webhook-Signature | string | Oui | Signature HMAC-SHA256 : sha256={résumé_hexadécimal} |
X-Webhook-Timestamp | string | Oui | Horodatage Unix en millisecondes |
X-Webhook-ID | string | Oui | ID d'événement unique pour la déduplication |
User-Agent | string | Oui | Mercozy-Webhook/1.0 (+https://www.mercozy.com/docs/webhooks) |
Verification de Signature
Chaque webhook inclut un en-tête X-Webhook-Signature contenant une signature HMAC-SHA256. Vérifiez toujours cette signature avant de traiter l'événement pour vous assurer que la requête provient de Mercozy.
Node.js
const crypto = require('crypto');
function verifyWebhook(rawBody, signature, timestamp, secret) {
// Signature is computed over "timestamp.body"
const message = timestamp + '.' + rawBody;
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express middleware
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-webhook-signature'];
const ts = req.headers['x-webhook-timestamp'];
if (!verifyWebhook(req.body, sig, ts, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Process event...
res.status(200).json({ received: true });
});Python
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
# Signature is computed over "timestamp.body"
message = (timestamp + '.').encode() + payload
expected = 'sha256=' + hmac.new(
secret.encode(),
message,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# Flask example
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
sig = request.headers.get('X-Webhook-Signature')
ts = request.headers.get('X-Webhook-Timestamp')
if not verify_webhook(request.data, sig, ts, WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.get_json()
# Process event...
return {'received': True}, 200PHP
<?php
function verifyWebhook(string $payload, string $signature, string $timestamp, string $secret): bool {
// Signature is computed over "timestamp.body"
$message = $timestamp . '.' . $payload;
$expected = 'sha256=' . hash_hmac('sha256', $message, $secret);
return hash_equals($expected, $signature);
}
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
if (!verifyWebhook($payload, $signature, $timestamp, $webhookSecret)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($payload, true);
// Process event...
http_response_code(200);
echo json_encode(['received' => true]);Politique de réessai
Si votre endpoint renvoie un code de statut non-2xx ou expire (10 secondes), Mercozy réessaiera la livraison avec un backoff exponentiel :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
Tentative 1 | Non | Immédiat | |
Tentative 2 | Non | Après ~1s | |
Tentative 3 | Non | Après ~4s |
Après 3 tentatives échouées, la livraison est marquée comme échouée. Vous pouvez réessayer manuellement depuis le tableau de bord ou via l'API.
Bonnes pratiques
Répondez en moins de 5 secondes — Renvoyez un statut 200 immédiatement et traitez l'événement de manière asynchrone. Le délai d'expiration de Mercozy est de 10 secondes.
Vérifiez toujours les signatures — Vérifiez l'en-tête X-Webhook-Signature avant de traiter tout événement pour empêcher les requêtes usurpées.
Gérez les doublons (idempotence) — Utilisez l'en-tête X-Webhook-ID pour dédupliquer les événements. Stockez les ID d'événements traités et ignorez ceux déjà gérés.
Utilisez des endpoints HTTPS — Mercozy exige des URL HTTPS en production pour protéger les données webhook en transit.
Journalisez et surveillez — Journalisez tous les webhooks entrants et surveillez les échecs. Utilisez l'API de journaux de livraison pour vérifier le statut.