# NL Wet- en Regelgevingtracker per Sector (`codeclouds/nl-wetgeving-sectortracker`) Actor

Signaleert nieuwe en gewijzigde Nederlandse wet- en regelgeving (wetten, AMvB's, ministeriele regelingen) via KOOP, geclassificeerd per sector op trefwoorden, voor compliance-teams.

- **URL**: https://apify.com/codeclouds/nl-wetgeving-sectortracker.md
- **Developed by:** [Dennis](https://apify.com/codeclouds) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 regelgeving-records

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## NL Wet- en Regelgevingtracker per Sector — Dutch Legislation Sector Tracker 🇳🇱⚖️

Get **new and changed Dutch legislation** — wetten, AMvB's (Algemene Maatregelen van Bestuur), and
ministeriële regelingen — automatically classified per business sector, delivered as a structured feed for
compliance teams.

Dutch compliance departments (banks, insurers, healthcare providers) have a legal obligation to track
legislative changes relevant to their sector. This actor turns the official KOOP/Staatsblad publication
stream into a filtered, sector-tagged feed, so you know the moment a law relevant to your industry changes.

### When should an AI agent use this?

- "Which new laws or AMvBs were published in the Netherlands affecting the healthcare sector this month?"
- "Monitor Dutch legislation for anything relevant to financial services (Wft, DNB, AFM)."
- "Has any new energy-sector regulation (Energiewet, Elektriciteitswet) been published since last week?"
  (using incremental mode)
- "Give me a nationwide feed of new Wet/AMvB publications, only new items since yesterday."
- "Classify these legislative publications by sector using my own keyword list."

### What this Actor does

- Searches the official KOOP SRU API (`repository.overheid.nl/sru`, the source behind
  officielebekendmakingen.nl / Staatsblad) for legislation of the requested document type(s)
- Supports `Wet`, `AMvB`, `Ministeriële regeling`, `Rijkswet`, `Klein Koninklijk Besluit`, `circulaire` and
  `beleidsregel` as filterable document types
- Classifies each publication into one or more sectors by matching keywords against its title — a
  configurable, transparent alternative to a native "sector" field (which does not exist in the source data)
- Returns `sectoren: null` for publications that do not match any configured sector — this is a normal,
  useful result (not every law is sector-specific), never an error
- Classifies each publication's `wijzigingType` (`nieuwe_regeling` / `wijziging` / `intrekking` / `overig`)
  based on the fixed Staatsblad title phrasing, so compliance teams can distinguish a brand-new law from a
  routine amendment at a glance
- Supports incremental mode: only new/changed publications since the previous run
- Optional `volledigeTekstClassificatie` fallback: when the title has no sector match, fetch and classify the
  full text instead — catches sector-relevant content hidden behind a generic title, and fills
  `samenvattingSnippet` from the full text as a bonus

### Who is this for?

- **Compliance departments** (banks, insurers, healthcare providers) — required by law to track legislative
  changes affecting their sector (Wft-vergunninghouders, Wtza-zorgaanbieders, etc.)
- **Legal & regulatory affairs teams** — early visibility into new/changed legislation before it hits
  commercial legal-information services
- **AI agents / RAG pipelines** — a structured, machine-readable feed of Dutch legislation to ground legal
  research or compliance-monitoring assistants
- **Consultancies & law firms** — a base data feed for building sector-specific legislative alerts for clients

### Input

| Field | Type | Description |
|---|---|---|
| `documentTypes` | array | Which KOOP document types to fetch. Default `["Wet", "AMvB"]`. Options: `Wet`, `AMvB`, `Ministeriële regeling`, `Rijkswet`, `Klein Koninklijk Besluit`, `circulaire`, `beleidsregel`. |
| `sectorKeywords` | object | Map of sector name → list of keywords, matched case-insensitively against the title. Leave empty (default) to use the built-in set: `zorg`, `bouw`, `financiële sector`, `arbeidsrecht`, `energie`, `mobiliteit`. Provide your own object to fully override the defaults. |
| `publishedAfter` | string | Only publications modified on/after this date (`YYYY-MM-DD`). |
| `maxResults` | integer | Maximum number of records to return (1-10000). Default `200`. |
| `incrementalMode` | boolean | Only fetch publications newer than the previous run. Default `false`. |
| `volledigeTekstClassificatie` | boolean | When the title has no sector match, fetch and classify the full text instead (1 extra HTTP request per unmatched record). Also fills `samenvattingSnippet`. Default `false`. |
| `trackSectorTrend` | boolean | Compare the number of sector-match-alerts per sector this run against the previous run. Default `false`. |

### Output

```json
{
  "id": "stb-2026-116",
  "titel": "Besluit van 20 mei 2026 tot wijziging van het Uitvoeringsbesluit kinderbijslagvoorziening BES in verband met de invoering van de dubbele kinderbijslag bij intensieve zorg BES",
  "documentType": "AMvB",
  "wijzigingType": "wijziging",
  "sectoren": ["zorg"],
  "publicatiedatum": "2026-05-27",
  "publicatienummer": "116",
  "bron": "Staatsblad",
  "volledigeTekstUrl": "https://repository.overheid.nl/frbr/officielepublicaties/stb/2026/stb-2026-116/1/html/stb-2026-116.html",
  "samenvattingSnippet": null,
  "sectorMatchViaVolledigeTekst": false
}
```

**`sectorMatchViaVolledigeTekst`** is `true` only when `volledigeTekstClassificatie` is enabled and the sector
match was found in the full text after the title itself had no match — this is the signal for the extra
`sector-match-verrijkt` charge, and it also means `samenvattingSnippet` got filled from the full text.

**`sectoren` is often `null`** — most legislation does not match a configured sector keyword. This is a
valid, expected result, not a failure to classify.

**`wijzigingType` is `"overig"` when the title doesn't match a known Staatsblad phrasing** — this is an
honest fallback, not a guess. It never invents a `nieuwe_regeling`/`wijziging`/`intrekking` label without a
matching, live-confirmed title pattern.

#### Same-day duplicate protection (`incrementalMode`)

`dt.modified` filtering only has day-level granularity, so running the actor a second time on the same day
(e.g. a morning + evening schedule) used to re-deliver — and re-charge for — the same records. The actor now
also tracks which record IDs were already delivered today (in the key-value store) and skips them on a
second run the same day, at no charge. No behavior change across different days.

#### Run summary (free extra dataset record)

Whenever at least one record is delivered, one extra dataset item with `"type": "RUN_SUMMARY"` is pushed at
the end of the run — no extra charge: total records, a breakdown per sector and per `wijzigingType`, and how
many sector matches were found only via the full-text fallback.

#### Sector trend between runs (`trackSectorTrend`, optional, separately charged)

With `trackSectorTrend: true`, the actor counts how many sector-match-alerts occurred per sector this run and
compares that against the previous run's count (stored in its key-value store). One extra dataset record per
sector seen this run or last run:

```json
{
  "type": "sector-trend-signaal",
  "sector": "zorg",
  "huidigAantal": 12,
  "vorigAantal": 10,
  "percentageVerandering": 20
}
```

`percentageVerandering` is `null` when the sector wasn't seen in the previous run (no known baseline) or the
previous count was `0` (division by zero gives no meaningful percentage). Charged as `sector-trend-signaal`,
only for sectors where a percentage was actually computable.

### Use cases

**Daily nationwide legislation feed, incremental:**

```json
{ "incrementalMode": true }
```

**Monitor only healthcare and financial-sector legislation, using the built-in defaults:**

```json
{
  "documentTypes": ["Wet", "AMvB", "Ministeriële regeling"],
  "publishedAfter": "2026-01-01"
}
```

Then filter the output dataset on `sectoren` containing `"zorg"` or `"financiële sector"`.

**Use a fully custom sector keyword set:**

```json
{
  "sectorKeywords": {
    "cybersecurity": ["cyberbeveiliging", "nis2", "digitale weerbaarheid"],
    "privacy": ["avg", "gegevensbescherming", "persoonsgegevens"]
  }
}
```

### Pricing

This Actor uses Apify's Pay-Per-Event (PPE) pricing model.

- **Actor Start:** $0.00005 (Apify default)
- **`regelgeving-record`:** $0.003 per delivered record (base data)
- **`sector-match-alert`:** $0.008 extra, only when a record matches at least one configured sector
- **`sector-match-verrijkt`:** $0.006 extra on top of `sector-match-alert`, only with `volledigeTekstClassificatie`
  enabled and only when the match was found via the full-text fallback (title itself had no match)
- **`sector-trend-signaal`:** $0.008 per sector, only with `trackSectorTrend` enabled and a previous count
  actually known for that sector

### Legal

This actor uses the **official public SRU API** of the Dutch government (KOOP / repository.overheid.nl, the
same source behind officielebekendmakingen.nl / Staatsblad) — the same source used by
[NL CAO-wijzigingen Database](https://apify.com/codeclouds/nl-cao-wijzigingen-database). No scraping of
protected websites, no login, no terms-of-service conflicts.

- Wetten, AMvB's and ministeriële regelingen are, by definition, generally binding rules — not decisions
  about individual natural persons. This is a lower AVG/GDPR-risk data source than most other actors in this
  portfolio.
- Sector classification is a best-effort keyword match on the publication title, **not legal advice**. It
  does not replace a qualified legal/compliance review of whether a specific law applies to your
  organization.

### FAQ

**Q: How fresh is the data?**
A: Publications appear in the feed the same day KOOP publishes them.

**Q: Why is `sectoren` often `null`?**
A: Most Dutch legislation does not concern any of the configured sectors — this is expected, not a bug.

**Q: Can I add my own sectors?**
A: Yes — set `sectorKeywords` to your own object; it fully replaces the built-in defaults.

**Q: How do I get only new/changed legislation?**
A: Enable `incrementalMode` and schedule the actor; it remembers the date of the previous run.

**Q: Does this include jurisprudence (court rulings)?**
A: No — this actor covers wet- en regelgeving (legislation) only, not rechtspraak (case law).

**Q: What's the difference between `wijzigingType` and `sectoren`?**
A: `sectoren` tells you *which industry* a publication is about; `wijzigingType` tells you *what kind of legal
event* it is (brand-new regulation vs. an amendment to an existing one vs. a repeal). Use both together, e.g.
filter on `sectoren` containing `"zorg"` AND `wijzigingType == "nieuwe_regeling"` to spot entirely new
healthcare legislation specifically.

### Related Actors

- **[NL CAO-wijzigingen Database](https://apify.com/codeclouds/nl-cao-wijzigingen-database)** — tracks
  collective labour agreement (CAO) changes on the same official KOOP SRU source, for the arbeidsrecht/HR
  angle specifically.

***

*Zoekwoorden: wetgeving monitor, regelgeving tracker Nederland, compliance monitoring wet- en regelgeving,
Staatsblad wijzigingen, AMvB monitor, wetswijzigingen per sector, regulatory tracker Netherlands.*

### Keywords

wetgeving, regelgeving, compliance, staatsblad, wet, amvb, ministeriele-regeling, sector, netherlands, legal-monitoring

### Changelog

#### 0.4.0 - Sector trend between runs

- Added `trackSectorTrend` (opt-in) — compares the number of sector-match-alerts per sector against the
  previous run via the key-value store, exposed as a `sector-trend-signaal` dataset record per sector. New
  `sector-trend-signaal` event ($0.008), only charged when a previous count is actually known for that sector.

#### 0.3.2 - Bugfix

- Fixed same-day duplicate charges in `incrementalMode`: a second run on the same day (`dt.modified` only has
  day-level granularity) no longer re-delivers and re-charges the same records. Delivered IDs for the current
  day are now tracked in the key-value store.
- Added a free `RUN_SUMMARY` dataset record at the end of each run (totals per sector/`wijzigingType`, and
  how many matches came via the full-text fallback). No pricing change.

#### 0.3.1 - Bugfix

- Fixed `incrementalMode` never seeing the previous run's `lastRunDate`: the actor was reading/writing to
  Apify's per-Run *default* key-value store, which is not shared between separate runs. Now uses a named,
  persistent key-value store. A new baseline will be captured on the next run.

#### 0.3.0

- Added `volledigeTekstClassificatie` (default `false`): when a title has no sector match, optionally fetch
  and classify the full text instead — catches sector-relevant content hidden behind a generic title, same
  patroon as nl-cao-wijzigingen-database. Fills `samenvattingSnippet` from the full text as a side effect. New
  `sectorMatchViaVolledigeTekst` field flags matches found this way. New charged event `sector-match-verrijkt`
  ($0.006, on top of `sector-match-alert`), confirmed by the user (2026-07-14).

#### 0.2.0

- Added `wijzigingType` classification (`nieuwe_regeling`/`wijziging`/`intrekking`/`overig`) based on fixed
  Staatsblad title phrasing, so a brand-new law can be told apart from a routine amendment without a full-text
  fetch. No pricing change — enrichment of the existing per-record output.

#### 0.1.0

- Initial release. Fetch Dutch legislation (Wet/AMvB/Ministeriële regeling/etc.) via the official KOOP SRU
  API, classify per sector via configurable keyword matching, incremental mode.

# Actor input Schema

## `documentTypes` (type: `array`):

Which KOOP document types (dt.type) to fetch. Exact spelling/capitalization as used by the source.

## `sectorKeywords` (type: `object`):

Map of sector name -> list of keywords used to classify each document by matching against its title (case-insensitive). Provide your own object to override the built-in defaults (zorg, bouw, financiele-sector, arbeidsrecht, energie, mobiliteit). Leave empty to use the defaults.

## `publishedAfter` (type: `string`):

Only publications modified on/after this date (YYYY-MM-DD).

## `maxResults` (type: `integer`):

Maximum number of legislation records to return (1-10000).

## `incrementalMode` (type: `boolean`):

Only fetch publications newer than the previous run. Ideal for scheduled monitoring. On the very first call (no snapshot yet in the actor's key-value store) this has no effect and behaves like a full fetch; the run date and delivered-record IDs are then saved as the baseline. Uses a shared, persistent key-value store that scheduled monitoring runs also read/write, so an ad-hoc call in between can shift the baseline seen by the next scheduled run.

## `volledigeTekstClassificatie` (type: `boolean`):

When a title has no sector match, fetch and classify the full text instead (1 extra HTTP request per unmatched record). Also fills samenvattingSnippet. Charges the extra sector-match-verrijkt event when it finds a match this way.

## `trackSectorTrend` (type: `boolean`):

Compares the number of sector-match-alerts per sector this run against the previous run (via the actor's key-value store). New charged event sector-trend-signaal ($0.008), only when a previous count is actually known for that sector. On the very first call (no previous count snapshot yet) every sector's change is unknown, so nothing is charged and the current counts are simply saved as the baseline. Uses a shared, persistent key-value store that scheduled monitoring runs also read/write, so an ad-hoc call in between can affect the baseline seen by the next scheduled run.

## Actor input object example

```json
{
  "documentTypes": [
    "Wet",
    "AMvB"
  ],
  "sectorKeywords": {},
  "maxResults": 200,
  "incrementalMode": false,
  "volledigeTekstClassificatie": false,
  "trackSectorTrend": false
}
```

# Actor output Schema

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

Alle wetgevings-records in het default dataset.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("codeclouds/nl-wetgeving-sectortracker").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("codeclouds/nl-wetgeving-sectortracker").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 '{}' |
apify call codeclouds/nl-wetgeving-sectortracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,codeclouds/nl-wetgeving-sectortracker"
        }
    }
}

```

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/LzvxLGHnozMsDEOvq/builds/Togoen2W9T0c3nl7m/openapi.json
