Estrutura de erros
Quando uma requisição falha, a API retorna um JSON com success: false e um objeto error:
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Saldo insuficiente para realizar a operação"
}
}Em erros de validação (422), o campo fields detalha quais campos falharam:
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Dados inválidos",
"fields": [
{ "field": "amount", "message": "Deve ser maior que 0" },
{ "field": "pixKeyType", "message": "Valor inválido" }
]
}
}Códigos HTTP
| Status | Significado |
|---|---|
| 200 | Sucesso |
| 201 | Recurso criado com sucesso |
| 400 | Requisição inválida |
| 401 | Não autenticado |
| 402 | Saldo insuficiente |
| 403 | Sem permissão |
| 404 | Recurso não encontrado |
| 409 | Conflito de estado |
| 422 | Erro de validação |
| 429 | Rate limit excedido |
| 500 | Erro interno |
| 503 | Serviço indisponível |
Códigos de erro
Autenticação
| Código | Status HTTP | Descrição |
|---|---|---|
| UNAUTHORIZED | 401 | API Key ausente, inválida ou revogada |
| FORBIDDEN | 403 | Sem permissão para esta operação |
| API_KEY_EXPIRED | 401 | API Key expirada (não se aplica — chaves não expiram atualmente) |
Validação
| Código | Status HTTP | Descrição |
|---|---|---|
| VALIDATION_ERROR | 422 | Um ou mais campos não passaram na validação |
| INVALID_PIX_KEY | 400 | Formato de chave PIX inválido para o tipo especificado |
| INVALID_AMOUNT | 400 | Valor deve ser positivo e no máximo 2 casas decimais |
| INVALID_QR_CODE | 400 | Código EMV malformado ou não reconhecido |
Saldo e pagamentos
| Código | Status HTTP | Descrição |
|---|---|---|
| INSUFFICIENT_BALANCE | 402 | Saldo insuficiente para cobrir o valor + taxa |
| PAYMENT_FAILED | 400 | Falha no processamento bancário |
| PIX_KEY_NOT_FOUND | 400 | Chave PIX não encontrada no sistema bancário |
| DUPLICATE_EXTERNAL_REF | 409 | externalRef já usado em outra transação |
Estornos
| Código | Status HTTP | Descrição |
|---|---|---|
| REFUND_DEADLINE_EXPIRED | 400 | Prazo de 90 dias para estorno expirado |
| REFUND_AMOUNT_EXCEEDS_ORIGINAL | 400 | Valor do estorno maior que o original |
| ALREADY_REFUNDED | 409 | Transação já foi estornada integralmente |
| REFUND_NOT_ALLOWED | 400 | Tipo de transação não suporta estorno |
Webhooks
| Código | Status HTTP | Descrição |
|---|---|---|
| WEBHOOK_LIMIT_REACHED | 409 | Limite de 10 webhooks por conta atingido |
| INVALID_WEBHOOK_URL | 400 | URL deve ser HTTPS |
| UNKNOWN_EVENT | 400 | Evento não reconhecido |
Geral
| Código | Status HTTP | Descrição |
|---|---|---|
| NOT_FOUND | 404 | Recurso não encontrado |
| RATE_LIMIT_EXCEEDED | 429 | Limite de requisições atingido |
| INTERNAL_ERROR | 500 | Erro interno — tente novamente em alguns instantes |
| SERVICE_UNAVAILABLE | 503 | Serviço temporariamente indisponível |
Boas práticas de tratamento de erros
Implementar retry com backoff
Para erros 5xx e 503, implemente retry com backoff exponencial:
fn: () => Promise<T>,
maxRetries = 3
): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn()
} catch (err: any) {
const status = err.response?.status
const shouldRetry = [500, 502, 503, 504].includes(status)
if (!shouldRetry || attempt === maxRetries) throw err
const delay = Math.min(1000 * 2 ** attempt, 30000)
await new Promise(r => setTimeout(r, delay))
}
}
throw new Error('Max retries reached')
}Não retentar erros 4xx
Erros 4xx indicam problema na requisição (dados inválidos, saldo insuficiente, etc.). Retentar sem corrigir o problema não vai resolver.
// Trate o erro na lógica da aplicação
throw new ApplicationError(error.response.data.error.code)
}