Skip to main content

pypncp — Cliente Python assíncrono para a API de Consulta do PNCP

Project description

pypncp

CI PyPI Python Version License Coverage

Cliente Python assíncrono para a API de Consulta do PNCP — Portal Nacional de Contratações Públicas.


Como usar

Adicionar ao projeto

uv add pypncp          # com uv (recomendado)
pip install pypncp     # ou com pip

Ou direto no pyproject.toml:

[project]
dependencies = ["pypncp>=0.1"]

Criar o cliente

from pypncp import PNCPClient

async def buscar():
    async with PNCPClient() as client:
        ...  # client pronto

Exemplos por recurso

Contratos — datas aceitas como str "YYYYMMDD", str "YYYY-MM-DD" ou date:

from datetime import date

async with PNCPClient() as client:
    page = await client.contratos.list(
        data_inicial="20250101",       # ou date(2025, 1, 1)
        data_final="20250331",
    )
    for contrato in page.data:
        print(contrato.numero_contrato_empenho, contrato.valor_global)

    # Paginação automática
    async for c in client.contratos.list_all(
        data_inicial=date(2025, 1, 1),
        data_final=date(2025, 3, 31),
    ):
        print(c.objeto_contrato, c.orgao_nome)

Contratações (licitações)codigo_modalidade é obrigatório em list_publicacao e list_atualizacao, opcional em list_com_proposta:

from datetime import date

async with PNCPClient() as client:
    # Publicações — modalidade obrigatória (1 = Pregão)
    async for compra in client.contratacoes.list_all_publicacao(
        data_inicial=date(2025, 1, 1),
        data_final=date(2025, 3, 31),
        codigo_modalidade=1,
    ):
        print(compra.objeto_compra, compra.orgao_nome)

    # Propostas abertas — modalidade opcional, data_final >= hoje
    async for compra in client.contratacoes.list_all_com_proposta(
        data_final=date.today(),
    ):
        print(compra.objeto_compra, compra.data_abertura_proposta)

    # Atualizações — modalidade obrigatória
    async for compra in client.contratacoes.list_all_atualizacao(
        data_inicial=date(2025, 1, 1),
        data_final=date(2025, 3, 31),
        codigo_modalidade=5,
    ):
        ...

Atas de registro de preço:

from datetime import date

async with PNCPClient() as client:
    async for ata in client.atas.list_all(
        data_inicial=date(2025, 1, 1),
        data_final=date(2025, 12, 31),
    ):
        print(ata.objeto_contratacao, ata.orgao_nome)

Paginação

# Automática — list_all*() itera todas as páginas
async for contrato in client.contratos.list_all(
    data_inicial="20250101",
    data_final="20251231",
):
    ...

# Manual — list() devolve Page[T] com metadados
page = await client.contratos.list(
    data_inicial="20250101",
    data_final="20251231",
    pagina=1,
)
print(f"Página {page.numero_pagina} de {page.total_paginas}")
print(f"Itens nesta página: {len(page.data)}")
print(f"Há mais páginas: {page.has_more}")

# page pode ser usado como iterador assíncrono
async for item in page:
    print(item)

Tratamento de erros

from pypncp import PNCPError, NotFoundError, RateLimitError

try:
    page = await client.contratos.list(
        data_inicial="20250101",
        data_final="20251231",
    )
except NotFoundError:
    print("Recurso não encontrado (HTTP 404)")
except RateLimitError:
    print("Muitas requisições (HTTP 429)")
except PNCPError as e:
    print(f"Erro na API: {e}")

Exemplo completo com FastAPI

from datetime import date

from fastapi import FastAPI, HTTPException
from pypncp import PNCPClient, NotFoundError

app = FastAPI()


@app.get("/contratos")
async def listar_contratos(data_inicial: str, data_final: str, pagina: int = 1):
    async with PNCPClient() as client:
        page = await client.contratos.list(
            data_inicial=data_inicial,
            data_final=data_final,
            pagina=pagina,
        )
        return {
            "contratos": [c.model_dump() for c in page.data],
            "pagina": page.numero_pagina,
            "total_paginas": page.total_paginas,
            "total_registros": page.total_registros,
        }


@app.get("/contratos/{orgao_cnpj}/{ano}/{sequencial}")
async def get_contrato(orgao_cnpj: str, ano: int, sequencial: int):
    async with PNCPClient() as client:
        try:
            contrato = await client.contratos.get(
                orgao_cnpj=orgao_cnpj, ano=ano, sequencial=sequencial,
            )
            return contrato.model_dump()
        except NotFoundError:
            raise HTTPException(status_code=404, detail="Contrato não encontrado")

Modelos

Contrato

