API & MCP

Zwei Zugänge zumselben Datenbestand: eine öffentliche REST-API für eigene Clients und ein MCP-Endpunkt für Agenten und IDE-Tools.

Beta. Basis-URL https://judic.ch — REST unter /api/v2/, MCP unter /mcp.

Für eigene Clients & Integrationen

REST API
GET /api/v2/…

Alle Endpunkte antworten mit JSON. Antwortlisten nutzen daten und meta.

EndpointBeschreibung
/api/v2/entscheideListe mit daten/meta; Query: gericht, von/bis, stichwort, sprache, richter, vorinstanz, sortierung, reihenfolge, versatz.
/api/v2/entscheid/<id>Vollentscheid; Metadaten unter /metadaten.
/api/v2/gesetz/<id>Bundesrecht; Detailpfade /gliederung, /<artikel>/wortlaut, /zitiert-von, /leitentscheide.
/api/v2/kantongesetz/<kanton>/<id>Kantonale Gesetzestexte (derzeit Zürich, Aargau und Schwyz); Keys deutsch (gesetz_id, systematische_nummer).
/api/v2/bbl/<jahr>/<seite>Bundesblatt-Fundstelle(n) zu einem Zitat (z. B. BBl 2013 2683, 2771 f.); Query bis, anfangsseite, volltext, sprache. seite kann jede Seite im Dokument sein, nicht nur die Anfangsseite.
/api/v2/uebersetzenPOST mit text, quell_sprache, ziel_sprache → uebersetzter_text.
/api/v2/statistikBestandsstatistik (entscheide_gesamt, nach_gericht, …).
/api/v2/openapi.jsonOpenAPI 3 Spezifikation (auch /api/v2/openapi.yaml).

Beispiel-Anfragen

GET https://judic.ch/api/v2/entscheide?gericht=bger&limit=5&sortierung=publikationsdatum&reihenfolge=absteigend
GET https://judic.ch/api/v2/entscheid/bger_8C_388_2024/metadaten
GET https://judic.ch/api/v2/gesetz/311.0/9/zitiert-von?limit=20
GET https://judic.ch/api/v2/bbl/2013/2771?bis=2772
GET https://judic.ch/api/v2/openapi.json

Caching

Antworten enthalten Cache-Control-Header, die Clients und Proxies das Zwischenspeichern erlauben:

EndpointCache-Control
/api/v2/entscheide (Homepage-Default: gericht=bger, limit 10/25/50, versatz=0, sortierung=publikationsdatum, reihenfolge=absteigend, ungefiltert)public, max-age<=3600; Server-Cache bis kurz nach dem nächsten BGer-Publikationsfenster
/api/v2/entscheide (gefiltert mit stichwort, sachgebiet, erledigung oder vorinstanz)public, max-age=600 (10 Minuten)
/api/v2/entscheide (sonstige Listenabfragen, inkl. ungefiltertes gericht=bger mit anderem limit)public, max-age=120 (2 Minuten)
/api/v2/vorinstanzenpublic, max-age=600 (10 Minuten)
/api/v2/entscheid/<entscheid_id>public, max-age=3600 (1 Stunde)
/api/v2/entscheid/<entscheid_id>/metadatenpublic, max-age=3600 (1 Stunde)
/api/v2/statistikpublic, max-age=300 (5 Minuten)

GET /api/v2/gesetz/<identifier>

Übersicht zu einem Bundeserlass. identifier ist eine SR-Nummer (z. B. 311.0) oder eine bekannte Abkürzung aus fedlex_mapping.json (z. B. StGB).

Detailendpunkte: /gliederung?sprache=de, /<artikel>, /<artikel>/wortlaut?sprache=de, /<artikel>/zitiert-von, /<artikel>/materialien, /<artikel>/kommentar, /<artikel>/historie und /<artikel>/leitentscheide. sprache akzeptiert de, fr oder it.
EndpointBeschreibung
/api/v2/gesetz/311.0Metadaten, Fedlex-URLs und meistzitierte Artikel.
/api/v2/gesetz/311.0/gliederung?sprache=deGliederung aus lokalem Fedlex-XML; Fallback auf OpenCaseLaw-Artikelliste.
/api/v2/gesetz/311.0/9/wortlaut?sprache=deArtikelwortlaut aus Fedlex-Akoma-Ntoso; Fallback auf OpenCaseLaw.
/api/v2/gesetz/311.0/9/zitiert-von?limit=20&versatz=0Entscheide, die den Artikel zitieren; gespeist aus decision_law_refs.

