Documentação
O pncp.dev repassa as rotas públicas do PNCP. Se você já sabe chamar o pncp.gov.br, já sabe usar isto: troque o endereço e mande a sua chave num header.
Começar
Crie a sua chave no painel. Leva um minuto e não pede cartão. Depois é só chamar:
curl "https://api.pncp.dev/api/consulta/v1/contratacoes/publicacao?dataInicial=20260907&dataFinal=20260913&codigoModalidadeContratacao=6&pagina=1&tamanhoPagina=10" \
-H "x-api-key: $PNCP_API_KEY"A resposta é o JSON do PNCP, sem nenhuma alteração.
Sua chave
Toda chamada precisa da sua chave. O melhor jeito de mandar é no header x-api-key:
x-api-key: pncp_a1b2c3d4e5f6...Para um teste rápido, a chave também pode ir na URL, no parâmetro api_key. Serve para uma aba do navegador ou para uma ferramenta que não deixa mexer em header:
curl "https://api.pncp.dev/api/consulta/v1/orgaos?pagina=1&api_key=$PNCP_API_KEY"A gente tira esse parâmetro da URL antes de tudo: ele nunca chega no PNCP e não entra no cache. Ainda assim, no seu código prefira o header. URL fica salva no histórico do navegador e costuma aparecer em log de erro.
A chave inteira aparece uma vez só, na hora que você cria. Depois o painel mostra só o começo dela. Perdeu? Crie outra e revogue a antiga. Você pode ter várias ao mesmo tempo, uma para cada ambiente.
Rotas
Qualquer rota que comece com /api/ no PNCP funciona aqui, com os mesmos parâmetros. As mais usadas:
- O que devolve
- licitações publicadas num período
- O que devolve
- licitações com proposta ainda aberta
- O que devolve
- contratos assinados
- O que devolve
- atas de registro de preço
- O que devolve
- detalhe de uma compra
Os parâmetros são os mesmos do PNCP: data em AAAAMMDD, tamanhoPagina de 10 para cima. Para saber o que cada campo significa, vale a documentação oficial do PNCP.
Cota e limites
Cada chamada desconta uma requisição da sua cota do mês. A cota zera todo dia 1º, no horário de Brasília. O plano grátis dá 100.000 requisições por mês.
Quando a cota acaba, seus créditos entram no lugar sozinhos e nada para. Sem cota e sem crédito, a resposta é 429, com a data em que a cota volta.
Também existe um limite por minuto, contado por chave, para não sobrecarregar o PNCP. Ele só conta as chamadas que chegam lá: resposta que veio do cache não gasta esse limite.
Chamada recusada também desconta. Passou do limite por minuto, acabou a cota, o PNCP falhou: cada tentativa conta uma requisição. É isso que segura um loop que saiu do controle antes de ele pesar no PNCP.
Cache
A gente guarda cada resposta por 5 minutos. Nesse tempo, quem pedir a mesma coisa recebe na hora, sem ir até o PNCP. Ainda assim desconta da sua cota: a chamada foi sua.
O que vem na resposta
Toda resposta que deu certo traz o saldo da sua cota nos headers, para você acompanhar sem abrir o painel:
x-quota-limit: 100000
x-quota-remaining: 99994
x-quota-reset: 1790823600
x-pncp-dev: hitO x-pncp-dev diz o que aconteceu com a sua chamada:
hitbuscamos no PNCP agoracacheveio da cópia que a gente guardouauthfaltou a chave, ou ela não vale maisquotaacabou a cota do mês ou o limite por minutodeniedessa rota não é públicamethodsó GET passa por aquiwaf-blockedo PNCP recusou, mesmo depois de tentarmos de novoupstream-erroro PNCP não respondeu, ou a falha foi nossa
Erros
Os erros que são nossos vêm em JSON. O code nunca muda, então dá para o seu programa decidir o que fazer; a mensagem em português é para você ler no log:
{
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Cota mensal esgotada. Compre um pacote ou aguarde o próximo mês.",
"resetAt": 1790823600
}
}Erro que vem do próprio PNCP (uma data errada, por exemplo) chega até você do jeito que ele mandou, com o status original. A gente não mexe na resposta do PNCP.
O que não dá para fazer
- Só GET. Aqui só se consulta dado público. POST, PUT e DELETE recebem
405. - Só rotas
/api/. O resto do site do PNCP não passa por aqui. - Nada de área logada do gov.br. A gente nunca repassa o header
Authorization. Por isso a API de envio de dados do PNCP não funciona aqui, e isso é de propósito.