# Flemish Permit Leads (Omgevingsvergunningen) (`codeclouds/be-flemish-permit-leads`) Actor

Monitor official Flemish urban-planning (stedenbouwkundige) and IIOA environmental permit projects from open data: filters, status changes, WGS84 geometry and privacy-safe B2B project leads.

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

## Pricing

from $5.00 / 1,000 permit leads

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

## Flemish Permit Leads (Omgevingsvergunningen)

Turn the official Flemish **Omgevingsloket** open data into a clean, searchable B2B lead feed of **stedenbouwkundige aanvragen** (urban-planning applications) and **IIOA projects** (classified installations and activities): current status, submission date, competent authority, act, project link and optional WGS84 geometry. No portal scraping, no manual dossier work. Ready for a CRM, a map or an AI agent.

This Actor uses only the public **MercatorNet WFS 2.0.0** of the Flemish Government. The citizen portal behind an anti-bot wall is not scraped. Subdivision permits (`VK` codes) are deliberately excluded and remain the domain of the separate **Flanders Subdivision Permit Monitor** Actor.

### When should an AI agent use this?

- "Which new urban-planning applications were filed in Flanders in the last 30 days?"
- "Which environmental projects fall inside a bounding box around Ghent?"
- "Monitor Flemish permit applications and return only new or status-changed projects."
- "Fetch IIOA applications and filter the results client-side on class 1, province Vlaams-Brabant and an active status."

### What this Actor does

- Reads the official layers `lu:lu_omv_gd_v2` and `lu:lu_omv_iioa_v2` without an API key, account or captcha.
- Returns one record per official GD or IIOA source feature with a stable `recordKey`, project number, project type, current status, status date, submission date, phase, competent authority, act, official project link and IIOA attributes.
- Filters server-side on source layer, project type, status in full mode, competent authority, project numbers, a date window and a geographic bounding box.
- Fetches records oldest-first and stably using keyset pagination: `datum_indiening ASC,id ASC` for snapshots and `datum_huidige_toestand ASC,id ASC` for change monitoring. New status updates therefore join the back of the backlog instead of being skipped.
- Distinguishes applications, notifications, amendments, transfers and discontinuations from the official source fields.
- Computes `statusGroep`, `dagenSindsIndiening` and a tolerant `geometryCenterLat`/`geometryCenterLon` without an external geocoder.
- Offers `geometryMode=none`, `centroid` or `full`: no location, the centre of the geometry bounding box, or the complete WGS84 GeoJSON geometry (`Polygon`/`MultiPolygon`).
- Detects new, content-changed and status-changed source features through a monitor-specific named key-value store. `changes_only` scans on the status date and deliberately drops status filters so decisions are not missed.
- Deduplicates on `recordKey` (`sourceLayer + sourceRecordId`, with UUID and project-number fallbacks). Multiple IIOA installations under the same project number are therefore kept.
- Survives feed drift in optional fields: unknown statuses, empty strings, null values and unexpected geometry never crash a run. If the mandatory sort date or id for stable pagination is missing, that layer stops explicitly with an error status.
- Exports **no raw applicant or operator names**. `bedrijfssignaalAanwezig` is only a yes/no signal when the source contains a 9/10-digit KBO-like number.

### Coverage and scope

On 25 September 2026 the official catalogue reported:

- **786,291** urban-planning projects and notifications in `lu:lu_omv_gd_v2`;
- **195,332** IIOA projects and notifications in `lu:lu_omv_iioa_v2`.

The live probe of the last 200 records per layer contained mostly `OMV2019_AANVRAAG` for GD and applications, notifications, transfers and amendments for IIOA. IIOA class 1, 2 and 3 all occur live.

Subdivision codes are actively excluded. This Actor is therefore a broad non-subdivision feed and not a duplicate of `be-verkavelingsvergunningen`.

### Quick start

Start small: `maxResults` applies **per selected source layer**.

**1. New applications from the last 30 days:**

```json
{
  "mode": "full_snapshot",
  "layers": ["gd", "iioa"],
  "recordTypes": ["application"],
  "lookbackDays": 30,
  "geometryMode": "centroid",
  "maxResults": 10
}
```

**2. Only open IIOA applications with a company signal:**

```json
{
  "layers": ["iioa"],
  "recordTypes": ["application"],
  "statuses": [
    "Geen beslissing genomen",
    "In behandeling (in eerste aanleg)",
    "In behandeling (na beroep)"
  ],
  "companySignalOnly": true,
  "geometryMode": "none",
  "maxResults": 25
}
```

**3. Monitor new and changed projects:**

