Aller au contenu

Bénéficiaires

Enregistrez une destination de payout une fois, puis payez-la par son id plutôt que par son numéro.

Un bénéficiaire est une destination enregistrée : un nom, un numéro Mobile Money et l'opérateur qui le dessert. Vous le créez une fois, puis le payez par son id. Le numéro reste ainsi absent de chaque appel de payout et des logs produits par ces appels.

C'est aussi le seul moyen de payer deux fois la même personne sans ressaisir la destination des fonds. Une ressaisie est souvent la cause d'un envoi vers le mauvais téléphone.

Créer un bénéficiaire

POSThttps://api.wajub.com/beneficiaries
channelstringobligatoire
L'opérateur qui dessert le numéro, comme cm.mtn ou cm.orange. La forme générique est expliquée ci-dessous.
namestringobligatoire
Le bénéficiaire, tel qu'il doit apparaître sur le payout. Également utilisé comme nom du titulaire du compte.
phonestringfacultatif
Le numéro qui reçoit les fonds. Obligatoire sauf si vous transmettez account_number. Le champ s'appelle phone, pas phone_number.
account_numberstringfacultatif
La destination lorsqu'il ne s'agit pas d'un numéro de téléphone. L'un des deux champs est obligatoire. phone renseigne celui-ci si vous l'omettez.
emailstringfacultatif
L'adresse de contact du bénéficiaire. Elle ne sert actuellement à aucun envoi.
country_codestringfacultatif
Deux lettres. Par défaut, les deux premières lettres du slug du canal. cm.mtn donne donc CM.
notestringfacultatif
Texte libre pour votre propre référence, limité à 1 000 caractères.
metadataobjectfacultatif
Vos propres paires clé-valeur, renvoyées sans modification à chaque lecture.

Envoyez la requête avec la clé secrète. La création d'un bénéficiaire possède une limite de requêtes plus stricte que le reste de l'API. Ajouter une destination représente en effet la moitié de ce dont un attaquant a besoin pour déplacer des fonds.

curl https://api.wajub.com/beneficiaries   -H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…"   -H "Content-Type: application/json"   -H "Idempotency-Key: beneficiary-amina"   -d '{
    "channel": "cm.mtn",
    "name": "Amina Traoré",
    "phone": "+237670000000"
  }'

La réponse est 201 Created. Chaque payout utilise le champ id, préfixé par ben_ en live et ben_test_ dans la sandbox. Les deux environnements ne peuvent donc jamais être confondus.

Réponse · 201 Created
{
"code": 201,
"status": "Created",
"message": "Beneficiary created successfully",
"beneficiary": {
"id": "ben_7Kq2mX9vL4tRb3nP8sZc",
"name": "Amina Traoré",
"phone": "+237670000000",
"country_code": "CM",
"note": "Retainer, paid on the 1st",
"metadata": [
],
"sandbox": false,
"is_active": true,
"type": "standard",
"payment_method": {
"id": "pm_4Dw8kR2xN6vQ",
"type": "mobile_money",
"name": "MTN Mobile Money"
},
"created_at": "2026-09-11T14:00:00Z",
"updated_at": "2026-09-11T14:00:00Z"
}
}

La destination ne figure pas dans la réponse

payment_method contient un id, un type et un libellé, mais jamais le numéro qui reçoit les fonds. Aucun endpoint de l'API ne permet de relire la destination d'un bénéficiaire. Si vous devez montrer au bénéficiaire où ses fonds sont envoyés, conservez votre propre copie lors de la création. Les champs laissés vides sont retirés de la réponse au lieu d'être renvoyés avec null. Un objet metadata vide revient sous forme de [], et non {}. Typez-le donc comme une map pouvant aussi arriver sous forme de tableau vide.

Le canal détermine l'opérateur

Indiquez directement l'opérateur lorsque vous le connaissez, avec cm.mtn ou cm.orange. Sinon, transmettez le canal générique du pays, comme cm.mobile. L'opérateur est alors déterminé à partir du numéro.

Cette résolution peut échouer. Elle renvoie alors une erreur claire au lieu de choisir un opérateur au hasard.

Réponse · 422 quand le numéro ne correspond à aucun opérateur
{
"message": "Could not determine operator from phone number for cm.mobile.",
"errors": {
"channel": [
"Could not determine operator from phone number for cm.mobile. Use a valid number (e.g. MTN +23767..., Orange +23769...) or specify the channel explicitly (e.g. cm.mtn, cm.orange)."
]
}
}

Si vous connaissez déjà l'opérateur, indiquez-le. La forme générique sert lorsque vous ne disposez que d'un numéro.

Payer un autre compte Wajub

Quand la personne que vous payez a déjà un compte Wajub, utilisez le canal wajub et son numéro de compte à 11 chiffres. L'argent ne quitte jamais Wajub : un solde est débité, l'autre crédité, sans réseau intermédiaire et sans attente.

Un bénéficiaire sur un autre compte Wajub
{
"name": "Boutique Ada",
"channel": "wajub",
"account_number": "12345678901"
}

