Erros
Erros vêm em JSON com status HTTP. Quando há um código estável, ele está em codigo: trate pelo código, nunca pelo texto da mensagem.
Status
| Status | Quando | O que fazer |
|---|---|---|
401 |
Chave ausente, inválida ou revogada. | Confira o header X-Api-Key e se a chave está ativa. |
404 |
CNPJ não encontrado, rota inexistente ou método diferente de GET. |
Confira CNPJ e rota. Um CNPJ fora da base não quer dizer que a empresa não existe. |
409 |
Busca ampla que pede confirmação, ou cursor de uma publicação anterior. | Veja o codigo. |
422 |
Parâmetro inválido ou recorte fora da cobertura publicada. | Corrija o parâmetro indicado. |
429 |
Cota diária esgotada. | Pare até a virada do dia; não repita em laço. |
503 |
Base em carga, conjunto sem publicação completa ou muitas consultas pesadas ao mesmo tempo. | Veja o codigo. Com Retry-After, espere esses segundos; nos demais, consulte /v1/meta e tente de novo com intervalo crescente. |
504 |
Busca confirmada interrompida após 60 segundos. | Refine os filtros. |
Rotas inexistentes e métodos diferentes de GET respondem 404 em texto puro. Sem chave, uma rota inexistente responde 401: a chave é verificada antes da rota.
Formatos do corpo
Um cliente robusto trata os três:
{"detail": "limit deve estar entre 1 e 100"}{
"detail": {
"codigo": "recorte_nao_coberto",
"mensagem": "UF ou modalidade fora da janela PNCP publicada."
}
}{
"erro": true,
"codigo": "base_indisponivel",
"mensagem": "Base em carga inicial ou indisponível. Tente novamente em alguns minutos."
}def codigo_do_erro(corpo: dict) -> str | None:
detail = corpo.get("detail")
if isinstance(detail, dict):
return detail.get("codigo")
return corpo.get("codigo")function codigoDoErro(corpo) {
const detail = corpo?.detail;
if (detail && typeof detail === "object") return detail.codigo ?? null;
return corpo?.codigo ?? null;
}Códigos
| Código | Status | Significado e ação |
|---|---|---|
busca_ampla_requer_confirmacao |
409 | A busca varreria boa parte da base. Traz custo_estimado e linhas_estimadas. Refine ou repita com confirmar_varredura=true. |
busca_demorada |
409, 504 | Passou do tempo limite (12 s, ou 60 s se confirmada). Com pode_tentar_com_aprovacao: true, repita com confirmar_varredura=true; senão, refine. |
municipio_uf_incompativel |
422 | O município não existe na UF. Traz ufs_validas ou sugestoes de grafia. |
recorte_nao_coberto |
422 | UF ou modalidade fora da janela PNCP publicada. Veja meta.ufs e meta.modalidades. |
geracao_oportunidades_expirada |
409 | Nova publicação de oportunidades durante a paginação. Recomece sem cursor. |
geracao_despesas_expirada |
409 | Nova publicação de despesas durante a paginação. Recomece sem cursor. |
oportunidades_indisponiveis |
503 | Não há janela PNCP completa publicada. |
despesas_indisponiveis |
503 | Não há janela de despesas completa publicada. |
api_sobrecarregada |
503 | Há muitas consultas do mesmo tipo em andamento (buscas textuais, totais, páginas profundas, despesas). Vem com Retry-After: espere e repita; diminua o paralelismo do cliente. |
consulta_demorada |
503 | A consulta passou do tempo limite e foi interrompida para proteger a base. Refine os filtros ou tente de novo. |
base_indisponivel |
503 | Base em carga ou indisponível. Tente de novo em alguns minutos. |
base_carregando |
503 | /v1/meta: o catálogo ainda está carregando. |