Formato padrão
Toda resposta de erro segue o schema APIErrorResponse — dois campos, sempre presentes:error— código estável, feito para tratamento programático. Ramifique a sua lógica por ele, nunca pelo texto.message— descrição legível, sujeita a mudança sem aviso.
5xx a mensagem é sempre genérica (“An internal error occurred. Please try again later.”) — detalhes internos nunca vazam no corpo da resposta.
Códigos de erro
Status HTTP
CSRF (403)
Requisições de escrita (POST/PUT/PATCH/DELETE) autenticadas por cookie de sessão exigem o padrão double-submit cookie:
- O backend entrega um cookie
csrf_tokenlegível por JavaScript (deliberadamente não HttpOnly). - O cliente ecoa o valor do cookie no header
X-CSRF-Tokenem toda mutação. - Header ausente ou diferente do cookie →
403com{"error": "forbidden", "message": "CSRF token missing or invalid"}.
GET/HEAD/OPTIONS) nunca passam pela verificação.
Chamadas com API Key são isentas de CSRF. Tráfego server-to-server não tem contexto de navegador nem cookies ambientes — a autenticação já é um header
Authorization explícito que um atacante precisaria possuir de qualquer forma. Se você integra apenas via Bearer sk-..., pode ignorar esta seção.403 de CSRF, você provavelmente está autenticando com cookie sem querer — use API Key para integrações server-to-server.
Headers X-RateLimit-*
Respostas de rotas medidas por cota (chamadas com API Key aos grupos /consents, /policies e /exports) trazem três headers, na convenção GitHub/Stripe:
Use-os para se auto-regular sem precisar consultar o estado do plano. Chamadas do dashboard (cookie) não consomem cota e não recebem esses headers. Quando a cota esgota, a API responde
429 com quota_exceeded.
Os rate limits por janela de tempo (too_many_requests) são independentes da cota mensal: endpoints sensíveis (login, recuperação de senha, contato) têm limites por IP e por e-mail, e o ingest público do banner aceita 30 req/min por cliente e 600 req/min por site. Esses limites não emitem headers X-RateLimit-* — apenas o 429.
Limites de corpo (413)
Cada rota limita o tamanho do corpo antes de qualquer processamento:
Corpo com
Content-Length acima do teto é rejeitado de imediato com 413 e código invalid_request. Corpos sem Content-Length (chunked) que estourem o teto durante a leitura podem aparecer como 400 de bind — trate ambos como “reduza o payload”.
Esses tetos protegem o processo, não o negócio: limites por item (tamanho de campos, linhas do batch) são validados no DTO e retornam 400 com mensagem específica.
Dúvidas? suporte@consentfly.com.br