Le compte doit exister, ne peut pas être le vôtre, et ne peut pas être un compte que Wajub a gelé — chaque cas est refusé avec 422 à la création du bénéficiaire, et un versement vers un compte gelé depuis échoue de lui-même. Le payer est un virement ordinaire, avec les mêmes plafonds et les mêmes statuts ; il réussit simplement tout de suite, et il est gratuit — il n'y a aucun réseau à payer entre deux comptes Wajub. Sur un compte dont Wajub vérifie les bénéficiaires, le nom est comparé à la fiche de conformité du destinataire plutôt qu'aux données d'un opérateur.

En sandbox

Un versement sandbox sur ce canal est simulé comme n'importe quel autre : il réussit, échoue ou reste en attente selon le scénario demandé, et le solde sandbox du destinataire n'est jamais crédité. Seul le live déplace de l'argent entre comptes.

Payer un bénéficiaire

Transmettez l'id à l'emplacement où un payout attend un destinataire. Le reste du transfert ne change pas.

POSThttps://api.wajub.com/transfers

Le corps correspond à celui décrit dans Transferts, avec une chaîne à la place de l'objet inline.

Payer un bénéficiaire enregistré
{
"beneficiary": "ben_7Kq2mX9vL4tRb3nP8sZc",
"amount": 15000,
"currency": "XAF",
"description": "September retainer"
}

Enregistrer un bénéficiaire ne sécurise pas son paiement

Un bénéficiaire est une destination, pas une protection contre les doublons. Chaque POST /transfers nécessite toujours sa propre valeur Idempotency-Key, que le bénéficiaire soit enregistré ou non. Sans elle, une nouvelle tentative paie deux fois. Consultez Idempotence.

Éléments modifiables ou non

PUThttps://api.wajub.com/beneficiaries/{id}

La mise à jour accepte cinq champs. La destination n'en fait pas partie.

ChampModifiable
name, email, country_code, metadataOui
phoneOui, uniquement comme coordonnée de contact
channel, account_number, la destination du payoutNon

Récupérer un bénéficiaire

GEThttps://api.wajub.com/beneficiaries/{id}

Cet appel récupère par son id le même objet que celui renvoyé à la création. Utilisez-le pour vérifier qu'un bénéficiaire est toujours actif avant un payout. Rappelez-vous qu'il n'indique toujours pas le numéro qui reçoit les fonds.

curl https://api.wajub.com/beneficiaries/ben_7Kq2mX9vL4tRb3nP8sZc   -H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…"

Une réponse 404 couvre trois situations sans les distinguer : l'id n'existe pas, appartient à un autre compte ou dépend de l'autre environnement. Le cas le plus courant est la lecture d'un id ben_test_ avec une clé live.

Lister les bénéficiaires

GEThttps://api.wajub.com/beneficiaries

Les résultats sont renvoyés du plus récent au plus ancien, par groupes de vingt-cinq, sauf si vous augmentez per_page, dont le maximum est 100. L'enveloppe contient items et meta. Transmettre cursor change à la fois le mode de pagination et la forme de meta, comme pour les transferts.

Réponse · 200 OK
{
"code": 200,
"status": "OK",
"message": "Beneficiaries retrieved",
"items": [
{
"id": "ben_7Kq2mX9vL4tRb3nP8sZc",
"name": "Amina Traoré",
"type": "standard",
"is_active": true
}
],
"meta": {
"current_page": 1,
"per_page": 25,
"total": 1
}
}

search ne fonctionne pas de la même manière dans les deux environnements. Dans la sandbox, la recherche porte directement sur le nom, l'e-mail, le téléphone et l'id. En live, elle utilise l'index de recherche, qui couvre aussi le code pays et le type. Une recherche live peut donc renvoyer des résultats absents dans la sandbox.

is_active filtre selon l'indicateur correspondant. Le filtre type mérite une explication.

TypeCréé parVérifié
standardVos propres appels APIÀ la création
privilegedWajub, dans le back-officeSeulement après vérification par Wajub

Par défaut, la liste renvoie uniquement les bénéficiaires standard. Ce choix est volontaire. Un bénéficiaire privileged peut ne pas être vérifié. Un payout live vers une destination non vérifiée est refusé avec This beneficiary payment method has not been verified yet and cannot receive live payouts.. Utilisez type=privileged ou type=all uniquement si vous souhaitez réellement les afficher.

Vos propres bénéficiaires sont marqués comme vérifiés dès leur création, car le marchand garantit ses propres bénéficiaires. Un bénéficiaire standard peut donc être payé immédiatement.

Supprimer un bénéficiaire

DELETEhttps://api.wajub.com/beneficiaries/{id}

La réponse est 200. L'enregistrement disparaît des listes et ne peut plus être payé. Les transferts déjà envoyés vers ce bénéficiaire continuent de le référencer, afin que votre historique reste lisible.

L'API ne permet aucune restauration. Recréer la même destination produit un nouveau bénéficiaire avec un nouvel id, et ne récupère pas l'ancien.

Événements envoyés à votre webhook

ÉvénementDéclencheur
beneficiary.createdUn enregistrement est réellement créé. Pas lors du renvoi d'un doublon décrit plus haut, qui ne crée rien
beneficiary.updatedL'un des cinq champs modifiables change
beneficiary.deletedUn bénéficiaire est supprimé

Que pensez-vous de ce contenu ?