En bref
L’API de Retrait de Blockradar vous permet d’envoyer des stablecoins depuis vos portefeuilles vers des adresses blockchain externes. Elle prend en charge les retraits individuels, les retraits par lots vers plusieurs destinataires et fournit une estimation des frais avant l’exécution.
Prérequis
Avant d’utiliser l’API de Retrait, assurez-vous d’avoir :
Portefeuille Créé
Créez un portefeuille via l’API Créer Portefeuille ou le tableau de bord. Vous aurez besoin du walletId pour les opérations de retrait.
ID de l'Actif
Obtenez l’assetId du token que vous souhaitez retirer depuis Actifs dans le tableau de bord ou via l’API Obtenir Actifs .
Solde Suffisant
Assurez-vous que votre portefeuille dispose d’un solde suffisant de l’actif à retirer, plus de la monnaie native (ETH, BNB, MATIC, etc.) pour couvrir les frais de réseau.
L’API de Retrait envoie des stablecoins depuis votre portefeuille Blockradar vers n’importe quelle adresse blockchain externe :
Retrait Individuel Envoyez des actifs à une adresse de destinataire avec un seul appel API.
Retrait par Lots Envoyez des actifs à plusieurs destinataires en un seul appel API, réduisant les frais généraux et simplifiant les paiements en masse.
Estimation des Frais Calculez les frais de réseau avant l’exécution pour garantir un solde suffisant et afficher les coûts aux utilisateurs.
Mode Signature Seule Signez les transactions sans les diffuser pour des cas d’utilisation avancés comme la signature hors ligne ou la soumission personnalisée.
Portefeuille Principal vs Adresse Enfant
L’API de Retrait est disponible à deux niveaux :
Portefeuille Principal Retirez directement depuis votre portefeuille principal. Idéal pour les opérations de trésorerie et la gestion centralisée des fonds.
Adresse Enfant Retirez depuis des adresses enfants individuelles. Parfait pour les opérations spécifiques aux utilisateurs et la gestion séparée des fonds.
Endpoints
Opération Portefeuille Principal Adresse Enfant Retirer POST /v1/wallets/{walletId}/withdrawPOST /v1/wallets/{walletId}/addresses/{addressId}/withdrawFrais de Réseau POST /v1/wallets/{walletId}/withdraw/network-feePOST /v1/wallets/{walletId}/addresses/{addressId}/withdraw/network-feeSignature Seule POST /v1/wallets/{walletId}/withdraw/signPOST /v1/wallets/{walletId}/addresses/{addressId}/withdraw/sign
Retrait Individuel
Envoyez des actifs à une seule adresse de destinataire.
Paramètres de la Requête
Paramètre Type Requis Description assetIdstring Oui* L’UUID de l’actif à retirer. Requis si le tableau assets n’est pas fourni. addressstring Oui* L’adresse du portefeuille de destination. Requis si le tableau assets n’est pas fourni. amountstring Oui* Le montant du retrait. Doit être supérieur à 0. Requis si le tableau assets n’est pas fourni. referencestring Non Votre ID de suivi interne pour le retrait. notestring Non Un court message ou une remarque interne. Non visible sur la blockchain. metadataobject Non Paires clé-valeur personnalisées pour des détails de transaction supplémentaires.
Les paramètres marqués avec * sont requis pour les retraits individuels mais ne sont pas nécessaires si vous utilisez le tableau assets pour les retraits par lots.
Exemple de Retrait Individuel
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/withdraw \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"assetId": "asset-uuid-ici",
"address": "0xAdresseDestinataire...",
"amount": "100",
"reference": "paiement-12345",
"note": "Paiement mensuel",
"metadata": {
"userId": "user_abc123",
"payoutType": "salaire"
}
}'
const withdrawal = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /withdraw` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assetId: 'asset-uuid-ici' ,
address: '0xAdresseDestinataire...' ,
amount: '100' ,
reference: 'paiement-12345' ,
note: 'Paiement mensuel' ,
metadata: {
userId: 'user_abc123' ,
payoutType: 'salaire'
}
})
}
). then ( r => r . json ());
console . log ( 'Retrait initié:' , withdrawal . data );
Réponse de Retrait Individuel
{
"message" : "Retrait initié avec succès" ,
"statusCode" : 200 ,
"data" : {
"id" : "tx-uuid-123" ,
"hash" : "0xabc123..." ,
"status" : "PENDING" ,
"amount" : "100" ,
"recipientAddress" : "0xAdresseDestinataire..." ,
"reference" : "paiement-12345" ,
"note" : "Paiement mensuel" ,
"metadata" : {
"userId" : "user_abc123" ,
"payoutType" : "salaire"
},
"createdAt" : "2024-01-15T10:30:00Z"
}
}
Retraits par Lots
Envoyez des actifs à plusieurs destinataires en un seul appel API. Les retraits par lots sont exécutés séquentiellement, et chaque retrait est traité comme une transaction blockchain séparée.
Quand Utiliser les Retraits par Lots
Paiements en masse : Payez plusieurs employés, fournisseurs ou partenaires à la fois
Distributions : Envoyez des actifs à plusieurs adresses
Transferts multi-destinataires : Envoyez différents montants à différentes adresses
Efficacité opérationnelle : Réduisez les appels API et simplifiez la logique de paiement
Paramètres de Requête par Lots
Pour les retraits par lots, utilisez le tableau assets au lieu des paramètres individuels :
Paramètre Type Requis Description assetsarray Oui Tableau d’objets de retrait (max 20 par lot)
Chaque élément du tableau assets :
Champ Type Requis Description idstring Oui L’UUID de l’actif à retirer addressstring Oui L’adresse du portefeuille de destination amountstring Oui Le montant du retrait. Doit être supérieur à 0. referencestring Non Note de référence optionnelle pour ce retrait notestring Non Un court message ou une remarque interne. Non visible sur la blockchain. metadataobject Non Paires clé-valeur personnalisées pour des détails de transaction supplémentaires.
Exemple de Retrait par Lots
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/withdraw \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"assets": [
{
"id": "asset-uuid-usdc",
"address": "0xDestinataire1...",
"amount": "100",
"reference": "paiement-001",
"note": "Salaire janvier"
},
{
"id": "asset-uuid-usdc",
"address": "0xDestinataire2...",
"amount": "150",
"reference": "paiement-002",
"note": "Salaire janvier"
},
{
"id": "asset-uuid-usdt",
"address": "0xDestinataire3...",
"amount": "200",
"reference": "paiement-003",
"note": "Paiement fournisseur"
}
]
}'
const batchWithdrawal = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /withdraw` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assets: [
{
id: 'asset-uuid-usdc' ,
address: '0xDestinataire1...' ,
amount: '100' ,
reference: 'paiement-001' ,
note: 'Salaire janvier'
},
{
id: 'asset-uuid-usdc' ,
address: '0xDestinataire2...' ,
amount: '150' ,
reference: 'paiement-002' ,
note: 'Salaire janvier'
},
{
id: 'asset-uuid-usdt' ,
address: '0xDestinataire3...' ,
amount: '200' ,
reference: 'paiement-003' ,
note: 'Paiement fournisseur'
}
]
})
}
). then ( r => r . json ());
console . log ( 'Résultat du retrait par lots:' , batchWithdrawal . data );
Réponse de Retrait par Lots
{
"message" : "Retrait par lots initié avec succès" ,
"statusCode" : 200 ,
"data" : {
"success" : [
{
"index" : 0 ,
"id" : "tx-uuid-1" ,
"hash" : "0xabc..." ,
"status" : "PENDING" ,
"amount" : "100" ,
"recipientAddress" : "0xDestinataire1..." ,
"reference" : "paiement-001"
},
{
"index" : 1 ,
"id" : "tx-uuid-2" ,
"hash" : "0xdef..." ,
"status" : "PENDING" ,
"amount" : "150" ,
"recipientAddress" : "0xDestinataire2..." ,
"reference" : "paiement-002"
},
{
"index" : 2 ,
"id" : "tx-uuid-3" ,
"hash" : "0xghi..." ,
"status" : "PENDING" ,
"amount" : "200" ,
"recipientAddress" : "0xDestinataire3..." ,
"reference" : "paiement-003"
}
],
"errors" : []
}
}
Gestion des Échecs Partiels
Les retraits par lots supportent le succès partiel. Si certains retraits échouent, les autres seront quand même exécutés :
const result = await batchWithdrawal . json ();
// Traiter les retraits réussis
result . data . success . forEach ( tx => {
console . log ( `✓ ${ tx . reference } : ${ tx . hash } ` );
});
// Gérer les retraits échoués
result . data . errors . forEach ( error => {
console . error ( `✗ Index ${ error . index } : ${ error . error } ` );
// Logique de réessai ou rapport d'erreurs ici
});
Règles de Retrait par Lots
Règle Valeur Taille maximale du lot 20 retraits par requête Taille minimale du lot 1 retrait Ordre d’exécution Séquentiel Gestion des erreurs Succès partiel (les échecs n’arrêtent pas les retraits suivants)
Estimation des Frais de Réseau
Estimez toujours les frais avant d’exécuter des retraits pour garantir un solde suffisant en monnaie native et afficher des coûts précis aux utilisateurs.
Estimation de Frais Individuelle
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/withdraw/network-fee \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"assetId": "asset-uuid-ici",
"address": "0xAdresseDestinataire...",
"amount": "100"
}'
const fee = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /withdraw/network-fee` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assetId: 'asset-uuid-ici' ,
address: '0xAdresseDestinataire...' ,
amount: '100'
})
}
). then ( r => r . json ());
console . log ( 'Frais de réseau:' , fee . data . networkFee );
console . log ( 'Frais en USD:' , fee . data . networkFeeInUSD );
Réponse de Frais Individuelle
{
"message" : "Frais de réseau récupérés avec succès" ,
"statusCode" : 200 ,
"data" : {
"networkFee" : "0.00001247904" ,
"networkFeeInUSD" : "0.01" ,
"transactionFee" : "0" ,
"nativeBalance" : "0.5" ,
"nativeBalanceInUSD" : "450.00" ,
"estimatedArrivalTime" : 30
}
}
Estimation de Frais par Lots
Estimez les frais pour plusieurs retraits à la fois :
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/withdraw/network-fee \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"assets": [
{
"id": "asset-uuid-1",
"address": "0xDestinataire1...",
"amount": "100"
},
{
"id": "asset-uuid-2",
"address": "0xDestinataire2...",
"amount": "50"
}
]
}'
const batchFee = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /withdraw/network-fee` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assets: [
{
id: 'asset-uuid-1' ,
address: '0xDestinataire1...' ,
amount: '100'
},
{
id: 'asset-uuid-2' ,
address: '0xDestinataire2...' ,
amount: '50'
}
]
})
}
). then ( r => r . json ());
console . log ( 'Frais de réseau total:' , batchFee . data . totalNetworkFee );
console . log ( 'Frais total en USD:' , batchFee . data . totalNetworkFeeInUSD );
Réponse de Frais par Lots
{
"message" : "Frais de réseau récupérés avec succès" ,
"statusCode" : 200 ,
"data" : {
"fees" : [
{
"index" : 0 ,
"assetId" : "asset-uuid-1" ,
"address" : "0xDestinataire1..." ,
"amount" : "100" ,
"networkFee" : "0.00001247904" ,
"transactionFee" : "0" ,
"estimatedArrivalTime" : 30
},
{
"index" : 1 ,
"assetId" : "asset-uuid-2" ,
"address" : "0xDestinataire2..." ,
"amount" : "50" ,
"networkFee" : "0.00000504" ,
"transactionFee" : "0" ,
"estimatedArrivalTime" : 30
}
],
"totalNetworkFee" : "0.00001751904" ,
"totalNetworkFeeInUSD" : "0.02" ,
"totalTransactionFee" : "0" ,
"nativeBalance" : "0.073690520542044578" ,
"nativeBalanceInUSD" : "66.54" ,
"estimatedArrivalTime" : 60 ,
"errors" : []
}
}
Champs de Réponse des Frais
Champ Description networkFeeFrais de gas en unités de token natif (retrait individuel) networkFeeInUSDFrais de gas convertis en USD (retrait individuel) feesTableau des estimations de frais individuelles (retrait par lots) totalNetworkFeeSomme de tous les frais de réseau (retrait par lots) totalNetworkFeeInUSDFrais de réseau total en USD (retrait par lots) transactionFeeFrais de transaction de la plateforme (si applicable) nativeBalanceSolde actuel en token natif nativeBalanceInUSDSolde en token natif en USD estimatedArrivalTimeTemps de confirmation attendu en secondes errorsTableau des estimations échouées (retrait par lots)
Mode Signature Seule
Signez les transactions sans les diffuser sur la blockchain. Utile pour :
Signature hors ligne : Préparez les transactions pour une soumission ultérieure
Flux multi-signatures : Collectez les signatures avant la soumission
Inspection des transactions : Examinez les détails de la transaction avant la diffusion
Exemple de Signature Seule
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/withdraw/sign \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"assetId": "asset-uuid-ici",
"address": "0xAdresseDestinataire...",
"amount": "100"
}'
const signedTx = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /withdraw/sign` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assetId: 'asset-uuid-ici' ,
address: '0xAdresseDestinataire...' ,
amount: '100'
})
}
). then ( r => r . json ());
console . log ( 'Transaction signée:' , signedTx . data . signedTransaction );
Réponse de Signature Seule
{
"message" : "Transaction signée avec succès" ,
"statusCode" : 200 ,
"data" : {
"id" : "tx-uuid-123" ,
"signedTransaction" : "0xf86c..." ,
"status" : "SIGNED" ,
"amount" : "100" ,
"recipientAddress" : "0xAdresseDestinataire..." ,
"createdAt" : "2024-01-15T10:30:00Z"
}
}
Retraits depuis Adresse Enfant
Retirez depuis des adresses enfants individuelles au lieu du portefeuille principal :
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/withdraw \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"assetId": "asset-uuid-ici",
"address": "0xAdresseDestinataire...",
"amount": "50",
"reference": "retrait-utilisateur-123"
}'
const childWithdrawal = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /addresses/ ${ addressId } /withdraw` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assetId: 'asset-uuid-ici' ,
address: '0xAdresseDestinataire...' ,
amount: '50' ,
reference: 'retrait-utilisateur-123'
})
}
). then ( r => r . json ());
console . log ( 'Retrait depuis adresse enfant:' , childWithdrawal . data );
Les retraits depuis adresse enfant supportent également les opérations par lots en utilisant le tableau assets, suivant le même format que les retraits par lots du portefeuille principal.
Événements Webhook
Surveillez l’achèvement des retraits via les webhooks :
Événement Description withdraw.successRetrait terminé et confirmé sur la blockchain withdraw.failedLe retrait a échoué à l’exécution withdraw.cancelledLe retrait a été annulé avant l’achèvement
Payload du Webhook
{
"event" : "withdraw.success" ,
"data" : {
"id" : "081d6315-159f-4c38-b02a-c4708836c5bd" ,
"reference" : "paiement-12345" ,
"senderAddress" : "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a" ,
"recipientAddress" : "0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22" ,
"amount" : "100" ,
"amountPaid" : "100" ,
"fee" : null ,
"currency" : "USD" ,
"blockNumber" : 6928833 ,
"hash" : "0x5fcb7dd11cbb5a6d64da08cf7e0d63c1a1e7b9d1b89e3e8d1c6a5f4b3a2c1d0e" ,
"status" : "SUCCESS" ,
"type" : "WITHDRAW" ,
"note" : "Paiement mensuel" ,
"asset" : {
"id" : "asset-uuid" ,
"name" : "USD Coin" ,
"symbol" : "USDC" ,
"decimals" : 6
},
"wallet" : {
"id" : "wallet-uuid" ,
"name" : "Trésorerie Principale"
},
"blockchain" : {
"id" : "blockchain-uuid" ,
"name" : "ethereum" ,
"network" : "mainnet"
},
"metadata" : {
"userId" : "user_abc123" ,
"payoutType" : "salaire"
},
"createdAt" : "2024-01-15T10:30:00Z" ,
"updatedAt" : "2024-01-15T10:31:00Z"
}
}
Exemple de Flux Complet
Voici une implémentation complète montrant le flux estimation des frais → confirmation utilisateur → retrait :
async function processWithdrawal ( walletId , assetId , recipientAddress , amount ) {
const apiKey = process . env . BLOCKRADAR_API_KEY ;
const baseUrl = 'https://api.blockradar.co/v1' ;
// Étape 1: Estimer les frais de réseau
const feeResponse = await fetch (
` ${ baseUrl } /wallets/ ${ walletId } /withdraw/network-fee` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assetId ,
address: recipientAddress ,
amount
})
}
). then ( r => r . json ());
// Étape 2: Vérifier si nous avons assez de solde natif pour le gas
const fee = feeResponse . data ;
if ( parseFloat ( fee . nativeBalance ) < parseFloat ( fee . networkFee )) {
throw new Error ( `Gas insuffisant: nécessaire ${ fee . networkFee } , disponible ${ fee . nativeBalance } ` );
}
// Étape 3: Afficher les frais à l'utilisateur (dans votre UI)
console . log ( `Frais de réseau: ${ fee . networkFee } (≈$ ${ fee . networkFeeInUSD } )` );
console . log ( `Temps estimé: ${ fee . estimatedArrivalTime } s` );
// Étape 4: Exécuter le retrait (après confirmation de l'utilisateur)
const withdrawal = await fetch (
` ${ baseUrl } /wallets/ ${ walletId } /withdraw` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : apiKey
},
body: JSON . stringify ({
assetId ,
address: recipientAddress ,
amount ,
reference: `retrait- ${ Date . now () } `
})
}
). then ( r => r . json ());
console . log ( 'Retrait initié:' , withdrawal . data . id );
console . log ( 'Hash de transaction:' , withdrawal . data . hash );
// Étape 5: Écouter le webhook pour confirmer l'achèvement
return withdrawal . data ;
}
// Utilisation
processWithdrawal (
'wallet-uuid' ,
'asset-uuid-usdc' ,
'0xAdresseDestinataire...' ,
'100'
);
Réponses d’Erreur
{
"message" : "Solde insuffisant pour le retrait" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_BALANCE" ,
"data" : {
"required" : "100" ,
"available" : "50.25" ,
"asset" : "USDC"
}
}
{
"message" : "Solde insuffisant en token natif pour le gas" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_GAS" ,
"data" : {
"required" : "0.005" ,
"available" : "0.001" ,
"token" : "ETH"
}
}
{
"message" : "Adresse de destinataire invalide" ,
"statusCode" : 400 ,
"error" : "INVALID_ADDRESS" ,
"data" : {
"address" : "adresse_invalide_ici"
}
}
{
"message" : "Actif non trouvé" ,
"statusCode" : 404 ,
"error" : "ASSET_NOT_FOUND" ,
"data" : {
"assetId" : "asset-uuid-invalide"
}
}
{
"message" : "Le montant doit être supérieur à 0" ,
"statusCode" : 400 ,
"error" : "INVALID_AMOUNT" ,
"data" : {
"amount" : "0"
}
}
{
"message" : "La taille du lot dépasse la limite maximale" ,
"statusCode" : 400 ,
"error" : "BATCH_SIZE_EXCEEDED" ,
"data" : {
"maximum" : 20 ,
"provided" : 25
}
}
Meilleures Pratiques
Sécurité
Validez les adresses : Vérifiez toujours les adresses des destinataires avant d’initier des retraits
Utilisez des références : Suivez les retraits avec des IDs de référence uniques pour la réconciliation
Implémentez les webhooks : Écoutez les événements withdraw.success et withdraw.failed pour confirmer le statut
Vérifiez AML : Blockradar examine automatiquement les adresses—examinez les transactions signalées
Gestion des Frais
Estimez avant d’exécuter : Appelez toujours l’endpoint network-fee avant les retraits
Surveillez le solde natif : Assurez-vous d’avoir suffisamment d’ETH/BNB/MATIC pour les frais de gas
Utilisez les lots pour l’efficacité : Regroupez plusieurs retraits pour réduire les appels API et les frais généraux opérationnels
Gestion des Erreurs
Gérez les échecs partiels : Dans les retraits par lots, vérifiez les tableaux success et errors
Implémentez les réessais : Utilisez le backoff exponentiel pour les échecs transitoires
Enregistrez toutes les transactions : Stockez les IDs de transaction et les hashes pour le débogage et la réconciliation
Utilisez des tailles de lot appropriées : Les lots plus grands réduisent les appels API mais augmentent le temps de requête individuelle
Mettez en cache les IDs d’actifs : Stockez les IDs d’actifs localement pour éviter les recherches répétées
Implémentez la limitation de débit : Respectez les limites de débit de l’API pour éviter le throttling
Référence API
Endpoints du Portefeuille Principal
Endpoint Description Retirer Exécuter un retrait individuel ou par lots Frais de Réseau Estimer les frais de retrait Signature Seule Signer sans diffuser
Endpoints de l’Adresse Enfant
Endpoint Description Retirer Exécuter un retrait individuel ou par lots Frais de Réseau Estimer les frais de retrait Signature Seule Signer sans diffuser
Support
L’API de Retrait fournit une interface flexible pour envoyer des stablecoins vers des adresses externes. Commencez par des retraits individuels et l’estimation des frais, puis intégrez les opérations par lots pour les paiements en masse à mesure que vos besoins augmentent.