Documentação
Boas práticas e confiabilidade
Integrar pagamentos é, acima de tudo, tratar o incerto com cuidado. A maioria dos problemas em produção (pagamento duplicado, cliente marcado como "falha" sem ter falhado, estorno indevido) vem de interpretar um timeout como erro. Esta página reúne as regras que evitam isso.
1. Todo valor é inteiro em centavos [#valores]
Nunca use ponto flutuante. R$ 19,90 é 1990; R$ 1.000,00 é 100000. Float introduz arredondamento que, em dinheiro, vira divergência de conciliação.
2. Idempotência é a regra de ouro dos saques [#idempotencia]
- Sempre envie um
externalIdúnico por solicitação de saque (ex.: um UUID ou o id do saque no seu sistema). - Reenviar a mesma solicitação com o mesmo
externalIddevolve o saque original (a resposta trazidempotentReplay: true) — não cria um segundo nem debita de novo. - Nunca reutilize um
externalIdpara solicitações diferentes.
Com
externalId, um retry depois de um timeout é seguro: no pior caso você recebe de volta o saque que já existia.
3. Timeout e erro NÃO são a mesma coisa [#classes-de-erro]
| Resposta | Significado | O que fazer |
|---|---|---|
2xx | Aceito. Saque nasce WITHDRAW_REQUEST (assíncrono); o resultado final vem por webhook. | Aguarde o webhook / consulte o status. |
4xx rápido (400/403/422) | Recusa definitiva (saldo insuficiente, validação, IP não autorizado). | Seguro tratar como recusa. Ajuste e reenvie se fizer sentido. |
429 | Rate limit. | Respeite o header retry-after + backoff exponencial com jitter. |
5xx / timeout / sem resposta | INCERTO — o recurso pode ter sido criado. | NÃO trate como falha. Reconcilie por externalId antes de qualquer ação. |
Saldo insuficiente retorna
400em menos de 1 segundo, antes de qualquer criação. Um500ou um timeout não é saldo insuficiente — é estado incerto.
4. Nunca estorne nem reprocesse às cegas [#reconciliacao]
Antes de estornar o cliente ou reenviar depois de um timeout/5xx, confirme o estado real:
- Saque:
GET /withdraws/{externalId}. - Cobrança:
GET /transactions/{transaction_id}.
E nunca faça retry automático em estado intermediário (WITHDRAW_REQUEST / WITHDRAW_PROCESSING): aguarde o webhook final. Retry sem confirmação é a causa nº 1 de empresas pagarem o mesmo destinatário duas vezes.
5. Webhooks: confirme, não confie [#webhooks]
- Responda
2xxem até 10 segundos e não redirecione (redirect conta como falha). - Seja idempotente: deduplique pelo id da entrega (você pode receber o mesmo evento 2–3x em retries).
- Confirme por reconsulta antes de liberar produto/serviço — o retorno no navegador do comprador não é fonte de verdade, só o status/API é.
- Valide a assinatura (HMAC) nos endpoints cadastrados no painel. O destino individual por
postbackUrlnão é assinado → para esses, confirme sempre porGET.
Detalhes em Webhooks e Verificação de assinatura.
6. Respeite os limites [#rate-limit]
Cada rota tem um limite por janela de 60s (veja cada endpoint). Em 429, use o retry-after. Prefira webhooks a polling intenso de status — é mais rápido pra você e não gasta seu limite.
7. Segurança das credenciais [#seguranca]
- A
secretKeysó no backend. Nunca em front-end, app, repositório, URL ou bundle do cliente. - Use allowlist de IP nas chaves (principalmente para saque).
- Para rotacionar: crie uma chave nova, migre as integrações e revogue a antiga.
8. Facilite a conciliação e o suporte [#suporte]
- Guarde
externalId,transaction_idewithdrawal_idno seu banco, ligados ao seu pedido. - Ao abrir um chamado, mande o ref/trace id do erro (veja Trace ID e debug) — localiza a chamada exata sem expor dados sensíveis.
- Em saques, use
restrictReceiverDocument: truesempre que souber para quem está pagando (protege contra reatribuição de chave PIX).
Checklist rápido [#checklist]
- Valores em centavos (inteiros), nunca float
-
externalIdúnico em todo saque - Timeout /
5xx→ reconcilia por externalId, nunca estorna às cegas -
4xxrápido = recusa definitiva;5xx/timeout = incerto -
429→retry-after+ backoff exponencial - Sem retry automático em
WITHDRAW_REQUEST/WITHDRAW_PROCESSING - Webhook idempotente + confirma por reconsulta antes de liberar
-
secretKeysó no servidor