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 :

  1. Consultation des banques (bank-list) : Récupération des codes banques, noms des établissements et providerCode valides pour un pays cible.
  2. Vérification du compte (check-account) : Validation obligatoire des coordonnées du compte destinataire (bankName strictement requis).
  3. Calcul du coût (cost-calculate) : Évaluation des frais d'opération.
  4. Calcul du montant à débiter (debited-amount) : Obtention du montant total prélevé (en XOF) et du jeton de cotation indispensable (quoteId).
  5. Exécution de l'opération (operation) : Soumission du transfert en POST avec le quoteId et une référence partenaire optionnelle (externalReference).
  6. Suivi du statut (/thirdparty/operation) : Vérification de l'état de la transaction en GET via 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: IN pour l'Inde, BJ pour le Bénin, NG pour le Nigeria). L'utilisation d'un nom de pays en texte brut (ex: "Inde" au lieu de "IN") entraînera une erreur COUNTRY 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: IN pour l'Inde).

Tester la liste des banques

Consultez les banques disponibles pour un pays destinataire au format ISO 2 lettres.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (1)

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é via bank-list (ex: CNRB0000232).
    • bankName (obligatoire) : Strictement requis. Le nom exact de la banque (ex: "Canara Bank"). Ne doit pas être null ou 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 bankName obligatoire : Si le paramètre bankName est omis, transmis à null ou 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.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (7)

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.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (2)

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.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (5)

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 quoteId renvoyé 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/json
    • X-Auth-ApiKey: <votre_api_key>
    • X-Auth-ApiSecret: <votre_api_secret>

Structure du Body JSON

ChampTypeDescription
amountnumberMontant de la transaction (ex: 10000)
recipientCountrystringCode ISO 2 lettres du pays destinataire (ex: "IN")
senderCountrystringCode ISO 2 lettres du pays émetteur (ex: "BJ")
recipientNamestringPrénom du destinataire (ex: "CENTRE")
recipientSurnamestringNom de famille du destinataire (ex: "DEVKI LUGGAGE")
recipientAccountNumberstringNuméro de compte du destinataire (ex: "232201001617")
recipientBankCodestringCode banque destinataire (ex: "CNRB0000232")
recipientBankNamestringStrictement requis. Nom de la banque destinataire (ex: "Canara Bank")
recipientMsisdnstringNuméro de téléphone du destinataire au format international (ex: "+919876543210")
recipientNationalitystringCode ISO 2 lettres de la nationalité du destinataire (ex: "IN")
recipientAddressstringAdresse physique du destinataire (ex: "Rue des Indes")
recipientIdTypestringType de pièce d'identité (ex: "PASSPORT", "CNI")
recipientIdNumberstringNuméro de la pièce d'identité (ex: "IN1234567")
remittancePurposestringMotif du transfert (ex: "Family Maintenance")
relationshipSenderstringRelation avec l'émetteur (ex: "Brother")
sourceOfFundsstringProvenance des fonds (ex: "Salary")
quoteIdstringObligatoire. L'identifiant de cotation récupéré à l'étape 4
externalReferencestringOptionnel. 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 du POST, 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.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (0)

Aucun paramètre d'URL configuré.

Corps de la Requête (JSON Body)

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ètre reference (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 par externalReference seule renverra une erreur RESSOURCE_NOT_FOUND si 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.

Authentification (En-têtes B-MO)
Paramètres d'URL / Query Parameters (1)

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();