```json
{
  "mode": "changes_only",
  "lookbackDays": 90,
  "overlapDays": 2,
  "maxResults": 200
}
```

### Input

| Field | Type | Description |
|---|---|---|
| `mode` | select | `full_snapshot` delivers everything within the filters; `changes_only` uses the status date, its own monitor cursor and delivers only new, changed or status-changed source features. |
| `layers` | multi-select | `gd`, `iioa` or both. Default both. |
| `recordTypes` | multi-select | `application`, `notification`, `amendment`, `transfer` or `all`. Default only `application`; `all` cannot be combined with the other options. |
| `statuses` | string list | Free source statuses for `full_snapshot`. Default open statuses; empty means all statuses. In `changes_only` this filter is ignored so decisions are seen. |
| `authorityContains` | string | Substring filter on the competent authority, for example `Gent` or `Provincie Limburg`. |
| `companySignalOnly` | checkbox | Only records where `aanvrager` or `exploitant` contains a 9/10-digit KBO-like number. The identity itself is not exported. |
| `lookbackDays` | number | Snapshot: days back on the submission date. First changes run: days back on the status date. Ignored when `submissionFrom` is set. |
| `submissionFrom` / `submissionTo` | date | `submissionFrom` uses the submission date in full mode and the status date in changes mode; `submissionTo` remains a submission-date upper bound. |
| `projectNumbers` | string list | One or more numeric project numbers for targeted dossier lookups. |
| `bbox` | object | Optional WGS84 box with `west`, `south`, `east` and `north`. |
| `geometryMode` | select | `none`, `centroid` (bounding-box centre) or `full` (GeoJSON outline plus centre). |
| `overlapDays` | number | In `changes_only`, after a fully completed scan per layer, 2 status days are re-checked by default for late corrections. |
| `maxResults` | number | 1–20,000 per source layer, default 100. After a truncated scan the next run automatically resumes from the keyset cursor. |
| `includeSummary` | checkbox | Adds one free summary record. |

### Output

One JSON record per unique official source feature. Human-readable labels are Flemish (Dutch); as a deliberate technical exception, API keys stay on stable WFS/Apify conventions:

```json
{
  "recordKey": "iioa:id:1025042",
  "sourceLayer": "iioa",
  "sourceLayerName": "IIOA-projecten en meldingen",
  "sourceRecordId": 1025042,
  "projectnummer": "2026100049",
  "voorwerpUuid": "l_QmMjkaSMqmav3wq73Lfw",
  "projectUrl": "https://omgevingsloket.omgeving.vlaanderen.be?project=2026100049",
  "projectTypeCode": "OMV2019_AANVRAAG",
  "projectTypeDescription": "Aanvraag omgevingsproject",
  "projectSoort": "aanvraag",
  "handelingOmschrijving": null,
  "currentStatus": "In behandeling (in eerste aanleg)",
  "statusGroep": "open",
  "datumIndiening": "2026-09-24",
  "datumHuidigeStatus": "2026-09-25",
  "bevoegdeOverheid": "Provincie Vlaams-Brabant",
  "fase": "Eerste Aanleg",
  "bedrijfssignaalAanwezig": true,
  "inrichtingsnummer": "20190830-0036",
  "iioaKlasse": 1,
  "dagenSindsIndiening": 1,
  "geometry": null,
  "geometryCenterLat": 50.872046,
  "geometryCenterLon": 4.461038,
  "bron": "vlaamse-overheid-mercatornet-wfs",
  "opgehaaldOp": "2026-09-25T12:00:00.000Z",
  "changeType": "snapshot"
}
```

`datumHuidigeStatus` is the source status date, not a guaranteed decision date. `geometryCenterLat/Lon` is the bounding-box centre; `geometryMode=full` adds the complete WGS84 GeoJSON geometry.

### Use cases

- **B2B lead generation:** contractors, architects, installers and advisers follow new construction, renovation and industrial environmental projects.
- **Area monitoring:** filter with `bbox` on a region, port, business campus or development area without processing every Flemish dossier.
- **CRM updates:** schedule weekly `changes_only` runs and receive only new or changed dossiers.
- **IIOA monitoring:** fetch installations and filter the results client-side on class 1, 2 or 3, procedural phase and installation number.

### Pricing

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

- **Actor Start:** $0.00005;
- **`permit-lead`:** $0.005 per delivered snapshot record;
- **`permit-change`:** $0.01 per new, content-changed or status-changed record.

