Sign in
Paiements et retraits/Payout API

API de retrait

Envoyez des retraits depuis votre solde marchand vers n'importe quelle adresse blockchain.

L'API de retrait vous permet de retirer par programmation des fonds depuis votre solde marchand vers n'importe quelle adresse blockchain.

Pour tous les endpoints de retrait, vous devez utiliser une Payout API key distincte pour générer la signature sign. Cette clé est différente de votre API key classique et doit être générée dans les paramètres de votre projet.

Créer un retrait

Crée une demande de retrait depuis votre solde marchand.

POST/v1/payout

Paramètres de la requête

ChampTypeRequisDescription
currencystringouiDevise du retrait (voir References)
networkstringouiCode de réseau (voir References)
amountstringouiMontant du retrait
to_addressstringouiAdresse blockchain du destinataire
order_idstringnonClé d'idempotence — unique au sein d'un projet. Un POST répété avec le même order_id ne crée pas de nouveau retrait — le retrait existant est renvoyé à la place
url_callbackstringnonURL pour les webhooks de retrait. Omettez ce champ pour désactiver les webhooks pour ce retrait
memostring | nullnonTag de destination / mémo. Actuellement utilisé uniquement par les réseaux TON et SOL ; max. 255 caractères
from_currencystringnonSolde source à débiter et à convertir automatiquement en currency au moment du retrait. Vous permet de payer en actifs volatils (BTC, ETH, …) tout en gardant votre solde dans un stablecoin comme USDT — vous n'avez pas à détenir vous-même la crypto volatile. Passez "USDT" pour débiter le solde USDT
fee_optionstringnonMode de facturation des frais. deduct (par défaut) — frais de réseau + frais de plateforme déduits de amount, le destinataire reçoit amount - fees. add — frais ajoutés en supplément, le marchand est débité de amount + fees, le destinataire reçoit exactement amount

Idempotence. Au sein d'un projet, un retrait est unique par order_id. Renvoyer le même POST avec le même order_id est sûr — l'API renvoie le retrait existant au lieu d'en créer un doublon. Passez toujours un order_id pour les retraits en production.

Exemples de requête

Shell
curl -X POST https://api.2328.io/api/v1/payout \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"TRX","network":"TRX-TRC20","amount":"1.00","to_address":"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t","order_id":"9ed25264-8be4-439f-acf5-2a8732538d27","url_callback":"https://your-site.com/webhook/payout","memo":null,"fee_option":"deduct"}'

Exemple de réponse

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dea62-1727-72aa-ac2c-eaf2ade193ef",
    "order_id": "9ed25264-8be4-439f-acf5-2a8732538d27",
    "status": "pending",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "1.00",
    "merchant_amount": "1",
    "network_amount": "0.89",
    "amount_usd": "0.33",
    "to_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "memo": null,
    "txid": null,
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-02T23:29:50+03:00",
    "updated_at": "2026-05-02T23:29:50+03:00"
  }
}

Frais. Par défaut, fee_option: deduct — les frais de réseau + frais de plateforme sont déduits de amount (le destinataire reçoit amount - fees). Passez fee_option: add pour facturer les frais en supplément — le destinataire reçoit exactement amount et le marchand est débité de amount + fees.

Calculer un retrait

Estime les montants et frais d'un retrait sans créer de retrait ni débiter votre solde. Utilisez-le pour afficher à l'utilisateur le montant exact qu'il recevra (ou paiera) avant qu'il confirme.

POST/v1/payout/calc

Paramètres de la requête

Identiques à Créer un retrait — mêmes champs, même signature. order_id, url_callback, to_address et memo sont acceptés mais ignorés : aucun retrait n'est enregistré et aucun callback n'est envoyé.

Exemple de requête

Shell
curl -X POST https://api.2328.io/api/v1/payout/calc \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"USDT","network":"TRX-TRC20","amount":"100","fee_option":"add"}'

Exemple de réponse

JSON
{
  "state": 0,
  "result": {
    "currency": "USDT",
    "network": "TRX-TRC20",
    "amount": "100",
    "fee_option": "add",
    "merchant_amount": "103.00000000",
    "network_amount": "100",
    "total_fee": "3.00000000",
    "total_fee_usd": "3.00000000"
  }
}

Aperçu uniquement. Ce endpoint est en lecture seule — aucun solde n'est débité et aucun enregistrement de retrait n'est créé. Appelez-le autant que nécessaire pour afficher le détail des frais dans votre interface.

Statut du retrait

Récupérez le statut d'une demande de retrait.

