Documentation API Transfert International d'Argent (Money Remit)
Spécifications d'intégration, cycle séquentiel en 4 étapes et guide de test en environnement PAP pour les transferts d'argent transfrontaliers vers portefeuilles mobiles (Mobile Wallets).
Présentation
L'API Money Remit B-MO permet aux partenaires d'exécuter des transferts de fonds transfrontaliers vers des portefeuilles mobiles (Mobile Wallets) en Afrique (ex: Togo, Ghana, Côte d'Ivoire, etc.).
L'intégration d'un transfert d'argent s'articule obligatoirement en 4 étapes séquentielles :
- Prérequis corridor (
GET /thirdparty/money-remit/requirements) : Découverte dynamique des contraintes KYC, des montants min/max et des choix autorisés selon le pays destinataire. - Validation formelle (
POST /thirdparty/money-remit/requirements/check) : Vérification de la conformité du formulaire et des énumérations par le compilateur avant tout appel financier. - Exécution de l'opération (
POST /thirdparty/money-remit/operation) : Ordre de virement vers le wallet mobile récepteur et interrogation en direct du switch télécom. - Vérification du statut (
GET /thirdparty/operation) : Suivi de l'état final de la transaction via votre référence externe unique.
URL de Base (selon l'environnement sélectionné) :
- TEST (Défaut) :
https://svc.test.bestcash.me/external- PAP :
https://svc.pap.bestcash.me/external- LIVE (Production) :
https://svc.bmo.bestcash.me/externalVous pouvez basculer d'un environnement à un autre à tout moment depuis le menu déroulant en haut des consoles d'essai
<ApiPlayground />ci-dessous.En-têtes obligatoires :
X-Auth-ApiKey: Votre identifiant partenaire APIX-Auth-ApiSecret: Votre clé secrète APIContent-Type:application/jsonAccept:application/json
Condition indispensable pour les étapes 3 et 4
[!CAUTION]
Interrogation du switch télécom en temps réel & Compte Mobile Money actif
Lors de l'appel à l'étape 3 (
/operation), le serveur Bestcash interroge le réseau télécom distant en temps réel. Si le numéro de téléphone renseigné n'est pas un compte Mobile Money existant et actif sur le réseau de destination (ex: T-Money ou Moov au Togo, MTN Mobile Money ou Vodafone Cash au Ghana), l'appel est rejeté immédiatement avec l'erreur :400 Bad Request : BENEFICIARY ACCOUNT NOT FOUNDRecommandation stricte pour vos tests :
- À l'étape 3 (
/operation), remplacez le numéro de test par un vrai numéro Mobile Money actif de l'opérateur du pays cible.- Le numéro doit être transmis au format international sans espaces ni signe
+(ex:22890000000pour le Togo,233243109307pour le Ghana).- Sans portefeuille actif, le switch télécom rejettera systématiquement la transaction.
Règles strictes de validation du formulaire
[!WARNING]
1. Aucun champ superflu ("Extra Fields")
N'envoyez aucun champ non réclamé par l'endpoint des prérequis (par exemple
recipientCurrency). La présence d'un champ non supporté entraîne un rejet immédiat avec l'erreur400 VALIDATION FAILED (extra fields).
[!IMPORTANT]
2. Respect scrupuleux de la casse des énumérations
Les valeurs textuelles des listes de choix (
choices) doivent respecter la casse exacte renvoyée à l'étape 1 :
Salary(et nonSALARYnisalary)Family Maintenance(et nonfamily maintenanceniFAMILY MAINTENANCE)Sister(et nonSISTER)CIpour la carte d'identité
1. Récupérer les prérequis par pays (GET /thirdparty/money-remit/requirements)
Chaque pays de destination applique ses propres contraintes réglementaires (KYC), ses plafonds financiers et ses listes de choix autorisées. Cet endpoint permet d'interroger dynamiquement la configuration du corridor.
- Méthode :
GET - URL :
/external/thirdparty/money-remit/requirements - Paramètres de requête (Query params) :
countryCode(obligatoire) : Code pays ISO 3166-1 alpha-2 du pays récepteur (ex:TGpour le Togo,GHpour le Ghana,CIpour la Côte d'Ivoire).
Tester la récupération des prérequis corridor
Obtenez dynamiquement les champs obligatoires et les choix KYC autorisés pour un pays de destination.
Exemple de requête cURL
curl -X GET "https://svc.pap.bestcash.me/external/thirdparty/money-remit/requirements?countryCode=GH" \
-H "X-Auth-ApiKey: +2290196666262" \
-H "X-Auth-ApiSecret: y7MwWuWeQORtpA==" \
-H "Accept: application/json"
Exemple de réponse HTTP 200
{
"isProviderMandatory": false,
"minAmount": 100,
"maxAmount": 10000,
"mandatoryFields": [
{ "code": "recipientSurname", "type": "string" },
{ "code": "recipientName", "type": "string" },
{ "code": "recipientMsisdn", "type": "numeric" },
{
"code": "remittancePurpose",
"type": "choice",
"choices": [
"Family Maintenance",
"Salary",
"Savings",
"Business Travel",
"Education Support"
]
},
{
"code": "sourceOfFunds",
"type": "choice",
"choices": [
"Salary",
"Savings",
"Business Income",
"Loan",
"Others"
]
},
{
"code": "relationshipSender",
"type": "choice",
"choices": [
"Sister",
"Brother",
"Father",
"Mother",
"Friend"
]
}
],
"providers": [
{ "name": "MTN", "code": "", "minAmount": 100, "maxAmount": 10000 }
]
}
2. Valider les données du transfert (POST /thirdparty/money-remit/requirements/check)
Permet de soumettre l'intégralité des champs KYC et financiers pour validation par le compilateur avant toute exécution financière. Cela garantit qu'aucun champ obligatoire ne manque et que les formats de données sont conformes.
- Méthode :
POST - URL :
/external/thirdparty/money-remit/requirements/check - En-têtes requis :
Content-Type: application/jsonAccept: application/jsonX-Auth-ApiKey: +2290196666262X-Auth-ApiSecret: y7MwWuWeQORtpA==
Tester la validation des données KYC
Vérifiez la conformité de vos données avant exécution.
Aucun paramètre d'URL configuré.
Exemple de requête cURL (Corridor Ghana - GH)
curl -X POST "https://svc.pap.bestcash.me/external/thirdparty/money-remit/requirements/check" \
-H "X-Auth-ApiKey: +2290196666262" \
-H "X-Auth-ApiSecret: y7MwWuWeQORtpA==" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"amount": 100,
"recipientSurname": "Amor",
"recipientName": "Prince",
"recipientMsisdn": "233243109307",
"recipientAddressLine1": "centre-ville",
"recipientIdType": "CI",
"recipientNationality": "GH",
"recipientBirthDate": "2000-04-09",
"recipientIdNumber": "123698547",
"recipientIdExpiryDate": "2029-04-09",
"senderPhone": "+2299225098",
"senderFirstName": "Antoine",
"senderLastName": "Atrokpo",
"senderCountry": "BJ",
"senderNationality": "BJ",
"senderDateOfBirth": "2000-12-12",
"senderIdType": "CI",
"senderIdNumber": "123589647",
"senderIdExpiryDate": "2029-04-09",
"senderAddress": "Dantokpa",
"senderCity": "Cotonou",
"remittancePurpose": "Family Maintenance",
"sourceOfFunds": "Salary",
"relationshipSender": "Sister"
}'
Exemple de réponse HTTP 200 (Succès)
{
"code": 200,
"message": "VALIDATION SUCCESS"
}
Exemple de réponse HTTP 400 (Échec de validation)
{
"code": 400,
"message": "Validation Failed",
"errors": {
"sourceOfFunds": [
"This value is not valid."
],
"remittancePurpose": [
"This value should not be blank."
]
}
}
3. Exécuter l'opération financière (POST /thirdparty/money-remit/operation)
Initie le virement vers le wallet mobile récepteur et déclenche le contrôle auprès du switch de l'opérateur distant.
- Méthode :
POST - URL :
/external/thirdparty/money-remit/operation - Champ spécifique partenaire obligatoire :
externalReference(obligatoire) : Votre identifiant unique de transaction (ex:"REMIT-GH-AMOR-001"ou"REMIT-TG-SUCCESS-001").
Tester l'exécution du transfert d'argent
Initiez le virement Mobile Money avec une référence unique.
Aucun paramètre d'URL configuré.
Exemple de requête cURL
curl -X POST "https://svc.pap.bestcash.me/external/thirdparty/money-remit/operation" \
-H "X-Auth-ApiKey: +2290196666262" \
-H "X-Auth-ApiSecret: y7MwWuWeQORtpA==" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"amount": 100,
"externalReference": "REMIT-GH-AMOR-001",
"recipientSurname": "Amor",
"recipientName": "Prince",
"recipientMsisdn": "233243109307",
"recipientAddressLine1": "centre-ville",
"recipientIdType": "CI",
"recipientNationality": "GH",
"recipientBirthDate": "2000-04-09",
"recipientIdNumber": "123698547",
"recipientIdExpiryDate": "2029-04-09",
"senderPhone": "+2299225098",
"senderFirstName": "Antoine",
"senderLastName": "Atrokpo",
"senderCountry": "BJ",
"senderNationality": "BJ",
"senderDateOfBirth": "2000-12-12",
"senderIdType": "CI",
"senderIdNumber": "123589647",
"senderIdExpiryDate": "2029-04-09",
"senderAddress": "Dantokpa",
"senderCity": "Cotonou",
"remittancePurpose": "Family Maintenance",
"sourceOfFunds": "Salary",
"relationshipSender": "Sister"
}'
Réponses possibles
Succès nominal (HTTP 201 CREATED - Statut CONFIRMED)
{
"prefixedAmount": "1 133 F CFA",
"prefixedOperationCost": "0 F CFA",
"prefixedTotalOperationCost": "1 133 F CFA",
"operationCode": "04182325042934",
"status": "CONFIRMED",
"operationCost": 0.0,
"amount": 1133.0,
"operationType": "MONEY_REMITTANCE-MOBILE_WALLET",
"reference": "TPMW20260908164229511",
"creationDate": "2026-09-08T16:42:29+00:00",
"recipientReceivedPrefixedAmount": "10 GHS",
"recipientMsisdn": "233243109307"
}
Exécution sandbox simulée / test non déboursé (HTTP 201 - Statut FAILED)
{
"prefixedAmount": "5 883 F CFA",
"prefixedOperationCost": "0 F CFA",
"operationCode": "",
"status": "FAILED",
"operationCost": 0.0,
"amount": 5883.0,
"operationType": "MONEY_REMITTANCE-MOBILE_WALLET",
"reference": "TPMW20260908164229511",
"creationDate": "2026-09-08T16:42:29+00:00"
}
[!NOTE] Interprétation du code HTTP 201 : Une réponse HTTP 201 signifie que la requête a été acceptée et traitée techniquement par le système. Cependant, l'opération n'est considérée comme un succès financier que si la propriété
"status"vaut"CONFIRMED"ou"ONGOING". Un statut"FAILED"indique un échec au niveau de l'opérateur distant ou de la ligne bénéficiaire, même en présence d'un code HTTP 201.
4. Vérifier le statut de l'opération (GET /thirdparty/operation)
Permet d'interroger à tout moment l'état d'un transfert précédemment initié en utilisant votre référence unique partenaire (externalReference).
- Méthode :
GET - URL :
/external/thirdparty/operation - Paramètres de requête (Query params) :
externalReference(obligatoire) : La référence unique transmise à l'étape 3 (ex:REMIT-GH-AMOR-001).
Tester la vérification de statut de transfert
Consultez l'état final d'un transfert avec votre externalReference.
Exemple de requête cURL
curl -X GET "https://svc.pap.bestcash.me/external/thirdparty/operation?externalReference=REMIT-GH-AMOR-001" \
-H "X-Auth-ApiKey: +2290196666262" \
-H "X-Auth-ApiSecret: y7MwWuWeQORtpA==" \
-H "Accept: application/json"
Exemple de réponse HTTP 200
{
"status": "CONFIRMED",
"operationCost": 0.0,
"amount": 1133.0,
"operationType": "MONEY_REMITTANCE-MOBILE_WALLET",
"reference": "TPMW20260908164229511",
"creationDate": "2026-09-08T16:42:29+00:00",
"externalReference": "REMIT-GH-AMOR-001"
}
Dictionnaire des paramètres de transfert
| Paramètre | Type | Présence | Description & Format |
|---|---|---|---|
amount | number | Obligatoire | Montant du transfert à envoyer. |
externalReference | string | Obligatoire (étape 3) | Référence unique générée par le partenaire pour identifier l'opération. |
recipientMsisdn | string | Obligatoire | Numéro Mobile Money récepteur en format international sans + (ex: 233243109307). |
recipientName | string | Obligatoire | Nom de famille du bénéficiaire. |
recipientSurname | string | Obligatoire | Prénom du bénéficiaire. |
recipientNationality | string | Obligatoire | Code pays ISO 3166-1 alpha-2 de la nationalité du récepteur (ex: GH, TG). |
recipientBirthDate | string | Obligatoire | Date de naissance du récepteur au format YYYY-MM-DD (ex: 2000-04-09). |
recipientIdType | string | Obligatoire | Type de pièce d'identité du récepteur (CI pour carte d'identité, PASSPORT, etc.). |
recipientIdNumber | string | Obligatoire | Numéro de la pièce d'identité du récepteur. |
recipientIdExpiryDate | string | Obligatoire | Date d'expiration de la pièce au format YYYY-MM-DD (ex: 2029-04-09). |
recipientAddressLine1 | string | Obligatoire | Adresse physique ou quartier de résidence du récepteur. |
senderPhone | string | Obligatoire | Numéro de téléphone de l'émetteur au format international (ex: +2299225098). |
senderFirstName | string | Obligatoire | Prénom de l'émetteur. |
senderLastName | string | Obligatoire | Nom de famille de l'émetteur. |
senderCountry | string | Obligatoire | Code pays ISO 3166-1 alpha-2 de résidence de l'émetteur (ex: BJ). |
senderNationality | string | Obligatoire | Code pays ISO 3166-1 alpha-2 de la nationalité de l'émetteur (ex: BJ). |
senderDateOfBirth | string | Obligatoire | Date de naissance de l'émetteur au format YYYY-MM-DD (ex: 2000-12-12). |
senderIdType | string | Obligatoire | Type de pièce d'identité de l'émetteur (CI, PASSPORT, etc.). |
senderIdNumber | string | Obligatoire | Numéro de pièce d'identité de l'émetteur. |
senderIdExpiryDate | string | Obligatoire | Date d'expiration de la pièce au format YYYY-MM-DD (ex: 2029-04-09). |
senderAddress | string | Obligatoire | Adresse physique de l'émetteur (ex: Dantokpa). |
senderCity | string | Obligatoire | Ville de l'émetteur (ex: Cotonou). |
remittancePurpose | string | Obligatoire | Motif du transfert parmi les choix autorisés (ex: Family Maintenance, Salary, Savings). |
sourceOfFunds | string | Obligatoire | Provenance des fonds parmi les choix autorisés (ex: Salary, Savings, Business Income). |
relationshipSender | string | Obligatoire | Relation avec le bénéficiaire parmi les choix autorisés (ex: Sister, Brother, Father, Friend). |
Codes d'erreurs et Dépannage
| Code HTTP | Message d'erreur | Cause probable & Action de résolution |
|---|---|---|
401 Unauthorized | Full authentication is required | En-têtes X-Auth-ApiKey ou X-Auth-ApiSecret manquants, expirés ou erronés. |
400 Bad Request | VALIDATION FAILED (extra fields) | Un champ non pris en charge (ex: recipientCurrency) a été inclus dans le corps JSON. Retirez tout champ non présent dans la liste des prérequis. |
400 Bad Request | This value is not valid. | Valeur d'énumération non reconnue ou casse incorrecte pour remittancePurpose, sourceOfFunds, relationshipSender ou idType. |
400 Bad Request | BENEFICIARY ACCOUNT NOT FOUND | Le numéro de téléphone mobile money n'existe pas ou n'est pas actif auprès de l'opérateur télécom distant. Vérifiez le numéro et testez avec un portefeuille réel actif. |
400 Bad Request | REVENUE SHARING NOT CONFIGURED | La grille de partage de commissions pour ce corridor n'est pas encore activée sur votre compte marchand. Contactez le support technique Bestcash pour son activation. |
400 Bad Request | TARGET COUNTRY NOT FOUND / COUNTRY NOT FOUND | Le code pays de destination est inconnu du système. Utilisez un code ISO 3166-1 alpha-2 valide (ex: TG, GH, CI). |
400 Bad Request | COUNTRY NOT SUPPORTED / UNSUPPORTED DESTINATION | Les transferts vers ce corridor ne sont pas encore opérationnels ou ouverts à votre compte. |
400 Bad Request | INSUFFICIENT BALANCE | Le solde de votre compte émetteur BMO est insuffisant pour couvrir le montant du transfert et les frais associés. |
400 Bad Request | INVALID RECIPIENT MSISDN / INVALID OR MISSING PHONE NUMBER | Le numéro du destinataire est manquant ou ne respecte pas le format international (sans +). |
400 Bad Request | OPERATION CONFIG NOT FOUND | La configuration de routage pour ce corridor/opérateur est manquante côté plateforme. |
400 Bad Request | SERVICE UNREACHABLE | Indisponibilité temporaire du switch télécom ou du partenaire local. Réessayez la requête après quelques instants. |
404 Not Found | RESSOURCE_NOT_FOUND | La référence externe recherchée (externalReference) n'existe pas en base (l'opération a été rejetée avant création). |
Exemples d'implémentation de bout en bout
const axios = require('axios');
const BASE_URL = 'https://svc.pap.bestcash.me/external';
const HEADERS = {
'X-Auth-ApiKey': '+2290196666262',
'X-Auth-ApiSecret': 'y7MwWuWeQORtpA==',
'Content-Type': 'application/json',
'Accept': 'application/json'
};
async function executeMoneyRemit() {
try {
// 1. Récupérer les prérequis
console.log('--- 1. Consultation des prérequis (GH) ---');
const reqRes = await axios.get(`${BASE_URL}/thirdparty/money-remit/requirements?countryCode=GH`, {
headers: HEADERS
});
console.log('Prérequis reçus :', reqRes.data);
// Données du transfert
const remitData = {
amount: 100,
recipientSurname: "Amor",
recipientName: "Prince",
recipientMsisdn: "233243109307", // Portefeuille Mobile Money actif sans le '+'
recipientAddressLine1: "centre-ville",
recipientIdType: "CI",
recipientNationality: "GH",
recipientBirthDate: "2000-04-09",
recipientIdNumber: "123698547",
recipientIdExpiryDate: "2029-04-09",
senderPhone: "+2299225098",
senderFirstName: "Antoine",
senderLastName: "Atrokpo",
senderCountry: "BJ",
senderNationality: "BJ",
senderDateOfBirth: "2000-12-12",
senderIdType: "CI",
senderIdNumber: "123589647",
senderIdExpiryDate: "2029-04-09",
senderAddress: "Dantokpa",
senderCity: "Cotonou",
remittancePurpose: "Family Maintenance",
sourceOfFunds: "Salary",
relationshipSender: "Sister"
};
// 2. Valider les données du formulaire
console.log('--- 2. Validation formelle ---');
const checkRes = await axios.post(`${BASE_URL}/thirdparty/money-remit/requirements/check`, remitData, {
headers: HEADERS
});
console.log('Résultat validation :', checkRes.data);
// 3. Exécuter l'opération financière
const externalReference = `REMIT-GH-${Date.now()}`;
console.log(`--- 3. Exécution de l'opération (${externalReference}) ---`);
const opRes = await axios.post(`${BASE_URL}/thirdparty/money-remit/operation`, {
...remitData,
externalReference
}, { headers: HEADERS });
console.log('Réponse opération :', opRes.data);
// 4. Suivre le statut
console.log('--- 4. Vérification du statut ---');
const statusRes = await axios.get(`${BASE_URL}/thirdparty/operation?externalReference=${externalReference}`, {
headers: HEADERS
});
console.log('Statut final :', statusRes.data);
} catch (error) {
console.error('Erreur :', error.response ? error.response.data : error.message);
}
}
executeMoneyRemit();