Virements sortants

L'API encaisse ; elle décaisse aussi. Envoyez de l'argent depuis votre solde vers un compte Orange Money, par API ou depuis le dashboard.

Disponibles vers Orange Money. Les virements sortants sont ouverts vers les comptes Orange Money CI. En attendant que l'envoi automatique vers Orange soit branché, chaque virement Orange est exécuté par l'équipe NguePay, dans les meilleurs délais, en jours ouvrés. Wave et MTN MoMo sont bientôt disponibles. Stripe ne verse pas sur un compte Mobile Money ivoirien.

À quoi ça sert

Un virement est l'inverse d'un paiement : vous envoyez de l'argent à quelqu'un. C'est ce qui permet à une place de marché de payer ses vendeurs, à une application de verser des commissions, ou à vous de retirer votre solde vers votre propre compte.

Tout se pilote par API avec votre clé secrète : votre back-office déclenche les virements sans ouvrir le dashboard NguePay. Certains virements passent par une validation de l'équipe NguePay avant de partir ; votre intégration n'a rien de particulier à faire pour ça.

Le solde, d'abord

Un virement est financé par votre solde NguePay, alimenté par les paiements que vous encaissez. Vous ne pouvez pas envoyer ce que vous n'avez pas encore reçu.

ChampCe que c'est
availableCe que vous pouvez engager maintenant.
pendingDéjà promis à des virements en cours, y compris ceux en validation NguePay.
available_xof, pending_xofLes mêmes en XOF entiers (available et pending sont en centimes).
total_xofavailable + pending, en XOF entiers.
currencyXOF.
updated_atDernier mouvement du solde.
Les deux existent séparément pour une raison précise : sans pending, deux virements lancés à une seconde d'intervalle verraient le même solde et passeraient tous les deux. La provision est retenue dès l'enregistrement, pas à la confirmation.
curl https://api.live.nguepay.com/api/v1/balance \
  -H "Authorization: Bearer sk_live_VOTRE_CLE"
{
  "success": true,
  "data": {
    "available": 1250000,
    "available_xof": 12500,
    "pending": 400000,
    "pending_xof": 4000,
    "total_xof": 16500,
    "currency": "XOF",
    "updated_at": "2026-09-18T10:14:02.000000Z"
  },
  "message": ""
}

Envoyer un virement

POST/v1/payouts

Authentification par clé secrète. 30 appels par minute.

ChampTypeRequisDescription
amountentier✅XOF entiers. De 200 à 2 000 000.
referencechaîne (≤ 150)✅Votre référence. Clé d'idempotence.
beneficiary_providerchaîne✅*Uniquement une valeur de la liste GET /payouts/providers : orange pour l'instant.
beneficiary_numberchaîne✅*+225 suivi de 10 chiffres.
beneficiary_namechaîne (≤ 150)✅*Nom du bénéficiaire.
payout_account_uuiduuid✅*Un de vos comptes de reversement, vérifié.
descriptionchaîne (≤ 255)❌Motif, visible dans votre historique.
metadataobjet❌Vos données libres, renvoyées telles quelles. La clé _nguepay est réservée et ignorée.

* Deux formes de bénéficiaire, exclusives : soit payout_account_uuid (retrait vers un de vos comptes), soit le trio beneficiary_* (versement à un tiers). Envoyer les deux est refusé — il ne doit jamais y avoir de doute sur qui reçoit l'argent.

curl -X POST https://api.live.nguepay.com/api/v1/payouts \
  -H "Authorization: Bearer sk_live_VOTRE_CLE" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "reference": "vir_vendeur_10452",
    "beneficiary_provider": "orange",
    "beneficiary_number": "+2250700000000",
    "beneficiary_name": "Awa Kone",
    "description": "Commission vendeur septembre"
  }'

La réponse