Beispiel-Anfragen

GET https://judic.ch/api/v2/gesetz/311.0
GET https://judic.ch/api/v2/gesetz/StGB/9/wortlaut?sprache=de
GET https://judic.ch/api/v2/gesetz/311.0/9/zitiert-von?limit=20&sortierung=publikationsdatum&reihenfolge=absteigend

GET /api/v2/kantongesetz/<kanton>/<gesetz_id>

Übersicht zu einem kantonalen Gesetzestext. Derzeit Zürich (ZH, ZH-Lex), Aargau (AG, LexWork) und Schwyz (SZ, SRSZ). gesetz_id ist ein Kürzel wie GOG/KV oder die systematische Nummer. Fehlt der Text lokal, wird er on-demand geholt.

Detailendpunkte: /kopf, /gliederung?sprache=de, /<artikel> und /<artikel>/wortlaut?sprache=de. Reader: /gesetz/ZH/GOG, /gesetz/AG/KV, /gesetz/SZ/KV. Suche: GOG/ZH, KV/AG, KV/SZ.
EndpointBeschreibung
/api/v2/kantongesetz/ZH/GOGMetadaten, Quelle, Artikelanzahl und kanonisches Kürzel.
/api/v2/kantongesetz/ZH/GOG/kopfTitel- und Versionskopf für den Gesetzesreader.
/api/v2/kantongesetz/ZH/GOG/gliederung?sprache=deGliederung aus der gecachten JSON-Datei.
/api/v2/kantongesetz/ZH/GOG/3/wortlaut?sprache=deArtikelwortlaut inklusive Absätzen und Fussnoten.

Beispiel-Anfragen

GET https://judic.ch/api/v2/kantongesetz/ZH/GOG
GET https://judic.ch/api/v2/kantongesetz/AG/KV/gliederung?sprache=de
GET https://judic.ch/api/v2/kantongesetz/SZ/100.100/1/wortlaut?sprache=de

GET /api/v2/bbl/<jahr>/<seite>

Fundstelle(n) zu einem Bundesblatt-Zitat, z. B. BBl 2013 2683, 2771 f. → /api/v2/bbl/2013/2771?bis=2772. seite darf jede Seite innerhalb eines Dokuments sein, nicht nur dessen Anfangsseite — das umschliessende Dokument wird automatisch über die offiziellen Fedlex-Metadaten gefunden (die gedruckte Seitenzahl ist keine eli-Sequenznummer). Ohne volltext=true liefert die Antwort nur die angefragte(n) Seite(n), nicht das ganze, oft sehr lange Dokument.

sprache akzeptiert de (Standard), fr oder it — die Seitenzahl ist je Sprachfassung eigenständig gezählt. Ergebnisse sind dateibasiert gecacht (amtliche Publikationen ändern sich nicht nachträglich).
ParameterTypStandardBeschreibung
jahrInteger (Pfad)—Jahrgang des Zitats, z. B. 2013
seiteInteger (Pfad)—zitierte Seite, z. B. 2683 (beliebige Seite im Dokument)
bisIntegerseiteletzte Seite des Bereichs (inklusive), max. 10 Seiten ab seite
anfangsseiteInteger—Prüfung gegen die zitierte Dokument-Anfangsseite → anfangsseite_passt in der Antwort
volltextBooleanfalsetrue liefert das ganze Dokument (text + seiten als Objekt) statt nur der angefragten Seite(n)
spracheDE/FR/ITdeSprachfassung; eigene Seitenzählung pro Sprache

Beispiel-Anfragen

GET https://judic.ch/api/v2/bbl/2013/2771?bis=2772
GET https://judic.ch/api/v2/bbl/2006/1253
GET https://judic.ch/api/v2/bbl/2013/2683?volltext=true

