# PNCP Selected Documents Monitor (`amycole/pncp-selected-documents-monitor`) Actor

Compare selected official PNCP PDFs with page evidence and bounded recovery. $0.05 per completed observation, including unchanged; platform usage included. Externally serialized writers only.

- **URL**: https://apify.com/amycole/pncp-selected-documents-monitor.md
- **Developed by:** [amycole](https://apify.com/amycole) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$50.00 / 1,000 completed observations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## PNCP — Monitor de Documentos Selecionados

Acompanhe um pequeno conjunto de documentos oficiais de um processo PNCP já conhecido. Receba diferenças de texto PDF com páginas, trechos de evidência e IDs estáveis de eventos, sem substituir seu fluxo de pesquisa de licitações.

### O que faz

- Lista os anexos retornados pelo PNCP para um processo.
- Observa de 1 a 4 PDFs públicos selecionados, com texto extraível.
- Separa baseline inicial, mudanças de conteúdo/metadados, ausência de diferença e aquisição incompleta.
- Salva um checkpoint privado vinculado ao usuário de execução, Actor, processo e watch, no armazenamento dedicado escolhido por ID.
- Recupera o último resultado confirmado por `inspect` se a saída falhar depois do commit.

**É obrigatório um único gravador, serializado pelo chamador, por armazenamento.** Chamadas, agendas, execuções manuais e retries sobrepostos não são suportados. Verificações de revisão detectam conflitos observados; não são uma trava distribuída atômica.

### Primeiro uso

1. Execute `prepare` apenas com `operation` e `pncpId`.
2. Escolha IDs de documentos da lista oficial retornada.
3. Crie um key-value store novo, vazio e dedicado; autorize somente esse store e informe seu ID real em `stateStoreId`.
4. Execute `observe` com `watchKey`, `documentIds`, `expectedRevision: 0`, `retentionPolicy: "keep_last_2_commits"` e `writerPolicy: "externally_serialized"`.
5. Use a revisão confirmada nas observações seguintes. Em resultado incerto, consulte o run/inspect antes de iniciar outro.

Uma observação unchanged não grava checkpoint nem consome revisão. O baseline registra a primeira observação bem-sucedida, não comprova alterações anteriores.

### Retenção e recuperação

O consentimento de retenção autoriza substituir os slots gerenciados desse novo store e compactar histórico antigo de documentos/eventos. Três pares fixos de snapshot/recibo mantêm os checkpoints atual e anterior confirmados, mais preparação. Cada snapshot contém documentos atuais e evidência da última transição, não um histórico ilimitado.

`inspect` não consulta o PNCP. Retorna hashes e recibo confirmado. `recoverable_events` é replay, não novas notificações: deduplique por `event_id` e `receipt_id`. Exporte o que precisa conservar além da janela de dois checkpoints. Não há e-mail, garantia de entrega por webhook ou confirmação automática de consumo.

Não há migração, reset ou exclusão automática de stores 5A antigos. Checkpoint atual ausente/corrompido suspende a operação, sem apresentá-lo como estado antigo ou baseline novo. Saídas de runs e histórico da plataforma têm retenção e custos próprios da Apify.

### Escopo e limites

Somente PDFs de texto: até quatro selecionados, 8 MiB de downloads combinados e 500 páginas por PDF. Também há limites de lista e bytes de checkpoint/recibo. Aquisição incompleta preserva o estado confirmado anterior; não significa unchanged nem exclusão.

Sem OCR, busca nacional, decisão de aplicabilidade jurídica, interpretação integral de tabelas, correspondência automática entre revisões, garantia de todo o histórico do órgão ou aconselhamento licitatório. IDs diferentes exigem correspondência confirmada pelo usuário. Mudanças substantivas precisam de revisão humana.

### Preço e cobrança

US$ 0,05 por observação `observe` completa, incluindo baseline, mudança, ausência de diferença e mudança de configuração; cobre até quatro PDFs selecionados. `prepare`, `inspect` e aquisições incompletas não geram esse evento. Não há taxa de início nem por linha do Dataset. O preço do evento inclui o uso da plataforma durante o run (PPE + usage separado desativado). Armazenamento e acesso após o run podem ter custos normais do seu plano Apify. Zero eventos em prepare/inspect não garante que toda retenção ou acesso posterior seja gratuito. Configure um limite suficiente para um evento.

A cobrança só é solicitada depois da verificação de estado e da gravação de OUTPUT e Dataset. `BILLING`, no armazenamento padrão do run, registra a confirmação separadamente. Não há cobrança intencional por aquisição incompleta ou falha de negócio. Porém, uma falha da plataforma **depois de uma cobrança aceita**, ou timeout da resposta de cobrança, pode deixar o run FAILED com cobrança efetuada. `pending`/`unknown` exigem conferência manual: não repetimos a cobrança incerta. Estado e faturamento não formam uma transação atômica. Repetir a observação como um novo run é outra observação faturável; consulte `inspect` para recuperar resultados sem esse evento.

### API e saídas

Fixe número/tag de build e confirme o build ID retornado. Guarde o run ID; não repita o POST de início às cegas após timeout. Baixe OUTPUT JSON e Dataset completo em JSON/CSV. Leia `status` e `commit_status` de negócio, não apenas SUCCEEDED da plataforma.

Saída: `selected-private-5b-1`; estado: `selected-state-5b-1`; recibo: `selected-commit-receipt-5b-1`. Exemplos e limites operacionais seguem abaixo. Não é serviço oficial do PNCP nem endosso de órgão público.

***

## English — PNCP Selected Documents Monitor

Monitor a small, selected set of official PNCP documents for a procurement you already know. Receive PDF text differences with page references, quoted evidence and stable event IDs—without rebuilding your tender-search workflow.

### What it does

- Lists the attachments returned by PNCP for one procurement ID.
- Observes 1–4 selected public, text-based PDFs.
- Separates the initial baseline, content or metadata changes, unchanged observations and incomplete acquisition.
- Saves a private, runtime-user/Actor/procurement/watch-bound checkpoint in the dedicated store you explicitly select.
- Recovers the last committed result through `inspect` if output delivery fails after a state commit.

**One externally serialized writer per store is required.** Overlapping API calls, schedules, manual runs and retries are not supported. Revision checks detect observed conflicts; they are not an atomic distributed lock.

### First use

1. Run `prepare` with only `operation` and `pncpId`.
2. Choose document IDs from the returned official list.
3. Create a new, empty, dedicated key-value store and authorize that store only. Pass its actual ID to `stateStoreId`.
4. Run `observe` with `watchKey`, `documentIds`, `expectedRevision: 0`, `retentionPolicy: "keep_last_2_commits"` and `writerPolicy: "externally_serialized"`.
5. Use the confirmed revision for subsequent observations. If a run outcome is uncertain, inspect it before starting another.

Unchanged observations do not write a new checkpoint or consume a revision. A baseline records the first successful observation; it does not establish earlier changes.

### Retention and recovery

Retention consent permits overwriting this new store’s managed slots and compacting older document/event history. Three fixed snapshot/receipt pairs retain the current and previous committed checkpoints plus staging. Each snapshot retains current documents and its latest transition evidence—not an unlimited history.

`inspect` makes no PNCP request. It returns current document hashes and a verified committed receipt. Its `recoverable_events` are a replay, not new notifications: deduplicate by `event_id` and `receipt_id`. Export results you need to retain beyond the two-checkpoint window. There is no email, webhook delivery guarantee or automatic acknowledgment.

The Actor does not automatically migrate, reset or delete legacy 5A stores. A missing or corrupt current checkpoint suspends the operation; it is not silently replaced with an older state or a new baseline. Separate run outputs and platform history have their own Apify retention and costs.

### Scope and limits

Text PDFs only; up to four selected documents, 8 MiB combined downloads and 500 pages per PDF. Listing and checkpoint/receipt byte limits also apply. Incomplete acquisition preserves the prior committed state and does not mean “unchanged” or “deleted.”

No OCR, nationwide discovery, legal applicability decision, full table semantics, automatic revision correspondence, guaranteed full issuer history or procurement advice. Different document IDs require explicit user-confirmed correspondence. Every substantive difference still requires human review.

### Price and billing

US$0.05 per fully completed `observe`, including initial baseline, changed, unchanged and configuration-changed observations; includes up to four selected PDFs. `prepare`, `inspect` and incomplete acquisition do not emit this billing event. No start fee or per-Dataset-row fee. The event price includes platform usage during the run (separate PPE + usage disabled). Post-run storage and access can incur standard charges under your Apify plan. Zero events for prepare/inspect does not guarantee free retention or later access. Set a sufficient run limit for one event.

The charge is requested only after verified state and saved OUTPUT and Dataset. The run-default `BILLING` record confirms billing separately. Incomplete acquisition and business failure are not intentionally charged. However, platform failure **after an accepted charge**, or a charging-response timeout, can leave a FAILED run that was charged. `pending`/`unknown` requires manual review: uncertain charges are not retried. State and billing are not an atomic transaction. Starting a new observation run is a separate billable observation; use `inspect` to recover stored results without this event.

### API and outputs

Pin a build number/tag and verify the returned build ID. Persist the run ID; never blindly repeat a start request after a timeout. Retrieve the full OUTPUT JSON and Dataset JSON/CSV. Read business `status` and `commit_status`, not platform SUCCEEDED alone.

Output: `selected-private-5b-1`; state: `selected-state-5b-1`; receipt: `selected-commit-receipt-5b-1`. Exact examples and operational limits follow below. The implementation is not an official PNCP service or an endorsement by a public authority.

## Exemplos / Examples

### 1. Prepare — funciona sem store ou token no INPUT / no store or token in INPUT

```json
{"operation":"prepare","pncpId":"09509569000151-1-000010/2026"}
```

### 2. Observe — escolha seu próprio store / select your own store

Crie um armazenamento vazio dedicado em sua conta e selecione-o no campo `stateStoreId`; autorize apenas esse recurso. Os consentimentos de retenção e gravação serializada são explícitos, sem defaults silenciosos. Nunca use o ID de um store de demonstração ou de outro usuário.

Create an empty dedicated store in your account and select it in `stateStoreId`; grant access to that resource only. Retention and serialized-writer consent are explicit, with no silent defaults. Never use somebody else's or a demonstration store's ID.

Replace the placeholder with its actual 17-character ID. Choose document IDs returned by your current prepare. / Substitua o placeholder pelo ID real de 17 caracteres e escolha IDs do prepare atual.

```json
{"operation":"observe","pncpId":"09509569000151-1-000010/2026","watchKey":"my-serial-watch","stateStoreId":"REPLACE_WITH_YOUR_STORE_ID","documentIds":[10,9],"expectedRevision":0,"retentionPolicy":"keep_last_2_commits","writerPolicy":"externally_serialized"}
```

For the next observation, use the last confirmed `committed_revision`. An unchanged run keeps that revision. / Na próxima observação, use a última `committed_revision` confirmada; unchanged mantém essa revisão.

### 3. Inspect — recuperar, não renotificar / recover, do not renotify

```json
{"operation":"inspect","pncpId":"09509569000151-1-000010/2026","watchKey":"my-serial-watch","stateStoreId":"REPLACE_WITH_YOUR_STORE_ID"}
```

`last_committed_receipt.status_at_commit` describes the historical commit. `recoverable_events` may contain old baseline/change events while the current report has `new_event_count: 0` and no alerts. / O recibo descreve o commit anterior; seus eventos recuperáveis não são eventos novos desta consulta.

## Limites operacionais / Operational limits

- 1 procurement, 1–4 selected public text PDFs; total downloads 8 MiB; up to 500 pages per PDF, all with extractable text.
- Returned list: at most 1,000 records / 2 MiB. Checkpoint: 16,000,000 compressed bytes, 64,000,000 expanded bytes, 33 files. Receipt: 4,000,000 canonical JSON bytes. A large legitimate change can exceed these safety limits and suspend without advancing HEAD.
- Eight managed records per dedicated store; two committed snapshots plus staging. Each snapshot contains current documents and its last transition evidence, not all history. Apify run outputs/history have separate retention.
- Supported/default/minimum/maximum memory 512 MiB; recommended total run timeout 300 seconds, restart-on-error off and an explicit cost cap. HTTP socket timeout is 90 seconds, not an overall download deadline. No automatic acquisition retries or custom URLs.
- Missing/corrupt HEAD, receipt or archive: suspend; never silently reset or report the previous checkpoint as latest. First-publication failure after CONTROL may require explicit owner intervention or a newly authorized store. Never delete individual state records to force a baseline.
- Deleting a store removes originals, extracted text and receipts. Only the owner should explicitly perform such deletion. This Actor does not delete an existing legacy store or automatically migrate 5A.
- The wire-format identifiers retain their stable names: `selected-private-5b-1`, `selected-state-5b-1`, `selected-commit-receipt-5b-1`. They identify compatibility, not a promise of multiwriter support or unlimited history.

## Verificação / Verification

The supported sequential workflow has been exercised through the authenticated API with two official PDFs: prepare, a successful fresh baseline, an unchanged independent run without checkpoint advancement, and inspect replay. Complete JSON/CSV and persisted hashes/receipt were compared. Offline synthetic tests additionally exercise repeated changes, bounded retention and output-failure recovery. These tests do not establish customer outcomes, general extraction accuracy or legal correctness.

O fluxo serializado foi verificado pela API autenticada com dois PDFs oficiais: prepare, baseline novo bem-sucedido, nova execução unchanged sem consumir revisão, e inspect. JSON/CSV e hashes/recibo persistidos foram comparados. Testes sintéticos locais cobrem mudanças repetidas, retenção e recuperação após falha de saída; não comprovam benefício comercial, precisão geral ou correção jurídica.

### Paid-event acceptance / Aceitação da cobrança

Five private API runs on the same tested paid build covered prepare, insufficient-budget refusal before acquisition, fresh baseline, unchanged and inspect. Settled platform event counts were **0 / 0 / 1 / 1 / 0**; both completed observations had a confirmed BILLING journal. Baseline and unchanged reports/complete JSON and CSV were saved, and unchanged/inspect preserved the same HEAD, archive and receipt. Initial terminal billing counters can lag (one observed 0 later settled to 1): compare refreshed run metadata with BILLING before deciding to retry. Owner-account tests establish event accounting, not payment by an external customer or willingness to pay. 91 offline tests plus 125 subtests covered persistence and billing boundaries; synthetic tests are distinct from official-PDF retrieval.

Cinco runs privados no mesmo build pago verificaram prepare, recusa por orçamento insuficiente antes da aquisição, baseline novo, unchanged e inspect. Contagens finais de eventos: **0 / 0 / 1 / 1 / 0**, com BILLING confirmado nas duas observações completas. JSON/CSV e estado persistido foram comparados. Contadores logo após o término podem atrasar (0 passou para 1); confira metadados atualizados e BILLING antes de repetir. Testes do proprietário comprovam contabilização, não pagamento de cliente externo ou demanda comercial. 91 testes locais e 125 subtestes cobrem limites de persistência/cobrança; PDFs sintéticos não substituem a verificação com documentos oficiais.

# Actor input Schema

## `operation` (type: `string`):

prepare: returned list only; observe: selected PDF observation; inspect: saved state without PNCP requests.

## `pncpId` (type: `string`):

One PNCP procurement identifier.

## `watchKey` (type: `string`):

Required for observe/inspect. Stable label within your platform user and procurement. Not a storage or owner identifier.

## `documentIds` (type: `array`):

Required only for observe. One to four unique positive IDs chosen from prepare; omit for prepare and inspect.

## `correspondences` (type: `array`):

Optional for observe only. Explicit old/new IDs with saved old content; omit unless a verified correspondence is needed.

## `stateStoreId` (type: `string`):

ID real do armazenamento NOVO, dedicado e previamente autorizado (READ/WRITE). Obrigatório em observe/inspect. Nunca nome, criação automática ou fallback. Estado5A/identidade diferente é recusado.

## `retentionPolicy` (type: `string`):

Obrigatório em observe. Autoriza substituir os slots e compactar documentos/eventos antigos neste NOVO armazenamento dedicado. Mantém dois checkpoints confirmados e um slot temporário. Não é arquivo histórico completo. Sem migração/limpeza automática do5A.

## `writerPolicy` (type: `string`):

Obrigatório. O chamador garante apenas uma execução gravadora por armazenamento, sem sobreposição de tarefa, agenda, tentativa ou execução manual. Verificações de conflito não são trava atômica.

## `expectedRevision` (type: `integer`):

0 somente para estado novo. Use committed_revision do último resultado confirmado/inspect. Alteração inesperada suspende a comparação; unchanged não incrementa a revisão.

## Actor input object example

```json
{
  "operation": "prepare",
  "pncpId": "09509569000151-1-000010/2026",
  "watchKey": "comusa-selected-5a",
  "documentIds": [
    10,
    9
  ],
  "correspondences": []
}
```

# Actor output Schema

## `report` (type: `string`):

Full result, selected coverage, committed alerts and diagnostics

## `summary` (type: `string`):

No description

## `billing` (type: `string`):

Separate run billing journal; pending or unknown must be reviewed without blind retry

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "pncpId": "09509569000151-1-000010/2026"
};

// Run the Actor and wait for it to finish
const run = await client.actor("amycole/pncp-selected-documents-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "pncpId": "09509569000151-1-000010/2026" }

# Run the Actor and wait for it to finish
run = client.actor("amycole/pncp-selected-documents-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "pncpId": "09509569000151-1-000010/2026"
}' |
apify call amycole/pncp-selected-documents-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,amycole/pncp-selected-documents-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/EA3FhHzn9GksNaBQX/builds/LlmRcFpRDwMdtUkUU/openapi.json
