Aller au contenu

Transferts

Refus avant l'envoi, échec chez l'opérateur ou limitation dans une boucle de payouts.

Un transfert envoie vos fonds vers l'extérieur. Il est donc plus strictement contrôlé qu'un paiement : clé autorisée, fréquence des appels et solde disponible. La plupart des problèmes de transfert proviennent du fonctionnement normal de l'un de ces trois contrôles.

Erreur 406 Private Key Required pour une clé publique

Vous avez envoyé une clé publique. Les payouts, le solde, les remboursements, les litiges et les bénéficiaires acceptent uniquement une clé privée.

RouteClé publiqueClé privée
/payments, /accountsAcceptéeAcceptée
/transfers, /balance, /refunds, /disputes, /beneficiaries406Acceptée

Notez le code. Il s'agit de 406, pas de 403. Une branche qui attend 403 pour détecter une mauvaise clé ne s'exécute jamais ici.

Erreur 403 This API key does not have permission to write transfer liée au scope

Vous avez envoyé une clé restreinte sans le scope nécessaire. Les payouts exigent transfer.write et les routes de lecture exigent transfer.read. Les scopes sont figés à la création de la clé. Pour les élargir, créez une nouvelle clé.

Le transfert a immédiatement échoué

Lisez reason sur l'objet du transfert. Trois valeurs couvrent la plupart des cas.

reasonCauseAction
insufficient_balanceVotre solde disponible ne couvre pas le montant et les fraisApprovisionnez le solde, puis créez un nouveau transfert
invalid_recipientLe numéro ou le compte n'est pas valide pour ce canalCorrigez le bénéficiaire, aucun fonds n'a été transféré
recipient_unregisteredAucun portefeuille de cet opérateur ne correspond au numéroComparez le numéro au préfixe de l'opérateur

Les deuxième et troisième valeurs proviennent généralement de la même erreur : le numéro appartient à un autre opérateur que le channel indiqué. Au Cameroun, un numéro qui commence par +23767 appartient à MTN et +23769 à Orange. Utiliser le mauvais canal échoue sans vous coûter de fonds. Formats de numéros de téléphone contient le tableau des préfixes.

Le moment du règlement explique souvent insufficient_balance. Un encaissement succeeded n'est pas encore utilisable. Il devient disponible après le règlement. Votre solde contient une valeur available et une valeur pending. Un payout utilise uniquement available.

Je ne peux pas annuler un transfert

Il n'existe aucun endpoint d'annulation. POST /transfers crée le transfert. GET /transfers et GET /transfers/{id} le lisent. Une fois créé, le transfert passe à succeeded, failed ou cancelled si le prestataire l'interrompt lui-même.

Ce choix est volontaire. Un payout s'exécute sans intervention humaine. Une période d'annulation permettrait de reprendre les fonds après leur crédit au bénéficiaire. Validez avant d'envoyer.

Réponse 429 dans une boucle de payouts

Les payouts possèdent leur propre plafond en plus des quatre limites générales : 20 par minute et par équipe, quel que soit votre plan. Une boucle sur une liste de bénéficiaires l'atteint bien avant le quota de l'équipe.

La réponse 429 de ce plafond ne contient pas le champ type présent avec les limites générales. Un handler qui lit toujours type échoue donc sur la réponse qu'il doit justement traiter.

Réponse de la limitation des payouts
{
"code": 429,
"status": "Too Many Requests",
"message": "Too Many requests. Merchant limit : 360",
"retry_after": 24
}

Espacez les appels, respectez retry_after et exécutez les lots de payouts en dehors des périodes où une personne peut en attendre un. Gestion des limites de requêtes présente cette stratégie.

Il n'existe aucun transfert groupé

Aucun téléversement CSV, endpoint par lots ou tableau de destinataires n'est disponible. Chaque transfert correspond à un POST /transfers avec un bénéficiaire, d'où le plafond de 20 par minute.

Pour payer de nombreuses personnes, utilisez une file avec un groupe limité de workers, une clé d'idempotence dérivée de la ligne du payout et des nouvelles tentatives sur la file plutôt que sur l'appel.

Le bénéficiaire affirme n'avoir rien reçu

Avant de suspecter le transfert, vérifiez ses données.

Interrogez le transfert, pas le bénéficiaire
curl https://api.wajub.com/transfers/po_9xh0XQ5wu2lxCSUGajfv \
  -H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
  | jq '.transfer | { status, reason, amount, currency, created_at }'

succeeded signifie que l'opérateur a confirmé le crédit. Les fonds se trouvent alors chez le bénéficiaire. La question doit lui être adressée ou transmise à son opérateur, pas à Wajub. processing signifie que le transfert est toujours en cours. En Mobile Money, il dure généralement moins de deux minutes, mais peut prendre plus de temps sur un réseau encombré.

Que pensez-vous de ce contenu ?