Un payout transfère de la crypto de votre solde IzichangePay vers une adresse externe. Cas d’usage : rembourser un client, payer un prestataire, reverser des gains. Scope requis : payouts:write · Endpoint : POST /v1/payouts

1. Créer le retrait

La réponse contient le id du payout et son statut initial. Ce n’est pas une confirmation : la transaction n’est pas encore diffusée.

2. Libeller le montant en fiat

Vous n’êtes pas obligé de raisonner en crypto. Avec amountType="fiat", amount est exprimé dans fiatCurrency et converti en assetCode au moment de la création :
Ici vous demandez « l’équivalent de 75 000 XOF en USDT.TRC20 ». Quatre points à connaître :
  • Le taux est le spot marché, sans marge. C’est votre crypto qui sort : nous ne prenons pas de spread sur la conversion. C’est une différence avec les settlements, où une marge s’applique.
  • L’arrondi se fait vers le bas, aux décimales on-chain de l’actif. Nous n’envoyons jamais plus que l’équivalent demandé — le bénéficiaire reçoit donc un montant très légèrement inférieur à la conversion exacte.
  • Le taux est figé à la création, pas au moment de la diffusion on-chain.
  • Tout le reste du traitement est en crypto. La réponse et les webhooks renvoient amount et feeAmount dans assetCode, jamais en fiat. Les frais de service sont calculés sur le montant crypto converti. Si vous devez restituer le montant fiat à votre utilisateur, conservez-le de votre côté : l’API ne le rejoue pas.
Ne réutilisez pas amount de la réponse comme s’il était en fiat. En mode fiat, la valeur que vous avez envoyée et celle que vous recevez ne sont pas dans la même unité.

3. Qui paie les frais

feeBearer décide de qui supporte les frais de service :
  • merchant (défaut) — le bénéficiaire reçoit exactement amount, les frais sont débités de votre solde en plus.
  • customer — les frais sont prélevés sur amount : le bénéficiaire reçoit moins que le montant demandé.
En customer, ne diffusez jamais amount comme « montant reçu » à votre utilisateur. Le montant réellement envoyé est plus faible. Lisez amount et feeAmount dans le webhook payout.confirmed pour communiquer le bon chiffre.

4. Suivre l’issue

Un payout traverse plusieurs états. Abonnez-vous à ces événements :
Rappel : les champs de la ressource sont dans data.object, pas dans data.
Vous pouvez aussi interroger l’état à tout moment : GET /v1/payouts/{id}.

Le hash on-chain

txid est le hash de la transaction : votre référence de rapprochement, vérifiable sur un explorateur. Il apparaît dès la diffusion, donc sur payout.confirmed. Un transfert interne n’en a pas — il ne touche pas la chaîne. Sur un retrait finalisé avant que le hash ne soit enregistré automatiquement, txid est null. Un appel le récupère auprès du custodian et le fixe définitivement :
Sans effet et sans coût si le hash est déjà connu : l’appel renvoie simplement le payout. Le retrait doit être confirmed ou failed, sinon l’API répond 400.

5. Frais réseau

networkFeeAmount mérite une lecture attentive :
  • Avant payout.confirmed, c’est une estimation figée à la création.
  • Après, c’est le coût réel constaté on-chain.
  • Sur Tron, il peut valoir 0 alors que la transaction a bien coûté quelque chose : nous utilisons de l’énergie déléguée, qui ne se paie pas en TRX. Un 0 n’est donc pas une anomalie.
networkFeeAssetCode est la monnaie native du réseau (TRX, BNB, ETH…), différente de assetCode. C’est dans cette unité qu’il faut libeller networkFeeAmount : afficher « 0,8 USDT de frais réseau » pour un retrait USDT.TRC20 est faux, ce sont des TRX. networkFeeUsdEquivalent donne la contre-valeur en USD de ces frais. Elle sert à comparer des frais payés dans des monnaies natives différentes sans avoir à récupérer vous-même un taux. C’est un indicatif de reporting : rien de ce montant ne vous est facturé en USD.
Ce champ n’est renseigné qu’à la confirmation, quand le coût réel est constaté on-chain — il n’accompagne pas l’estimation. Sur payout.created il vaut null (donc absent du webhook). Ne le lisez qu’à partir de payout.confirmed.
Ces trois champs sont renvoyés aussi bien par GET /v1/payouts/{id} que dans les webhooks payout.*. Rappel : dans le webhook, un champ null est omis, pas envoyé à null.

Erreurs courantes

Catalogue complet : Codes d’erreur.

Voir aussi

Se faire reverser en fiat

Convertir la crypto en mobile money plutôt que l’envoyer on-chain.

Événements webhook

Le format exact de payout.*.