Duplicate source features, summaries and records that are not written cost nothing. `maxResults: 10` with two layers returns 20 records: about $0.10 in `full_snapshot` or $0.20 in `changes_only`, plus $0.00005 Actor Start. Check `completedLayers`, `incompleteLayers`, `layerResults` and `snapshotCommitted` in RUN\_SUMMARY.

### Legal

- **Source:** official Flemish open data from Departement Omgeving, served through the MercatorNet Public Download Service.
- **Licence/attribution:** Flemish Government open data under the model licence for free reuse (Modellicentie voor gratis hergebruik v1.0) — reuse and commercial exploitation are permitted, with attribution as the only condition. Attribution: `Bron: Vlaamse Overheid — MercatorNet Publieke Download Service`.
- **Privacy:** `aanvrager` and `exploitant` are never exported. Only the derived boolean `bedrijfssignaalAanwezig` can be delivered; the privacy setting therefore stays conservative.
- **Independence:** this Actor is not affiliated with or endorsed by the Flemish Government.
- **Use:** the data is a source indicator, not legal or financial advice. Always verify decisions in the official Omgevingsloket.

### FAQ

**Q: Are subdivision permits (verkavelingen) included as well?**
A: No. Project type codes containing `VK` are excluded. Use the separate [Flanders Subdivision Permit Monitor](https://apify.com/CodeClouds/be-verkavelingsvergunningen) Actor for those.

**Q: What is the difference from `be-verkavelingsvergunningen`?**
A: That Actor specialises in all subdivision permits and amendments. This Actor delivers the broader GD and IIOA feed without that specialised production.

**Q: Is `bevoegdeOverheid` the same as municipality or province?**
A: No. It is the authority handling the dossier. Use `bbox` for a geographic area filter.

**Q: What does `changes_only` do on the first run?**
A: Without a previous snapshot for the same monitor configuration, recent status updates are delivered as new. Afterwards new status-date values suffice; the current status filter is not applied, so transitions to `Vergunning` or `Weigering` stay visible.

**Q: Can a change fall outside the window?**
A: Content corrections without a change of `datum_huidige_toestand` cannot be detected reliably through this WFS feed; that requires a full scan. If `maxResults` truncates a layer, the next run does not restart from the beginning but resumes from the stored keyset cursor. The per-layer watermark is only raised once the scan is complete.

**Q: Can two runs use the same monitor at the same time?**
A: No. Avoid overlapping runs for the same filter configuration. Different monitor configurations have separate snapshot keys, but concurrent writes to the same key can overwrite each other.

**Q: What does `bedrijfssignaalAanwezig` mean?**
A: Only that the source contains a 9/10-digit KBO-like number in `aanvrager` or `exploitant`. The name, the number and other identifiers are not exported.

### Related Actors

- **[Flanders Subdivision Permit Monitor](https://apify.com/CodeClouds/be-verkavelingsvergunningen)** — specialised feed for Flemish subdivision permits and amendments.
- **[NL Vergunningen & Bekendmakingen Leadfeed](https://apify.com/codeclouds/nl-vergunningen-leadfeed)** — Dutch counterpart for combined Dutch permit and announcement leads.

*Zoekwoorden: omgevingsvergunning Vlaanderen, omgevingsvergunningen Vlaanderen, Omgevingsloket, stedenbouwkundige vergunning, stedenbouwkundige aanvraag, IIOA, ingedeelde installaties, industriële vergunning, Vlaamse overheid, Vlaamse bedrijfsvergunning, vergunningenmonitor, leadgeneration Vlaanderen, omgevingsaanvraag, melding omgevingsproject, MercatorNet, GeoJSON.*

### Keywords

flanders, vlaanderen, belgium, environmental permit, omgevingsvergunning, omgevingsloket, urban planning, stedenbouwkundige vergunning, iioa, industrial permit, permit monitor, lead generation, mercatornet, open data, wfs, geojson

### Changelog

#### 0.1.0

- Initial release with GD/IIOA coverage, filters, WGS84 geometry and privacy-safe status-date monitoring.

# Actor input Schema

## `mode` (type: `string`):

full\_snapshot levert alle gefilterde projecten. changes\_only gebruikt datum\_huidige\_toestand, een monitor-specifieke snapshot en levert alleen nieuwe, gewijzigde of statusgewijzigde projecten. Als maxResults een scan afkapt, hervat de volgende run automatisch bij de keysetcursor.

## `layers` (type: `array`):

Selecteer gd voor stedenbouwkundige projecten en iioa voor ingedeelde installaties en activiteiten. Verkavelingen zitten bewust niet in deze actor.

## `recordTypes` (type: `array`):

Selecteer application voor aanvragen, notification voor meldingen, amendment voor bijstellingen, transfer voor overdrachten of all voor alle types behalve de permanent uitgesloten VK-verkavelingscodes. Standaard worden alleen aanvragen opgehaald.

## `statuses` (type: `array`):

Vrije bronstatussen uit huidige\_toestand voor full\_snapshot. Standaard worden open dossiers gebruikt; leeg betekent alle statussen. Dit filter wordt bewust genegeerd in changes\_only zodat een dossier dat van open naar Vergunning of Weigering gaat niet wordt gemist.

## `authorityContains` (type: `string`):

Optionele substring-filter op vvo\_huidige\_toestand, bijvoorbeeld Gent, Turnhout of Provincie Limburg. Dit is de bevoegde overheid en niet noodzakelijk de geografische gemeente.

## `companySignalOnly` (type: `boolean`):

Als aan, worden alleen projecten behouden waarvan aanvrager of exploitant een 9/10-cijferig KBO-achtig nummer bevat. De actor exporteert geen namen, nummers of ruwe persoonsgegevens.

## `lookbackDays` (type: `number`):

Voor full\_snapshot zoekt de actor standaard 30 dagen terug in datum\_indiening. Voor de eerste changes\_only-run is dit 30 dagen terug in datum\_huidige\_toestand.

## `submissionFrom` (type: `string`):

Optionele absolute YYYY-MM-DD-startdatum. In full\_snapshot filtert dit op datum\_indiening; in changes\_only op datum\_huidige\_toestand. Deze datum heeft voorrang op lookbackDays en de vorige watermark.

## `submissionTo` (type: `string`):

Optionele absolute YYYY-MM-DD-einddatum, bijvoorbeeld 2026-09-30.

## `projectNumbers` (type: `array`):

Optionele lijst met numerieke projectnummers, bijvoorbeeld \["2026088373", "2026100049"]. Leeg laten haalt alle nummers binnen de overige filters op.

## `bbox` (type: `object`):

Optionele WGS84-bounding box in decimale graden om alleen projecten binnen een gebied op te halen.

## `geometryMode` (type: `string`):

none levert geen geometrie, centroid alleen een afgeleid middelpunt en full de volledige WGS84 GeoJSON-contour plus middelpunt.

## `overlapDays` (type: `number`):

Bij changes\_only wordt vanaf de laatste volledig afgeronde scan per bronlaag standaard twee dagen opnieuw op de statusdatum bekeken. Een eerste run zonder scanstart gebruikt lookbackDays.

## `maxResults` (type: `number`):

Maximum aantal geleverde records per geselecteerde bronlaag. Als de limiet voor het einde van de WFS-scan wordt bereikt, blijft een monitor-specifieke keysetcursor staan en verwerkt de volgende run de resterende backlog.

## `includeSummary` (type: `boolean`):

Voegt één gratis dataset-item toe met aantallen per laag, projectsoort, status, overheid en bedrijfssignaal.

## Actor input object example

```json
{
  "mode": "full_snapshot",
  "layers": [
    "gd",
    "iioa"
  ],
  "recordTypes": [
    "application"
  ],
  "statuses": [
    "Geen beslissing genomen",
    "In behandeling (in eerste aanleg)",
    "In behandeling (na beroep)"
  ],
  "companySignalOnly": false,
  "lookbackDays": 30,
  "geometryMode": "centroid",
  "overlapDays": 2,
  "maxResults": 100,
  "includeSummary": false
}
```

# Actor output Schema

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

Flemish urban-planning and IIOA permit project records in the 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 = {
    "layers": [
        "gd",
        "iioa"
    ],
    "recordTypes": [
        "application"
    ],
    "statuses": [
        "Geen beslissing genomen",
        "In behandeling (in eerste aanleg)",
        "In behandeling (na beroep)"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("codeclouds/be-flemish-permit-leads").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 = {
    "layers": [
        "gd",
        "iioa",
    ],
    "recordTypes": ["application"],
    "statuses": [
        "Geen beslissing genomen",
        "In behandeling (in eerste aanleg)",
        "In behandeling (na beroep)",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("codeclouds/be-flemish-permit-leads").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 '{
  "layers": [
    "gd",
    "iioa"
  ],
  "recordTypes": [
    "application"
  ],
  "statuses": [
    "Geen beslissing genomen",
    "In behandeling (in eerste aanleg)",
    "In behandeling (na beroep)"
  ]
}' |
apify call codeclouds/be-flemish-permit-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,codeclouds/be-flemish-permit-leads"
        }
    }
}
```

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/XcU9bx6FTUGT6Mepc/builds/4VlaPrQHqr4X94dTm/openapi.json
