API AxiaPay
Encaissez (collection) et décaissez (disbursement) de l'argent mobile depuis votre application, et recevez chaque changement de statut par webhook signé.
Obtenir une clé APIConsulter les tarifsAuthentification
Chaque requête porte votre clé secrète dans l'en-tête Authorization. Ne l'exposez jamais dans une application mobile ou un navigateur.
Authorization: Bearer axp_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
Base URL : https://axiapay.app/api/public/v1 Environnement de test : utilisez la même base sur https://axiapay.app avec une clé dédiée.
Qui paie les frais ? (fee_bearer)
Toutes les opérations API portent la commission AxiaPay de l'opérateur concerné. Selon le réseau, elle peut inclure une part fixe et un montant minimum. Le champ optionnel fee_bearer décide qui la supporte :
"merchant"(valeur par défaut) — les frais sont à votre charge. Encaissement : le client paieamount, vous receveznet_amount(montant − frais). Décaissement : le destinataire reçoitamount, votre portefeuille est débité denet_amount(montant + frais)."client"— les frais sont répercutés sur le client. Encaissement : le client paiecharged_amount(montant + frais), vous recevez le montant intégral. Décaissement : votre portefeuille est débité du montant exact, le destinataire reçoitcharged_amount(montant − frais).
Chaque réponse renvoie fee_bearer, fee, charged_amount (montant réellement prélevé ou versé) et net_amount (impact sur votre portefeuille).
1. Encaissement — POST /collections
Débite le client via un push USSD/mobile money. Le montant est exprimé en unité entière de la devise du pays de l'opérateur. Par défaut les frais sont déduits : vous recevez net_amount. Avec "fee_bearer": "client", le client est prélevé des frais en plus et vous recevez le montant intégral.
curl -X POST https://axiapay.app/api/public/v1/collections \
-H "Authorization: Bearer axp_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"operator": "mtn_bj",
"phone": "97000000",
"customer_name": "Awa Diallo",
"reference": "CMD-1042",
"fee_bearer": "client",
"callback_url": "https://mon-site.com/axiapay/webhook"
}'201 Created
{
"data": {
"id": "0f6c1f2c-....",
"type": "collection",
"status": "pending",
"amount": 5000,
"fee": 275,
"fee_bearer": "client",
"charged_amount": 5275,
"net_amount": 5000,
"currency": "XOF",
"country": "BJ",
"operator": "mtn_bj",
"phone": "97000000",
"reference": "CMD-1042",
"created_at": "2026-08-20T14:00:00.000Z"
}
}2. Décaissement — POST /disbursements
Envoie de l'argent vers un numéro mobile money. Votre portefeuille AxiaPay est débité de net_amount au moment de la demande. Par défaut ("merchant") il s'agit du montant + frais et le destinataire reçoit le montant entier ; avec "fee_bearer": "client" vous êtes débité du montant exact et le destinataire reçoit charged_amount (montant − frais). Si l'opération échoue, le montant est automatiquement recrédité. Sans solde suffisant dans la devise concernée, la requête est refusée (insufficient_funds).
curl -X POST https://axiapay.app/api/public/v1/disbursements \
-H "Authorization: Bearer axp_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 25000,
"operator": "orange_ci",
"phone": "0700000000",
"recipient_name": "Kofi Mensah",
"fee_bearer": "merchant",
"reference": "PAYOUT-88"
}'3. Statut — GET /operations/{id}
Renvoie l'état à jour d'une opération (pending, success, failed). Le statut est rafraîchi auprès du prestataire à chaque appel.
curl https://axiapay.app/api/public/v1/operations/0f6c1f2c-.... \
-H "Authorization: Bearer axp_live_xxx"4. Portefeuille — GET /balance
Renvoie le solde disponible de votre portefeuille, par devise. Les encaissements réussis créditent le solde du montant net ; les décaissements le débitent.
curl https://axiapay.app/api/public/v1/balance -H "Authorization: Bearer axp_live_xxx"
{
"data": {
"balances": [
{ "currency": "XOF", "balance": 124500 },
{ "currency": "USD", "balance": 320 }
]
}
}5. Catalogue — GET /operators
Liste les opérateurs actifs, leur pays et leur devise. Utilisez la valeur operator dans vos requêtes.
curl https://axiapay.app/api/public/v1/operators -H "Authorization: Bearer axp_live_xxx"6. Tarifs par opérateur — GET /rates
Renvoie la grille complète par opérateur : pourcentages, parts fixes, montants minimums et disponibilité pour l'encaissement et le décaissement. Utilisez-la pour présenter le coût exact à vos clients avant de créer une opération.
curl https://axiapay.app/api/public/v1/rates -H "Authorization: Bearer axp_live_xxx"
{
"data": [
{
"operator": "mtn_bj",
"operator_label": "MTN MoMo Bénin",
"country": "BJ",
"country_name": "Bénin",
"currency": "XOF",
"collection_rate": 0.045,
"collection_fixed_fee": 0,
"collection_min_amount": null,
"disbursement_rate": 0.03,
"disbursement_fixed_fee": 100,
"disbursement_min_amount": null,
"collection_available": true,
"disbursement_available": true
}
]
}7. Taux de change — GET /exchange-rates
Renvoie les taux de conversion de devises en direct, base XOF : chaque valeur indique combien vaut 1 unité de la devise en XOF. Filtre optionnel ?currency=EUR,USD. Les taux sont rafraîchis toutes les heures.
curl "https://axiapay.app/api/public/v1/exchange-rates?currency=EUR,USD,GHS" \
-H "Authorization: Bearer axp_live_xxx"
{
"data": {
"base": "XOF",
"rates": {
"EUR": 655.95348962,
"USD": 568.08009829,
"GHS": 49.51581038
},
"updated_at": "2026-09-28T15:40:00.000Z"
},
"meta": { "total": 3 }
}Sans filtre, l'endpoint renvoie plus de 130 devises. Pour convertir un montant : montant_XOF = montant_devise × rates[devise].
8. Code OTP (certains opérateurs)
Certains réseaux exigent un code OTP reçu par le client avant de débiter son compte. Deux cas :
- Code connu à l'avance — ajoutez
"otp": "123456"à la requête d'encaissement. Le paiement est confirmé immédiatement. - Code demandé par le réseau — la requête renvoie l'erreur
OTP_REQUIRED. Demandez le code au client, puis relancez la même requête avec"otp". Si le code est refusé (INVALID_OTP), le client doit en générer un nouveau.
422 invalid_request
{ "error": "invalid_request", "message": "OTP_REQUIRED" }
// Relance avec le code saisi par le client :
-d '{ "amount": 5000, "operator": "moov_bj", "phone": "97000000", "otp": "775427" }'9. Paiement par carte bancaire
L'opérateur spécial card (pays XX, International USD) encaisse par carte Visa/Mastercard avec 3-D Secure. Frais : 6 % + 0,20 USD, ajoutés au montant. Le client est redirigé vers une page de paiement hébergée : le paramètre return_url (obligatoire) indique où le ramener après le paiement.
curl -X POST https://axiapay.app/api/public/v1/collections \
-H "Authorization: Bearer axp_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"operator": "card",
"phone": "00000000",
"return_url": "https://mon-site.com/paiement/retour",
"reference": "CMD-2048"
}'
201 Created
{
"data": {
"id": "9a1b....",
"status": "pending",
"payment_url": "https://pay.alphapay.example/secure/....",
"charged_amount": 5513,
"currency": "XOF"
}
}Redirigez le client vers payment_url. Après validation 3-D Secure, il revient sur votre return_url et le statut passe à success (webhook collection.success).
10. RDC en dollars (USD)
La RDC dispose d'un corridor en USD (code pays XC) avec trois opérateurs. Les montants sont exprimés en USD ; les conversions utilisent les taux en direct de GET /exchange-rates.
Opérateur Encaissement Décaissement
airtel_cd_usd Airtel 5 % 5 %
orange_cd_usd Orange 5 % 3 %
vodacom_cd_usd Vodacom 5 % 4,7 %
curl -X POST https://axiapay.app/api/public/v1/collections \
-H "Authorization: Bearer axp_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "amount": 25, "operator": "airtel_cd_usd", "phone": "970000000" }'11. Mode test
Ajoutez "test": true à vos requêtes d'encaissement ou de décaissement pour vérifier votre intégration sans aucun impact : la requête est validée (montant, opérateur, disponibilité du pays), les frais sont calculés, mais rien n'est débité, rien n'est envoyé au réseau mobile et aucun webhook n'est émis. La réponse simulée porte le statut "test".
curl -X POST https://axiapay.app/api/public/v1/collections \
-H "Authorization: Bearer axp_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "amount": 5000, "operator": "mtn_bj", "phone": "97000000", "test": true }'
201 Created
{ "data": { "id": "test_....", "status": "test", "amount": 5000, "fee": 275, "net_amount": 4725 } }12. Webhooks
À chaque changement de statut, AxiaPay envoie un POST JSON à votre URL de notification.
POST https://mon-site.com/axiapay/webhook
X-AxiaPay-Event: collection.success
X-AxiaPay-Signature: 3f2b... (HMAC-SHA256 hex du corps brut)
{
"event": "collection.success",
"sent_at": "2026-08-20T14:01:12.000Z",
"data": { "id": "0f6c1f2c-....", "status": "success", "amount": 5000, "reference": "CMD-1042" }
}Vérifiez toujours la signature avec le secret whsec_… de votre clé, puis répondez 200. Événements : collection.success, collection.failed, disbursement.success, disbursement.failed.
// Node.js
import crypto from "node:crypto";
const expected = crypto
.createHmac("sha256", process.env.AXIAPAY_WEBHOOK_SECRET)
.update(rawBody)
.digest("hex");
if (expected !== req.headers["x-axiapay-signature"]) return res.status(401).end();13. Erreurs
401 unauthorized → clé API absente, invalide ou désactivée
422 invalid_request → champ manquant ou format incorrect
400 operation_failed → opérateur/pays indisponible ou refus du réseau mobile
404 not_found → opération inconnue pour cette clé