Causes d'échec

Le catalogue des 9 catégories normalisées — libellé, origine, action recommandée.

Sur un failed ou un cancelled, az54 normalise la cause de l'échec en une catégorie fermée : failureCategory. C'est sur cette valeur qu'il faut brancher votre logique — jamais sur failureReason ni failureCode, le message et le code bruts du PSP, qui ne sont pas contractuels (même règle que pour message sur les erreurs API).

Où les trouver

  • Le webhook sortant, sur toute notification dont le status est terminal en échec (failed ou cancelled), pay-in comme pay-out. Peu importe le canal qui a produit la transition : callback PSP, polling, ou dispatch synchrone d'un pay-out.
  • La réponse HTTP synchrone d'un POST /v1/pay-in, quand le paiement échoue avant même la sollicitation du payeur (ex. corridor résolu mais rejeté immédiatement par l'opérateur).
  • La réponse HTTP synchrone d'un POST /v1/pay-out, quand le prestataire répond en échec sans passer par un callback et qu'aucun autre prestataire du canal ne peut prendre le relais. Si az54 rejoue le versement ailleurs, la réponse porte un statut non terminal (initiated) et aucune cause d'échec : l'issue n'est pas encore acquise, elle vous parviendra par webhook — ou se relira sur les deux lectures ci-dessous.
  • GET /v1/transactions, sur chaque ligne de votre historique, et GET /v1/transactions/by-id/{transactionId} pour une transaction précise (Réconciliation). Ces deux-là portent aussi failedAt (voir plus bas), que les canaux ci-dessus n'ont pas.

Le reçu public ne les porte pas.

Le catalogue

failureCategoryLibelléOrigineAction recommandée
INSUFFICIENT_FUNDSSolde insuffisantCompte mobile money du payeurDemander au client de recharger son compte mobile money, puis relancer avec un nouvel order_id.
INVALID_RECIPIENTDestinataire invalideNuméro du destinataireVérifier le numéro et l'opérateur auprès du destinataire (format international, compte mobile money actif), puis relancer avec un nouvel order_id.
LIMIT_EXCEEDEDPlafond dépasséPlafond du compte ou de l'opérateurDécouper le montant en plusieurs transactions sous le plafond, ou faire relever le plafond du compte auprès de l'opérateur. Un plafond journalier se réinitialise sous 24 h.
PROVIDER_ERRORErreur opérateurOpérateur mobile money ou prestataire de paiementRien à corriger de votre côté : relancer avec un nouvel order_id. Si l'échec se répète sur le même opérateur, consulter failureReason/failureCode et le journal des tentatives sur GET /v1/transactions/by-id/{transactionId} avant d'escalader ; le support az54 reste le recours si ça ne suffit pas à trancher.
TIMEOUTDélai dépasséRéseau de l'opérateurConfirmer le statut réel avant toute relance (GET /v1/transactions/by-id/{transactionId}, authentifié) : l'opérateur a pu débiter le client sans nous répondre. Ne relancer qu'une fois confirmé.
CANCELLED_BY_USERAnnulé par le payeurPayeurLe payeur a refusé la demande ou n'a pas saisi son code PIN à temps. Le recontacter, puis relancer le paiement avec un nouvel order_id.
UNKNOWNRaison non déterminéeNon identifiéeL'opérateur n'a pas renvoyé de motif exploitable. Consulter le détail technique et le journal des tentatives sur GET /v1/transactions/by-id/{transactionId} ; transmettre l'order_id au support az54 seulement si ça ne suffit pas à trancher.
PROVIDER_UNAVAILABLEPrestataire indisponibleSystème du prestataire de paiementRien à corriger de votre côté : le prestataire a déclaré son système indisponible avant toute sollicitation du payeur, et az54 rejoue l'encaissement chez un autre prestataire du même canal quand il en existe un. Ne relancer qu'après une notification d'échec définitif, avec un nouvel order_id.
PROVIDER_NOT_AUTHORIZEDHabilitation PSP manquanteConfiguration du compte az54 chez le prestataire de paiementNe pas relancer : l'échec est persistant, un nouvel order_id échouera à l'identique tant que la configuration n'est pas corrigée côté az54/PSP. Contacter le support az54 avec l'order_id.
PROVIDER_INSUFFICIENT_LIQUIDITYDemande prise en charge par le supportRéserve de décaissement az54 chez le prestataire de paiementRien à corriger de votre côté : votre solde az54 n'est pas en cause et le montant y a été recrédité. Votre demande est prise en charge, le support az54 revient vers vous dès que le versement peut être relancé. Ne relancez pas d'ici là.

Ce catalogue est la source de vérité : c'est le même qui s'affiche dans le tableau de bord marchand et le backoffice az54. Il est aussi servi par GET /v1/transactions/failure-categories (public, sans authentification), pour l'obtenir par API plutôt que de le recopier à la main.

failureReason et failureCode : le détail brut, pas contractuel

failureReason porte le message du PSP tel quel — parfois en anglais, avec son propre vocabulaire ("1006: Insufficient balance").

failureCode en isole la partie code, quand le PSP en fournit une :

{
  "failureCategory": "INSUFFICIENT_FUNDS",
  "failureReason": "1006: Insufficient balance",
  "failureCode": "1006"
}

Il est machine-lisible, mais pas plus contractuel que failureReason : chaque PSP a son propre référentiel de codes, az54 ne s'engage que sur failureCategory. Servez-vous-en pour vos tickets support et vos statistiques internes, pas pour brancher votre logique métier.

Il est absent (null, ou omis du corps du webhook) dans deux cas :

  • le PSP n'a renvoyé qu'un message, sans code. Le code n'est jamais re-dérivé de failureReason en coupant sur ": " — ce séparateur apparaît aussi à l'intérieur des messages ;
  • la transaction est antérieure au 2026-08-28. Ces échecs gardent leur failureReason complet, code fusionné compris ; il n'existe aucun moyen fiable de les rétro-remplir.

failedAt : quand l'échec a eu lieu

Les deux lectures par clé d'API — GET /v1/transactions et GET /v1/transactions/by-id/{transactionId} — servent failedAt, l'instant où la transaction est passée en failed ou cancelled. Il vaut null tant qu'elle n'a pas échoué.

Ne le confondez pas avec updatedAt, qui suit la dernière écriture sur la transaction, quelle qu'elle soit.

Sur les transactions antérieures au 2026-08-28, failedAt a été rempli depuis updatedAt : c'est une approximation de l'instant réel de l'échec, exacte tant que la ligne n'a pas été retouchée après coup.

On this page