Documentation API Transfert Bancaire International (BMO)
Spécifications techniques, étapes d'intégration séquentielle et environnement PAP pour les transferts bancaires externes internationaux.
Présentation
L'API Transfert Bancaire International BMO permet aux partenaires d'exécuter des transferts de fonds vers des comptes bancaires à l'international.
Le parcours d'intégration s'exécute séquentiellement en 5 étapes clés d'initialisation et d'exécution, suivies d'une étape de suivi de statut :
- Consultation des banques (
bank-list) : Récupération des codes banques, noms des établissements etproviderCodevalides pour un pays cible. - Vérification du compte (
check-account) : Validation obligatoire des coordonnées du compte destinataire (bankNamestrictement requis). - Calcul du coût (
cost-calculate) : Évaluation des frais d'opération. - Calcul du montant à débiter (
debited-amount) : Obtention du montant total prélevé (en XOF) et du jeton de cotation indispensable (quoteId). - Exécution de l'opération (
operation) : Soumission du transfert enPOSTavec lequoteIdet une référence partenaire optionnelle (externalReference). - Suivi du statut (
/thirdparty/operation) : Vérification de l'état de la transaction enGETvia la référence interne (reference).
Environnement PAP (Pré-production) & Authentification :
- Base URL PAP :
https://svc.pap.bestcash.me/external(Environnement fonctionnel et validé pour les tests BMO)- En-têtes d'authentification obligatoires :
X-Auth-ApiKey: Votre clé API partenaire (ex:+2290196666262)X-Auth-ApiSecret: Votre secret API partenaire (ex:y7MwWuWeQORtpA==)
REMARQUE CRITIQUE — Format des codes pays (ISO 2 lettres) : Tous les arguments de pays (
country,recipientCountry,senderCountry,recipientNationality) doivent impérativement être renseignés au format ISO à 2 caractères (ex:INpour l'Inde,BJpour le Bénin,NGpour le Nigeria). L'utilisation d'un nom de pays en texte brut (ex: "Inde" au lieu de "IN") entraînera une erreurCOUNTRY NOT FOUND.
1. Consultation de la liste des banques (GET /external/thirdparty/bank-transfer/bank-list)
Récupère la liste des banques partenaires disponibles dans le pays de destination, avec leurs codes (code), leurs noms (name) et leurs codes providers (providerCode).
- Méthode :
GET - URL :
/external/thirdparty/bank-transfer/bank-list - Paramètres de requête (Query params) :
country(obligatoire) : Code pays ISO à 2 lettres (ex:INpour l'Inde).
Tester la liste des banques
Consultez les banques disponibles pour un pays destinataire au format ISO 2 lettres.
Exemple de réponse HTTP 200 (Corridor Inde - IN)
{
"banks": [
{
"minAmount": 0,
"maxAmount": 0,
"dailyMaxAmount": 0,
"monthlyMaxAmount": 0,
"weeklyMaxAmount": 0,
"name": "Canara Bank",
"code": "CNRB0000232",
"country": "IN",
"currency": "INR",
"subCode": null,
"iban": "",
"providerCode": "PRVCAN001",
"mandatoryFields": []
},
{
"minAmount": 0,
"maxAmount": 0,
"dailyMaxAmount": 0,
"monthlyMaxAmount": 0,
"weeklyMaxAmount": 0,
"name": "State Bank of India",
"code": "SBIN0000001",
"country": "IN",
"currency": "INR",
"subCode": null,
"iban": "",
"providerCode": "PRVSBI001",
"mandatoryFields": []
}
],
"defaultCurrency": "INR"
}
2. Vérification du compte destinataire (GET /external/thirdparty/bank-transfer/check-account)
Permet de vérifier la validité des coordonnées du compte bancaire destinataire avant d'initier l'opération.
- Méthode :
GET - URL :
/external/thirdparty/bank-transfer/check-account - Paramètres de requête (Query params) :
accountNumber(obligatoire) : Le numéro de compte bancaire (ex:232201001617).msisdn(obligatoire) : Numéro de téléphone du titulaire (ex:919876543210).fullname(obligatoire) : Nom complet du titulaire du compte (ex:CENTRE DEVKI LUGGAGE).bankCode(obligatoire) : Code de la banque récupéré viabank-list(ex:CNRB0000232).bankName(obligatoire) : Strictement requis. Le nom exact de la banque (ex:"Canara Bank"). Ne doit pas êtrenullou vide, sous peine d'une erreur 400 (This value should not be null).country(obligatoire) : Code pays ISO à 2 lettres (ex:IN).providerCode(optionnel / recommandé) : Code du provider bancaire (ex:PRVCAN001).
ATTENTION — Champ
bankNameobligatoire : Si le paramètrebankNameest omis, transmis ànullou sous forme de chaîne vide, le serveur renvoie une erreur HTTP 400 Bad Request (This value should not be null). Transmettez toujours le libellé de la banque obtenu à l'étape 1 (bank-list).
Tester la vérification de compte
Validez l'existence et l'état du compte bancaire destinataire.
Exemple de réponse HTTP 200
{
"active": true
}
3. Calculer le coût d'une opération (GET /external/thirdparty/bank-transfer/cost-calculate)
Calcule les frais appliqués au transfert vers le pays cible.
- Méthode :
GET - URL :
/external/thirdparty/bank-transfer/cost-calculate - Paramètres de requête (Query params) :
amount(obligatoire) : Montant de la transaction (ex:10000).country(obligatoire) : Code pays ISO à 2 lettres (ex:IN).
Tester le calcul du coût
Estimez les frais d'opération pour un transfert bancaire vers l'Inde.
Exemple de réponse HTTP 200
{
"cost": 100.0,
"targetMonetaryArea": {
"currencyShortName": "F CFA",
"currencyCode": "XOF"
}
}
4. Calculer le montant à débiter (GET /external/thirdparty/bank-transfer/debited-amount)
Cette étape calcule le montant total qui sera débité sur le compte de l'expéditeur et génère le quoteId indispensable pour soumettre l'opération.
- Méthode :
GET - URL :
/external/thirdparty/bank-transfer/debited-amount - Paramètres de requête (Query params) :
amount(obligatoire) : Montant de l'opération (ex:10000).country(obligatoire) : Code pays ISO à 2 lettres du destinataire (ex:IN).msisdn(obligatoire) : Numéro du receveur (ex:919876543210).accountNumber(obligatoire) : Numéro de compte destinataire (ex:232201001617).currency(obligatoire) : Devise cible (ex:INR).
Tester la cotation du montant à débiter
Obtenez le montant total prélevé et le quoteId.
Exemple de réponse HTTP 200
{
"totalAmount": 76924.0,
"quoteId": "QR61997FD6A14BB36D",
"monetaryArea": {
"reference": "MONAXOF001",
"name": "UEMOA",
"currencyLongName": "Franc CFA",
"currencyShortName": "F CFA",
"currencyRate": null,
"currencyCode": "XOF"
}
}
IMPORTANT : Conservez précieusement le
quoteIdrenvoyé dans la réponse (ex:"QR61997FD6A14BB36D"). Il doit impérativement être injecté dans la requête de l'étape suivante.
5. Effectuer l'opération de transfert (POST /external/thirdparty/bank-transfer/operation)
Exécute le transfert bancaire international en utilisant le quoteId obtenu lors de la cotation.
- Méthode :
POST - URL :
/external/thirdparty/bank-transfer/operation - Headers requis :
Content-Type: application/jsonX-Auth-ApiKey: <votre_api_key>X-Auth-ApiSecret: <votre_api_secret>
Structure du Body JSON
| Champ | Type | Description |
|---|---|---|
amount | number | Montant de la transaction (ex: 10000) |
recipientCountry | string | Code ISO 2 lettres du pays destinataire (ex: "IN") |
senderCountry | string | Code ISO 2 lettres du pays émetteur (ex: "BJ") |
recipientName | string | Prénom du destinataire (ex: "CENTRE") |
recipientSurname | string | Nom de famille du destinataire (ex: "DEVKI LUGGAGE") |
recipientAccountNumber | string | Numéro de compte du destinataire (ex: "232201001617") |
recipientBankCode | string | Code banque destinataire (ex: "CNRB0000232") |
recipientBankName | string | Strictement requis. Nom de la banque destinataire (ex: "Canara Bank") |
recipientMsisdn | string | Numéro de téléphone du destinataire au format international (ex: "+919876543210") |
recipientNationality | string | Code ISO 2 lettres de la nationalité du destinataire (ex: "IN") |
recipientAddress | string | Adresse physique du destinataire (ex: "Rue des Indes") |
recipientIdType | string | Type de pièce d'identité (ex: "PASSPORT", "CNI") |
recipientIdNumber | string | Numéro de la pièce d'identité (ex: "IN1234567") |
remittancePurpose | string | Motif du transfert (ex: "Family Maintenance") |
relationshipSender | string | Relation avec l'émetteur (ex: "Brother") |
sourceOfFunds | string | Provenance des fonds (ex: "Salary") |
quoteId | string | Obligatoire. L'identifiant de cotation récupéré à l'étape 4 |
externalReference | string | Optionnel. Votre référence partenaire unique |
DÉPANNAGE — Erreur
REVENUE SHARING NOT CONFIGURED: Si le serveur retourne une erreur HTTP avec le message"REVENUE SHARING NOT CONFIGURED"lors duPOST, cela indique que le profil de votre clé API n'a pas encore de grille de commissions/partage de revenus associée sur l'environnement BestCash (PAP ou Sandbox). Action requise : Contactez l'administrateur ou le support BestCash pour associer la configuration Revenue Sharing à votre compte partenaire (X-Auth-ApiKey).
Tester la soumission d'un transfert bancaire
Exécutez le transfert bancaire en envoyant le payload JSON complet avec le quoteId.
Aucun paramètre d'URL configuré.
Exemple de réponse HTTP 200 (Statut ONGOING)
{
"prefixedAmount": "76 924 F CFA",
"prefixedOperationCost": "100 F CFA",
"operationCode": "",
"status": "ONGOING",
"operationCost": 100.0,
"amount": 76924.0,
"operationType": "MONEY_REMITTANCE-BANK",
"reference": "TPBA20260727105904132",
"creationDate": "2026-07-27T10:59:04+00:00",
"recipientReceivedPrefixedAmount": "10 000 INR",
"recipientCurrency": "INR",
"senderKyc": {
"nationality": "BJ",
"dateOfBirth": "",
"idType": "",
"idNumber": "",
"idIssueDate": "",
"idExpiryDate": "",
"address": "",
"city": "",
"country": "BJ",
"firstName": "",
"lastName": "",
"province": null,
"postalCode": null,
"msisdn": null
},
"recipientKyc": {
"nationality": "IN",
"dateOfBirth": "",
"idType": "PASSPORT",
"idNumber": "IN1234567",
"idIssueDate": "",
"idExpiryDate": "",
"address": "Rue des Indes",
"city": "",
"country": "IN",
"firstName": "DEVKI LUGGAGE",
"lastName": "CENTRE",
"province": "India",
"postalCode": null,
"msisdn": "+919876543210"
},
"receivedAmount": "10000",
"markupAmount": 0.9230769230780425,
"markupRate": 0.0,
"recipientBankAccountNumber": "232201001617"
}
6. Vérification du statut d'une opération (GET /external/thirdparty/operation)
Permet de suivre le statut du traitement d'une transaction bancaire précédemment soumise.
- Méthode :
GET - URL :
/external/thirdparty/operation - Paramètres de requête (Query params) :
reference(recommandé) : La référence interne du système renvoyée lors du POST d'opération (ex:TPBA20260727111338139).externalReference(optionnel) : La référence partenaire fournie initialement lors du POST.
BONNE PRATIQUE — Suivi par
reference: Lors du suivi d'une transaction, l'interrogation doit s'effectuer principalement via le paramètrereference(référence interne renvoyée par le système lors de la réponse POST d'exécution, ex:TPBA20260727111338139). Cela garantit un retour immédiat de l'état de la transaction (ex:ONGOING,SUCCESS,FAILED). L'interrogation directe parexternalReferenceseule renverra une erreurRESSOURCE_NOT_FOUNDsi elle n'est pas couplée avec la référence interne.
Tester la vérification de statut d'opération
Consultez le statut d'un transfert bancaire via sa référence interne.
Exemple de réponse HTTP 200
{
"status": "ONGOING",
"operationCost": 100.0,
"amount": 76924.0,
"operationType": "MONEY_REMITTANCE-BANK",
"reference": "TPBA20260727111338139",
"creationDate": "2026-07-27T11:13:38+00:00",
"externalReference": null
}
Exemple d'intégration complet en Node.js / Axios (Corridor Inde - IN)
Le script suivant déroule l'ensemble du parcours séquentiel fonctionnel et validé avec les commandes curl réelles en environnement PAP :
import axios from 'axios';
const BASE_URL = 'https://svc.pap.bestcash.me/external';
const headers = {
'X-Auth-ApiKey': '+2290196666262',
'X-Auth-ApiSecret': 'y7MwWuWeQORtpA==',
'Content-Type': 'application/json'
};
async function executeBankTransferWorkflow() {
try {
// 1. Récupération de la liste des banques pour l'Inde (country=IN)
console.log('--- 1. Consultation des banques (Inde) ---');
const bankListRes = await axios.get(`${BASE_URL}/thirdparty/bank-transfer/bank-list`, {
headers,
params: { country: 'IN' }
});
// Canara Bank (CNRB0000232)
const selectedBank = bankListRes.data.banks.find(b => b.code === 'CNRB0000232') || bankListRes.data.banks[0];
const bankCode = selectedBank.code; // 'CNRB0000232'
const bankName = selectedBank.name; // 'Canara Bank' (Obligatoire)
const providerCode = selectedBank.providerCode || 'PRVCAN001';
console.log(`Banque sélectionnée : ${bankName} (Code: ${bankCode})`);
// 2. Vérification du compte destinataire (bankName obligatoire)
console.log('--- 2. Vérification du compte destinataire ---');
const checkAccountRes = await axios.get(`${BASE_URL}/thirdparty/bank-transfer/check-account`, {
headers,
params: {
accountNumber: '232201001617',
msisdn: '919876543210',
fullname: 'CENTRE DEVKI LUGGAGE',
bankCode: bankCode,
bankName: bankName, // Champ strictement obligatoire
country: 'IN',
providerCode: providerCode
}
});
if (!checkAccountRes.data.active) {
throw new Error("Le compte destinataire n'est pas actif ou valide.");
}
console.log('Compte vérifié et actif !');
// 3. Calcul du coût de l'opération
console.log('--- 3. Calcul du coût ---');
const costRes = await axios.get(`${BASE_URL}/thirdparty/bank-transfer/cost-calculate`, {
headers,
params: {
amount: 10000,
country: 'IN'
}
});
console.log(`Frais estimés : ${costRes.data.cost} ${costRes.data.targetMonetaryArea?.currencyCode}`);
// 4. Cotation du montant à débiter et génération du quoteId (Devise INR)
console.log('--- 4. Cotation (debited-amount) ---');
const debitedRes = await axios.get(`${BASE_URL}/thirdparty/bank-transfer/debited-amount`, {
headers,
params: {
amount: 10000,
country: 'IN',
msisdn: '919876543210',
accountNumber: '232201001617',
currency: 'INR'
}
});
const quoteId = debitedRes.data.quoteId;
console.log(`QuoteId généré : ${quoteId} (Montant total XOF: ${debitedRes.data.totalAmount})`);
// 5. Exécution du transfert bancaire (POST)
console.log('--- 5. Soumission du transfert ---');
const operationRes = await axios.post(`${BASE_URL}/thirdparty/bank-transfer/operation`, {
amount: 10000,
recipientCountry: 'IN',
senderCountry: 'BJ',
recipientName: 'CENTRE',
recipientSurname: 'DEVKI LUGGAGE',
recipientAccountNumber: '232201001617',
recipientBankCode: bankCode,
recipientBankName: bankName,
recipientMsisdn: '+919876543210',
recipientNationality: 'IN',
recipientAddress: 'Rue des Indes',
recipientIdType: 'PASSPORT',
recipientIdNumber: 'IN1234567',
remittancePurpose: 'Family Maintenance',
sourceOfFunds: 'Salary',
relationshipSender: 'Brother',
quoteId: quoteId,
externalReference: `BANK-TRANS-IND-${Date.now()}`
}, { headers });
const internalReference = operationRes.data.reference;
console.log(`Transfert soumis avec succès ! Statut: ${operationRes.data.status}`);
console.log(`Référence interne générée : ${internalReference}`);
// 6. Suivi du statut de la transaction via la référence interne
console.log('--- 6. Suivi du statut ---');
const statusRes = await axios.get(`${BASE_URL}/thirdparty/operation`, {
headers,
params: { reference: internalReference }
});
console.log(`Statut final de l'opération : ${statusRes.data.status}`);
} catch (error) {
if (error.response?.data?.message?.includes('REVENUE SHARING NOT CONFIGURED')) {
console.error("Dépannage : Le partage de revenus (Revenue Sharing) n'est pas configuré pour votre clé API. Contactez l'administrateur BestCash.");
} else {
console.error('Erreur durant le workflow :', error.response?.data || error.message);
}
}
}
executeBankTransferWorkflow();