Structure des réponses
L'enveloppe JSON, le format des listes, la forme des erreurs et les identifiants communs à tous les endpoints.
Chaque endpoint répond avec la même enveloppe JSON, en cas de succès comme d'échec. Trois clés sont toujours présentes : un seul handler de réponses couvre donc toute l'API, et vous ne distinguez que les parties qui changent.
Les trois clés toujours présentes
code répète le statut HTTP dans le corps, pour les clients qui lisent difficilement les en-têtes.
status est le libellé HTTP de ce code (OK, Created, Not Found, Unprocessable Content), et
jamais la chaîne littérale error. message est une courte phrase qui décrit ce qui s'est passé,
destinée à vos logs plutôt qu'à vos clients.
Tout le reste du corps dépend de ce que vous avez demandé.
Une ressource
Quand vous récupérez ou créez un seul objet, il arrive sous une clé qui porte le nom de son type. Un
paiement revient sous transaction, un client sous customer, un transfert sous transfer. Il n'y
a pas d'enveloppe générique data à déballer.
Un endpoint peut ajouter ses propres clés de premier niveau à côté de la ressource quand elles n'en sont pas des propriétés. La création d'un paiement est le premier cas que vous rencontrerez : l'URL de la page hébergée décrit la session que vous venez d'ouvrir, pas la ligne de transaction. Elle se place donc à côté de la ressource plutôt qu'à l'intérieur.
Plusieurs ressources
Les endpoints de liste dérogent volontairement à la règle de nommage. Le tableau s'appelle toujours
items, quel que soit son contenu, et un objet meta porte l'état de la pagination. Écrire une seule
fonction de liste qui marche pour les paiements, les clients, les transferts et les événements vaut
donc la peine.
meta existe sous deux formes, et celle que vous recevez dépend de votre requête. Par défaut, vous
paginez par numéro de page et meta vous indique où vous en êtes par rapport au total. Envoyez
plutôt un paramètre cursor et l'API passe en pagination par curseur : c'est ce qu'il vous faut pour
un gros export ou une reprise de données, car elle reste correcte pendant que de nouvelles lignes
arrivent.
La taille de page vaut 25 par défaut et plafonne à 100. Pagination explique comment parcourir une collection du début à la fin.
Erreurs
Une erreur garde les trois mêmes clés. Le code HTTP est dans la plage 4xx ou 5xx, status est le
libellé de ce code, et message dit ce qui n'a pas marché. Comme l'enveloppe ne change pas, un appel
en échec se lit avec le même code qu'un appel réussi.
Deux classes d'erreurs ajoutent un champ à traiter explicitement. Un échec de validation contient
errors, un objet indexé par nom de champ dont les valeurs sont des tableaux de messages : un champ
peut donc échouer sur plusieurs règles à la fois. Une réponse bloquée par la limite de requêtes
contient retry_after, le nombre de secondes à attendre, ce qui vous évite de deviner un délai.
Un 409 Conflict contient aussi errors, et il ne signifie qu'une chose : vous avez réutilisé une
reference qui existe déjà sur un autre paiement. Traitez-le comme une soumission en double plutôt
que comme une mauvaise requête.
Un 404 vous indique quelle ressource manquait, Payment Not Found plutôt qu'un message générique :
le champ message suffit donc pour aiguiller l'erreur sans examiner l'URL appelée. Le catalogue
complet des codes se trouve dans la référence API.
N'analysez pas le message
message est du texte libre, et il change. Basez vos décisions sur code, et sur les clés de
errors quand vous avez besoin du détail par champ. Quelques échecs côté serveur renvoient code
et status sans aucun message : lisez-le donc avec prudence.
Statuts de paiement
Le status d'une transaction prend l'une de neuf valeurs. Les transitions entre elles, et celles qui
sont finales, sont décrites dans Concepts clés.
| Statut | Signification |
|---|---|
pending | Créé, en attente d'une action du client. |
processing | Confirmé auprès du prestataire, règlement en cours. |
succeeded | Fonds reçus. Vous pouvez livrer la commande. |
failed | Refusé par le prestataire ou par le portefeuille. |
cancelled | Annulé par le client ou par vous. |
expired | La fenêtre de paiement s'est fermée avant la fin. |
partial | Une partie du montant a été capturée, sur un paiement fractionné. |
refunded | Entièrement remboursé après un succès. |
partially_refunded | Partiellement remboursé après un succès. |
Identifiants
Chaque objet porte un id construit de la même façon : un préfixe qui nomme le type, puis test_
quand l'objet vit dans la sandbox, puis une chaîne aléatoire. Le préfixe vous dit ce que vous avez
entre les mains sans rien consulter, et le segment test_ empêche de confondre un identifiant
sandbox avec un identifiant live dans un log ou un ticket de support.
| Préfixe | Objet | Partie aléatoire |
|---|---|---|
trx_ | Paiement | 20 caractères |
po_ | Transfert sortant | 20 caractères |
rfd_ | Remboursement | 20 caractères |
dsp_ | Litige | 20 caractères |
ben_ | Bénéficiaire | 20 caractères |
acc_ | Sous-compte Sync | 20 caractères |
cus_ | Client | 24 caractères |
evt_ | Événement webhook | 24 caractères |
Ainsi, un paiement sandbox s'écrit trx_test_CSUGajfv9xh0XQ5wu2lx et son jumeau en production
trx_CSUGajfv9xh0XQ5wu2lx. Stockez les identifiants en texte de longueur illimitée, jamais dans une
colonne fixe de 24 ou 32 caractères. Les factures et les liens de paiement suivent leurs propres
règles, listées dans Concepts clés.
Dates
Chaque horodatage est au format ISO 8601 en UTC, avec un décalage explicite plutôt qu'un suffixe Z.
"created_at": "2026-05-24T10:21:08+00:00"Les deux écritures désignent le même instant et tout parseur ISO 8601 les gère. Mais si vous comparez des horodatages sous forme de chaînes, ce que vous ne devriez pas faire, c'est ce décalage que vous recevrez réellement.
Montants
Les montants sont exprimés dans l'unité principale de la devise. 5000 dans une réponse signifie
5 000 XAF, et non 50 XAF, soit l'inverse de ce que font la plupart des API de paiement. Le franc CFA
n'a pas de subdivision utilisée au quotidien : une convention en unité mineure inventerait une
coupure qui n'existe pas.
Les valeurs reviennent sous forme de nombres arrondis à deux décimales, et le minimum que vous
pouvez débiter est 0.01 dans l'unité de la devise. Lisez le champ currency avant tout calcul, car
un même chiffre signifie des choses très différentes en XAF et en USD.