GET /api/v2/entscheide

Paginierte Liste der Entscheide, filterbar nach Gericht, Sachgebiet, Themen/Abteilung, Erledigung, Veröffentlichungsdatum und Vorinstanz.

ParameterTypStandardBeschreibung
limitInteger20Einträge pro Seite (max. 500)
versatzInteger0Offset für Paginierung
vonYYYY-MM-DD—Publikationsdatum >=
bisYYYY-MM-DD—Publikationsdatum <=
gerichtStringalleEin Gericht oder Kommaliste, z. B. bger,bge,bstger. Die Startseite nutzt standardmässig bger.
sachgebietString—Teilstring-Suche in Sachgebiet, case-insensitiv
erledigungString—Mehrfach möglich (z. B. Abweisung)
stichwortString—Mehrfach möglich; matcht Sachgebiet, Themen und Abteilung
spracheDE/FR/IT—Mehrfach möglich
richter1/3/5—Mehrfach möglich (Anzahl Richter)
vorinstanzString—Mehrfach möglich als Gericht|Kammer. Ohne Kammer (Gericht| oder nur Gericht) werden nur Rows ohne Kammerangabe gematcht.
sortierungStringpublikationsdatumpublikationsdatum, entscheiddatum, geschaeftsnummer, erledigung oder sachgebiet
reihenfolgeStringabsteigendabsteigend oder aufsteigend
publikationsdatum ist das Listendatum: publication_date, sonst Datum aus scraped_at, sonst entscheiddatum. meta.gesamt kann bei einem kalten Cache kurzzeitig null sein, während der COUNT im Hintergrund berechnet wird (meta.zaehlung_ausstehend).

Beispiel-Anfragen

GET https://judic.ch/api/v2/entscheide?limit=5
GET https://judic.ch/api/v2/entscheide?sachgebiet=strafrecht&erledigung=Abweisung&limit=10
GET https://judic.ch/api/v2/entscheide?von=2025-01-01&bis=2025-03-31&versatz=20
GET https://judic.ch/api/v2/entscheide?sprache=DE&sprache=FR&richter=5
GET https://judic.ch/api/v2/entscheide?gericht=bger&vorinstanz=Obergericht%20des%20Kantons%20Z%C3%BCrich%7CIII.%20Strafkammer
GET https://judic.ch/api/v2/entscheide?gericht=bger,bge&stichwort=strafprozess&sortierung=erledigung&reihenfolge=aufsteigend

Antwort-Struktur

{
  "daten": [
    {
      "referenz": "8C_388/2024",
      "entscheid_id": "bger_8C_388_2024",
      "entscheiddatum": "2024-11-15",
      "publikationsdatum": "2025-01-08",
      "sachgebiet": "Öffentliches Recht",
      "themen": "Sozialversicherung; AHV; Beiträge",
      "erledigung": "Abweisung",
      "sprache": "DE",
      "anzahl_richter": 3,
      "gericht": "bger",
      "ist_bge": false,
      "ist_bge_geplant": false,
      "vorinstanz_gericht": "Sozialversicherungsgericht des Kantons Zürich",
      "vorinstanz_kammer": null,
      "titel": null,
      "api_url": "/api/v2/entscheid/bger_8C_388_2024",
      "viewer_url": "/entscheid/bger_8C_388_2024"
    }
  ],
  "meta": {
    "gesamt": 1842,
    "limit": 5,
    "versatz": 0,
    "geliefert": 5,
    "zaehlung_ausstehend": false
  }
}

GET /api/v2/vorinstanzen

Liefert die häufigsten Vorinstanz-Gericht/Kammer-Kombinationen für Filter-UIs.

ParameterTypStandardBeschreibung
gerichtStringbgerEin Gericht oder Kommaliste, z. B. bger,bge
limitInteger80Maximal 200 Einträge
min_anzahlInteger1Nur Kombinationen mit mindestens so vielen Entscheiden
Gerichtsnamen werden nominativ gruppiert. Das Feld vorinstanz kann direkt als Query-Parameter für /api/v2/entscheide verwendet werden.

Beispiel-Anfrage

