# Swiss Building Permits — Baugesuche Schweiz (`alpinedata/swiss-building-permits`) Actor

Daily structured feed of Swiss building permit applications (Baugesuche/Baupublikationen) from the official cantonal gazettes API (amtsblattportal.ch). Applicant, project, location, parcel, objection deadline.

- **URL**: https://apify.com/alpinedata/swiss-building-permits.md
- **Developed by:** [alpine data](https://apify.com/alpinedata) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 18.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## Swiss Building Permits — Baugesuche Schweiz

Structured daily feed of **Swiss building permit applications** (Baugesuche / Baupublikationen / demandes d'autorisation de construire), extracted from the public REST API of [amtsblattportal.ch](https://www.amtsblattportal.ch) — the platform that hosts the official gazettes of a growing number of Swiss cantons. The API's own documentation describes it as freely accessible and designed for productive use; this actor turns it into clean, normalized records.

As of August 2026, this is the only Apify actor for Swiss building permits.

Fuer Zulieferer, Handwerksbetriebe, Geruestbauer, Solar- und Heizungsfirmen: Jedes neue Baugesuch aus den abgedeckten Kantonen als strukturierter Datensatz — mit Bauherr, Vorhaben, Adresse, Parzelle und Einsprachefrist, taeglich per Schedule in CRM, Tabelle oder n8n/Make. Kommerzielle Schweizer Dienste verkaufen dieselben Daten ab CHF 45 pro Monat im Abo.

### What you get per record

| Field | Description | Coverage\* |
|---|---|---|
| `title` | Official publication title | 100% |
| `projectDescription` | What is being built or changed | ~99% |
| `buildingContractor` / `parties` | Applicant / building owner (Bauherr) — company with UID, or person, as officially published | ~96% |
| `projectFramer` | Architect / planner, where published | where published |
| `projectLocation` | Street addresses of the construction site | ZH-family: 100% |
| `parcels` | Cadastre / parcel and building zone | ZH-family: 100% |
| `municipality`, `canton` | BFS municipality id + name, canton code | 100% |
| `publicationDate`, `objectionDeadlineDate` | Publication date, computed objection deadline | deadline: ZH-family 100% |
| `legalRemedy` | Official legal remedy text | where published |
| `pdfUrl`, `xmlUrl` | Official signed PDF + structured XML | 100% |

\*Measured on a 400-record sample across all covered cantons, 2026-08-14. Cantonal schemas differ; fields absent in the official publication stay empty rather than being guessed.

### Use cases

- **Construction suppliers and craftsmen** — see building owners the day their project is published, filtered by canton or municipality.
- **Architects, analysts** — monitor building activity, zones and project types.
- **Automation users (n8n, Make, Zapier)** — schedule daily, push new permits into any tool via the Apify API.

### Input

```json
{
  "cantons": ["ZH", "BE"],
  "dateFrom": "",
  "dateTo": "",
  "maxItems": 1000
}
```

Leave `dateFrom`/`dateTo` empty to get **yesterday and today** — ideal for a daily schedule. Optional `keyword` filter (official API search, `*` wildcard supported).

**Proxy is required and enabled by default.** The gazette API does not accept connections from Apify's address range, so requests are routed through Apify Proxy. Leave the proxy setting untouched unless you supply your own working proxy.

### Output example

```json
{
  "title": "Bauprojekt: Seebacherstrasse 20, Zürich",
  "projectDescription": "Ersatzneubau Wohnhaus ...",
  "buildingContractor": [{ "type": "company", "name": "…", "uid": "CHE-…", "address": { "town": "Muttenz" } }],
  "projectLocation": [{ "street": "Seebacherstrasse", "houseNumber": "20", "zip": "8052", "town": "Zürich" }],
  "parcels": [{ "district": "11", "cadastre": "SE2215", "buildingZone": "W4" }],
  "canton": "ZH",
  "publicationDate": "2026-08-14",
  "objectionDeadlineDate": "2026-09-03",
  "pdfUrl": "https://www.amtsblattportal.ch/api/v1/publications/…/pdf"
}
```

### Coverage — read this before you rely on it

The portal hosts the gazettes of a **subset of cantons**. Building permits currently published there and covered by this actor: **ZH, BE, VS, BL, BS, ZG, SZ, OW, SH, SO, NW, AR, TI**. Cantons with separate gazettes (e.g. AG, SG, LU) are not included yet; the canton selector only offers covered cantons. Volume measured in mid-August 2026: **150–250 permit applications per weekday** across covered cantons.

### Reliability

- Data comes from the official REST API — no fragile HTML scraping.
- A **scheduled daily self-test** checks that a weekday window yields data and that no unknown cantonal rubric codes appeared; failures raise an alert to the maintainer.
- Cost: pure API work, no browser — runs use a fraction of a compute unit, plus the proxy traffic needed to reach the source.

### Legal notes

- This is an **unofficial** tool. It is not a service of the Swiss Confederation, the cantons, or the portal operator. Legally binding is only the signed PDF of each publication — every record links to it.
- Records are delivered **as officially published**, without enrichment. If you process personal data from publications (e.g. private building owners), compliance with data protection law for your use case is your responsibility.
- No completeness guarantee: coverage follows the portal's cantons and the official API's availability.

# Actor input Schema

## `cantons` (type: `array`):

Limit to specific cantons. Only cantons whose official gazette publishes building permits on amtsblattportal.ch are listed — others would return zero results. Empty = all covered cantons.

## `dateFrom` (type: `string`):

Start of the publication date window. Leave empty for 'yesterday' (recommended for daily monitoring).

## `dateTo` (type: `string`):

End of the publication date window. Leave empty for 'today'.

## `keyword` (type: `string`):

Optional keyword searched by the official API in the publication content (supports \* wildcard).

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

Stop after this many permit records.

## `proxyConfiguration` (type: `object`):

Proxy used for all requests. The official gazette API does not accept connections from Apify's address range, so a proxy is required — leave Apify Proxy enabled. Disable only when you supply your own working proxy.

## `includeRawXml` (type: `boolean`):

Attach the full official XML of each publication to the record (field rawXml).

## `subRubricsOverride` (type: `array`):

Advanced: query exactly these sub-rubric codes instead of the built-in curated list of building-permit rubrics.

## `selfTest` (type: `boolean`):

Runs the maintenance self-test (yesterday's window, drift detection, fails loudly on anomalies). Used by the maintainer's daily schedule.

## Actor input object example

```json
{
  "cantons": [],
  "dateFrom": "",
  "dateTo": "",
  "keyword": "",
  "maxItems": 1000,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "includeRawXml": false,
  "subRubricsOverride": [],
  "selfTest": false
}
```

# Actor output Schema

## `permits` (type: `string`):

One record per officially published building permit application

## `runSummary` (type: `string`):

Window, counts, drift alerts of this run

# 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 = {
    "cantons": [],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("alpinedata/swiss-building-permits").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 = {
    "cantons": [],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("alpinedata/swiss-building-permits").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 '{
  "cantons": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call alpinedata/swiss-building-permits --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,alpinedata/swiss-building-permits"
        }
    }
}

```

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/dJM1cMdYFkCxEScMy/builds/b2Tv2hclRk9rRkZKS/openapi.json
