API & Agenten

Eine kostenlose, selbstbediente API für Schweizer Baugesuche — aggregiert aus 14 kantonalen Amtsblatt-Quellen (über die öffentliche amtsblattportal.ch-API), harmonisiert in ein Modell (bgch.v1) und als JSON & XML abrufbar. Aktuell 2'926 Publikationen aus 13 Kantonen / 462 Gemeinden (Stand: 10.07.2026, älteste: 09.06.2026).

Swagger-Docs OpenAPI JSON /meta (Live-Coverage) MCP-Server llms-full.txt llms.txt RSS

Garantie & rechtlicher Hinweis

Auth & Rate-Limits

Zugriff ist ohne Anmeldung möglich. Ein kostenloser Key hebt das Limit an — mehr braucht es nicht.

LimitHeader
Anonym (pro IP)120 Requests / StundeX-RateLimit-Limit, -Remaining, -Reset; bei 429 zusätzlich Retry-After
Mit Key5000 Requests / Stunde

Key mitgeben als HTTP-Header: Authorization: Bearer bg_<key>. Key unten anfordern (Double-Opt-in per E-Mail, wird genau einmal angezeigt).

Quickstart

Startpunkt für Agenten: /llms-full.txt (vollständige Referenz, agent-optimiert) oder /api/docs (Swagger). Alle Beispiele unten funktionieren so wie sie sind (echte Werte).

curl — Liste, Filter, Cursor

# List + filter: energy/heating permits in canton Zürich matching "Wärmepumpe"
curl -s "https://baugesuche.switchli.ch/api/v1/publications?canton=ZH&category=energie_heizung&q=W%C3%A4rmepumpe&limit=5"

# With a free key (5000 req/h instead of 120):
curl -s -H "Authorization: Bearer bg_your_key_here" \
  "https://baugesuche.switchli.ch/api/v1/publications?canton=ZH&limit=5"

# Follow the cursor to the next page: take next_cursor from the response above,
# pass it back as &cursor=... — stable under infinite history (no OFFSET).
curl -s "https://baugesuche.switchli.ch/api/v1/publications?canton=ZH&limit=5&cursor=NEXT_CURSOR_FROM_PREVIOUS_RESPONSE"

# One full record (JSON), incl. links to the official PDF/XML:
curl -s "https://baugesuche.switchli.ch/api/v1/publications/d22d21f6-e361-4655-bd1d-8c2350863cdb"

Python — urllib (no dependencies)

import json
import urllib.parse
import urllib.request

BASE = "https://baugesuche.switchli.ch/api/v1"
# API_KEY = "bg_your_key_here"  # optional: raises the rate limit to 5000/h

def get(path, **params):
    url = f"{BASE}{path}?" + urllib.parse.urlencode({k: v for k, v in params.items() if v})
    req = urllib.request.Request(url, headers={"Accept": "application/json"})
    # req.add_header("Authorization", "Bearer " + API_KEY)  # uncomment with a key
    with urllib.request.urlopen(req, timeout=15) as r:
        return json.load(r)

# Filtered search
page = get("/publications", canton="ZH", category="energie_heizung", q="Wärmepumpe", limit=5)
print(page["total"], "matches")
for item in page["items"]:
    print(item["publication_date"], item["municipality"]["name"], "-", item["title"][:70])

# Paginate every match with the keyset cursor
cursor = ""
while True:
    page = get("/publications", canton="ZH", category="energie_heizung", limit=50, cursor=cursor)
    for item in page["items"]:
        pass  # ... process item (bgch.v1 dict)
    cursor = page["next_cursor"]
    if not cursor:
        break

JavaScript — fetch

const BASE = "https://baugesuche.switchli.ch/api/v1";
// const API_KEY = "bg_your_key_here"; // optional: 5000 req/h