GET https://judic.ch/api/v2/vorinstanzen?gericht=bger&limit=80&min_anzahl=2

Antwort

{
  "daten": [
    {
      "gericht": "Obergericht des Kantons Zürich",
      "kammer": "III. Strafkammer",
      "anzahl": 128,
      "vorinstanz": "Obergericht des Kantons Zürich|III. Strafkammer"
    },
    {
      "gericht": "Sozialversicherungsgericht des Kantons Zürich",
      "kammer": null,
      "anzahl": 96,
      "vorinstanz": "Sozialversicherungsgericht des Kantons Zürich|"
    }
  ]
}

GET /api/v2/entscheid/<entscheid_id>

Vollständiges strukturiertes JSON eines einzelnen Entscheids: Metadaten, Besetzung, Vorinstanz, Regesten und der strukturierte Entscheidstext.

Referenz-Format — Präfix + normalisierte Referenz:
BGer: 1C_195/2026 → bger_1C_195_2026
BGE: 150 IV 462 → bge_150_iv_462
BStGer: SK.2025.23 → bstger_SK.2025.23 (Punkte bleiben erhalten)

Beispiel-Anfrage

GET https://judic.ch/api/v2/entscheid/bger_8C_388_2024

Antwort-Struktur (gekürzt)

{
  "entscheid_id": "bger_8C_388_2024",
  "referenz": "8C_388/2024",
  "meta": {
    "referenz": "8C_388/2024",
    "datum": "2024-11-15",
    "sprache": "DE",
    "abteilung": "I. sozialrechtliche Abteilung",
    "gegenstand": "AHV (Beiträge)",
    "erledigung": "Abweisung",
    "anzahl_richter": 3
  },
  "sachverhalt": { "abschnitte": [ ... ] },
  "erwaegungen": { "abschnitte": [ ... ] },
  "dispositiv": { "raw": "...", "punkte": [ ... ] },
  "referenzen": {
    "bge_zitiert": [{ "referenz": "141 III 433", "url": "...", "existiert": true }],
    "bger_zitiert": [{ "referenz": "8C_100/2023", "existiert": true }],
    "bstger_zitiert": [{ "referenz": "SK.2025.23", "existiert": true }],
    "gesetze": [{ "text": "Art. 42 BGG", "url": "..." }]
  }
}

existiert markiert Referenzen, deren docket_number in der lokalen DB vorkommt — der Viewer nutzt das für klickbare Links.


GET /api/v2/entscheid/<entscheid_id>/metadaten

Gleiche Struktur wie /api/v2/entscheid/<entscheid_id>, aber ohne Volltext (abschnitte). Ideal für Listen und Vorschauen.

Beispiel-Anfrage

GET https://judic.ch/api/v2/entscheid/bger_8C_388_2024/metadaten

GET /api/v2/statistik

Statistiken über den Datenbankbestand: Gesamtanzahl Entscheide, Anzahl mit vollständigem Text, Datumsbereich und letzte Veröffentlichung.

Beispiel-Anfrage

GET https://judic.ch/api/v2/statistik

Antwort

{
  "entscheide_gesamt": 18420,
  "mit_volltext": 3241,
  "entscheiddatum_bereich": {
    "fruehestes": "2000-01-15",
    "spaetestes": "2026-04-17"
  },
  "neuestes_publikationsdatum": "2026-04-19",
  "nach_gericht": { "bger": 15000, "bge": 2800, "bstger": 620 },
  "gesetze_durchsuchbar": 412
}

GET /api/v2/taxonomie

Liefert die Rechtsgebiets-Taxonomie für Filter-UIs. Jeder Eintrag enthält eine Gruppe, Filter-IDs, Labels und Match-Keywords.

Beispiel-Anfrage

GET https://judic.ch/api/v2/taxonomie

GET /api/v2/letzte-aktualisierung

Meldet den letzten erfolgreichen Pipeline-Lauf und die heute hinzugekommenen Entscheide pro Gericht.

Antwort

{
  "letzte_aktualisierung": "2026-07-13T13:18:42",
  "letzte_aktualisierung_quelle": "BGer-Neuheiten-Scraper",
  "heute_hinzugefuegt": {
    "bger": 42
  }
}