{
  "success": true,
  "data": {
    "uuid": "5c8e1a70-2b31-4f0c-9d22-77ab3e1f9c44",
    "reference": "vir_vendeur_10452",
    "status": "pending",
    "review": "awaiting_execution",
    "amount": 500000,
    "amount_xof": 5000,
    "currency": "XOF",
    "provider": "orange",
    "beneficiary": {
      "type": "mobile_money",
      "provider": "orange",
      "name": "Awa Kone",
      "number": "orange — ************00",
      "payout_account_uuid": null
    },
    "description": "Commission vendeur septembre",
    "metadata": [],
    "failure_reason": null,
    "awaiting_operator_funds": false,
    "attempts": 0,
    "processed_at": null,
    "created_at": "2026-09-18T10:15:00.000000Z",
    "links": { "self": "/api/v1/payouts/5c8e1a70-2b31-4f0c-9d22-77ab3e1f9c44" }
  },
  "message": "Virement enregistré."
}
Le numéro du bénéficiaire revient masqué dans beneficiary.number et dans les webhooks. Vous l'avez envoyé, vous le connaissez ; le rediffuser ne ferait que l'exposer à chaque lecture.
ChampDescription
statuspending, processing, succeeded, failed ou canceled — voir le cycle de vie.
reviewÉtape de validation NguePay tant que le virement est pending : awaiting_approval ou awaiting_execution ; null sinon. Voir plus bas.
providerConnecteur qui exécute le virement (orange pour un virement Orange Money) — peut différer de beneficiary.provider, l'opérateur du bénéficiaire.
beneficiary.typemobile_money ou bank.
beneficiary.payout_account_uuidVotre compte de reversement visé, ou null pour un tiers.
metadataVos métadonnées, telles qu'envoyées ([] si aucune) ; NguePay n'y ajoute rien. La clé _nguepay est réservée : envoyée, elle est ignorée et jamais renvoyée.
failure_reasonMotif d'échec, ex. rejected_by_review — voir le cycle de vie.
awaiting_operator_fundsVoir plus bas.
attemptsNombre de soumissions automatiques à l'opérateur ; reste à 0 pour un virement envoyé par l'équipe NguePay.
processed_atDate de conclusion (succès, échec, annulation), sinon null.
links.selfChemin relatif du virement.

Description complète : objet Virement. La même forme est renvoyée par GET /payouts (liste data.payouts), GET /payouts/{uuid} et POST /payouts/{uuid}/cancel.

Idempotence

Une même reference ne peut donner qu'un seul virement. Rejouez l'appel — retry réseau, double clic, worker relancé — et vous récupérez le virement existant avec un 200 au lieu d'un 201. Aucun second virement, aucune seconde provision retenue.

C'est la protection la plus importante de cette API : un paiement créé deux fois se rembourse, un virement envoyé deux fois est parti chez le bénéficiaire.

Rejouer suppose de redemander la même chose. Une reference déjà utilisée avec un autre montant est refusée en 422 avec NGP005 : vous rendre l'ancien virement vous ferait croire que le nouveau est parti.

Validation par l'équipe NguePay

Les virements automatiques sont activés compte par compte, par l'équipe NguePay, après vérification de vos documents (KYC). Tant qu'ils ne sont pas activés, chaque virement est validé par un administrateur NguePay avant de partir, le montant restant réservé sur votre solde pendant ce temps.

Une fois activés, un virement part automatiquement, sauf s'il remplit l'une des conditions ci-dessous : il attend alors la validation de l'équipe NguePay.

Le virement est validé par NguePay si…Seuil
les virements automatiques ne sont pas activés sur votre comptetous les virements
son montant dépasse votre plafond par virement500 000 XOF par défaut
le cumul de vos virements partis sans validation aujourd'hui, celui-ci compris, dépasse votre plafond journalier2 000 000 XOF par défaut
votre KYC n'est plus validé—
le compte de reversement visé (payout_account_uuid) a été ajouté ou modifié récemmentmoins de 48 heures

Vos plafonds sont fixés par NguePay à l'activation (500 000 XOF par virement et 2 000 000 XOF par jour par défaut) et peuvent être ajustés ; NguePay peut aussi désactiver les virements automatiques à tout moment. Votre état et vos plafonds sont renvoyés dans le champ automatic de GET /payouts/providers et affichés sur la page Virements du dashboard. Les motifs de la validation ne sont pas exposés : vous voyez seulement que le virement est en validation.

Le contrat ne change pas : pendant la validation, status reste pending. Le champ review de l'objet Virement précise l'étape :

reviewSignificationDans le dashboard
awaiting_approvalUn administrateur NguePay doit valider le virement.« En validation NguePay »
awaiting_executionLe virement est validé ; l'équipe NguePay l'envoie depuis le compte Orange de NguePay, puis enregistre la référence de l'opérateur.« En cours d'envoi »
nullAucune intervention NguePay en attente.statut normal
Un virement Orange Money passe par awaiting_execution même s'il n'avait pas besoin de validation (virements automatiques activés, sous vos plafonds) : tant que l'envoi automatique vers Orange n'est pas branché, c'est l'équipe NguePay qui l'exécute, dans les meilleurs délais, en jours ouvrés.

