Aller au contenu principal

Webhooks

Les webhooks envoient une requête HTTP à votre serveur dès qu'une opération atteint un statut final. C'est le moyen recommandé pour mettre à jour vos commandes et vos soldes, sans interroger l'API en boucle.

Événements

ÉvénementDéclenché lorsque
mobile_money_deposit.completedUn dépôt a abouti et votre wallet est crédité
mobile_money_deposit.failedUn dépôt a échoué
mobile_money_payout.completedUn retrait a abouti
mobile_money_payout.failedUn retrait a échoué

Format d'une livraison

Chaque livraison est une requête POST dont le corps est au format JSON.

En-têteValeur
Content-Typeapplication/json
X-Webhook-EventNom de l'événement, par exemple mobile_money_deposit.completed
X-Webhook-SignatureSignature HMAC-SHA256 du corps de la requête, encodée en hexadécimal
{
"transaction_id": "TXN-VSWC4SQ2",
"type": "mobile_money_deposit",
"status": "completed",
"metadata": {}
}

Répondez avec un code 2xx dès réception. Toute autre réponse, un délai dépassé ou une redirection est traité comme un échec, et la livraison est retentée automatiquement.

Vérifier la signature

Calculez le HMAC-SHA256 du corps brut de la requête avec le secret de votre abonnement, puis comparez-le à l'en-tête X-Webhook-Signature à l'aide d'une comparaison à temps constant. Rejetez toute requête dont la signature ne correspond pas.

verify-webhook.js
import crypto from 'node:crypto';
import express from 'express';

const app = express();

app.post('/webhooks/trustsend', express.raw({ type: 'application/json' }), (req, res) => {
const expected = crypto
.createHmac('sha256', process.env.TRUSTSEND_WEBHOOK_SECRET)
.update(req.body)
.digest('hex');

const received = Buffer.from(req.get('X-Webhook-Signature') ?? '', 'utf8');
const computed = Buffer.from(expected, 'utf8');

if (received.length !== computed.length || !crypto.timingSafeEqual(received, computed)) {
return res.status(401).end();
}

const event = JSON.parse(req.body.toString('utf8'));
// Traitez l'événement, idéalement de façon asynchrone
res.status(200).end();
});
attention

Calculez la signature sur le corps tel qu'il a été reçu, avant tout parsing JSON : un corps re-sérialisé ne produit pas la même signature.

Créer un abonnement

POST/api/v1/business/webhooks
ParamètreTypeRequisDescription
urlstringOuiURL de votre serveur, accessible publiquement ; les adresses privées ou internes sont refusées
eventsstring[]OuiListe des événements à recevoir
{
"url": "https://api.maboutique.com/webhooks/trustsend",
"events": ["mobile_money_deposit.completed", "mobile_money_payout.failed"]
}

Réponse 201

{
"data": {
"url": "https://api.maboutique.com/webhooks/trustsend",
"events": ["mobile_money_deposit.completed", "mobile_money_payout.failed"],
"active": true,
"secret": "whsec_4f1c…",
"message": "Webhook subscribed. Store the secret securely — used to verify X-Webhook-Signature on delivery."
}
}
attention

Le secret n'est renvoyé qu'à la création de l'abonnement. Stockez-le de façon sécurisée : il sert à vérifier chaque livraison.

Lister les abonnements

GET/api/v1/business/webhooks

Réponse 200

{
"data": [
{
"id": 3,
"url": "https://api.maboutique.com/webhooks/trustsend",
"events": ["mobile_money_deposit.completed"],
"active": true,
"created_at": "2026-09-12T10:00:00.000+00:00"
}
]
}

Supprimer un abonnement

DELETE/api/v1/business/webhooks/:id

Supprime l'abonnement ainsi que son historique de livraisons.

Historique des livraisons

GET/api/v1/business/webhooks/:id/deliveries

Renvoie les 50 dernières tentatives de livraison, utiles pour diagnostiquer une intégration.

Réponse 200

{
"data": [
{
"id": 100,
"event_type": "mobile_money_deposit.completed",
"status": "success",
"retry_count": 0,
"last_error": null,
"created_at": "2026-09-12T10:00:43.000+00:00",
"updated_at": "2026-09-12T10:00:43.000+00:00"
}
]
}
statusSignification
pendingLivraison en attente d'envoi
retryingTentative échouée, nouvel essai programmé
successLivraison acceptée par votre serveur
failedLivraison abandonnée ; last_error indique la dernière cause
remarque

Nécessite la fonctionnalité webhooks dans votre offre.