Best Practices

  • Paginierung nutzen: Für grosse Datenmengen immer mit limit/versatz arbeiten und Ergebnisse seitenweise abrufen.
  • Server-Caching respektieren: Antworten gemäss Cache-Control im Client oder Proxy cachen, um Last und Latenz zu reduzieren.
  • Metadaten-Endpoint bevorzugen: Für Listenansichten /metadaten statt Volltext-Endpunkt verwenden.
  • Referenzen normalisieren: In Pfaden immer / und Leerzeichen durch _ ersetzen.
  • Gesetzesartikel klein halten: Artikel in Gesetzespfaden klein schreiben, z. B. /gesetz/311.0/269quater.

curl Beispiele

curl "https://judic.ch/api/v2/entscheide?limit=25&versatz=0"
curl "https://judic.ch/api/v2/entscheide?von=2026-01-01&erledigung=Abweisung&sprache=DE"
curl "https://judic.ch/api/v2/entscheid/bger_8C_388_2024/metadaten"

fetch Beispiel (Browser/Node)

const res = await fetch("https://judic.ch/api/v2/entscheide?limit=10");
if (!res.ok) {
  throw new Error(`Judic API ${res.status}`);
}
const payload = await res.json();
console.log(payload.meta, payload.daten);

API-Änderungen

Kurzüberblick für Clients, die noch /api/v1/ nutzen. v1 bleibt lauffähig und unverändert; neue Features kommen nur unter /api/v2/.

v1v2
/api/v1/…/api/v2/…
data / meta.total / offset / returneddaten / meta.gesamt / versatz / geliefert
court, from/to, keyword, vigericht, von/bis, stichwort, vorinstanz
sort / order (pub_date, desc)sortierung / reihenfolge (publikationsdatum, absteigend)
ref (Maschinen-ID), referenceentscheid_id, referenz
/metadata, /stats, /taxonomy, /last-update, /translate/metadaten, /statistik, /taxonomie, /letzte-aktualisierung, /uebersetzen
/structure, /cited-by, /leading-cases, /header/gliederung, /zitiert-von, /leitentscheide, /kopf
lang, min_countsprache, min_anzahl

Vollständige Spec: /api/v2/openapi.json. Endpoint-Liste zu v1 steht im Projekt-README.

Für Agenten & IDEs

MCP

Der MCP-Server (Model Context Protocol) macht Entscheide und Gesetzestexte als Tools für Claude, Cursor und andere Clients verfügbar. Er liest dieselbe öffentliche API v2 — ohne eigene Datenbank und ohne Authentifizierung.

GET/POST /mcp

Streamable-HTTP-Endpunkt. Produktive URL: https://judic.ch/mcp.

Client-Konfiguration: {"mcpServers":{"judic":{"url":"https://judic.ch/mcp"}}}

Beispiel-Anfrage

POST https://judic.ch/mcp
Content-Type: application/json
Accept: application/json, text/event-stream

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"demo","version":"1"}}}

Verfügbare Tools

ToolBeschreibung
search_entscheideEntscheide filtern (Datum, Stichwort, Gericht, Vorinstanz, …).
get_entscheid / get_entscheid_metadataVolltext oder nur Metadaten eines Entscheids.
get_gesetz / get_gesetz_structure / get_gesetz_wortlautBundeserlasse: Übersicht, Gliederung, Artikelwortlaut (Fedlex).
get_gesetz_cited_by / get_gesetz_kommentar / …Zitate, Kommentar, Materialien, Historie, Leitentscheide.
get_kantongesetz / get_kantongesetz_gliederung / get_kantongesetz_wortlautKantonale Erlasse ZH/AG/SZ inkl. Paragraphenwortlaut.
get_bblBundesblatt-Fundstelle(n) zu einem Zitat (z. B. BBl 2013 2683, 2771 f.) — findet das Dokument automatisch, auch ab einer Seite mitten im Text.
judic_statsUmfang und Datumsbereich des Datenbestands.

Details und Betrieb: mcp_server/README.md im Repo. REST-Äquivalente stehen im Abschnitt API.