Erros
Formato
Fora do endpoint de token, todo erro tem esta forma:
{
"error": {
"type": "invalid_request_error",
"code": "invalid_json",
"message": "Requisicao invalida.",
"doc_url": "https://doc-crpay.deskhotel.com.br/errors/invalid_json",
"request_id": "req_01KYFJH8NS4KY0ZTBPVEG1QZTG"
}
}
Programe contra o code, nunca contra a message. O código é estável e faz
parte do contrato; a mensagem é texto para humanos e pode ser reescrita a
qualquer momento.
POST /oauth/token é a exceção: ele segue o formato da RFC 6749
({"error": "...", "error_description": "..."}), porque é o que qualquer
biblioteca OAuth2 pronta espera encontrar.
request_id
Toda resposta — com erro ou sem — traz um request_id, no corpo do erro e no
header Crpay-Request-Id.
Registre-o no seu log. Ao abrir um chamado, ele é o que permite encontrar exatamente a requisição em questão, em segundos, sem precisar de print de tela nem de "aconteceu por volta das três da tarde".
Tipos
type |
Significado | O que fazer |
|---|---|---|
invalid_request_error |
A requisição está errada | Corrija e reenvie. Repetir igual não adianta. |
authentication_error |
Token ausente, inválido, expirado ou sem escopo | Obtenha um token novo; se persistir, revise os escopos. |
rate_limit_error |
Excedeu o limite | Aguarde o Retry-After e tente de novo. |
api_error |
Falha do nosso lado | Retente com espera crescente. Se persistir, abra chamado com o request_id. |
Códigos
Autenticação
code |
HTTP | Causa |
|---|---|---|
unauthorized |
401 | Header Authorization ausente, malformado, ou token inválido/expirado |
insufficient_scope |
403 | O token não tem o escopo exigido pelo endpoint. A mensagem diz qual falta. |
Token inválido e token expirado devolvem a mesma resposta, de propósito — distinguir daria informação a quem está tentando forjar um.
Requisição
code |
HTTP | Causa |
|---|---|---|
invalid_json |
400 | Corpo não é JSON válido |
payload_too_large |
413 | Corpo acima do limite |
bad_request |
400 | Requisição inválida por outro motivo |
not_found |
404 | Rota inexistente |
Idempotência
code |
HTTP | Causa |
|---|---|---|
idempotency_key_required |
400 | Falta o header Idempotency-Key numa operação que movimenta dinheiro |
idempotency_key_reuse |
409 | A mesma chave já foi usada com uma requisição diferente |
idempotency_in_progress |
409 | Outra requisição com essa chave está sendo processada agora |
Ver Idempotência.
Limite
code |
HTTP | Causa |
|---|---|---|
rate_limited |
429 | Limite excedido. O header Retry-After diz quantos segundos aguardar. |
Servidor
code |
HTTP | Causa |
|---|---|---|
internal_error |
500 | Falha inesperada nossa |
Como tratar
async function chamarCrpay(caminho, opcoes) {
const res = await fetch(`https://api-crpay.deskhotel.com.br${caminho}`, opcoes);
if (res.ok) return res.json();
const { error } = await res.json();
// registre SEMPRE o request_id — sem ele, o suporte trabalha no escuro
console.error('crpay falhou', { code: error.code, request_id: error.request_id });
switch (error.type) {
case 'authentication_error':
// token vencido ou escopo insuficiente: renove e tente UMA vez
throw new ErroAutenticacao(error);
case 'rate_limit_error': {
const esperar = Number(res.headers.get('Retry-After') || 60);
await new Promise((r) => setTimeout(r, esperar * 1000));
return chamarCrpay(caminho, opcoes);
}
case 'api_error':
// falha nossa: retente com espera crescente, mantendo a MESMA
// Idempotency-Key, para nao cobrar duas vezes
throw new ErroTemporario(error);
default:
// invalid_request_error: repetir a mesma requisicao nao vai funcionar
throw new ErroPermanente(error);
}
}
Quando retentar
| Situação | Retentar? |
|---|---|
| 429 | Sim, após o Retry-After |
| 500 | Sim, com espera crescente, mesma Idempotency-Key |
| Timeout de rede | Sim, mesma Idempotency-Key |
400, 404, 409 key_reuse |
Não — corrija a requisição primeiro |
| 401, 403 | Só depois de obter um token novo ou ajustar os escopos |
O ponto que mais causa prejuízo em integração de pagamento: em timeout você
não sabe se a operação aconteceu. Retentar sem a mesma Idempotency-Key é
como cobrar de novo. Com ela, o crpay reconhece a repetição e devolve o
resultado da primeira tentativa.