Erros
Toda falha da API responde com o mesmo envelope, em qualquer rota e em qualquer status:
{
"error": {
"type": "invalid_request_error",
"code": "amount_too_small",
"message": "amount must be >= 100",
"param": "amount",
"request_id": "req_01J...",
"details": { "min": 100 }
}
}
type, code, message e request_id vêm sempre. param aparece quando a falha é de um valor
específico do corpo ou da query. details é o único lugar onde cabe dado extra do erro, por exemplo
o saldo que faltou ou o limite que estourou; nada de campo solto fora dele.
Programe contra code, nunca contra message. A mensagem é em inglês, curta, e pode mudar sem
aviso; o código é contrato.
Os oito tipos
type é a família e resolve o tratamento genérico: invalid_request_error,
authentication_error, permission_error, not_found_error, idempotency_error,
rate_limit_error, acquirer_error e internal_error.
A lista completa de code por operação está na referência da API, dentro de cada
resposta de erro. Ela não é repetida aqui de propósito: uma cópia à mão apodrece.
O que fazer com cada classe
Isso é o que a referência não diz. É a leitura operacional dos códigos:
| Classe | Códigos típicos | O que fazer |
|---|---|---|
| Corrigir e repetir | validation_failed, invalid_document, invalid_document_for_country, amount_too_small, amount_too_large, invalid_expires_in, invalid_url, unsupported_payment_method, unsupported_network, unsupported_coin, unsupported_currency, missing_idempotency_key |
Conserte o corpo e repita com a mesma Idempotency-Key. Nada foi criado. |
| Repetir depois | rate_limited, acquirer_timeout, acquirer_rejected, acquirer_unavailable |
Em rate_limited, respeite o Retry-After. Em acquirer_timeout, espere 60 s e repita com a mesma chave (a cobrança pode existir no processador); só troque de chave se o 503 voltar com Idempotent-Replayed: true. Nos outros 503 do processador, tente de novo com chave nova: a resposta de erro ficou gravada na chave antiga. |
| Nunca repetir igual | idempotency_conflict, refund_unsupported_for_payment_method, invalid_state, insufficient_balance, daily_limit_exceeded, pix_key_not_verified |
É decisão de negócio, não falha passageira. Repetir o mesmo pedido dá o mesmo erro. |
| Conferir a chave | invalid_api_key, revoked_api_key, seller_not_allowed, kyc_required, payout_locked, insufficient_scope |
A chave ou a conta não podem fazer isso agora. Ver Autenticação. |
| Split | too_many_splits, split_recipient_is_payer, duplicate_split_recipient, split_recipient_not_authorized, split_recipient_not_eligible, split_amount_too_small, split_exceeds_net, split_percent_exceeded, split_quota_exceeded, split_rejected_by_partner, split_authorization_self, split_authorization_exists, split_base_unsupported_for_payment_method, split_rejected_for_voucher |
Até split_quota_exceeded, nada foi criado: corrija e repita com a mesma chave. split_rejected_by_partner deixa a cobrança failed: chave nova e um chamado. O que fazer em cada um está em Split. |
| Cripto | crypto_wallet_missing, crypto_wallet_not_usable, crypto_fee_below_cost, crypto_charges_paused, crypto_unavailable |
Cadastre a carteira ou espere a carência (details.usable_from). Os dois 503 são passageiros: repita depois. Depósito em moeda ou rede diferente da cobrança (USDT numa cobrança USDC, por exemplo) não paga e não vira erro de API: devolver é combinado à mão com o comprador. O contrato está em Cobrança em cripto. |
| Internacional | payment_method_unavailable, card_charge_in_progress, installments_not_supported, splits_unsupported_for_payment_method, fx_rate_unavailable |
installments_not_supported: corrija e repita com a mesma chave, nada foi criado. payment_method_unavailable (veja details.reason) e fx_rate_unavailable são passageiros: não ofereça o método agora e tente depois. card_charge_in_progress: espere. Cartão recusado não é erro de API: volta 201 com status: "failed". Resposta 202 não é erro: a cobrança pode existir, nunca recrie com outra chave. O contrato está em Cartão internacional. |
| Não existe | resource_not_found |
Id errado, de outra conta ou do outro ambiente. Os três respondem igual, de propósito. |
| Falar com a gente | internal_error |
Anote o request_id e abra um chamado. |
idempotency_in_progress é o único 409 que pede retentativa: a sua própria requisição anterior
ainda está rodando. Espere e repita igual.
O request_id
Toda resposta, com erro ou sem, traz o header X-Request-Id, e o mesmo valor aparece em
error.request_id. Ele é o que localiza a requisição exata nos nossos logs.
Registre esse valor junto de todo erro 5xx que você logar. Um chamado com request_id se resolve
em minutos; um chamado com "deu erro ontem à tarde" não se resolve.
Próximo passo
Paginação para as listagens, ou Limites para o que dispara rate_limited
e os tetos de valor e de tamanho.
Referência: Cria uma cobrança (PIX, voucher, cripto, cartão ou carteira) é a operação com mais códigos de erro possíveis, e cada
um deles está descrito na resposta correspondente.