Em resumo
A API de Saque da Blockradar permite que você envie stablecoins das 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 de Saque, certifique-se de ter:
Chave API
Obtenha sua chave API no Painel da Blockradar . Navegue até Configurações → Chaves API para gerar uma.
Carteira Criada
Crie uma carteira via API Criar Carteira ou pelo painel. Você precisará do walletId para operações de saque.
ID do Ativo
Obtenha o assetId do token que deseja sacar em Ativos no painel ou via API Obter Ativos .
Saldo Suficiente
Certifique-se de que sua carteira tenha saldo suficiente do ativo para sacar, além de moeda nativa (ETH, BNB, MATIC, etc.) para cobrir as taxas de rede.
Como Funciona
A API de Saque envia stablecoins da sua carteira Blockradar para qualquer endereço blockchain externo:
Saque Individual Envie ativos para um endereço de 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 sobrecarga e simplificando pagamentos em massa.
Estimativa de Taxas Calcule taxas de rede antes da execução para garantir saldo suficiente e mostrar custos aos usuários.
Modo Apenas Assinatura Assine transações sem transmiti-las para casos de uso avançados como assinatura offline ou envio personalizado.
Carteira Principal vs Endereço Filho
A API de Saque está disponível em dois níveis:
Carteira Principal Saque diretamente da sua carteira principal. Ideal para operações de tesouraria e gerenciamento centralizado de fundos.
Endereço Filho Saque de endereços filhos individuais. Perfeito para operações específicas de usuários e gerenciamento segregado de fundos.
Endpoints
Operação Carteira Principal Endereço Filho Sacar 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-feeApenas Assinar POST /v1/wallets/{walletId}/withdraw/signPOST /v1/wallets/{walletId}/addresses/{addressId}/withdraw/sign
Saque Individual
Envie ativos para um único endereço de destinatário.
Parâmetros da Requisição
Parâmetro Tipo Obrigatório Descrição assetIdstring Sim* O UUID do ativo a sacar. Obrigatório se o array assets não for fornecido. addressstring Sim* O endereço da carteira 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 de rastreamento interno para o saque. notestring Não Uma mensagem curta ou nota interna. Não visível na blockchain. metadataobject Não Pares chave-valor personalizados para detalhes adicionais da transação.
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-aqui",
"address": "0xEnderecoDestinatario...",
"amount": "100",
"reference": "pagamento-12345",
"note": "Pagamento mensal",
"metadata": {
"userId": "user_abc123",
"payoutType": "salario"
}
}'
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-aqui' ,
address: '0xEnderecoDestinatario...' ,
amount: '100' ,
reference: 'pagamento-12345' ,
note: 'Pagamento mensal' ,
metadata: {
userId: 'user_abc123' ,
payoutType: 'salario'
}
})
}
). then ( r => r . json ());
console . log ( 'Saque iniciado:' , withdrawal . data );
Resposta de Saque Individual
{
"message" : "Saque iniciado com sucesso" ,
"statusCode" : 200 ,
"data" : {
"id" : "tx-uuid-123" ,
"hash" : "0xabc123..." ,
"status" : "PENDING" ,
"amount" : "100" ,
"recipientAddress" : "0xEnderecoDestinatario..." ,
"reference" : "pagamento-12345" ,
"note" : "Pagamento mensal" ,
"metadata" : {
"userId" : "user_abc123" ,
"payoutType" : "salario"
},
"createdAt" : "2024-01-15T10:30:00Z"
}
}
Saques em Lote
Envie ativos para múltiplos destinatários em uma única chamada de API. Saques em lote são executados sequencialmente, e cada saque é processado como uma transação blockchain separada.
Quando Usar Saques em Lote
Pagamentos em massa : Pague múltiplos funcionários, fornecedores ou parceiros de uma vez
Distribuições : Envie ativos para múltiplos endereços
Transferências multi-destinatário : Envie diferentes valores para diferentes endereços
Eficiência operacional : Reduza chamadas de API e simplifique a lógica de pagamentos
Parâmetros de Requisição em Lote
Para saques em lote, use o array assets ao invés de parâmetros individuais:
Parâmetro Tipo Obrigatório Descrição assetsarray Sim Array de objetos de saque (máximo 20 por lote)
Cada item no array assets:
Campo Tipo Obrigatório Descrição idstring Sim O UUID do ativo a sacar addressstring Sim O endereço da carteira 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 nota interna. Não visível na blockchain. 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": "0xDestinatario1...",
"amount": "100",
"reference": "pagamento-001",
"note": "Salário janeiro"
},
{
"id": "asset-uuid-usdc",
"address": "0xDestinatario2...",
"amount": "150",
"reference": "pagamento-002",
"note": "Salário janeiro"
},
{
"id": "asset-uuid-usdt",
"address": "0xDestinatario3...",
"amount": "200",
"reference": "pagamento-003",
"note": "Pagamento fornecedor"
}
]
}'
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: '0xDestinatario1...' ,
amount: '100' ,
reference: 'pagamento-001' ,
note: 'Salário janeiro'
},
{
id: 'asset-uuid-usdc' ,
address: '0xDestinatario2...' ,
amount: '150' ,
reference: 'pagamento-002' ,
note: 'Salário janeiro'
},
{
id: 'asset-uuid-usdt' ,
address: '0xDestinatario3...' ,
amount: '200' ,
reference: 'pagamento-003' ,
note: 'Pagamento fornecedor'
}
]
})
}
). then ( r => r . json ());
console . log ( 'Resultado do saque em lote:' , batchWithdrawal . data );
Resposta de Saque em Lote
{
"message" : "Saque em lote iniciado com sucesso" ,
"statusCode" : 200 ,
"data" : {
"success" : [
{
"index" : 0 ,
"id" : "tx-uuid-1" ,
"hash" : "0xabc..." ,
"status" : "PENDING" ,
"amount" : "100" ,
"recipientAddress" : "0xDestinatario1..." ,
"reference" : "pagamento-001"
},
{
"index" : 1 ,
"id" : "tx-uuid-2" ,
"hash" : "0xdef..." ,
"status" : "PENDING" ,
"amount" : "150" ,
"recipientAddress" : "0xDestinatario2..." ,
"reference" : "pagamento-002"
},
{
"index" : 2 ,
"id" : "tx-uuid-3" ,
"hash" : "0xghi..." ,
"status" : "PENDING" ,
"amount" : "200" ,
"recipientAddress" : "0xDestinatario3..." ,
"reference" : "pagamento-003"
}
],
"errors" : []
}
}
Tratando Falhas Parciais
Saques em lote suportam sucesso parcial. Se alguns saques falharem, outros ainda serão executados:
const result = await batchWithdrawal . json ();
// Processar saques bem-sucedidos
result . data . success . forEach ( tx => {
console . log ( `✓ ${ tx . reference } : ${ tx . hash } ` );
});
// Tratar saques com falha
result . data . errors . forEach ( error => {
console . error ( `✗ Índice ${ error . index } : ${ error . error } ` );
// Lógica de retentativa ou relatório de erros aqui
});
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 param saques subsequentes)
Estimando Taxas de Rede
Sempre estime as taxas antes de executar saques para garantir saldo suficiente de token nativo e mostrar 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-aqui",
"address": "0xEnderecoDestinatario...",
"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-aqui' ,
address: '0xEnderecoDestinatario...' ,
amount: '100'
})
}
). then ( r => r . json ());
console . log ( 'Taxa de rede:' , fee . data . networkFee );
console . log ( 'Taxa em USD:' , fee . data . networkFeeInUSD );
Resposta de Taxa Individual
{
"message" : "Taxa de rede obtida com sucesso" ,
"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": "0xDestinatario1...",
"amount": "100"
},
{
"id": "asset-uuid-2",
"address": "0xDestinatario2...",
"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: '0xDestinatario1...' ,
amount: '100'
},
{
id: 'asset-uuid-2' ,
address: '0xDestinatario2...' ,
amount: '50'
}
]
})
}
). then ( r => r . json ());
console . log ( 'Taxa de rede total:' , batchFee . data . totalNetworkFee );
console . log ( 'Taxa total em USD:' , batchFee . data . totalNetworkFeeInUSD );
Resposta de Taxa em Lote
{
"message" : "Taxa de rede obtida com sucesso" ,
"statusCode" : 200 ,
"data" : {
"fees" : [
{
"index" : 0 ,
"assetId" : "asset-uuid-1" ,
"address" : "0xDestinatario1..." ,
"amount" : "100" ,
"networkFee" : "0.00001247904" ,
"transactionFee" : "0" ,
"estimatedArrivalTime" : 30
},
{
"index" : 1 ,
"assetId" : "asset-uuid-2" ,
"address" : "0xDestinatario2..." ,
"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 de Resposta de Taxa
Campo Descrição networkFeeTaxa de gas em unidades de token nativo (saque individual) networkFeeInUSDTaxa de gas convertida para USD (saque individual) feesArray de estimativas de taxa individuais (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 de token nativo nativeBalanceInUSDSaldo de token nativo em USD estimatedArrivalTimeTempo esperado de confirmação em segundos errorsArray de estimativas com falha (saque em lote)
Modo Apenas Assinatura
Assine transações sem transmiti-las para a 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 detalhes da transação antes de transmitir
Exemplo de Apenas Assinatura
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-aqui",
"address": "0xEnderecoDestinatario...",
"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-aqui' ,
address: '0xEnderecoDestinatario...' ,
amount: '100'
})
}
). then ( r => r . json ());
console . log ( 'Transação assinada:' , signedTx . data . signedTransaction );
Resposta de Apenas Assinatura
{
"message" : "Transação assinada com sucesso" ,
"statusCode" : 200 ,
"data" : {
"id" : "tx-uuid-123" ,
"signedTransaction" : "0xf86c..." ,
"status" : "SIGNED" ,
"amount" : "100" ,
"recipientAddress" : "0xEnderecoDestinatario..." ,
"createdAt" : "2024-01-15T10:30:00Z"
}
}
Saques de Endereço Filho
Saque de endereços filhos individuais ao invés da carteira 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-aqui",
"address": "0xEnderecoDestinatario...",
"amount": "50",
"reference": "saque-usuario-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-aqui' ,
address: '0xEnderecoDestinatario...' ,
amount: '50' ,
reference: 'saque-usuario-123'
})
}
). then ( r => r . json ());
console . log ( 'Saque de endereço filho:' , childWithdrawal . data );
Saques de endereço filho também suportam operações em lote usando o array assets, seguindo o mesmo formato dos saques em lote da carteira principal.
Eventos de Webhook
Monitore a conclusão de saques através de webhooks:
Evento Descrição withdraw.successSaque concluído e confirmado na blockchain withdraw.failedO saque falhou ao executar withdraw.cancelledO saque foi cancelado antes da conclusão
Payload do Webhook
{
"event" : "withdraw.success" ,
"data" : {
"id" : "081d6315-159f-4c38-b02a-c4708836c5bd" ,
"reference" : "pagamento-12345" ,
"senderAddress" : "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a" ,
"recipientAddress" : "0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22" ,
"amount" : "100" ,
"amountPaid" : "100" ,
"fee" : null ,
"currency" : "USD" ,
"blockNumber" : 6928833 ,
"hash" : "0x5fcb7dd11cbb5a6d64da08cf7e0d63c1a1e7b9d1b89e3e8d1c6a5f4b3a2c1d0e" ,
"status" : "SUCCESS" ,
"type" : "WITHDRAW" ,
"note" : "Pagamento mensal" ,
"asset" : {
"id" : "asset-uuid" ,
"name" : "USD Coin" ,
"symbol" : "USDC" ,
"decimals" : 6
},
"wallet" : {
"id" : "wallet-uuid" ,
"name" : "Tesouraria Principal"
},
"blockchain" : {
"id" : "blockchain-uuid" ,
"name" : "ethereum" ,
"network" : "mainnet"
},
"metadata" : {
"userId" : "user_abc123" ,
"payoutType" : "salario"
},
"createdAt" : "2024-01-15T10:30:00Z" ,
"updatedAt" : "2024-01-15T10:31:00Z"
}
}
Exemplo de Fluxo Completo
Aqui está uma implementação completa mostrando o 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' ;
// Passo 1: Estimar taxa de rede
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 ());
// Passo 2: Verificar se temos saldo nativo suficiente para gas
const fee = feeResponse . data ;
if ( parseFloat ( fee . nativeBalance ) < parseFloat ( fee . networkFee )) {
throw new Error ( `Gas insuficiente: necessário ${ fee . networkFee } , disponível ${ fee . nativeBalance } ` );
}
// Passo 3: Mostrar taxa ao usuário (na sua UI)
console . log ( `Taxa de rede: ${ fee . networkFee } (≈$ ${ fee . networkFeeInUSD } )` );
console . log ( `Tempo estimado: ${ fee . estimatedArrivalTime } s` );
// Passo 4: Executar saque (após confirmação do usuário)
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: `saque- ${ Date . now () } `
})
}
). then ( r => r . json ());
console . log ( 'Saque iniciado:' , withdrawal . data . id );
console . log ( 'Hash da transação:' , withdrawal . data . hash );
// Passo 5: Escutar webhook para confirmar conclusão
return withdrawal . data ;
}
// Uso
processWithdrawal (
'wallet-uuid' ,
'asset-uuid-usdc' ,
'0xEnderecoDestinatario...' ,
'100'
);
Respostas de Erro
{
"message" : "Saldo insuficiente para saque" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_BALANCE" ,
"data" : {
"required" : "100" ,
"available" : "50.25" ,
"asset" : "USDC"
}
}
{
"message" : "Saldo insuficiente de token nativo para gas" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_GAS" ,
"data" : {
"required" : "0.005" ,
"available" : "0.001" ,
"token" : "ETH"
}
}
{
"message" : "Endereço de destinatário inválido" ,
"statusCode" : 400 ,
"error" : "INVALID_ADDRESS" ,
"data" : {
"address" : "endereco_invalido_aqui"
}
}
{
"message" : "Ativo não encontrado" ,
"statusCode" : 404 ,
"error" : "ASSET_NOT_FOUND" ,
"data" : {
"assetId" : "asset-uuid-invalido"
}
}
{
"message" : "O valor deve ser maior que 0" ,
"statusCode" : 400 ,
"error" : "INVALID_AMOUNT" ,
"data" : {
"amount" : "0"
}
}
{
"message" : "O tamanho do lote excede o limite máximo" ,
"statusCode" : 400 ,
"error" : "BATCH_SIZE_EXCEEDED" ,
"data" : {
"maximum" : 20 ,
"provided" : 25
}
}
Melhores Práticas
Segurança
Valide endereços : Sempre verifique os endereços de destinatário antes de iniciar saques
Use referências : Rastreie saques com IDs de referência únicos para reconciliação
Implemente webhooks : Escute os eventos withdraw.success e withdraw.failed para confirmar status
Verifique AML : Blockradar examina automaticamente endereços—revise transações sinalizadas
Gerenciamento de Taxas
Estime antes de executar : Sempre chame o endpoint network-fee antes de saques
Monitore o saldo nativo : Garanta ETH/BNB/MATIC suficiente para taxas de gas
Use lotes para eficiência : Agrupe múltiplos saques para reduzir chamadas de API e sobrecarga operacional
Tratamento de Erros
Trate falhas parciais : Em saques em lote, verifique ambos os arrays success e errors
Implemente retentativas : Use backoff exponencial para falhas transitórias
Registre todas as transações : Armazene IDs de transação e hashes para depuração e reconciliação
Use tamanhos de lote apropriados : Lotes maiores reduzem chamadas de API mas aumentam tempo de requisição individual
Armazene IDs de ativos em cache : Armazene 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 Carteira Principal
Endpoint Descrição Sacar Executar saque individual ou em lote Taxa de Rede Estimar taxas de saque Apenas Assinar Assinar sem transmitir
Endpoints do Endereço Filho
Endpoint Descrição Sacar Executar saque individual ou em lote Taxa de Rede Estimar taxas de saque Apenas Assinar Assinar sem transmitir
Suporte
A API de Saque fornece uma interface flexível para enviar stablecoins para endereços externos. Comece com saques individuais e estimativa de taxas, depois incorpore operações em lote para pagamentos em massa conforme suas necessidades crescem.