Campo Tipo Origem na API
numero_contrato_empenho str numeroContratoEmpenho
ano_contrato int anoContrato
sequencial_contrato int sequencialContrato
objeto_contrato str objetoContrato
processo str | None processo
orgao_cnpj str | None orgaoEntidade.cnpj
orgao_nome str | None orgaoEntidade.razaoSocial
orgao_uf str | None unidadeOrgao.ufSigla
fornecedor_nome str | None nomeRazaoSocialFornecedor
ni_fornecedor str | None niFornecedor
valor_inicial float | None valorInicial
valor_global float | None valorGlobal
data_assinatura date | None dataAssinatura
data_vigencia_inicio date | None dataVigenciaInicio
data_vigencia_fim date | None dataVigenciaFim
data_publicacao_pncp datetime | None dataPublicacaoPncp

Contratacao

Campo Tipo Origem na API
numero_compra str numeroCompra
ano_compra int anoCompra
sequencial_compra int sequencialCompra
objeto_compra str objetoCompra
orgao_cnpj str | None orgaoEntidade.cnpj
orgao_nome str | None orgaoEntidade.razaoSocial
orgao_uf str | None unidadeOrgao.ufSigla
modalidade_nome str | None modalidadeNome
data_publicacao_pncp datetime | None dataPublicacaoPncp
data_abertura_proposta datetime | None dataAberturaProposta
valor_total_estimado float | None valorTotalEstimado
valor_total_homologado float | None valorTotalHomologado
srp bool | None srp

Ata

Campo Tipo Origem na API
numero_ata_registro_preco str numeroAtaRegistroPreco
ano_ata int anoAta
objeto_contratacao str objetoContratacao
orgao_cnpj str | None cnpjOrgao
orgao_nome str | None nomeOrgao
vigencia_inicio datetime | None vigenciaInicio
vigencia_fim datetime | None vigenciaFim
data_publicacao_pncp datetime | None dataPublicacaoPncp
cancelado bool | None cancelado
possibilidade_adesao bool | None possibilidadeAdesao

Códigos de Modalidade

Código Modalidade
1 Pregão
2 Concorrência
3 Concurso
4 Leilão
5 Diálogo Competitivo
6 Consulta Pública
7 Credenciamento
8 Pré-qualificação
9 Manifestação de Interesse
10 Procedimento Auxiliar
99 Inexigibilidade
100 Dispensa

Referência da API

Recurso Endpoints
client.contratos GET /v1/contratos, GET /v1/contratos/atualizacao, GET /orgaos/{cnpj}/compras/{ano}/{sequencial}
client.contratacoes GET /v1/contratacoes/publicacao, GET /v1/contratacoes/proposta, GET /v1/contratacoes/atualizacao, GET /orgaos/{cnpj}/compras/{ano}/{sequencial}
client.atas GET /v1/atas, GET /v1/atas/atualizacao

Parâmetros obrigatórios por endpoint

Método Parâmetros obrigatórios
contratos.list() data_inicial, data_final
contratos.list_por_atualizacao() data_inicial, data_final
contratacoes.list_publicacao() data_inicial, data_final, codigo_modalidade
contratacoes.list_atualizacao() data_inicial, data_final, codigo_modalidade
contratacoes.list_com_proposta() data_final
atas.list() data_inicial, data_final

Documentação oficial: Swagger da API de Consulta


Para contribuir

Requisitos

  • Python 3.12+
  • uv
uv sync

Rodar verificações

git clone https://github.com/gabrielgz0/pypncp
cd pypncp
uv sync
uv run pytest -v
uv run ruff check src/ tests/
uv run mypy src/

Licença

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pypncp-0.1.2.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pypncp-0.1.2-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file pypncp-0.1.2.tar.gz.

File metadata

  • Download URL: pypncp-0.1.2.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypncp-0.1.2.tar.gz
Algorithm Hash digest
SHA256 46b3a0b41b87eb3c795d734e652108ebc50d4a44d67e4a46ebf44fbfdb473ef4
MD5 02da68dbfafa8c4f96b6e24775607bb2
BLAKE2b-256 443a7a9fcad6aa01b1bca3aa7c85abb77748dc72396bdde491a26053bdd5666c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypncp-0.1.2.tar.gz:

Publisher: ci.yml on gabrielgz0/pypncp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypncp-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: pypncp-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypncp-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 73324e58db912caf6e07feb71c07d4acda39faf0bc308c8f0bd19e76762961c6
MD5 668334e4daa131c2a62ea2853697c148
BLAKE2b-256 fbb1d37912403a3cd34837c410aa3236909f938698944a6d3d7f8716475e75c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypncp-0.1.2-py3-none-any.whl:

Publisher: ci.yml on gabrielgz0/pypncp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page