Développeurs
Documentation API IberionPay
Encaissez par MTN MoMo et Orange Money depuis votre site, votre application ou votre logiciel de gestion. Une clé secrète, un appel HTTP, un callback signé : le reversement part automatiquement sur votre numéro Mobile Money du même réseau que votre client.
1. Démarrage rapide
- Créez un compte, puis complétez votre dossier marchand (KYC). L'API est réservée aux marchands vérifiés.
- Dans Services → API et callbacks, enregistrez vos deux numéros de reversement (MTN MoMo et Orange Money).
- Générez une clé : vous obtenez une clé publique
pk_live_…et une clé secrètesk_live_…affichée une seule fois. - Renseignez votre URL de callback HTTPS et conservez le secret de signature.
- Appelez l'endpoint d'encaissement, puis traitez le callback.
URL de base : https://iberionpay.com/api/public/v1 — toutes les réponses sont en JSON, tous les montants sont des entiers en francs CFA (XAF), sans décimale.
2. Frais et montants
| Flux | Taux | Quand |
|---|---|---|
| Pay-in (collecte client) | 3 % | Au débit du client |
| Payout (reversement marchand) | 1,5 % | Au reversement sur votre numéro |
| Total prélevé | 4,5 % | Déduit du montant collecté |
Exemple sur 10 000 FCFA : pay-in 300 FCFA + payout 150 FCFA = 450 FCFA de frais, soit 9 550 FCFA reversés (net dans la réponse API).
Montant minimum 10 FCFA, maximum 500 000 FCFA par transaction. Les frais sont déduits du montant encaissé : si vous voulez recevoir un net précis, majorez le montant demandé au client.
3. Authentification
Chaque requête serveur porte votre clé secrète dans l'en-tête Authorization. Ne l'exposez jamais dans du code front-end, une application mobile ou un dépôt public.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx Content-Type: application/json
La clé publique pk_live_… sert uniquement à identifier votre compte (rapprochement, support). Vous pouvez détenir jusqu'à 5 clés actives et révoquer une clé à tout moment — la révocation est immédiate.
4. Créer un encaissement
POST https://iberionpay.com/api/public/v1/charges — déclenche la demande de paiement Mobile Money. Votre client reçoit une invite USSD/appli à valider avec son code secret.
| Champ | Type | Description |
|---|---|---|
amount | entier, requis | Montant en XAF à collecter (ex. 5000). |
customerPhone | texte, requis | Numéro du payeur, 9 chiffres (6XXXXXXXX). |
customerOperator | texte, requis | MTN_MOMO_CMR ou ORANGE_CMR — choisi par le client. |
customerName | texte, optionnel | Nom du payeur, 80 caractères max. |
metadata | objet, optionnel | Vos références (orderId, invoiceId…) renvoyées dans les callbacks. |
L'en-tête Idempotency-Key est votre référence de commande et doit être strictement unique pour chaque paiement, à vie. Si la même clé est renvoyée une seconde fois, la demande est refusée avec 409 idempotency_key_reused (la réponse indique la référence déjà utilisée) : aucun ancien encaissement n'est renvoyé et aucun paiement n'est validé par erreur. N'utilisez jamais un compteur susceptible de se réinitialiser ; préférez un identifiant unique (UUID ou identifiant de commande jamais réattribué).
curl -X POST https://iberionpay.com/api/public/v1/charges \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: CMD-1024" \
-H "Content-Type: application/json" \
-d '{
"amount": 10000,
"customerPhone": "6XXXXXXXX",
"customerOperator": "MTN_MOMO_CMR",
"customerName": "Jean Mbarga",
"metadata": { "orderId": "1024" }
}'Réponse 201 :
{
"data": {
"id": "6f0d6e2c-6a1e-4f3f-9d0b-2c9a1f7b1234",
"reference": "IBP-7K3M9Q",
"status": "collecting",
"amount": 10000,
"fee": 450,
"net": 9550
}
}amount est débité au client, fee correspond aux 4,5 % (3 % pay-in + 1,5 % payout) et net est le montant reversé sur votre numéro du même opérateur, automatiquement, dès que la collecte est confirmée.
5. Suivre un encaissement
GET https://iberionpay.com/api/public/v1/charges/{id ou référence} — état à jour d'une transaction. GET https://iberionpay.com/api/public/v1/charges renvoie vos 50 derniers encaissements.
curl https://iberionpay.com/api/public/v1/charges/IBP-7K3M9Q \ -H "Authorization: Bearer sk_live_..."
| status | Signification |
|---|---|
initiated | Encaissement créé, demande en préparation. |
collecting | En attente de validation par le client. |
collected | Paiement client confirmé, reversement en préparation. |
paying_out | Reversement en cours vers votre numéro. |
completed | Terminé : le net est arrivé sur votre numéro. |
failed | Refusé, annulé ou expiré : aucun débit conservé. |
refund_required | Collecté mais reversement bloqué : notre équipe intervient. |
Ne livrez la commande que sur completed (ou collected si vous acceptez le risque de reversement). N'interrogez pas cet endpoint en boucle serrée : privilégiez le callback, avec une vérification toutes les 10 secondes maximum en secours.
6. Consulter le solde
GET https://iberionpay.com/api/public/v1/balance — cumul de vos encaissements.
{
"data": {
"currency": "XAF",
"settled": 1250000, // net déjà reversé
"pending": 35000, // encaissements en cours
"fees": 56250, // frais prélevés
"count": 143 // nombre de transactions terminées
}
}7. Callbacks signés
Nous appelons votre URL HTTPS en POST à chaque changement d'état, avec ces en-têtes :
x-iberionpay-timestamp: 1735689600 x-iberionpay-signature: sha256=<hmac> x-iberionpay-delivery: <identifiant de livraison>
La signature est un HMAC-SHA256 de la chaîne timestamp + "." + corps brut avec votre secret whsec_…. Vérifiez-la avant de traiter le contenu, en comparaison à temps constant, et rejetez un timestamp de plus de 5 minutes.
import crypto from "crypto";
app.post("/iberionpay/callback", express.raw({ type: "*/*" }), (req, res) => {
const timestamp = req.header("x-iberionpay-timestamp") || "";
const received = (req.header("x-iberionpay-signature") || "").replace("sha256=", "");
const raw = req.body.toString("utf8");
const expected = crypto
.createHmac("sha256", process.env.IBERIONPAY_WEBHOOK_SECRET)
.update(timestamp + "." + raw)
.digest("hex");
const a = Buffer.from(received);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).send("invalid signature");
}
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.status(401).send("stale timestamp");
}
const { event, data } = JSON.parse(raw);
if (event === "charge.completed") {
// marquez la commande data.metadata.orderId comme payée (idempotent)
}
res.sendStatus(200); // répondez 2xx sous 10 s
});Corps reçu :
{
"event": "charge.completed",
"createdAt": "2026-08-25T18:20:31.000Z",
"data": {
"id": "6f0d6e2c-6a1e-4f3f-9d0b-2c9a1f7b1234",
"reference": "IBP-7K3M9Q",
"status": "completed",
"amount": 10000,
"fee": 450,
"net": 9550,
"currency": "XAF",
"customerPhone": "2376XXXXXXXX",
"customerOperator": "MTN_MOMO_CMR",
"customerName": "Jean Mbarga",
"source": "api",
"metadata": { "orderId": "1024" },
"createdAt": "2026-08-25T18:19:58.000Z"
}
}Événements : charge.pending, charge.completed, charge.failed, charge.refund_required. Sans réponse 2xx sous 10 secondes, nous relançons à 30 s, 2 min, 10 min, 1 h puis 6 h. Traitez chaque événement de manière idempotente (une même référence peut arriver deux fois) et rejouez une livraison manuellement depuis le tableau de bord si besoin.
8. Codes d'erreur
| HTTP | error | Que faire |
|---|---|---|
| 400 | invalid_body | Champ manquant ou type incorrect. |
| 400 | invalid_customer_phone | Numéro non valide (9 chiffres, commence par 6). |
| 400 | no_payout_number_for_operator | Enregistrez votre numéro pour cet opérateur dans API et callbacks. |
| 401 | unauthorized | Clé secrète absente, erronée ou révoquée. |
| 403 | merchant_not_approved | Votre KYC marchand n'est pas encore approuvé. |
| 402 | operator_rejected | Refus opérateur (solde, code, numéro) : aucun débit. |
| 409 | idempotency_key_reused | Cette référence a déjà servi à un encaissement : chaque paiement exige une clé unique. |
| 500 | charge_not_created | Erreur temporaire : réessayez avec une nouvelle clé unique. |
Format d'erreur : { "error": "unauthorized" }. Tous vos appels (méthode, statut, durée) sont consultables dans l'onglet « Appels API récents ».
9. Exemples d'intégration
Node.js / Next.js
const res = await fetch("https://iberionpay.com/api/public/v1/charges", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.IBERIONPAY_SECRET_KEY}`,
"Idempotency-Key": order.id,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: order.total,
customerPhone: order.phone,
customerOperator: order.operator, // "MTN_MOMO_CMR" | "ORANGE_CMR"
metadata: { orderId: order.id },
}),
});
const { data, error } = await res.json();
if (!res.ok) throw new Error(error);
// data.reference : affichez-la au client, attendez le callbackPHP / Laravel
$response = Http::withToken(env('IBERIONPAY_SECRET_KEY'))
->withHeaders(['Idempotency-Key' => $order->id])
->post('https://iberionpay.com/api/public/v1/charges', [
'amount' => $order->total,
'customerPhone' => $order->phone,
'customerOperator' => $order->operator,
'metadata' => ['orderId' => $order->id],
]);
if ($response->failed()) {
report($response->json('error'));
}
$charge = $response->json('data');Python
import os, requests
r = requests.post(
"https://iberionpay.com/api/public/v1/charges",
headers={
"Authorization": f"Bearer {os.environ['IBERIONPAY_SECRET_KEY']}",
"Idempotency-Key": str(order_id),
},
json={
"amount": total,
"customerPhone": phone,
"customerOperator": operator,
"metadata": {"orderId": str(order_id)},
},
timeout=30,
)
r.raise_for_status()
charge = r.json()["data"]Vérification de signature en PHP
$timestamp = $request->header('x-iberionpay-timestamp');
$received = str_replace('sha256=', '', $request->header('x-iberionpay-signature'));
$expected = hash_hmac('sha256', $timestamp . '.' . $request->getContent(), env('IBERIONPAY_WEBHOOK_SECRET'));
if (!hash_equals($expected, $received)) {
abort(401);
}10. Passage en production
- Stockez
sk_live_…etwhsec_…en variables d'environnement. - Utilisez une clé par plateforme (site, application, caisse) pour révoquer sans tout interrompre.
- Envoyez toujours une
Idempotency-Keystable par commande. - Ne validez la livraison que sur
charge.completed. - Journalisez
referenceetid: ce sont nos clés de support. - Rappel des frais : 3 % au pay-in et 1,5 % au payout, prélevés sur le montant collecté.
Prêt à intégrer ?
Générez vos clés et votre secret de callback depuis votre espace marchand.
Ouvrir API et callbacks