search_contratos
Search public procurement contracts on PNCP to analyze market history, supplier behavior, and agency spending. Default last 30 days, max 365 days per query.
Instructions
Search public procurement contracts (contratos) on PNCP. Useful for analyzing market history, supplier behavior, and agency spending patterns. Defaults to last 30 days when no date range is provided. Maximum date range per query: 365 days (PNCP limit); wider windows return HTTP 422. For multi-year searches, issue multiple calls.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| dataInicial | No | Start date YYYYMMDD | |
| dataFinal | No | End date YYYYMMDD | |
| cnpjOrgao | No | Filter by procuring agency CNPJ | |
| cnpjFornecedor | No | Filter by supplier CNPJ | |
| esfera | No | Filter by government sphere: 'federal', 'estadual', 'municipal', or 'distrital'. Applied client-side. | |
| palavraChave | No | Keyword filter on objetoContrato (client-side). | |
| valorMinimo | No | ||
| valorMaximo | No | ||
| pagina | No | ||
| tamanhoPagina | No |
Implementation Reference
- src/adapters/pncp.ts:291-315 (helper)listContratos adapter function: calls the PNCP API GET /contratos endpoint with params (dataInicial, dataFinal, cnpjOrgao, cnpjFornecedor, pagina, tamanhoPagina), parses via ContratosPageSchema, and caches with TTL_5_MIN.
export async function listContratos(params: ListContratosParams): Promise<ContratosPage> { const tamanhoPagina = clampPageSize(params.tamanhoPagina); const pagina = Math.max(params.pagina ?? 1, 1); const query: Record<string, unknown> = { pagina, tamanhoPagina }; if (params.dataInicial) query.dataInicial = params.dataInicial; if (params.dataFinal) query.dataFinal = params.dataFinal; if (params.cnpjOrgao) query.cnpjOrgao = params.cnpjOrgao; if (params.cnpjFornecedor) query.cnpjFornecedor = params.cnpjFornecedor; const cacheKey = `list:contratos:${JSON.stringify(query)}`; const cached = cache.get<ContratosPage>(cacheKey); if (cached) return cached; try { const { data } = await withRetry(() => consultaClient.get('/contratos', { params: query })); const parsed = ContratosPageSchema.parse(data); cache.set(cacheKey, parsed, TTL_5_MIN); return parsed; } catch (err) { if (err instanceof AxiosError) { throw new PncpError(describeAxiosError(err), err); } throw err; } } - src/schemas/pncp.ts:160-204 (schema)ContratoSchema (Zod) and ContratosPageSchema defining the structure of a contrato and the paginated response from PNCP.
export const ContratoSchema = z .object({ numeroControlePNCP: z.string(), numeroControlePNCPCompra: z.string().nullable().optional(), anoContrato: z.number(), sequencialContrato: z.number(), numeroContratoEmpenho: z.string().nullable().optional(), orgaoEntidade: orgaoEntidadeSchema.nullable().optional(), unidadeOrgao: unidadeOrgaoSchema.nullable().optional(), fornecedor: fornecedorSchema.nullable().optional(), objetoContrato: z.string().nullable().optional(), informacaoComplementar: z.string().nullable().optional(), valorInicial: z.number().nullable().optional(), valorGlobal: z.number().nullable().optional(), valorParcela: z.number().nullable().optional(), valorAcumulado: z.number().nullable().optional(), numeroParcelas: z.number().nullable().optional(), numeroRetificacao: z.number().nullable().optional(), dataAssinatura: z.string().nullable().optional(), dataVigenciaInicio: z.string().nullable().optional(), dataVigenciaFim: z.string().nullable().optional(), dataPublicacaoPncp: z.string().nullable().optional(), tipoContratoId: z.number().nullable().optional(), tipoContratoNome: z.string().nullable().optional(), categoriaProcessoId: z.number().nullable().optional(), categoriaProcessoNome: z.string().nullable().optional(), receitaDespesaCodigo: z.string().nullable().optional(), receitaDespesaNome: z.string().nullable().optional(), }) .passthrough(); export type Contrato = z.infer<typeof ContratoSchema>; export const ContratosPageSchema = z .object({ data: z.array(ContratoSchema).default([]), totalRegistros: z.number().optional(), totalPaginas: z.number().optional(), numeroPagina: z.number().optional(), paginasRestantes: z.number().optional(), empty: z.boolean().optional(), }) .passthrough(); export type ContratosPage = z.infer<typeof ContratosPageSchema>;