Tratamento de Erros
Como a API NFe/CTe Inbound sinaliza erros e como seu cliente deve reagir.
Sumário
Formato do Erro
Quando ocorre um erro, a API retorna um JSON no seguinte formato:
{
"errors": [
{
"code": 404,
"message": "Document not found for the given access key."
}
]
}
Códigos HTTP
| HTTP | Significa | O que fazer |
|---|---|---|
200 | Sucesso | Processe a resposta normalmente |
204 | Sucesso sem conteúdo | Operação realizada, sem corpo de resposta |
400 | Requisição inválida | Verifique os parâmetros enviados |
401 | Não autorizado | Verifique sua API Key ou token |
403 | Proibido | Sua conta não tem permissão para este recurso (API Key sem o papel exigido), ou a empresa não está com o inbound de NF-e ativo. Veja 403 com inbound de NF-e desativado |
404 | Não encontrado | O documento/empresa não existe |
409 | Conflito (duplicado) | Recurso já existe. Em POST .../manifestation-events (e no legado POST /manifest), significa que já existe um evento Pending ou Accepted para a mesma (accessKey, eventCode, nSequencia) — trate como idempotente |
422 | Entidade não processável | Dados válidos mas não processáveis. Ex.: GET .../inbound/{access_key}/pdf de um resumo de NF-e ou de um evento, que não têm DANFE (antes: 500). Não adianta repetir |
503 | Serviço indisponível | SEFAZ temporariamente fora. Tente novamente em alguns minutos |
504 | Timeout | A operação demorou muito. Tente novamente |
500 | Erro interno | Entre em contato com o suporte |
403 com inbound de NF-e desativado
Quando a empresa não está com o inbound de NF-e ativo (nunca habilitado ou desativado), as leituras de NF-e respondem 403 com o corpo de erro padrão. Antes, esses casos respondiam 500.
GET .../inbound/productinvoices/{access_key},/jsone/events/{event_key}GET .../inbound/{access_key},/events/{event_key}e/pdfDELETE .../inbound/productinvoicesrepetido numa empresa já desativada
Exceção: GET .../inbound/{access_key}/xml segue respondendo 400 nesse caso. A API Key é válida; o que falta é a habilitação do serviço. Reative com POST .../inbound/productinvoices (veja Ativar via API).
{
"errors": [
{
"code": 403,
"message": "Company: 5f4d4cee0a8b8e2c3a1bcd11 não habilitada para o NFe Distribuição"
}
]
}
Headers de Rate Limiting
Todas as respostas incluem headers indicando o status do rate limit:
| Header | Descrição |
|---|---|
X-RateLimit-Limit | Total de requisições permitidas por janela |
X-RateLimit-Remaining | Requisições restantes na janela atual |
X-RateLimit-Reset | Timestamp Unix quando a janela reinicia |
Quando o limite é excedido, a API retorna 429 Too Many Requests. Aguarde até X-RateLimit-Reset antes de tentar novamente.
Estratégia de Retry
Para erros 429, 503 e 504, recomendamos retry com backoff exponencial:
import time
import requests
def get_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
reset_time = int(response.headers.get('X-RateLimit-Reset', time.time() + 60))
wait_time = max(reset_time - time.time(), 1)
time.sleep(wait_time)
continue
if response.status_code in (503, 504):
wait_time = (2 ** attempt) * 1 # 1s, 2s, 4s
time.sleep(wait_time)
continue
return response
raise Exception("Max retries exceeded")