Cycle de vie

POST /payouts ─▶ pending · review = awaiting_approval   (validation NguePay, si requise)
                    │      ├─ refusé ─────────────────────▶ failed (rejected_by_review)
                    │      └─ validé
                    ▼
             pending · review = awaiting_execution  (Orange : envoi par l'équipe NguePay)
                    ├─ envoyé ────────────────────────────▶ succeeded
                    └─ échec de l'envoi ──────────────────▶ failed (manual_execution_failed)

Envoi automatique (Wave, MTN — bientôt) : pending · review = null ─▶ processing ─▶ succeeded | failed
Tant qu'il est pending (review compris) : POST /payouts/{uuid}/cancel ─▶ canceled
StatutSignificationProvision
pendingEnregistré, pas encore parti : en validation NguePay (review renseigné), ou en attente de soumission à l'opérateur — y compris en attente des fonds de l'opérateur.retenue
processingSoumis à l'opérateur, qui n'a pas encore conclu.retenue
succeededL'argent est arrivé chez le bénéficiaire.débitée
failedLe virement n'a pas abouti — voir failure_reason ci-dessous.rendue
canceledAnnulé par vous avant l'envoi.rendue
failure_reasonQuand
rejected_by_reviewRefusé lors de la validation NguePay.
manual_execution_failedValidé, mais l'envoi par l'équipe NguePay a échoué (numéro invalide, refus de l'opérateur…).
operator_float_insufficientEnvoi automatique : fonds de l'opérateur restés insuffisants pendant 24 h.
autre valeurMotif rendu par l'opérateur lors d'un envoi automatique.

Après un échec, relancez avec une nouvelle référence : l'ancienne rend le virement échoué.

Quand l'opérateur n'a pas encore les fonds

Pour les opérateurs à envoi automatique (Wave et MTN MoMo, bientôt disponibles), le virement est payé par le compte NguePay chez l'opérateur du bénéficiaire. Votre solde NguePay peut être suffisant alors que ce compte-là est momentanément à court.

Avant chaque envoi automatique, NguePay vérifie donc que ce compte peut payer. S'il ne le peut pas, le virement n'est pas envoyé et ne part pas en échec tout de suite :

Tant qu'il est en pending (hors envoi par l'équipe NguePay), vous pouvez l'annuler.

Annuler

curl -X POST https://api.live.nguepay.com/api/v1/payouts/{uuid}/cancel \
  -H "Authorization: Bearer sk_live_VOTRE_CLE"

Possible tant que le virement est en pending, y compris pendant la validation NguePay (review: "awaiting_approval") : la provision revient aussitôt à votre solde disponible et payout.canceled est émis. Plus d'annulation une fois review: "awaiting_execution" (l'équipe NguePay peut être en train d'envoyer), ni une fois parti chez l'opérateur — il ne s'annule plus : NguePay ne peut pas rappeler de l'argent déjà parti. L'annulation est alors refusée en 422.

Être notifié

Trois événements partent vers vos destinations webhook : payout.succeeded, payout.failed et payout.canceled. Un virement envoyé par l'équipe NguePay émet lui aussi payout.succeeded ; un refus de validation ou un échec d'envoi émet payout.failed. L'entrée en validation n'émet pas d'événement : la réponse de création porte déjà review.

{
  "event": "payout.succeeded",
  "data": {
    "payout_id": "5c8e1a70-2b31-4f0c-9d22-77ab3e1f9c44",
    "reference": "vir_vendeur_10452",
    "status": "succeeded",
    "review": null,
    "amount": 500000,
    "amount_xof": 5000,
    "currency": "XOF",
    "provider": "orange",
    "beneficiary": "orange — ************00",
    "failure_reason": null,
    "awaiting_operator_funds": false,
    "processed_at": "2026-09-18T14:02:11+00:00"
  }
}

Le webhook reprend les champs du virement sous une forme aplatie : payout_id (= uuid), beneficiary est la chaîne masquée, review y figure aussi (null : ces événements sont émis une fois le virement conclu), et il ne porte ni description, ni metadata, ni attempts, ni created_at. Détail dans la Référence des événements.

Comme pour les paiements, c'est le webhook qui fait foi. La réponse 201 dit seulement que le virement est enregistré et provisionné, pas qu'il est arrivé.

Le grand livre

Chaque mouvement de solde laisse une écriture : paiement encaissé, remboursement, virement, contre-passation d'un virement échoué. C'est ce qui vous permet de justifier votre solde ligne à ligne.

curl "https://api.live.nguepay.com/api/v1/ledger?source_type=payout&per_page=50" \
  -H "Authorization: Bearer sk_live_VOTRE_CLE"

curl "https://api.live.nguepay.com/api/v1/payouts?status=failed" \
  -H "Authorization: Bearer sk_live_VOTRE_CLE"

Le filtre status=pending de GET /payouts inclut les virements en validation NguePay.

Le grand livre est en lecture seule : une écriture ne se corrige pas, elle se contre-passe par une écriture inverse. balance_after est figé à l'écriture, ce qui permet de répondre « quel était mon solde ce jour-là » sans rejouer tout l'historique.

Champ (dans data.entries)Description
uuidIdentifiant de l'écriture.
directioncredit ou debit.
source_typepayment, refund, payout, payout_reversal ou adjustment.
amount / amount_xofMontant toujours positif, en centimes / en XOF entiers.
signed_amount_xofMontant en XOF, négatif pour un débit : additionnez sans lire direction.
balance_after / balance_after_xofSolde disponible juste après l'écriture, en centimes / en XOF entiers.
currencyXOF.
descriptionLibellé, ex. Paiement cmd_10452, Virement vir_001 non abouti.
created_atDate de l'écriture.

Opérateurs et plafonds

curl https://api.live.nguepay.com/api/v1/payouts/providers \
  -H "Authorization: Bearer sk_live_VOTRE_CLE"
{
  "success": true,
  "data": {
    "providers": ["orange"],
    "automatic": {
      "auto_enabled": true,
      "auto_max_xof": 500000,
      "auto_daily_max_xof": 2000000,
      "enabled_at": "2026-10-15T09:00:00+00:00"
    },
    "limits": { "min_xof": 200, "max_xof": 2000000, "daily_max_xof": 5000000 }
  },
  "message": ""
}

providers liste les opérateurs de bénéficiaire acceptés (valeurs de beneficiary_provider) ; limits donne les bornes par virement et le plafond journalier cumulé, en XOF entiers.

automatic décrit vos virements automatiques : auto_enabled (activés ou non par NguePay après vérification de vos documents), auto_max_xof et auto_daily_max_xof (vos plafonds sans validation, en XOF entiers ; 500 000 et 2 000 000 par défaut) et enabled_at (date d'activation, sinon null). Tant que auto_enabled vaut false, chaque virement est validé par NguePay.

Tous les opérateurs qui encaissent ne décaissent pas, et la liste dépend de la configuration de la plateforme : interrogez-la plutôt que de coder les codes en dur.

Opérateur du bénéficiaireVirements
Orange Money (orange)Disponible — exécuté par l'équipe NguePay depuis le compte Orange de NguePay, dans les meilleurs délais, en jours ouvrés
Wave (wave)Bientôt disponible (envoi automatique)
MTN MoMo (mtn)Bientôt disponible (envoi automatique)

L'opérateur du bénéficiaire reste lisible dans beneficiary.provider. Stripe ne verse pas sur un compte Mobile Money ivoirien et n'apparaît pas dans la liste.

Vos comptes de reversement Mobile Money

Pour un retrait vers vos propres comptes (payout_account_uuid), le numéro doit d'abord être vérifié par un code reçu par SMS. Ces comptes se gèrent depuis le dashboard (session de connexion, pas de clé API). Un compte ajouté ou modifié depuis moins de 48 heures fait passer ses virements par la validation NguePay.

RègleValeur
Validité du code10 minutes, 5 essais — au 5ᵉ échec, il faut un nouveau code
RenvoiPOST /v1/payout-accounts/{uuid}/resend-otp
Limite de renvoiUn envoi par minute pour un compte, 10 par heure pour le marchand — au-delà, 429 avec NGP007

Erreurs propres aux virements

CodeHTTPQuand
NGP005422Référence déjà utilisée pour un autre montant.
NGP016422Solde insuffisant. Le message précise de combien.
NGP017422Opérateur non ouvert aux virements (Wave et MTN MoMo pour l'instant), ou compte de reversement non vérifié.
NGP018422Plafond journalier dépassé (les virements en validation y comptent).

Ces refus ont lieu avant toute retenue : un virement refusé ne laisse ni trace exécutable ni provision immobilisée. La validation NguePay, elle, n'est pas une erreur : le virement est créé (201) et attend.

Ce qu'il faut éviter

Besoin d'aide ?