A API Dinie usa o formato RFC 9457 Problem Details para todas as respostas de erro. Todo erro tem uma estrutura consistente, uma URI de tipo legível por máquina e uma descrição legível por humanos.
Todos os erros são retornados com content type application/problem+json:
{
"type": "https://api.dinie.com.br/errors/invalid-request",
"title": "Invalid Request",
"status": 400,
"detail": "The 'cpf' field is required.",
"instance": "/v3/customers"
}| Campo | Tipo | Descrição |
|---|---|---|
type | string (URI) | URI que identifica o tipo de erro. Resolve para a documentação. |
title | string | Resumo curto do tipo de problema. Consistente em todas as ocorrências. |
status | integer | Código de status HTTP desta ocorrência. |
detail | string | Explicação legível específica desta ocorrência. |
instance | string (URI) | URI que identifica esta ocorrência específica (geralmente o path da requisição). |
| Campo | Tipo | Descrição |
|---|---|---|
code | string | Sub-tipo legível por máquina (ex.: missing_required_field, invalid_cpf) |
param | string | O parâmetro da requisição que causou o erro |
errors | array | Lista de erros individuais por campo (para falhas de validação) |
Tip: Use o campo
codepara tratamento programático de erros. Otypeidentifica a categoria ampla, enquanto ocodeaponta o problema específico.
Quando uma requisição tem sintaxe correta mas valores de campo inválidos, a resposta inclui um array errors com detalhes de cada campo inválido:
{
"type": "https://api.dinie.com.br/errors/validation-failed",
"title": "Validation Failed",
"status": 422,
"detail": "One or more fields failed validation.",
"errors": [
{
"param": "email",
"detail": "Must be a valid email address.",
"code": "invalid_format"
},
{
"param": "cpf",
"detail": "CPF is already registered.",
"code": "already_exists"
}
]
}Cada item no array errors contém:
| Campo | Descrição |
|---|---|
param | O nome do campo que falhou na validação |
detail | Explicação legível da falha de validação |
code | Código de erro de validação legível por máquina |
| Status | Tipo | Título | Quando |
|---|---|---|---|
| 400 | invalid-request | Invalid Request | Sintaxe malformada, content type ausente ou parâmetros inválidos |
| 401 | authentication-failed | Authentication Failed | Credenciais ou token ausentes ou inválidos |
| 403 | forbidden | Forbidden | Token válido mas permissões insuficientes |
| 404 | not-found | Not Found | Recurso não existe ou não está acessível para este parceiro |
| 409 | conflict | Conflict | Recurso já existe ou ação conflita com o estado atual |
| 422 | validation-failed | Validation Failed | Requisição parseada com sucesso mas valores dos campos são inválidos |
| 429 | rate-limit-exceeded | Rate Limit Exceeded | Muitas requisições. Verifique o header Retry-After. |
| 500 | internal | Internal Error | Erro inesperado no servidor |
Todas as URIs de tipo são prefixadas com https://api.dinie.com.br. Clique no tipo para ver causas comuns, exemplos e resolução.
Os SDKs lançam exceções tipadas para cada categoria de erro:
import Dinie, {
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
} from "dinie";
try {
const customer = await dinie.customers.create({
cpf: "invalid",
name: "Joao Silva",
email: "joao@example.com",
});
} catch (error) {
if (error instanceof ValidationError) {
console.error("Falha na validação:", error.message);
for (const fieldError of error.errors) {
console.error(` ${fieldError.param}: ${fieldError.detail}`);
}
} else if (error instanceof AuthenticationError) {
console.error("Falha na autenticação -- verifique as credenciais");
} else if (error instanceof RateLimitError) {
console.error(`Rate limit atingido. Tente novamente em ${error.retryAfter}s`);
} else if (error instanceof NotFoundError) {
console.error("Recurso não encontrado");
}
}Todas as respostas incluem headers de rate limit:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1709478060Quando limitado por rate (429), o header Retry-After indica quantos segundos esperar:
Retry-After: 30Nem todos os erros devem ser reenviados. Use esta tabela para decidir:
| Status | Reenviar? | Estratégia |
|---|---|---|
| 400 | Não | Corrija a requisição. O payload está malformado. |
| 401 | Uma vez | Renove o access token e reenvie. |
| 403 | Não | Verifique as permissões com seu gerente de conta. |
| 404 | Não | O recurso não existe. |
| 409 | Não | Resolva o conflito (ex.: recurso duplicado). |
| 422 | Não | Corrija os valores dos campos inválidos. |
| 429 | Sim | Aguarde o tempo indicado em Retry-After e reenvie. |
| 500 | Sim | Reenvie com exponential backoff. |
Para erros que podem ser reenviados (429, 500), use exponential backoff com jitter:
const MAX_RETRIES = 3;
async function requestWithRetry(fn: () => Promise<any>) {
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
try {
return await fn();
} catch (error) {
if (!isRetryable(error) || attempt === MAX_RETRIES) throw error;
const baseDelay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
const jitter = Math.random() * 500;
await sleep(baseDelay + jitter);
}
}
}Info: Os SDKs implementam retries automáticos com exponential backoff para respostas
429e500. Você pode configurar o número máximo de retries ao inicializar o client.