GET/v1/payout/status/{uuid}

Paramètres de chemin

ChampTypeRequisDescription
uuidstringouiUUID du retrait (depuis result.uuid à la création)

Exemple de réponse

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
    "order_id": "4dfdcc84402b1185b71cbe399321533e",
    "status": "completed",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "3.00",
    "merchant_amount": "3.00",
    "network_amount": "3.00",
    "amount_usd": "1.04",
    "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
    "memo": null,
    "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-07T00:08:38+03:00",
    "updated_at": "2026-05-07T00:08:54+03:00",
    "from_currency": "USDT",
    "debited_amount": "1.050735",
    "debited_currency": "USDT"
  }
}

Pour cette requête GET, la signature est calculée à partir d'un corps vide : hash_hmac('sha256', base64_encode(''), $apiKey)

Champs de réponse

Champs renvoyés dans result par POST /v1/payout et GET /v1/payout/status/{uuid} :

ChampTypeDescription
uuidstringUUID du retrait attribué par le système
order_idstringVotre identifiant interne de retrait (unique au sein du projet)
statusstringStatut actuel du retrait (voir ci-dessous)
currencystringDevise du retrait
networkstringCode de réseau
amountstringMontant du retrait demandé
merchant_amountstringMontant débité du solde marchand
network_amountstringMontant réellement envoyé on-chain (après frais de réseau + plateforme)
amount_usdstringÉquivalent en USD du montant du retrait
to_addressstringAdresse blockchain du destinataire
memostring | nullTag de destination / mémo (TON, SOL). null sinon
txidstring | nullHash de la transaction blockchain. null jusqu'à l'envoi de la transaction
block_numberint | nullNuméro du bloc dans lequel la transaction a été incluse. null tant qu'elle n'est pas incluse
error_typestring | nullRaison de l'échec lorsque status = failed (voir Types d'erreurs ci-dessous). null sinon
created_atstring (ISO 8601)Date de création du retrait
updated_atstring (ISO 8601)Date du dernier changement de statut
from_currencystring | nullSolde source débité pour le retrait lorsqu'une conversion automatique a été utilisée (par ex. USDT pour un retrait en BTC). null s'il n'y a pas eu de conversion
debited_amountstring | nullMontant réellement débité du solde source après conversion. Présent uniquement lorsque la conversion automatique est utilisée
debited_currencystring | nullDevise de debited_amount — le solde depuis lequel les fonds ont été débités

Statuts de retrait

Le champ status peut prendre les valeurs suivantes :

StatutDescription
pendingCréé, en attente de traitement
completedTerminé avec succès — txid est défini
failedErreur d'envoi — voir error_type
cancelledAnnulé

Types d'erreurs

Lorsque status = failed, le champ error_type indique la raison :

CodeDescription
aml_riskRetrait bloqué par les contrôles de risque AML (adresse du destinataire signalée comme à haut risque)

Notifications webhook

Lorsque le statut d'un retrait change, le système envoie un webhook POST à l'URL url_callback fournie lors de la création du retrait. Si url_callback n'a pas été fourni, aucun webhook n'est envoyé pour ce retrait.

  • Méthode : POST
  • Content-Type : application/json
  • Signature : champ sign dans le corps de la requête, calculé avec la Payout API key (la même clé utilisée pour signer les requêtes de retrait).

Le payload reflète l'objet result de GET /v1/payout/status/{uuid} plus un champ sign pour la vérification.

Payload

JSON
{
  "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
  "order_id": "4dfdcc84402b1185b71cbe399321533e",
  "status": "completed",
  "currency": "TRX",
  "network": "TRX-TRC20",
  "amount": "3.00",
  "merchant_amount": "3.00",
  "network_amount": "3.00",
  "amount_usd": "1.04",
  "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
  "memo": null,
  "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
  "block_number": null,
  "error_type": null,
  "created_at": "2026-05-07T00:08:38+03:00",
  "updated_at": "2026-05-07T00:08:54+03:00",
  "from_currency": "USDT",
  "debited_amount": "1.050735",
  "debited_currency": "USDT",
  "sign": "925ad7bf3d6841864101f7cc2c7e30652e70a06cdb04dbe07a0129480000ce4a"
}

Vérification de la signature. Utilisez le même algorithme que pour les webhooks de paiement, mais signez avec votre Payout API key au lieu de l'API key classique. Retirez le champ sign, encodez le payload restant en JSON, puis en Base64, puis calculez hash_hmac('sha256', $base64, $payoutApiKey) et comparez avec le sign reçu.