Pour un partenaire ou un intégrateur qui doit brancher son application sur la plateforme. Rien ici ne suppose d'accès au dépôt ni à l'infrastructure.
Une seule porte
Tous les appels passent par la passerelle, sur un seul domaine. Les services eux-mêmes ne sont joignables ni depuis internet, ni depuis le réseau du client : il n'existe pas d'autre chemin, et il n'en sera pas ouvert.
https://<passerelle>/<api>/<version>/<ressource>
Chaque appel porte un jeton OAuth 2.0. Sans jeton, la passerelle répond 401 ;
avec un jeton valable mais sans abonnement à l'API visée, 403.
Obtenir ses accès
Deux chemins, selon ce que le contrat prévoit :
Par l'exploitant — il crée votre application dans l'API Manager, l'abonne aux API de votre périmètre, et vous remet un identifiant et un secret client.
En libre-service, si le module d'abonnements est actif : le portail
développeur (https://<api-manager>/devportal) permet de créer une application,
de s'abonner et de générer ses clés. Les mêmes opérations existent en API
(/subscription/v1/keys, /subscription/v1/catalog), ce qui permet de les
automatiser.
Gardez le secret client comme un mot de passe : il ouvre tout votre périmètre. S'il fuit, demandez sa régénération — les clés se remplacent sans interrompre l'application, le temps de basculer.
Obtenir un jeton
curl -s -u "$CLIENT_ID:$CLIENT_SECRET" \
-X POST https://<passerelle>/oauth2/token \
-d grant_type=client_credentials
{ "access_token": "eyJ4NXQi…", "token_type": "Bearer", "expires_in": 3600 }
Le jeton vaut une heure. Le redemander à chaque appel fonctionne mais
sature l'annuaire : gardez-le en mémoire et renouvelez-le à l'approche de son
échéance, ou sur un 401. Ne le stockez pas dans un navigateur.
Appeler une API
curl -s -X POST https://<passerelle>/payment/v1/payment \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"accountNumber": "0000000001",
"msisdn": "770000000",
"operator": "orange",
"service": "MOMO",
"operation": "cashin",
"amount": 5000,
"currency": "XOF",
"country": "SN",
"orderId": "CMD-2026-000123",
"returnUrl": "https://mon-site/paiement/retour",
"cancelUrl": "https://mon-site/paiement/annule"
}'
partnerCode ne se déclare plus. La passerelle joint à votre requête une
affirmation signée nommant votre application ; la plateforme y lit votre code
partenaire. Omettez-le : c'est le seul usage qui vous garantisse qu'aucune
erreur de recopie ne dirige un paiement ailleurs.
Vous pouvez encore l'envoyer — vos intégrations en place continuent de
fonctionner — mais il est désormais vérifié : un code qui n'est pas celui
de votre application vaut 403 A00001, sans que le paiement soit engagé. Si
vous voyez ce refus, c'est que la valeur envoyée n'est pas la vôtre.
Le compte et le client sont deux acteurs. accountNumber est VOTRE compte
sur la plateforme — celui qui est crédité en cashin, débité en cashout ; il
vous est ouvert à la signature de votre contrat. msisdn est le numéro du
client, à l'autre bout de l'opération. Les confondre produit une demande
cohérente en apparence et fausse sur le fond.
Le numéro du client s'écrit sans indicatif, à la longueur que déclare son
pays — neuf chiffres au Sénégal, soit 770000000. La plateforme ajoute
l'indicatif elle-même et vous le renvoie (221770000000). Un numéro déjà
préfixé dépasse la longueur attendue et se fait refuser en
BR0001 — MSISDN length does not match.
service est le CODE du service tel que votre contrat l'emploie — MOMO,
VMC, DCB — et non son libellé. operator est le nom de l'opérateur ; la
casse est sans importance, la plateforme normalise.
orderId est votre référence, et la seule qui vous permettra de vous
retrouver. C'est elle que la plateforme conserve et qui apparaît dans l'API
des transactions. Fournissez-la toujours : sans elle, la demande est acceptée
— 200, frais calculés — mais la transaction n'est jamais enregistrée, et le
paiement devient introuvable. Rien ne vous le signale au moment de l'appel.
Le schéma publié ne marque pourtant pas ce champ obligatoire : c'est un
constat d'exploitation, pas une lecture du contrat.
partnerOrderId existe aussi, mais la plateforme la remplace par une
référence à elle (OXCI…) : ne vous en servez pas pour vos rapprochements.
operation vaut cashin (encaissement) ou cashout (décaissement). Le schéma
déclare obligatoires accountNumber, operator et service — auxquels
s'ajoutent, en pratique, msisdn et orderId. partnerCode y figure encore
comme obligatoire, mais ne l'est plus : la plateforme le déduit de votre jeton.
Un paiement n'est pas instantané : la réponse dit qu'il est accepté, pas qu'il est abouti. L'aboutissement vous parvient par rappel web, et se vérifie sur l'API des transactions.
Le catalogue
| API | Contexte | Ce qu'elle fait |
|---|---|---|
| Paiement | /payment/v1 |
Encaisser et décaisser. |
| Transactions | /transaction/v1 |
Rechercher, suivre, rapprocher. |
| Partenaires | /partner/v1 |
Le référentiel des marchands. |
| Référentiel | /content/v1 |
Pays, devises, institutions, moyens de paiement. |
| Comptes | /account/v1 · Soldes /balance/v1 |
Comptes, soldes, règlements, écritures. |
| Contrats et offres | /offer-service/V1 |
Contrats commerciaux, commissions. |
| Abonnements API | /subscription/v1 |
Applications, abonnements, clés. |
| Virements | /transfer/v1 · masse /transfer/bulk/v1 |
Virements sortants. |
| Abonnement opérateur (DCB) | /subscription-dcb/v1 · /rebill/v1 · /dcb-auth/v1 |
Abonnements sur facture, refacturation, OTP. |
| Notifications | /notification/v1 · rappels /hook/v1 |
Courriels et rappels web. |
| Rapports | /report/v1 |
Restitutions. |
Toutes ne sont pas ouvertes à tous : votre périmètre dépend de votre contrat et des modules installés chez l'exploitant (voir MODULES.md).
La documentation détaillée
Chaque API publie ses chemins, ses paramètres, ses schémas de corps et de
réponse dans le portail développeur : https://<api-manager>/devportal,
onglet API Console. Ces définitions ne sont pas écrites à la main — elles sont
importées depuis les services eux-mêmes à chaque déploiement, et suivent donc le
code.
Une ressource générique /* figure en fin de liste sur chaque API : c'est un
relais de compatibilité, pas une ressource à appeler.
Ce que répond la passerelle
| Code | Signification | Ce qu'il faut faire |
|---|---|---|
401 |
Jeton absent, expiré ou invalide. | Redemander un jeton. |
403 |
Jeton valable, mais l'application n'est pas abonnée à cette API. | Demander l'abonnement ; ce n'est pas un problème de code. |
403 A00001 |
Le partnerCode envoyé n'est pas celui de votre application. |
Omettez ce champ : la plateforme le déduit de votre jeton. Le paiement n'a pas été engagé. |
404 |
Chemin inconnu, ou API non déployée chez cet exploitant. | Vérifier le chemin dans le portail, puis le périmètre du contrat. |
429 |
Palier de débit dépassé. | Ralentir, réessayer avec un délai croissant. |
500 / 503 |
Le service derrière la passerelle est indisponible ou en quarantaine après des échecs répétés. | Réessayer ; si cela dure, prévenir l'exploitant — ce n'est pas votre appel qui est en cause. |
Les rappels web
Quand un paiement aboutit ou échoue, la plateforme appelle votre URL. C'est le seul moyen d'être averti sans interroger l'API en boucle.
Trois règles, quel que soit le détail du contrat :
- Répondez vite, en
2xx, et traitez ensuite. Un rappel qui attend votre traitement métier finit en délai dépassé, donc en rejeu. - Soyez idempotent : un même paiement peut vous être notifié plusieurs fois.
Rapprochez sur votre
orderId, pas sur l'ordre d'arrivée — et pas surpartnerOrderId, que la plateforme a remplacé par sa propre référence. - Ne faites pas confiance au seul rappel. Il peut se perdre. Confirmez sur l'API des transactions avant de livrer un bien ou un service.
Le format exact du rappel, sa signature et la politique de rejeu sont à confirmer avec l'équipe d'intégration : ils dépendent de la version du module de rappels installée, et ne sont pas fixés dans ce document.
Avant la mise en production
- Essayez d'abord sur l'installation de démonstration, avec de petits montants.
- Après votre premier paiement accepté, allez le retrouver dans l'API des
transactions. Un
200dit que la demande est partie, pas qu'elle a laissé une trace : c'est le seul contrôle qui distingue une intégration qui marche d'une intégration qui semble marcher. - Vérifiez votre comportement quand un paiement reste en cours plus de quinze minutes : c'est le cas le plus fréquent en conditions réelles, et le plus mal traité.
- Vérifiez votre comportement sur un
429et sur un503. - Convenez avec l'exploitant du volume attendu : les paliers de débit se règlent par API et par application.