async function search(params) {
  const qs = new URLSearchParams(params).toString();
  const res = await fetch(`${BASE}/publications?${qs}`, {
    headers: {
      "Accept": "application/json",
      // "Authorization": `Bearer ${API_KEY}`, // uncomment with a key
    },
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

const page = await search({ canton: "ZH", category: "energie_heizung", q: "Wärmepumpe", limit: 5 });
console.log(page.total, "matches");
for (const item of page.items) {
  console.log(item.publication_date, item.municipality.name, item.title);
}
// Next page: search({ canton: "ZH", limit: 50, cursor: page.next_cursor })

MCP-Server (für KI-Agenten)

Der differenzierende Teil: ein Model-Context-Protocol-Server über Streamable HTTP unter https://baugesuche.switchli.ch/mcp. Agenten (z. B. Claude) verbinden sich direkt und rufen Tools auf — ohne eigenen API-Client zu schreiben.

ToolZweck
search_baugesucheVolltext-/Filtersuche (Kanton, Kategorie, Gemeinde, Datum) → bgch.v1-Datensätze.
get_baugesuchEin vollständiger Datensatz per ID, inkl. Links zur amtlichen PDF/XML.
get_coverageAbgedeckte Kantone, Zahlen, ältester/neuester Datensatz, Garantie & Hinweis.

Verbindung (Claude Desktop / Agent-Config), stateless — keine Session nötig:

{
  "mcpServers": {
    "baugesuche": {
      "type": "streamable-http",
      "url": "https://baugesuche.switchli.ch/mcp"
    }
  }
}

Roher JSON-RPC-Aufruf über Streamable HTTP (Antwort ist Server-Sent-Events; die JSON-RPC-Nutzlast steht in der data:-Zeile):

curl -s -X POST "https://baugesuche.switchli.ch/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"search_baugesuche",
                 "arguments":{"query":"Wärmepumpe","canton":"ZH","limit":3}}}'

Kostenlosen API-Key anfordern

Optional — nur nötig, wenn 120 Requests/Stunde nicht reichen. Sie erhalten eine Bestätigungs-E-Mail (Double-Opt-in); der Key wird danach genau einmal angezeigt. Wir speichern nur den SHA-256-Hash.

Endpunkte & weiterführende Links

EndpunktZweck
GET /api/v1/metaCoverage, Taxonomie, Zahlen, Schema-/Docs-/MCP-URLs — hier starten.
GET /api/v1/publicationsGefilterte, keyset-paginierte Liste (bgch.v1).
GET /api/v1/publications/{id}Ein Datensatz als JSON (.xml harmonisiert, /original.xml amtliches Passthrough).
GET /api/v1/changes?since=…Inkrementeller Sync über ingested_at für Agenten/Mirrors.
POST /api/v1/keysKostenloser Key (Double-Opt-in per E-Mail).
/api/docsInteraktive Swagger-Dokumentation.
/api/v1/openapi.jsonOpenAPI-3-Schema (Codegen).
/mcpMCP-Server (Streamable HTTP, POST) für Agenten — Details & Beispiel oben.
/llms-full.txtVollständige agent-optimierte Referenz (Plain Text).
/feed.xmlRSS, unterstützt dieselben Filter-Parameter.

Kanton-Codes

ZH Zürich · BE Bern · SZ Schwyz · OW Obwalden · NW Nidwalden · ZG Zug · SO Solothurn · BS Basel-Stadt · BL Basel-Landschaft · SH Schaffhausen · AR Appenzell A.Rh. · TI Tessin · VS Wallis · CH weitere Gemeinden. Abdeckung: ZH ist von Gesetzes wegen vollständig; AG fehlt bewusst (nicht über amtsblattportal.ch publiziert). Live-Zahlen pro Kanton: /api/v1/meta.

Kategorie-Codes (statische Taxonomie, multi-label)

energie_heizung Energie & Heizung · solar_pv Solar & PV · neubau_wohnen Neubau Wohnen · umbau_sanierung Umbau & Sanierung · abbruch Abbruch · kleinbauten Kleinbauten · gewerbe_industrie Gewerbe & Industrie · landwirtschaft Landwirtschaft · aussenanlagen_infrastruktur Aussenanlagen & Infrastruktur · sonstiges Sonstiges.