Painel do parceiro → Desenvolvedores → “Obter chave de API”. A chave tem o formato smk_abcdefghij_plus48chars e é exibida uma única vez. Se você perdê-la, gere uma nova: a chave anterior deixa de funcionar na hora.
Adicione um header
Authorization: Bearer your_key.
Verifique o acesso
Consulte o saldo. Uma resposta JSON com data significa que a chave foi aceita.
{
"data": [
{
"asset_id": "usdt", // sempre usdt — não existe outro saldo
"available_atomic": "15000000", // 15 USDT em unidades mínimas (6 casas decimais)
"available": "15", // o mesmo valor em forma decimal
"held_atomic": "0", // reservado para saques não concluídos
"held": "0"
}
]
}
Se a requisição falhou
Resposta
Causa
401 unauthorized
A chave está faltando, contém um espaço ou está cortada. Depois de Bearer deve vir o identificador smk_… completo.
401 key_inactive
A chave foi revogada: uma nova chave foi gerada, mas a requisição ainda usa a anterior.
Cinco regras
A maioria dos erros de integração vem do descumprimento de uma destas regras.
1. Envie os valores como strings
Envie amount — uma string decimal: "0.001", "15" — ou amount_atomic — um inteiro em unidades mínimas: "100000" para 0.001 BTC. Use exatamente um dos dois campos. As respostas sempre trazem as duas formas: amount vem ao lado de amount_atomic.
exemplo
"amount": "0.001" // válido
"amount_atomic": "100000" // também válido
// os dois ao mesmo tempo — 422
2. Pegue asset_id apenas de /assets
Códigos permitidos: usdt, btc, xmr. Valores arbitrários e ids de exploradores de blocos são rejeitados com 422.
3. Idempotency-Key em toda requisição que cria algo
Um id único da tentativa. Se a conexão cair e o resultado for desconhecido, repita a requisição com a mesma chave: o resultado original é retornado e uma segunda operação não é criada. Obrigatório para POST /invoices, POST /payments, POST /payouts/preview e POST /payouts.
exemplo
Idempotency-Key: order-42-payment // primeira tentativa → 201, criado
Idempotency-Key: order-42-payment // nova tentativa → 200, o mesmo recurso
Idempotency-Key: order-42-payment // outro valor → 409 conflict
4. Campos vazios são omitidos
Valores null e strings vazias não são incluídos. Um pagamento que ainda não foi recebido não tem actual_amount, credited_amount nem fee. Verifique se a chave existe, não o valor dela.
exemplo
// pagamento ainda não recebido:
{ "payment_id": "pay_…", "status": "awaiting_deposit" }
// credited_amount simplesmente não aparece
5. Não feche o pedido com expired
expired não significa que a transferência nunca vai chegar. O endereço continua sendo monitorado por cerca de mais 6 horas, e uma transferência atrasada é creditada. Status finais com crédito: confirmed, confirmed_underpaid, confirmed_overpaid.
Cenários
Cada cenário cobre o ciclo completo: ordem das requisições, formato da resposta e significado dos campos. Os comentários nos exemplos JSON servem de explicação e não aparecem nas respostas reais.
Receber pagamentos
Cliente paga em BTC um pedido de 60 USD
Pedido order-42. Você precisa de cerca de 60 USDT; com o BTC a cerca de 60.000, o cliente deve enviar 0.001 BTC.
1
Obtenha a lista de ativos disponíveis
A resposta traz o código do ativo e decimals — o número de dígitos depois do ponto decimal.
{
"data": [
{
"asset_id": "btc", // ← use nas próximas requisições
"symbol": "BTC", // para mostrar ao usuário
"network": "bitcoin", // usado nos saques
"decimals": 8, // 1 BTC = 100000000 unidades mínimas
"price_usd": "60000" // indicativo, não serve para cotação
},
{
"asset_id": "usdt",
"symbol": "USDT",
"network": "TRON",
"decimals": 6,
"price_usd": "1.00"
}
]
}
2
Trave a cotação por 10 minutos
Trava a cotação enquanto o cliente está na página de pagamento. Nesta etapa não é criado nenhum pagamento nem endereço: só é calculada uma cotação. A resposta traz quantos USDT serão creditados por 0.001 BTC.
Valor em BTC esperado do cliente. Enviado como string, não como número.
Idempotency-Key
Opcional: nenhuma operação é criada. Você pode enviá-la para reutilizar a mesma cotação.
resposta
{
"data": {
"credit_lock_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
// ← guarde para a próxima etapa
"asset_id": "btc",
"expected_amount": "0.001", // valor esperado do cliente
"expected_amount_atomic": "100000",
"credit_usdt": "59.4", // ← valor que será creditado
"credit_usdt_atomic": "59400000",
"expires_at": "2026-08-11T17:20:00+00:00"
// ← depois deste horário o credit-preview perde a validade
}
}
Mostre ao cliente o expected_amount — quanto BTC ele deve enviar.
3
Crie o pagamento e obtenha o endereço
Esta etapa cria o pagamento e retorna o endereço de depósito. Não envie o valor nesta requisição — ele já foi definido no credit-preview, na etapa 2.
Id da resposta do credit-preview. Se a cotação travada tiver expirado, a API retorna 422 — solicite um novo preview.
external_id: "order-42"
O número do seu pedido. Serve para encontrar o pagamento depois e para evitar dois pagamentos para o mesmo pedido.
Idempotency-Key
Obrigatória. Use um valor único e estável, por exemplo o número do pedido com um sufixo.
resposta
{
"data": {
"payment_id": "pay_01HZX...", // ← id para consultar o status
"external_id": "order-42", // número do pedido enviado na requisição
"asset_id": "btc",
"expected_amount": "0.001",
"credit_usdt": "59.4",
"status": "awaiting_deposit", // aguardando a transferência
"channel": "api",
"deposit_address": "bc1qexampledepositaddress000000000",
// ← endereço a mostrar ao cliente
"expires_at": "2026-08-11T18:00:00+00:00",
"created_at": "2026-08-11T17:00:00+00:00"
}
}
Se a rede exigir memo, a resposta inclui deposit_memo. Uma transferência sem o memo não será creditada — mostre os dois campos.
4
Aguarde o pagamento
Consulte o pagamento a cada 10–30 segundos. O status segue awaiting_deposit → detected → processing → confirmed.
O intervalo recomendado é de 10–30 segundos. O limite é de 120 requisições por minuto por chave; não consulte com mais frequência.
resposta
{
"data": {
"payment_id": "pay_01HZX...",
"status": "detected", // transferência vista na rede,
// ainda sem confirmações suficientes
"asset_id": "btc",
"expected_amount": "0.001",
"actual_amount": "0.001", // ← valor que realmente chegou
"deposit_address": "bc1qexampledepositaddress000000000",
"created_at": "2026-08-11T17:00:00+00:00"
}
}
5
Pagamento confirmado
confirmed significa que os fundos foram creditados no saldo. O pedido pode ser fechado.
Informe ao cliente que a rede é TRC20. USDT enviados por outra rede não serão creditados neste endereço.
Cliente enviou menos do que o solicitado
Eram esperados 0.001 BTC e chegaram 0.0009 — por exemplo, a carteira do cliente descontou a taxa de rede do valor.
1
Verifique o pagamento
Se chegou menos que o expected_amount, mas o valor ainda é suficiente para ser creditado, o status é confirmed_underpaid e o credited_amount fica abaixo da cotação. Se o valor for pequeno demais, nada é creditado.
Compare credited_amount, não credit_usdt. O primeiro é o que foi creditado; o segundo é a cotação para um pagamento exato.
resposta
{
"data": {
"payment_id": "pay_01HZX...",
"external_id": "order-42",
"status": "confirmed_underpaid", // ← pagamento a menor, mas os fundos foram creditados
"asset_id": "btc",
"expected_amount": "0.001", // valor esperado
"actual_amount": "0.0009", // valor que realmente chegou
"credit_usdt": "59.4", // cotação para um pagamento exato
"credited_amount": "53.4", // ← valor realmente creditado
"fee": "0.6",
"created_at": "2026-08-11T17:00:00+00:00"
}
}
Os próximos passos ficam com você: pedir que o cliente complete o pagamento, entregar o pedido em parte ou cancelá-lo. A API retorna o valor efetivamente creditado.
Observação
Não decida “pago ou não” comparando actual_amount com expected_amount. Compare credited_amount com os USDT de que você precisa.
Cliente não pagou a tempo
O expires_at passou e nenhuma transferência chegou. O pagamento passa para expired; o endereço continua sendo monitorado.
1
Status expired
O prazo de pagamento terminou. O endereço continua sendo monitorado por cerca de 6 horas.
Se a transferência chegar dentro do prazo extra de monitoramento, o pagamento ainda passa para confirmed. Não exclua o pedido em expired: marque-o como atrasado e continue consultando.
Não gere um novo endereço logo depois de expired: o cliente pode já estar enviando para o anterior. Continuamos aguardando a transferência por mais 6 horas.
Faturas
Uma fatura em USD com página de pagamento hospedada. O cliente escolhe a rede; você recebe o crédito em USDT.
Uma fatura de 15 USD paga em USDT
Pedido order-15. O comerciante cria uma fatura em USD e envia ao cliente o link da página de pagamento.
1
Crie a fatura
A fatura fixa o valor em USD e quem paga a taxa, e retorna pay_url. Ainda não há endereço.
Valor do pedido como string. Este endpoint aceita só USD, não amount_atomic.
fee_on
merchant: você paga a taxa e o cliente vê 15.00. customer: o cliente paga a taxa.
Idempotency-Key
Obrigatória. Uma nova tentativa com a mesma chave retorna a mesma fatura.
partner_ref
Opcional. O Partner ID do integrador que configurou sua integração (programa de indicações da SnapEX Pay). Vincula sua conta a esse parceiro uma única vez; omita se você mesmo faz a integração.
Um pagamento a menor não fecha a fatura: o status fica underpaid e o mesmo endereço aguarda o restante (USDT: 72 horas). Se o restante não chegar a tempo, a fatura termina como partially_paid.
Observação
Não cite rotas internas na interface do cliente. A página de pagamento mostra só o endereço, o valor e a rede.
Não há API de reembolso. Uma segunda transferência concluída é um crédito separado, não um estorno da primeira.
Saques
Transferências de saída do seu saldo em USDT.
Envie ao cliente 15 USDT em BTC
amount é quanto sai do seu saldo, não quanto o destinatário recebe. O valor que o destinatário recebe é retornado pelo preview.
1
Verifique o saldo disponível
Use available, não available mais held. O held está reservado para saques não concluídos e não pode ser usado.
USDT debitados do seu saldo. Não é o valor que o destinatário recebe.
destination_asset_id
Ativo do destinatário. Código de GET /assets.
destination_network
Rede do destinatário. Para BTC — bitcoin. Pegue o valor de network em GET /assets.
destination_address
Endereço do destinatário. Confira antes de enviar: a transferência não pode ser cancelada.
Idempotency-Key
Obrigatória. Use uma chave separada para o preview.
resposta
{
"data": {
"preview_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd",
// ← id para a próxima etapa
"from_asset_id": "usdt",
"from_amount": "15", // valor debitado
"to_asset_id": "btc",
"to_amount": "0.000221", // ← valor que o destinatário recebe
"fee_amount": "0.000019", // taxa em BTC, já incluída
"expires_at": "2026-08-11T17:20:00+00:00"
// ← execute antes deste horário
}
}
Mostre to_amount ao usuário como o valor que ele vai receber. Se o valor não for aceitável, não execute o preview: ele expira em expires_at.
3
Execute o saque
Esta etapa debita e envia. Repita o endereço e a rede na requisição — isso impede que os dados sejam substituídos entre uma etapa e outra.
Confirme que o endereço do destinatário é da rede TRON. Uma transferência para outra rede não é executada: a requisição é rejeitada ou os fundos não vão chegar.
Saldo insuficiente para um saque
O saldo é de 10 USDT e foi solicitado um saque de 15.
1
O preview recusa a requisição
O saldo é verificado na cotação, antes de qualquer débito. O erro pode ser mostrado ao usuário na hora.
Recusa por regra de negócio. O envelope é o mesmo dos erros de validação.
details.amount
O erro fica vinculado a um campo e pode ser mostrado no formulário.
resposta
{
"error": {
"code": "validation_error",
"message": "The request is invalid.",
"details": {
"amount": ["Saldo insuficiente."]
// ← o motivo da recusa está vinculado a amount
}
}
}
Nada é reservado. Repetir com a mesma Idempotency-Key é seguro; antes, recarregue o saldo.
Observação
Considere o held: se parte dos fundos estiver reservada para outro saque, o available será menor que o esperado.
Operações
Histórico de pagamentos
O ledger é um registro de operações: créditos, débitos e reservas ficam guardados como lançamentos separados.
1
Obtenha o histórico por páginas
Os lançamentos vêm do mais recente para o mais antigo. Até 100 registros por requisição; a próxima página usa o cursor.
A operação já existia; é retornado o objeto original.
resposta
{
"data": {
"payout_id": "payout_01HZX...", // ← o mesmo id da primeira resposta
"external_id": "wd-77",
"debit_amount": "15",
"status": "processing", // o status pode ter mudado durante a espera
"created_at": "2026-08-11T17:10:00+00:00"
}
}
HTTP 201: a operação foi criada nesta requisição. HTTP 200: ela já existia. Os dois códigos indicam sucesso.
2
Se os parâmetros mudaram
Repetir a mesma chave com outro valor ou outro endereço é recusado. Isso evita divergência de parâmetros.
Conflito: a chave já está vinculada a outra operação.
O que fazer
Se for um novo saque, use uma nova Idempotency-Key.
resposta
{
"error": {
"code": "conflict",
"message": "Idempotency-Key was used with different parameters."
}
}
Observação
Gere a chave uma única vez e guarde-a junto com o pedido. Gerar uma chave nova antes de cada envio desativa a proteção contra duplicidade.
Em caso de HTTP 429, repita com a mesma chave após alguns segundos.
Webhooks
Quando uma fatura, um depósito, um saque, uma conversão ou o saldo mudam, a SnapEX envia uma requisição POST para a sua URL. O webhook é um sinal, não a fonte da verdade: verifique a assinatura HMAC e, para decisões importantes, consulte o objeto de novo pela API.
Configuração
Configure a URL no painel
Painel do parceiro → Desenvolvedores → bloco “Webhook”: informe a URL e clique em “Salvar”. Uma URL por conta; ela recebe todos os tipos de evento da tabela abaixo.
Guarde a chave secreta de assinatura
Ao salvar pela primeira vez, o painel mostra a chave secreta whsec_… uma única vez. Guarde-a apenas no seu servidor. Se você mudar a URL depois, a chave secreta continua a mesma.
Requisitos da URL
Uma URL https:// absoluta com host público: sem login:password na URL, sem localhost, e o host não pode resolver para um IP privado ou reservado. A URL é verificada ao salvar e de novo antes de cada tentativa de entrega.
O que chega
Header
Significado
Webhook-Id
Id único do evento (UUID), igual ao id no corpo. Não muda nas novas tentativas nem nos reenvios manuais — use-o para deduplicar.
Webhook-Timestamp
Horário Unix em segundos em que esta tentativa foi enviada. Cada nova tentativa traz um valor novo e uma assinatura nova.
Webhook-Signature
v1= seguido do HMAC-SHA256 em hex minúsculo da string “{Webhook-Timestamp}.{raw body}”. A chave é a chave secreta inteira, incluindo o prefixo whsec_.
{
"id": "6f1c2a8e-3b4d-4f5a-9c7e-1a2b3c4d5e6f", // = Webhook-Id
"type": "invoice.paid", // tipo de evento, veja a tabela abaixo
"created_at": "2026-09-25T12:00:10+00:00", // quando o evento aconteceu
"data": { // o objeto no momento do evento
"invoice_id": "INV-8K2M1Q0P",
"environment": "live",
"amount_usd": "15.00",
"charge_usd": "15.00",
"credit_usd": "13.85",
"status": "paid",
"external_id": "order-15",
"paid_at": "2026-09-25T12:00:10+00:00"
}
}
data depende do tipo: invoice.* — a fatura no mesmo formato de GET /invoices/{id} (attempts vem vazio, a tentativa atual está em payment); payment.* — o depósito (payment_id, external_id, status, valores); payout.* — o saque (payout_id, external_id, status, valores); conversion.* — a conversão (conversion_id, status, valores); balance.changed — asset_id, entry_type, available_atomic e held_atomic após a alteração.
Tipos de evento
Evento
Significado
invoice.created
Fatura criada; nenhuma forma de pagamento escolhida ainda (open).
invoice.awaiting
Uma forma de pagamento foi escolhida e o endereço foi gerado (awaiting).
invoice.underpaid
Parte do valor chegou; o mesmo endereço aguarda o restante (underpaid).
invoice.paid
O valor total foi pago e creditado (paid, final). É o único sinal para entregar o pedido.
invoice.partially_paid
O cliente pagou só uma parte, o prazo para completar o pagamento terminou e a parte recebida foi creditada para você (partially_paid, final).
invoice.expired
O prazo da fatura terminou sem pagamento (expired, final).
invoice.extra_payment
Outra transferência chegou depois que a fatura foi paga; ela é creditada separadamente.
payment.created
Um depósito foi criado.
payment.detected
A transferência foi vista na rede, mas ainda não foi creditada.
payment.credited
O depósito foi creditado (um dos status confirmed*).
payment.expired
O prazo do depósito expirou.
payout.created
Um saque foi criado e os fundos foram reservados.
payout.processing
O saque está sendo enviado.
payout.completed
Os fundos foram entregues ao destinatário.
payout.failed
O saque falhou.
conversion.completed
A conversão foi concluída.
conversion.failed
A conversão falhou total ou parcialmente.
balance.changed
Um lançamento de saldo foi registrado: crédito, reserva ou débito.
Entregue o pedido somente com invoice.paid — ele só é enviado quando o valor total foi pago. invoice.underpaid e invoice.partially_paid significam que o valor está incompleto.
Faturas criadas com environment=test são simuladas: passam pelos mesmos status e enviam os mesmos webhooks (data.environment = "test"), mas nunca alteram o saldo real.
Entrega e novas tentativas
Sucesso é qualquer resposta 2xx. Qualquer outro código, um timeout ou um erro de rede conta como falha. O corpo da resposta não é interpretado.
Timeouts: 5 s para conectar, 15 s para a requisição inteira.
Redirecionamentos não são seguidos: 301/302 conta como falha. Configure a URL final.
Até 5 tentativas por evento: a primeira e depois novas tentativas cerca de 10 s, 1 min, 5 min e 15 min após cada falha. Depois da quinta falha, a entrega automática para.
Na mesma página, o bloco “Entregas do webhook” mostra evento, código HTTP ou erro, horário e número da tentativa. O botão “Reenviar” envia o evento de novo com o mesmo Webhook-Id.
A entrega é at-least-once (pelo menos uma vez): um evento pode chegar várias vezes, e os eventos podem chegar fora de ordem (um evento reenviado pode chegar depois de um mais recente).
Verificação da assinatura
Leia o corpo bruto da requisição como bytes, antes de fazer o parse do JSON. Um JSON serializado de novo não vai bater com a assinatura.
Calcule o HMAC-SHA256 de “{Webhook-Timestamp}.{raw body}” usando sua chave secreta whsec_… como chave e codifique em hex.
Compare “v1=” + hex com o header Webhook-Signature usando uma função de tempo constante: hash_equals, crypto.timingSafeEqual, hmac.compare_digest.
Rejeite um Webhook-Timestamp que difira do seu relógio em mais de 5 minutos (recomendado). As novas tentativas trazem um timestamp novo, então isso não as quebra.
PHP
<?php
$secret = getenv('SNAPEX_WEBHOOK_SECRET'); // whsec_… do painel
$body = file_get_contents('php://input'); // corpo bruto, antes do parse do JSON
$timestamp = $_SERVER['HTTP_WEBHOOK_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_WEBHOOK_SIGNATURE'] ?? '';
$expected = 'v1='.hash_hmac('sha256', $timestamp.'.'.$body, $secret);
if (! ctype_digit($timestamp)
|| abs(time() - (int) $timestamp) > 300
|| ! hash_equals($expected, $signature)) {
http_response_code(400);
exit;
}
$event = json_decode($body, true);
// ignore se este Webhook-Id já foi processado; faça o trabalho pesado em uma fila
http_response_code(200);
Node.js
const crypto = require('crypto');
const express = require('express');
const app = express();
const secret = process.env.SNAPEX_WEBHOOK_SECRET; // whsec_… do painel
// corpo bruto, antes do parse do JSON
app.post('/hooks/snapex', express.raw({ type: 'application/json' }), (req, res) => {
const timestamp = req.get('Webhook-Timestamp') || '';
const signature = Buffer.from(req.get('Webhook-Signature') || '');
const expected = Buffer.from('v1=' + crypto.createHmac('sha256', secret)
.update(timestamp + '.').update(req.body).digest('hex'));
const ok = /^\d+$/.test(timestamp)
&& Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300
&& signature.length === expected.length
&& crypto.timingSafeEqual(signature, expected);
if (!ok) return res.sendStatus(400);
const event = JSON.parse(req.body.toString('utf8'));
// ignore se este Webhook-Id já foi processado; faça o trabalho pesado em uma fila
res.sendStatus(200);
});
Python
import hashlib, hmac, os, time
from flask import Flask, abort, request
app = Flask(__name__)
SECRET = os.environ["SNAPEX_WEBHOOK_SECRET"].encode() # whsec_… do painel
@app.post("/hooks/snapex")
def snapex_webhook():
body = request.get_data() # corpo bruto, antes do parse do JSON
timestamp = request.headers.get("Webhook-Timestamp", "")
signature = request.headers.get("Webhook-Signature", "")
expected = "v1=" + hmac.new(SECRET, timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
if not (timestamp.isascii() and timestamp.isdigit()) \
or abs(time.time() - int(timestamp)) > 300 \
or not hmac.compare_digest(expected.encode(), signature.encode()):
abort(400)
event = request.get_json()
# ignore se este Webhook-Id já foi processado; faça o trabalho pesado em uma fila
return "", 200
Checklist do handler
Verifique a assinatura sobre o corpo bruto com uma comparação de tempo constante; responda 400 se ela não bater.
Rejeite requisições cujo Webhook-Timestamp tenha mais de 5 minutos.
Guarde os Webhook-Id já processados e ignore as repetições. Não dependa da ordem: compare o status do evento com o que você já tem.
Responda 2xx rápido, bem antes dos 15 segundos, e faça o trabalho pesado de forma assíncrona.
Depois de um webhook, você pode consultar o objeto de novo pela API para confirmar: GET /invoices/{id}, GET /payments/{id}, GET /payouts/{id}.
Status
O selo “final” indica que o status não vai mais mudar. A única exceção são os depósitos expirados: uma transferência atrasada ainda pode chegar.
Depósitos
Status
Significado
O que fazer
awaiting_deposit
Endereço gerado, aguardando a transferência
Mostre ao cliente o endereço e o valor
detected
Transferência vista na rede, ainda não creditada
Aguarde. Não feche o pedido
processing
Convertendo para USDT
Aguarde
confirmed
O valor esperado chegou, fundos creditados
Feche o pedido
final
confirmed_underpaid
Chegou menos que o esperado, dentro da margem permitida
Confira o credited_amount e decida se é suficiente
final
confirmed_overpaid
Chegou mais que o esperado, creditado conforme o credit-preview
Feche o pedido. Fale com o suporte sobre o excedente
final
confirmed_mismatch
Mantido por compatibilidade
Não é usado em pagamentos novos
final
manual_review
Revisão manual necessária
Aguarde a revisão; não crie um segundo pagamento
expired
O prazo de pagamento expirou, o endereço continua monitorado por mais ~6 h
Não exclua o pedido; continue consultando
failed
Falha do lado do provedor
Crie um novo pagamento
final
cancelled
Pagamento cancelado
Crie um novo pagamento
final
refunded
Reembolsado pelo provedor
Concilie o saldo; fale com o suporte se não bater
final
Faturas
Status
Significado
O que fazer
open
Fatura criada, forma de pagamento não escolhida
Passe ao cliente o pay_url ou escolha o asset_id você mesmo
awaiting
Endereço gerado, aguardando a transferência
Mostre o endereço e o valor; consulte o status
underpaid
Parte do valor chegou; mesmo endereço
Peça ao cliente que envie o restante para este endereço
paid
A primeira transferência completa foi creditada
Feche o pedido
final
partially_paid
O cliente pagou só uma parte, o prazo para completar o pagamento terminou e a parte recebida foi creditada para você
Não entregue como pedido pago; acerte o restante com o cliente
final
expired
O prazo da fatura terminou
Crie uma nova fatura
final
Saques
Status
Significado
O que fazer
reserved
Fundos reservados para o saque
Aguarde
submitting
Enviado ao provedor
Aguarde
processing
O provedor está enviando on-chain
Aguarde
completed
Fundos entregues ao destinatário
Pronto
final
manual_review
Resultado incerto
Não crie outro saque; aguarde a revisão
failed
A transferência falhou; a reserva normalmente é liberada
Confira o saldo; se precisar, tente de novo com uma nova Idempotency-Key
final
Erros
Uma resposta de sucesso sempre vem em data. Um erro sempre vem em error. Não existem outros envelopes.
formato do erro
{
"error": {
"code": "validation_error", // código legível por máquina, veja a tabela abaixo
"message": "The request is invalid.",
"details": { // nem sempre está presente
"destination_address": ["The destination address field is required."]
// a chave é o campo que não passou na validação
}
}
}
HTTP
code
Quando
O que fazer
401
unauthorized
Chave ausente ou inválida
Confira o header Authorization: Bearer smk_… por inteiro, sem espaços nem quebras de linha
401
key_inactive
Chave revogada
A chave anterior foi revogada. Use a chave atual do painel
401
key_expired
Chave expirada
Gere uma nova chave
404
not_found
Id não encontrado ou pertence a outro comerciante
Use o payment_id ou payout_id da sua própria resposta
409
conflict
A Idempotency-Key está vinculada a outra operação, ou o external_id já foi usado
Para uma nova operação, use uma nova chave. Para repetir, use a mesma chave e os mesmos parâmetros
422
validation_error
Campos inválidos, credit-preview expirado, saldo insuficiente ou Idempotency-Key ausente
Veja em details o campo e o motivo
429
rate_limited
Limite de requisições excedido
Tente de novo mais tarde com a mesma Idempotency-Key
500
internal_error
Erro interno do servidor
Tente de novo mais tarde com a mesma Idempotency-Key. Se o erro continuar, fale com o suporte e informe o X-Request-Id