Sign in
Pagamentos e saques/Payout API

API de saques

Envie saques do saldo do seu comerciante para qualquer endereço blockchain.

A API de saques permite sacar fundos programaticamente do saldo do seu comerciante para qualquer endereço blockchain.

Para todos os endpoints de saque, você deve usar uma Payout API key separada para gerar a assinatura sign. Essa chave é diferente da sua API key comum e deve ser gerada nas configurações do projeto.

Criar saque

Cria uma solicitação de saque a partir do saldo do seu comerciante.

POST/v1/payout

Parâmetros da requisição

CampoTipoObrigatórioDescrição
currencystringsimMoeda do saque (veja References)
networkstringsimCódigo da rede (veja References)
amountstringsimValor do saque
to_addressstringsimEndereço blockchain do destinatário
order_idstringnãoChave de idempotência — única dentro de um projeto. Um POST repetido com o mesmo order_id não cria um novo saque — o existente é retornado
url_callbackstringnãoURL para webhooks do saque. Omita para desabilitar webhooks neste saque
memostring | nullnãoTag/memo de destino. Atualmente usado apenas pelas redes TON e SOL; máx. 255 caracteres
from_currencystringnãoSaldo de origem a ser debitado e convertido automaticamente em currency no momento do saque. Permite que você saque em ativos voláteis (BTC, ETH, …) mantendo o saldo em uma stablecoin como USDT — você não precisa manter a cripto volátil. Passe "USDT" para debitar do saldo USDT
fee_optionstringnãoComo as taxas são cobradas. deduct (padrão) — taxas de rede + plataforma subtraídas de amount, o destinatário recebe amount - fees. add — taxas adicionadas por cima, o comerciante é debitado em amount + fees e o destinatário recebe exatamente amount

Idempotência. Dentro de um projeto, um saque é único por order_id. Reenviar o mesmo POST com o mesmo order_id é seguro — a API retorna o saque existente em vez de criar uma duplicata. Sempre informe um order_id em saques de produção.

Exemplos de requisição

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"}'

Exemplo de resposta

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"
  }
}

Taxas. Padrão fee_option: deduct — taxas de rede + plataforma são subtraídas de amount (destinatário recebe amount - fees). Passe fee_option: add para cobrar as taxas por cima — o destinatário recebe exatamente amount e o comerciante é debitado em amount + fees.

Calcular saque

Estima os valores e taxas do saque sem criar um saque nem debitar o seu saldo. Use para mostrar ao usuário o valor exato que ele receberá (ou pagará) antes de confirmar.

POST/v1/payout/calc

Parâmetros da requisição

Idênticos a Criar saque — mesmos campos, mesma assinatura. order_id, url_callback, to_address e memo são aceitos, mas ignorados: nenhum saque é persistido e nenhum callback é enviado.

Exemplo de requisição

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"}'

Exemplo de resposta

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"
  }
}

Apenas pré-visualização. Este endpoint é somente leitura — nenhum saldo é debitado e nenhum registro de saque é criado. Chame quantas vezes precisar para exibir o detalhamento de taxas na sua interface.

Status do saque

Obtenha o status de uma solicitação de saque.

GET/v1/payout/status/{uuid}

Parâmetros do path

CampoTipoObrigatórioDescrição
uuidstringsimUUID do saque (de result.uuid na criação)

Exemplo de resposta

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"
  }
}

Para esta requisição GET, a assinatura é calculada a partir de um corpo vazio: hash_hmac('sha256', base64_encode(''), $apiKey)

Campos da resposta

Campos retornados em result por POST /v1/payout e GET /v1/payout/status/{uuid}:

CampoTipoDescrição
uuidstringUUID do saque atribuído pelo sistema
order_idstringSeu identificador interno do saque (único dentro do projeto)
statusstringStatus atual do saque (veja abaixo)
currencystringMoeda do saque
networkstringCódigo da rede
amountstringValor do saque conforme solicitado
merchant_amountstringValor debitado do saldo do comerciante
network_amountstringValor efetivamente enviado on-chain (após taxas de rede + plataforma)
amount_usdstringEquivalente em USD do valor do saque
to_addressstringEndereço blockchain do destinatário
memostring | nullTag/memo de destino (TON, SOL). null caso contrário
txidstring | nullHash da transação na blockchain. null até que a transação seja enviada
block_numberint | nullNúmero do bloco em que a transação foi incluída. null até a inclusão
error_typestring | nullMotivo da falha quando status = failed (veja Tipos de erro abaixo). null caso contrário
created_atstring (ISO 8601)Horário de criação do saque
updated_atstring (ISO 8601)Horário da última mudança de status
from_currencystring | nullSaldo de origem do qual o saque foi debitado quando houve conversão automática (ex.: USDT para um saque em BTC). null se não houve conversão
debited_amountstring | nullValor efetivamente debitado do saldo de origem após a conversão. Presente apenas quando há conversão automática
debited_currencystring | nullMoeda de debited_amount — o saldo do qual os fundos foram debitados

Status de saque

O campo status pode assumir os seguintes valores:

StatusDescrição
pendingCriado, aguardando processamento
completedConcluído com sucesso — txid está definido
failedErro de envio — veja error_type
cancelledCancelado

Tipos de erro

Quando status = failed, o campo error_type descreve o motivo:

CódigoDescrição
aml_riskSaque bloqueado pelas verificações de risco AML (endereço do destinatário sinalizado como de alto risco)

Notificações de webhook

Quando o status de um saque muda, o sistema envia um webhook POST para a URL url_callback informada na criação do saque. Se url_callback não foi informado, nenhum webhook é enviado para esse saque.

  • Método: POST
  • Content-Type: application/json
  • Assinatura: campo sign no corpo da requisição, calculado com a Payout API key (a mesma chave usada para assinar requisições de saque).

O payload espelha o objeto result de GET /v1/payout/status/{uuid} mais um campo sign para verificação.

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"
}

Verificando a assinatura. Use o mesmo algoritmo dos webhooks de pagamento, mas assine com sua Payout API key em vez da API key comum. Remova o campo sign, codifique o restante do payload em JSON, em seguida em base64 e calcule hash_hmac('sha256', $base64, $payoutApiKey), comparando com o sign recebido.