Enveloppe de réponse & erreurs
Format standard des réponses, catalogue des codes d'erreur, gestion des opérations asynchrones.
Toutes les réponses du Merchant API suivent une enveloppe JSON standard.
Succès synchrone
HTTP 200
{
"error": false,
"data": { /* contenu spécifique à l'endpoint */ }
}Succès asynchrone (POST mutants)
HTTP 202 Accepted
{
"error": false,
"http_status": 202,
"data": {
"operation_id": "op_2f4a…",
"type": "payout",
"status": "queued",
"env": "live",
"date": "2026-05-20T10:30:00.000Z",
"_links": { "self": "/api/v1/merchant/operations/op_2f4a…" }
}
}L'opération est en file d'attente. Suis son avancement via webhook (recommandé) ou polling sur GET /operations/:id.
Erreur
error
Toujours true en cas d'erreur, false en cas de succès
http_status
Écho du code HTTP de la réponse
code
Identifiant machine-readable stable de l'erreur (à utiliser dans le code)
message
Message human-readable, peut évoluer entre versions
details
Optionnel — tableau de violations de validation par champ, ou objet provider-spécifique
Toujours dispatcher sur code, jamais sur message. Le message peut être traduit ou reformulé sans préavis ; le code est garanti stable dans une version majeure.
Catalogue des codes
Authentification (401 / 403)
missing_api_key
401
Ajoute le header X-Api-Key
invalid_api_key
401
Vérifie la clé — peut-être révoquée ou mauvais env
merchant_inactive
403
Le compte n'est pas validé — contacte le support
ip_allowlist_empty
403
Configure au moins une IP autorisée dans le dashboard
ip_not_allowed
403
L'IP appelante n'est pas dans la whitelist live
Idempotency (400 / 409)
missing_idempotency_key
400
Ajoute le header Idempotency-Key
invalid_idempotency_key
400
Reformule la clé (8-128 chars [A-Za-z0-9_-])
idempotency_conflict
409
Tu réutilises une clé avec un body différent — utilise une nouvelle clé
Validation (400)
validation_error
400
Voir details[] pour la liste des champs invalides
invalid_body
400
Le body n'est pas du JSON valide
unknown_currency
400
La devise demandée n'est pas supportée
amount_too_small
400
Sous le minimum autorisé pour la devise
amount_too_large
400
Au-dessus du maximum autorisé pour la devise
Ressources (404 / 409)
transaction_not_found
404
Le transaction_reference n'existe pas ou n'appartient pas à ce marchand
operation_not_found
404
L'operation_id n'existe pas ou n'appartient pas à ce marchand
not_refundable
400
La transaction n'est pas dans un statut remboursable (déjà refunded, échouée, etc.)
Métier (réponses 200 avec opération failed)
Quand le worker traite une opération asynchrone et qu'elle échoue, la réponse GET /operations/:id contient un champ error avec un de ces codes :
insufficient_balance
Solde marchand insuffisant pour le payout
merchant_wallet_missing
Aucun wallet provisionné pour ce marchand (cas rare)
provider_rejected
Le provider MoMo / banque a refusé l'opération
provider_unavailable
Aucun handler pour le couple country/operator demandé
provider_error
Erreur réseau ou exception inattendue du provider
missing_provider_code
destination.provider_code absent pour un payout mobile_money
amount_exceeds_transaction
Tentative de refund supérieure au montant original
Infrastructure (5xx)
internal_error
500
Réessaie avec la même Idempotency-Key après un délai
auth_error
500
Erreur côté serveur sur la vérif de la clé — contacte le support
idempotency_error
500
Redis indisponible — réessaie après quelques secondes
Différencier erreur synchrone vs erreur asynchrone
Statuts d'opération
status
Sens
queued
En file d'attente, pas encore traitée
processing
En cours de traitement par un worker
succeeded
Terminée avec succès — voir result
failed
Échouée — voir error.code et error.message
expired
Pas encore utilisé (réservé pour les opérations à TTL)
Mis à jour