Em resumo
A API Withdraw da Blockradar permite enviar ativos stablecoin de suas carteiras para endereços blockchain externos. Suporta saques individuais, saques em lote para múltiplos destinatários e fornece estimativa de taxas antes da execução.
Pré-requisitos
Antes de usar a API Withdraw, certifique-se de ter:
Carteira criada
Crie uma carteira pela API Create Wallet ou pelo dashboard. Você precisará do walletId para as operações de saque.
ID do ativo
Obtenha o assetId do token que deseja sacar em Assets no dashboard ou pela API Get Assets .
Saldo suficiente
Garanta que sua carteira tenha saldo suficiente do ativo a ser sacado, além do token nativo (ETH, BNB, MATIC, etc.) para cobrir as taxas de rede.
Como funciona
A API Withdraw envia ativos stablecoin de sua carteira Blockradar para qualquer endereço blockchain externo:
Saque individual Envie ativos para um endereço destinatário com uma única chamada de API.
Saque em lote Envie ativos para múltiplos destinatários em uma única chamada de API, reduzindo overhead e simplificando pagamentos em massa.
Estimativa de taxas Calcule as taxas de rede antes da execução para garantir saldo suficiente e exibir os custos aos usuários.
Modo Sign-Only Assine transações sem transmiti-las para casos de uso avançados como assinatura offline ou envio personalizado.
Master Wallet vs Child Address
A API Withdraw está disponível em dois níveis:
Master Wallet Saque diretamente de sua master wallet. Ideal para operações de tesouraria e gestão centralizada de fundos.
Child Address Saque de child addresses individuais. Perfeito para operações específicas de usuário e gestão segregada de fundos.
Endpoints
Operação Master Wallet Child Address Withdraw POST /v1/wallets/{walletId}/withdrawPOST /v1/wallets/{walletId}/addresses/{addressId}/withdrawTaxa de Rede POST /v1/wallets/{walletId}/withdraw/network-feePOST /v1/wallets/{walletId}/addresses/{addressId}/withdraw/network-feeSign-Only POST /v1/wallets/{walletId}/withdraw/signPOST /v1/wallets/{walletId}/addresses/{addressId}/withdraw/sign
Saque individual
Envie ativos para um único endereço destinatário.
Parâmetros da requisição
Parâmetro Tipo Obrigatório Descrição assetIdstring Sim* O UUID do ativo a ser sacado. Obrigatório se o array assets não for fornecido. addressstring Sim* O endereço de destino. Obrigatório se o array assets não for fornecido. amountstring Sim* O valor do saque. Deve ser maior que 0. Obrigatório se o array assets não for fornecido. referencestring Não Seu ID interno de rastreamento para o saque. notestring Não Uma mensagem curta ou observação interna. Não visível on-chain. metadataobject Não Pares chave-valor personalizados para detalhes adicionais da transação.
Os parâmetros marcados com * são obrigatórios para saques individuais, mas não são necessários se você estiver usando o array assets para saques em lote.
Exemplo de saque individual
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-here",
"address": "0xRecipientAddress...",
"amount": "100",
"reference": "payout-12345",
"note": "Monthly payout",
"metadata": {
"userId": "user_abc123",
"payoutType": "salary"
}
}'
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-here' ,
address: '0xRecipientAddress...' ,
amount: '100' ,
reference: 'payout-12345' ,
note: 'Monthly payout' ,
metadata: {
userId: 'user_abc123' ,
payoutType: 'salary'
}
})
}
). then ( r => r . json ());
console . log ( 'Withdrawal initiated:' , withdrawal . data );
Resposta do saque individual
{
"message" : "Withdrawal initiated successfully" ,
"statusCode" : 200 ,
"data" : {
"id" : "tx-uuid-123" ,
"hash" : "0xabc123..." ,
"status" : "PENDING" ,
"amount" : "100" ,
"recipientAddress" : "0xRecipientAddress..." ,
"reference" : "payout-12345" ,
"note" : "Monthly payout" ,
"metadata" : {
"userId" : "user_abc123" ,
"payoutType" : "salary"
},
"createdAt" : "2024-01-15T10:30:00Z"
}
}
Saques em lote
Envie ativos para múltiplos destinatários em uma única chamada de API. Os saques em lote são executados sequencialmente, e cada saque é processado como uma transação blockchain independente.
Quando usar saques em lote
Pagamentos em massa : Pague vários funcionários, fornecedores ou parceiros de uma vez
Distribuições : Envie ativos para múltiplos endereços
Transferências multidestinatário : Envie valores diferentes para endereços diferentes
Eficiência operacional : Reduza chamadas de API e simplifique a lógica de pagamento
Parâmetros da requisição em lote
Para saques em lote, use o array assets em vez de parâmetros individuais:
Parâmetro Tipo Obrigatório Descrição assetsarray Sim Array de objetos de saque (máximo de 20 por lote)
Cada item no array assets:
Campo Tipo Obrigatório Descrição idstring Sim O UUID do ativo a ser sacado addressstring Sim O endereço de destino amountstring Sim O valor do saque. Deve ser maior que 0. referencestring Não Nota de referência opcional para este saque notestring Não Uma mensagem curta ou observação interna. Não visível on-chain. metadataobject Não Pares chave-valor personalizados para detalhes adicionais da transação.
Exemplo de saque em lote
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": "0xRecipient1...",
"amount": "100",
"reference": "payout-001",
"note": "January salary"
},
{
"id": "asset-uuid-usdc",
"address": "0xRecipient2...",
"amount": "150",
"reference": "payout-002",
"note": "January salary"
},
{
"id": "asset-uuid-usdt",
"address": "0xRecipient3...",
"amount": "200",
"reference": "payout-003",
"note": "Vendor payment"
}
]
}'
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: '0xRecipient1...' ,
amount: '100' ,
reference: 'payout-001' ,
note: 'January salary'
},
{
id: 'asset-uuid-usdc' ,
address: '0xRecipient2...' ,
amount: '150' ,
reference: 'payout-002' ,
note: 'January salary'
},
{
id: 'asset-uuid-usdt' ,
address: '0xRecipient3...' ,
amount: '200' ,
reference: 'payout-003' ,
note: 'Vendor payment'
}
]
})
}
). then ( r => r . json ());
console . log ( 'Batch withdrawal result:' , batchWithdrawal . data );
Resposta do saque em lote
{
"message" : "Batch withdrawal initiated successfully" ,
"statusCode" : 200 ,
"data" : {
"success" : [
{
"index" : 0 ,
"id" : "tx-uuid-1" ,
"hash" : "0xabc..." ,
"status" : "PENDING" ,
"amount" : "100" ,
"recipientAddress" : "0xRecipient1..." ,
"reference" : "payout-001"
},
{
"index" : 1 ,
"id" : "tx-uuid-2" ,
"hash" : "0xdef..." ,
"status" : "PENDING" ,
"amount" : "150" ,
"recipientAddress" : "0xRecipient2..." ,
"reference" : "payout-002"
},
{
"index" : 2 ,
"id" : "tx-uuid-3" ,
"hash" : "0xghi..." ,
"status" : "PENDING" ,
"amount" : "200" ,
"recipientAddress" : "0xRecipient3..." ,
"reference" : "payout-003"
}
],
"errors" : []
}
}
Tratamento de falhas parciais
Os saques em lote suportam sucesso parcial. Se alguns saques falharem, os demais ainda serão executados:
const result = await batchWithdrawal . json ();
// Process successful withdrawals
result . data . success . forEach ( tx => {
console . log ( `✓ ${ tx . reference } : ${ tx . hash } ` );
});
// Handle failed withdrawals
result . data . errors . forEach ( error => {
console . error ( `✗ Index ${ error . index } : ${ error . error } ` );
// Retry logic or error reporting here
});
Regras de saque em lote
Regra Valor Tamanho máximo do lote 20 saques por requisição Tamanho mínimo do lote 1 saque Ordem de execução Sequencial Tratamento de erros Sucesso parcial (falhas não interrompem saques posteriores)
Estimando taxas de rede
Sempre estime as taxas antes de executar saques para garantir saldo suficiente do token nativo e exibir custos precisos aos usuários.
Estimativa de taxa individual
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-here",
"address": "0xRecipientAddress...",
"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-here' ,
address: '0xRecipientAddress...' ,
amount: '100'
})
}
). then ( r => r . json ());
console . log ( 'Network fee:' , fee . data . networkFee );
console . log ( 'Fee in USD:' , fee . data . networkFeeInUSD );
Resposta de taxa individual
{
"message" : "Network fee fetched successfully" ,
"statusCode" : 200 ,
"data" : {
"networkFee" : "0.00001247904" ,
"networkFeeInUSD" : "0.01" ,
"transactionFee" : "0" ,
"nativeBalance" : "0.5" ,
"nativeBalanceInUSD" : "450.00" ,
"estimatedArrivalTime" : 30
}
}
Estimativa de taxa em lote
Estime taxas para múltiplos saques de uma vez:
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": "0xRecipient1...",
"amount": "100"
},
{
"id": "asset-uuid-2",
"address": "0xRecipient2...",
"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: '0xRecipient1...' ,
amount: '100'
},
{
id: 'asset-uuid-2' ,
address: '0xRecipient2...' ,
amount: '50'
}
]
})
}
). then ( r => r . json ());
console . log ( 'Total network fee:' , batchFee . data . totalNetworkFee );
console . log ( 'Total fee in USD:' , batchFee . data . totalNetworkFeeInUSD );
Resposta de taxa em lote
{
"message" : "Network fee fetched successfully" ,
"statusCode" : 200 ,
"data" : {
"fees" : [
{
"index" : 0 ,
"assetId" : "asset-uuid-1" ,
"address" : "0xRecipient1..." ,
"amount" : "100" ,
"networkFee" : "0.00001247904" ,
"transactionFee" : "0" ,
"estimatedArrivalTime" : 30
},
{
"index" : 1 ,
"assetId" : "asset-uuid-2" ,
"address" : "0xRecipient2..." ,
"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" : []
}
}
Campos da resposta de taxa
Campo Descrição networkFeeTaxa de gas em unidades do token nativo (saque individual) networkFeeInUSDTaxa de gas convertida para USD (saque individual) feesArray de estimativas individuais de taxa (saque em lote) totalNetworkFeeSoma de todas as taxas de rede (saque em lote) totalNetworkFeeInUSDTaxa total de rede em USD (saque em lote) transactionFeeTaxa de transação da plataforma (se aplicável) nativeBalanceSaldo atual do token nativo nativeBalanceInUSDSaldo do token nativo em USD estimatedArrivalTimeTempo esperado de confirmação em segundos errorsArray de quaisquer estimativas falhas (saque em lote)
Modo Sign-Only
Assine transações sem transmiti-las à blockchain. Útil para:
Assinatura offline : Prepare transações para envio posterior
Fluxos multi-assinatura : Colete assinaturas antes do envio
Inspeção de transações : Revise os detalhes da transação antes de transmiti-la
Exemplo de Sign-Only
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-here",
"address": "0xRecipientAddress...",
"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-here' ,
address: '0xRecipientAddress...' ,
amount: '100'
})
}
). then ( r => r . json ());
console . log ( 'Signed transaction:' , signedTx . data . signedTransaction );
Resposta de Sign-Only
{
"message" : "Transaction signed successfully" ,
"statusCode" : 200 ,
"data" : {
"id" : "tx-uuid-123" ,
"signedTransaction" : "0xf86c..." ,
"status" : "SIGNED" ,
"amount" : "100" ,
"recipientAddress" : "0xRecipientAddress..." ,
"createdAt" : "2024-01-15T10:30:00Z"
}
}
Saques de Child Address
Saque de child addresses individuais em vez da master wallet:
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-here",
"address": "0xRecipientAddress...",
"amount": "50",
"reference": "user-withdrawal-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-here' ,
address: '0xRecipientAddress...' ,
amount: '50' ,
reference: 'user-withdrawal-123'
})
}
). then ( r => r . json ());
console . log ( 'Child address withdrawal:' , childWithdrawal . data );
Os saques de child address também suportam operações em lote usando o array assets, seguindo o mesmo formato dos saques em lote da master wallet.
Eventos de Webhook
Monitore a conclusão dos saques por meio de webhooks:
Evento Descrição withdraw.successSaque concluído e confirmado na blockchain withdraw.failedO saque não foi executado withdraw.cancelledO saque foi cancelado antes da conclusão
Payload do Webhook
{
"event" : "withdraw.success" ,
"data" : {
"id" : "081d6315-159f-4c38-b02a-c4708836c5bd" ,
"reference" : "payout-12345" ,
"senderAddress" : "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a" ,
"recipientAddress" : "0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22" ,
"amount" : "100" ,
"amountPaid" : "100" ,
"fee" : null ,
"currency" : "USD" ,
"blockNumber" : 6928833 ,
"hash" : "0x5fcb7dd11cbb5a6d64da08cf7e0d63c1a1e7b9d1b89e3e8d1c6a5f4b3a2c1d0e" ,
"status" : "SUCCESS" ,
"type" : "WITHDRAW" ,
"note" : "Monthly payout" ,
"asset" : {
"id" : "asset-uuid" ,
"name" : "USD Coin" ,
"symbol" : "USDC" ,
"decimals" : 6
},
"wallet" : {
"id" : "wallet-uuid" ,
"name" : "Main Treasury"
},
"blockchain" : {
"id" : "blockchain-uuid" ,
"name" : "ethereum" ,
"network" : "mainnet"
},
"metadata" : {
"userId" : "user_abc123" ,
"payoutType" : "salary"
},
"createdAt" : "2024-01-15T10:30:00Z" ,
"updatedAt" : "2024-01-15T10:31:00Z"
}
}
Exemplo de fluxo completo
A seguir, uma implementação completa do fluxo: estimativa de taxa → confirmação do usuário → saque:
async function processWithdrawal ( walletId , assetId , recipientAddress , amount ) {
const apiKey = process . env . BLOCKRADAR_API_KEY ;
const baseUrl = 'https://api.blockradar.co/v1' ;
// Step 1: Estimate network fee
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 ());
// Step 2: Check if we have enough native balance for gas
const fee = feeResponse . data ;
if ( parseFloat ( fee . nativeBalance ) < parseFloat ( fee . networkFee )) {
throw new Error ( `Insufficient gas: need ${ fee . networkFee } , have ${ fee . nativeBalance } ` );
}
// Step 3: Display fee to user (in your UI)
console . log ( `Network fee: ${ fee . networkFee } (≈$ ${ fee . networkFeeInUSD } )` );
console . log ( `Estimated time: ${ fee . estimatedArrivalTime } s` );
// Step 4: Execute withdrawal (after user confirmation)
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: `withdraw- ${ Date . now () } `
})
}
). then ( r => r . json ());
console . log ( 'Withdrawal initiated:' , withdrawal . data . id );
console . log ( 'Transaction hash:' , withdrawal . data . hash );
// Step 5: Listen for webhook to confirm completion
return withdrawal . data ;
}
// Usage
processWithdrawal (
'wallet-uuid' ,
'asset-uuid-usdc' ,
'0xRecipientAddress...' ,
'100'
);
Respostas de erro
{
"message" : "Insufficient balance for withdrawal" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_BALANCE" ,
"data" : {
"required" : "100" ,
"available" : "50.25" ,
"asset" : "USDC"
}
}
{
"message" : "Insufficient native token balance for gas" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_GAS" ,
"data" : {
"required" : "0.005" ,
"available" : "0.001" ,
"token" : "ETH"
}
}
{
"message" : "Invalid recipient address" ,
"statusCode" : 400 ,
"error" : "INVALID_ADDRESS" ,
"data" : {
"address" : "invalid_address_here"
}
}
{
"message" : "Asset not found" ,
"statusCode" : 404 ,
"error" : "ASSET_NOT_FOUND" ,
"data" : {
"assetId" : "invalid-asset-uuid"
}
}
{
"message" : "Amount must be greater than 0" ,
"statusCode" : 400 ,
"error" : "INVALID_AMOUNT" ,
"data" : {
"amount" : "0"
}
}
{
"message" : "Batch size exceeds maximum limit" ,
"statusCode" : 400 ,
"error" : "BATCH_SIZE_EXCEEDED" ,
"data" : {
"maximum" : 20 ,
"provided" : 25
}
}
Boas práticas
Segurança
Valide endereços : Sempre verifique os endereços dos destinatários antes de iniciar saques
Use referências : Rastreie saques com IDs de referência únicos para conciliação
Implemente webhooks : Escute os eventos withdraw.success e withdraw.failed para confirmar o status
Verifique AML : A Blockradar faz triagem automática dos endereços; revise quaisquer transações sinalizadas
Gestão de taxas
Estime antes de executar : Sempre chame o endpoint network-fee antes dos saques
Monitore o saldo nativo : Garanta ETH/BNB/MATIC suficientes para as taxas de gas
Use lotes para mais eficiência : Agrupe vários saques para reduzir chamadas de API e overhead operacional
Tratamento de erros
Trate falhas parciais : Em saques em lote, verifique tanto o array success quanto errors
Implemente retentativas : Use backoff exponencial para falhas transitórias
Registre todas as transações : Armazene IDs e hashes de transações para depuração e conciliação
Desempenho
Use tamanhos de lote adequados : Lotes maiores reduzem chamadas de API, mas aumentam o tempo de cada requisição
Cache os IDs de ativos : Armazene os IDs de ativos localmente para evitar consultas repetidas
Implemente limitação de taxa : Respeite os limites de taxa da API para evitar throttling
Referência da API
Endpoints da Master Wallet
Endpoint Descrição Withdraw Executar saque individual ou em lote Network Fee Estimar taxas de saque Sign-Only Assinar sem transmitir
Endpoints de Child Address
Endpoint Descrição Withdraw Executar saque individual ou em lote Network Fee Estimar taxas de saque Sign-Only Assinar sem transmitir
Suporte
A API Withdraw fornece uma interface flexível para enviar ativos stablecoin para endereços externos. Comece com saques individuais e estimativa de taxas e, em seguida, incorpore operações em lote para pagamentos em massa conforme suas necessidades crescerem.