# Brazil Transport Legislation Monitor (`kman-br/monitor-legislacao`) Actor

Monitor public Brazilian legislative proposals, classify transport topics and export source links, procedural status and rule-based impact notes.

- **URL**: https://apify.com/kman-br/monitor-legislacao.md
- **Developed by:** [Kman](https://apify.com/kman-br) (community)
- **Categories:** Business, News
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 92.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## Brazil Transport Legislation Monitor

Collect public Brazilian legislative proposals from the Chamber of Deputies and the Federal Senate. The Actor classifies transport topics, normalizes procedural status and adds rule-based impact notes with official source links. It covers PL, PLP, MPV and PDL records.

The default output contains transport topics only. General records (`geral`) are excluded unless `transportOnly` is false. An empty result means no matching record in the collected sample; it does not establish that no relevant proposal exists.

### Input

```json
{
  "days": 30,
  "sources": ["camara", "senado"],
  "themes": [],
  "transportOnly": true,
  "maxPages": 3,
  "maxItems": 24,
  "budgetSeconds": 100,
  "timeoutMs": 8000,
  "useCache": false
}
```

| Field | Default | Meaning |
| --- | --- | --- |
| `days` | `30` | Inclusive lookback, 1–90 days. The Console form opens with 90; API calls without `days` use 30. |
| `endDate` | Today in Brazil | Optional `YYYY-MM-DD`, no later than today in `America/Sao_Paulo`. |
| `sources` | `camara`, `senado` | Sources selected before requests. `dou` is an unconfigured placeholder. |
| `themes` | `[]` | Topic IDs selected after classification; empty means all permitted topics. |
| `transportOnly` | `true` | Exclude general records. Selecting `geral` explicitly requires `false`. |
| `maxPages` | `3` | Chamber pages per query, 1–20. |
| `maxItems` | `24` | Collected candidates **per source**, 1–40. Filtering may return fewer. |
| `budgetSeconds` | `100` | Collection time budget, 1–110 seconds. |
| `timeoutMs` | `8000` | Request timeout, 100–30000 ms. |
| `useCache` | `false` | True uses a sanitized six-hour response cache. Persistence between runs is not guaranteed. |

Supported topic IDs are `transporte_combustivel` (trucks, road cargo and fuel transport), `criogenia_gases` (cryogenics and gases), `fretamento_usinas` (worker charter transport), `aditivos_combustivel` (fuel additives and blending), and `geral` (general). Topic matches may overlap. IDs remain compatible with the existing classification configuration.

For a weekly fuel transport sample:

```json
{ "days": 7, "themes": ["transporte_combustivel"], "maxItems": 12 }
```

For general records only:

```json
{ "days": 7, "transportOnly": false, "themes": ["geral"] }
```

### Output

The default dataset contains one normalized legislative record per row, with these fields: `id`, `idFonte`, `fonte`, `tipo`, `numero`, `ano`, `ementa`, `indexacao`, `dataApresentacao`, `dataAtualizacao`, `dataDeliberacao`, `criteriosPeriodo`, `linkOficial`, `autores`, `normaGerada`, `tramitacao`, `camposIndisponiveis`, `classificacao`, and `impacto`.

Source text and output field names remain in Portuguese. Nested classification includes topic IDs, scores and evidence; impact includes relevance, affected activities and a disclaimer. Missing source information remains explicit. Authors are limited to public legislative attribution (public name and, when available, party/state). Contact details and recognized personal identifiers are discarded or redacted before caching and export. Redaction rules do not guarantee detection of every possible identifier.

The default key-value store contains:

- `RESUMO`: period, source coverage, filters and counts of collected, selected and delivered records, plus the reason for technical partial results or failure. Topic counts can overlap.
- `EXECUCAO`: run status, duration, request statistics, source diagnostics and event totals. Records are delivered only when at least one source is usable and billing permits delivery; the reason for a `parcial` or failed run is recorded here.
- `DIGEST`: a Markdown summary of delivered records, with official links and coverage warnings.

Source coverage counts describe collection; delivered counts describe the filtered dataset. Diagnostics are stored in the key-value store and never emitted as dataset rows.

#### Sample output

A real record from a local SDK run with the default input (`{"days": 30}`) on October 24, 2026. That run collected 48 candidates and delivered 2 transport records; status was `parcial` because the 24-candidates-per-source limit was reached.

```json
{
  "id": "senado:9016660",
  "idFonte": "9016660",
  "fonte": "senado",
  "tipo": "MPV",
  "numero": "1343",
  "ano": 2026,
  "ementa": "Altera a Lei nº 13.703, de 8 de agosto de 2018, para criar a obrigatoriedade de cadastramento da operação de transporte e a geração do Código Identificador da Operação de Transporte - CIOT, e para dispor sobre medidas administrativas para o cumprimento da Política Nacional de Pisos Mínimos do Transporte Rodoviário de Cargas.",
  "indexacao": "",
  "dataApresentacao": "2026-03-19",
  "dataAtualizacao": "2026-10-07",
  "dataDeliberacao": "2026-07-14",
  "criteriosPeriodo": ["atualizacao"],
  "linkOficial": "https://www25.senado.leg.br/web/atividade/materias/-/materia/173212",
  "autores": [{ "nome": "Presidência da República" }],
  "normaGerada": "Lei nº 15.485 de 05/08/2026",
  "tramitacao": {
    "estagio": "lei",
    "urgencia": false,
    "arquivada": false,
    "situacaoOriginal": "TRANSFORMADA EM NORMA JURÍDICA COM VETO PARCIAL",
    "regime": null,
    "orgao": null,
    "ultimoAndamento": { "data": "2026-08-06", "descricao": "TRANSFORMADA EM NORMA JURÍDICA COM VETO PARCIAL" }
  },
  "camposIndisponiveis": [],
  "classificacao": {
    "temas": ["transporte_combustivel"],
    "scores": { "transporte_combustivel": 7, "criogenia_gases": 0, "fretamento_usinas": 0, "aditivos_combustivel": 0, "geral": 1 },
    "evidencias": {
      "transporte_combustivel": { "positivos": ["ciot", "transporte rodoviario de cargas"], "negativos": [], "semContexto": [] },
      "criogenia_gases": { "positivos": [], "negativos": [], "semContexto": [] },
      "fretamento_usinas": { "positivos": [], "negativos": [], "semContexto": [] },
      "aditivos_combustivel": { "positivos": [], "negativos": [], "semContexto": [] },
      "geral": { "positivos": ["transporte"], "negativos": [], "semContexto": [] }
    }
  },
  "impacto": {
    "ondeAfeta": {
      "setores": ["transportadoras de cargas e produtos perigosos", "distribuidoras de combustível e TRRs"],
      "atividades": ["transporte rodoviário, frete e operação de veículos tanque"],
      "ente": "União; alcance concreto a confirmar no texto oficial",
      "reguladoresPossiveis": ["ANTT", "CONTRAN/SENATRAN", "ANP"],
      "base": "Enquadramento genérico por tema; não confirma competência nem efeito jurídico."
    },
    "oQueMuda": ["Possível obrigação ou requisito novo", "Alteração de norma existente proposta ou descrita na ementa"],
    "normasMencionadas": ["Lei nº 13.703, de 8 de agosto de 2018"],
    "relevancia": 3,
    "condicao": "A fonte indica norma gerada ou publicada; vigência e alcance exigem leitura oficial.",
    "aviso": "Não é consultoria jurídica. Análise automática, não é parecer jurídico.",
    "fonte": "https://www25.senado.leg.br/web/atividade/materias/-/materia/173212"
  }
}
```

The matching `DIGEST` line for this record:

```markdown
- **MPV 1343/2026** (senado, lei, relevância 3/3): Altera a Lei nº 13.703, de 8 de agosto de 2018, para criar a obrigatoriedade de cadastramento da operação de transporte e a geração do Código Identificador da Operação de Transporte - CIOT, e para dispor sobre medidas administrativas para o cumprimento da Política Nacional de Pisos Mínimos do Transporte Rodoviário de Cargas. [Fonte oficial](https://www25.senado.leg.br/web/atividade/materias/-/materia/173212).
```

### Pricing

Pay per event: **US$ 0.010 per `inicio-run`** and **US$ 0.002 per `item-transporte`**, that is, US$ 2.00 per 1,000 delivered transport records plus the run start. After validating input and billing settings, the Actor collects the selected sources and charges `inicio-run` once only if at least one configured source is usable: its state is `ok` or `parcial`, with no technical failures or query errors. A successful response with zero records qualifies, as does partial coverage caused only by page or item limits. The unconfigured DOU placeholder does not qualify.

Each transport record actually delivered to the dataset incurs one `item-transporte` event, even when it matches multiple topics. Optional general records (`geral`) are free per item. Source diagnostics and errors remain in the key-value store and incur no item charge. An empty result can incur the start event when a usable source responded. If no source is usable, the Actor charges no events, delivers no records, writes a clear failure message to `EXECUCAO` and fails the run. With at least one usable source, available records are delivered and charged even if a different source has a technical error or the run takes 120 seconds or more; the run then succeeds (SUCCEEDED) with status `parcial`. The warning names each source with a technical error (for example, `senado`) in the run log, status message, `EXECUCAO` and `RESUMO`, so you can see which source needs a later retry.

In pay-per-event mode, the Actor checks `ACTOR_MAX_TOTAL_CHARGE_USD` and the platform allowance before collection and again before charging. If the cap prevents the start event, including an explicit zero cap, no requests are made, no events are charged and no records are delivered; status is `limite_cobranca`. Reaching a limit during delivery stops further records. A last confirmed item is counted; a refused item is not. If transport records are available but the cap covers the start event and not one record, nothing is charged or delivered and status is `limite_cobranca`.

The Actor charges only these two events. If the platform pricing lacks either event, differs from these prices, charges the automatic `apify-actor-start` or `apify-default-dataset-item` events, adds another paid event, or uses a paid pricing model other than pay per event, the run fails before collection, charging or output writes. If the platform restarts a run that has already charged (for example, after a migration or when a finished run is resurrected), the Actor stops without collecting or charging again; records already delivered stay in the dataset.

Without pay-per-event pricing, for example in local runs, the Actor charges nothing and still collects and delivers records. Spending caps, including an explicit zero, are ignored in this mode.

### Official sources and limitations

Data comes from the [Chamber of Deputies open data API](https://dadosabertos.camara.leg.br/) and the [Federal Senate open data API](https://legis.senado.leg.br/dadosabertos/). Only these official API hosts are requested. DOU/INLABS is not configured; it performs no login or collection.

Collection uses bounded pages, candidates, retries and a shared time budget. Requests are limited to at most one per second per host. The Chamber enriches each selected candidate with two additional requests. Larger inputs may exhaust the time budget; a source that runs out of time counts as a technical error, handled as described under Pricing. The Senate update query covers at most the latest 30 days relative to its API; historical movement coverage is incomplete. Administrative updates are not proof of legislative progress or a new obligation.

Classification and impact notes use deterministic rules. Accuracy and complete coverage are not established by these rules or local measurements. A proposal can appear separately in both chambers. Repeated runs may return the same record and produce new events; there is no cross-run deduplication. Always read the official record before making a decision.

This is **not legal/tax advice**. Automated analysis is not a legal opinion.

# Actor input Schema

## `days` (type: `integer`):

Includes the end date. API calls without this field use 30.

## `endDate` (type: `string`):

YYYY-MM-DD, no later than today in America/Sao_Paulo. Omit for today.

## `sources` (type: `array`):

Actor source filter, applied before collection. DOU is an unconfigured placeholder and makes no requests.

## `themes` (type: `array`):

Actor filter applied after classification. Empty selects all topics permitted by transportOnly. geral requires transportOnly=false.

## `transportOnly` (type: `boolean`):

Exclude geral by default. If false, general records may be exported, always without an item charge.

## `maxPages` (type: `integer`):

Time limits can stop collection earlier.

## `maxItems` (type: `integer`):

Bounds candidates before topic filtering; the Chamber uses two enrichment requests per item. At most 80 legislative records across both live sources.

## `budgetSeconds` (type: `integer`):

Shared across all requests; not the platform run timeout.

## `timeoutMs` (type: `integer`):

Retries and host rate limits also consume the collection budget.

## `useCache` (type: `boolean`):

true enables a sanitized six-hour response cache; cache persistence across platform runs is not guaranteed.

## Actor input object example

```json
{
  "days": 90,
  "sources": [
    "camara",
    "senado"
  ],
  "themes": [],
  "transportOnly": true,
  "maxPages": 3,
  "maxItems": 24,
  "budgetSeconds": 100,
  "timeoutMs": 8000,
  "useCache": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `digest` (type: `string`):

No description

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

RESUMO: status, per-source coverage, warnings and charged events.

## `execution` (type: `string`):

No description

# 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 = {
    "days": 90
};

// Run the Actor and wait for it to finish
const run = await client.actor("kman-br/monitor-legislacao").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 = { "days": 90 }

# Run the Actor and wait for it to finish
run = client.actor("kman-br/monitor-legislacao").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 '{
  "days": 90
}' |
apify call kman-br/monitor-legislacao --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kman-br/monitor-legislacao"
        }
    }
}
```

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/vQRBU99rHFsC2svLt/builds/hbiLWriaypQVpJ9TP/openapi.json
