Atenção Não existe ambiente de testes para saque. Qualquer chave com a permissão de saque, inclusive
pk_test_, transfere dinheiro de verdade.
Saldo#
GET /balance (permissão balance:read):
curl https://app.thronecorporate.com/api/v1/balance \
-H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
-H "Accept: application/json"{
"balance_cents": 543210,
"pending_balance_cents": 0,
"reserved_cents": 50000,
"available_cents": 543210,
"currency": "BRL"
}| Campo | O que é |
|---|---|
available_cents |
Saldo livre para saque pela API (igual a balance_cents) |
reserved_cents |
Valor preso em saques em andamento |
pending_balance_cents |
Saldo ainda pendente |
currency |
Sempre BRL |
O saldo da API é o saldo Pix da conta. O dinheiro de vendas no cartão (Sterling, Imperium, NovaCorp, Eminence, Apex, ShadowBank, Vortex) e no Internacional (Paycore) fica numa carteira separada, acompanhada pelo painel, e não é sacado pela API.
O saque por Pix independe do recebimento por Pix: a conta saca mesmo quando a criação de cobrança Pix responde pix_not_enabled.
Antes do primeiro saque#
Três exigências, todas obrigatórias:
- Permissão
withdrawals:writena chave. Ela não vem ligada; habilite em Chaves de API. - IPs de saque. Cadastre na chave o IP (ou faixa CIDR) do servidor que vai pedir o saque. Sem nenhum IP cadastrado, todo pedido volta
403 withdrawal_ip_not_authorized. Uma chave de produção com saque também exige a lista geral de IPs da chave, que vale para todas as chamadas dela; por isso, use uma chave só para saques. Veja as duas listas de IP. - Código do autenticador. Cada pedido leva no corpo o
totp_code: os 6 dígitos atuais do aplicativo autenticador do dono da conta (o mesmo 2FA do login). Sem 2FA ativado nesse usuário, nenhum saque é aceito.
Saque automático#
Para o seu servidor pedir saque sem uma pessoa digitando o código, ele precisa gerar o totp_code sozinho, a partir da chave do autenticador do dono da conta (a chave mostrada, em texto ou QR Code, quando o 2FA é ativado). É o TOTP padrão: 6 dígitos, renovados a cada 30 segundos; o Throne aceita também o código anterior e o seguinte. Qualquer biblioteca de TOTP gera o código (por exemplo, otplib no Node.js, pyotp no Python, spomky-labs/otphp no PHP).
Atenção Essa chave dá acesso ao 2FA do login do dono da conta. Guarde-a como a secret key: só no servidor, fora do código e do repositório.
Pedir saque#
POST /withdrawals:
curl -X POST https://app.thronecorporate.com/api/v1/withdrawals \
-H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"amount_cents": 50000,
"totp_code": "123456",
"destination": { "key": "12345678909", "key_type": "cpf" }
}'import { randomUUID } from 'node:crypto';
const res = await fetch('https://app.thronecorporate.com/api/v1/withdrawals', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.THRONE_PK}:${process.env.THRONE_SK}`,
'Content-Type': 'application/json',
Accept: 'application/json',
'Idempotency-Key': randomUUID(),
},
body: JSON.stringify({
amount_cents: 50000, // R$ 500,00
totp_code: codigoDoAutenticador,
destination: { key: '12345678909', key_type: 'cpf' },
}),
});
const saque = await res.json(); // 201, status "requested"import os, uuid, requests
r = requests.post(
"https://app.thronecorporate.com/api/v1/withdrawals",
headers={
"Authorization": f"Bearer {os.environ['THRONE_PK']}:{os.environ['THRONE_SK']}",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"amount_cents": 50000,
"totp_code": codigo_do_autenticador,
"destination": {"key": "12345678909", "key_type": "cpf"},
},
timeout=20,
)
saque = r.json() # r.status_code == 201| Campo | Obrigatório | Regra |
|---|---|---|
amount_cents |
Sim | Em centavos. Mínimo padrão R$ 50,00 (5000); a sua conta pode ter outro mínimo, nunca abaixo de R$ 10,00 (1000). Máximo R$ 500.000,00 por saque |
totp_code |
Sim | Texto com os 6 dígitos atuais do autenticador do dono da conta, entre aspas ("012345"). Enviado como número, volta erro de campo |
destination.key e destination.key_type |
Para Pix | key_type: cpf ou cnpj (só números), email, phone (formato internacional, +5511999998888) ou evp (a chave aleatória, com hífens) |
destination.address e destination.network |
Para cripto | network: BTC, ETH, USDT_TRC20 ou USDT_ERC20 |
Mande Pix ou cripto: com address presente, o saque é tratado como cripto. O saque cripto só é pago se a sua conta estiver configurada para pagar saques em cripto; se não estiver, termina failed e o valor volta.
Taxa, limites e ritmo#
- A taxa sai de dentro do valor pedido: o saldo é debitado em
amount_cents, a taxa aparece emfee_centse o destino recebenet_amount_cents. O valor pedido precisa ser maior que a taxa. - Existe um limite diário por conta, que soma os saques do dia (os recusados não contam).
- O mínimo e a taxa da sua conta aparecem no painel, na tela Saque.
- No máximo 1 pedido de saque por minuto. A janela conta mesmo quando o pedido é recusado por saldo ou por limite.
Acompanhar o saque#
A resposta 201 traz o saque com status: "requested":
{
"id": "0b8f3a52-6c1d-4e2f-9a7b-3c4d5e6f7a8b",
"type": "pix",
"status": "requested",
"amount_cents": 50000,
"fee_cents": 500,
"net_amount_cents": 49500,
"requested_at": "2026-10-03T14:40:00Z",
"completed_at": null,
"failure_reason": null
}| Status | O que significa |
|---|---|
requested |
Pedido aceito, na fila de pagamento |
processing |
Enviado ao banco. Pode voltar para requested enquanto espera a vez na fila |
completed |
Pago |
failed |
Não foi pago. O valor inteiro, taxa incluída, volta para o saldo |
Consulte com GET /withdrawals/{id} (permissão withdrawals:read). O campo failure_reason vem em linguagem pronta para mostrar ao seu cliente. A API não tem listagem de saques: guarde o id.
Os webhooks withdrawal.completed e withdrawal.failed avisam mais cedo, mas nem todo saque gera webhook. Consulte o GET até chegar em completed ou failed. Detalhes em Webhooks.
Repetir um pedido de saque#
Um saque repetido por engano é dinheiro saindo duas vezes. Siga esta ordem:
- A chamada falhou sem resposta (falha de conexão, timeout ou resposta sem o JSON da API). Repita com a mesma
Idempotency-Keye exatamente o mesmo corpo, inclusive o mesmototp_code, mesmo que ele já tenha vencido. Se o primeiro pedido chegou, a API devolve o saque original sem conferir o código de novo e sem contar no limite de 1 por minuto. - Veio
409 idempotency_key_processing. O primeiro pedido ainda está sendo registrado. Espere alguns segundos e repita igual ao passo 1. Se continuar por mais de 2 minutos, siga o passo 4. - Veio um erro
4xx, ou um503com o JSON da API. O saque não foi criado. Corrija o motivo e peça de novo com umaIdempotency-Keynova e um código novo. - Veio
500(erro inesperado). O saque pode ter sido criado. Não peça de novo antes de conferir o saldo (GET /balance) e a lista de saques no painel. Repetir com a mesma chave devolve409 idempotency_key_processingpor até 24 horas, sem criar outro saque.
Nunca gere uma Idempotency-Key nova para um saque cujo resultado você não conhece. Na dúvida, confira o saldo (GET /balance) e a lista de saques no painel.
Erros#
| Status | error |
O que fazer |
|---|---|---|
403 |
scope_required |
A chave precisa da permissão withdrawals:write |
403 |
withdrawal_ip_not_authorized |
Cadastre o IP do servidor nos IPs de saque da chave |
401 |
invalid_two_factor |
Código do autenticador errado ou vencido, ou o dono da conta não tem 2FA ativado. Gere um código novo; se continuar, confira o 2FA no painel |
422 |
insufficient_balance |
Saldo menor que amount_cents |
422 |
invalid_request |
Valor abaixo do mínimo da conta, acima do máximo ou menor que a taxa. Leia o message (abaixo de R$ 10,00 o erro vem como erro de campo) |
429 |
daily_limit_exceeded |
Passou do limite diário da conta |
429 |
rate_limited |
Mais de 1 pedido por minuto. Espere 60 segundos |
403 |
seller_not_approved |
A conta ainda não está liberada para operar |
Depois de um erro desta tabela, use uma Idempotency-Key nova. Depois de um 500, ou sem resposta, siga repetir um pedido de saque.