{"slug": "how-to-download-german-federal-court-decisions-bgh-bverfg-bag-as-json-and-for", "title": "How to download German federal court decisions (BGH, BVerfG, BAG) as JSON and Markdown for legal RAG", "summary": "A developer built an Apify actor that converts German federal court decisions from rechtsprechung-im-internet.de into structured JSON and Markdown for legal RAG pipelines. The tool parses the portal's 23.5 MB XML index of 84,835 decisions and per-decision ZIP/XML files into fields such as Leitsatz, Tenor, Tatbestand, Gründe, Normen, Aktenzeichen and ECLI, with filters for court, date range, document type and keywords. A test run on 6 November 2026 returned three decisions in 45 seconds, and the developer recommends chunking along section boundaries while carrying case metadata into every chunk for citation.", "body_md": "If you build anything with German law, such as a legal research tool, a RAG assistant for a law firm or a monitor for new rulings, the best free source is the federal government's open-data portal **rechtsprechung-im-internet.de**. It lists decisions of all federal courts: Bundesgerichtshof (BGH), Bundesverfassungsgericht (BVerfG), Bundesverwaltungsgericht, Bundesfinanzhof, Bundesarbeitsgericht (BAG), Bundessozialgericht and Bundespatentgericht.\n\nThe catch is the format. There is no search API. You get a table of contents as one XML file (about **23.5 MB, 84,835 decisions** when I fetched it on 5 November 2026) and, for each decision, a ZIP file containing an XML document in the court's own schema.\n\nThis guide shows how to turn that into clean JSON you can filter, store and embed.\n\n*Disclosure: I built the tool used below, [German Federal Court Decisions](https://apify.com/fast_data_asap/german-federal-court-decisions) on Apify. The approach works without it too; the last section shows what it saves you.*\n\nYes. Court decisions are official works under **§ 5 of the German Copyright Act (UrhG)** and are not protected by copyright. The decisions on the portal are already anonymised by the courts. That makes them one of the few large, clean, legally unproblematic text corpora for German-language legal AI.\n\nEach decision XML has structured sections. The ones that matter most:\n\n| Field | German term | What it is | \n|---|---|---|\n| `leitsatz` | Leitsatz | The headnote: the legal rule the court establishes. The most valuable text for retrieval. | \n| `tenor` | Tenor | The operative part: what was decided. | \n| `tatbestand` | Tatbestand | The facts of the case. | \n| `entscheidungsgruende` /`gruende` | Entscheidungsgründe / Gründe | The reasoning. Usually the longest part. | \n| `normen` | Normen | The statutes the decision relies on (e.g. \"§ 280 BGB\"). | \n| `fileNumber` | Aktenzeichen | The case number, e.g. `III ZR 3/26` . | \n| `ecli` | ECLI | The European Case Law Identifier. | \n\nNot every decision has every section. Short procedural decisions (Beschlüsse) often have only a Tenor and Gründe and no Leitsatz.\n\nWith the actor, one HTTP call returns the decisions as JSON:\n\n```\ncurl -X POST \"https://api.apify.com/v2/acts/fast_data_asap~german-federal-court-decisions/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"courts\": [\"BGH\", \"BAG\", \"BVerfG\"],\n    \"lastDays\": 14,\n    \"maxDecisions\": 6,\n    \"includeFullText\": true,\n    \"outputFormat\": \"markdown\"\n  }'\n```\n\nI ran exactly this on 6 November 2026. It took 45 seconds, most of it spent loading the 23 MB index, and returned three decisions published in that window:\n\n| Court | Date | Aktenzeichen | Type | Words | \n|---|---|---|---|---|\n| BGH, 7. Zivilsenat | 2026-10-28 | VII ZB 47/25 | Beschluss | 1,872 | \n| BGH, 1. Zivilsenat | 2026-10-28 | I ZR 91/25 | Beschluss | 357 | \n| BVerfG, 2. Senat | 2026-10-23 | 2 BvR 1421/26 | rejected urgent application | 1,056 | \n\nTwo practical notes:\n\n`ecli`.\nUseful filters: `dateFrom` / `dateTo`, `documentType` (`Urteil` or `Beschluss`), `fileNumber` (e.g. `\"ZR\"` for civil senates) and `keywords`, which search the title and headnote, or with `keywordsInFullText: true` the full text.\n\nLegal text chunks best along its own structure. Don't cut a Leitsatz in half, and keep the case number and court on every chunk so the assistant can cite properly:\n\n``` python\nimport json\n\ndef chunks_for(decision, max_words=350):\n    meta = {\n        \"court\": decision[\"court\"],\n        \"date\": decision[\"decisionDate\"],\n        \"aktenzeichen\": decision[\"fileNumber\"],\n        \"ecli\": decision.get(\"ecli\"),\n        \"normen\": decision.get(\"normen\") or [],\n    }\n    sections = [\n        (\"Leitsatz\", decision.get(\"leitsatz\")),\n        (\"Tenor\", decision.get(\"tenor\")),\n        (\"Tatbestand\", decision.get(\"tatbestand\")),\n        (\"Gründe\", decision.get(\"entscheidungsgruende\") or decision.get(\"gruende\")),\n    ]\n    for name, text in sections:\n        if not text:\n            continue\n        words = text.split()\n        for start in range(0, len(words), max_words):\n            part = \" \".join(words[start:start + max_words])\n            yield {**meta, \"section\": name, \"text\": part}\n\ndecisions = json.load(open(\"decisions.json\"))\nchunks = [c for d in decisions for c in chunks_for(d)]\nprint(len(chunks), \"chunks\")\n```\n\nTwo tips that make a measurable difference in retrieval:\n\n`normen` as metadata.\nA daily schedule with `lastDays: 7` and the courts you care about, plus deduplication on `ecli` in your vector store, keeps the corpus current. For topic alerts, add `keywords` (for example `[\"DSGVO\"]` or `[\"Kündigung\"]`) and send new hits to Slack or e-mail with n8n or Make.\n\nDoing this by hand means downloading and parsing the 23.5 MB index, mapping court names and senates, fetching and unzipping one archive per decision, parsing the court XML schema, converting its formatting to Markdown, and handling the portal's occasional stalls. The actor does all of that, retries stalled downloads, and only charges for decisions it actually returns: **$0.001 per decision**. Failed downloads are free.\n\nThe README has the full field list and more examples: [German Federal Court Decisions on Apify](https://apify.com/fast_data_asap/german-federal-court-decisions).\n\n*Data: rechtsprechung-im-internet.de (Federal Ministry of Justice), fetched 5–6 November 2026. This article is about data access, not legal advice.*", "url": "https://wpnews.pro/news/how-to-download-german-federal-court-decisions-bgh-bverfg-bag-as-json-and-for", "canonical_source": "https://dev.to/fast_data_asap/how-to-download-german-federal-court-decisions-bgh-bverfg-bag-as-json-and-markdown-for-legal-rag-jlp", "published_at": "2026-11-06 12:45:14+00:00", "updated_at": "2026-11-06 12:53:46.950579+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "large-language-models", "ai-products"], "entities": ["Apify", "Bundesgerichtshof", "Bundesverfassungsgericht", "Bundesarbeitsgericht", "rechtsprechung-im-internet.de"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/how-to-download-german-federal-court-decisions-bgh-bverfg-bag-as-json-and-for", "markdown": "https://wpnews.pro/news/how-to-download-german-federal-court-decisions-bgh-bverfg-bag-as-json-and-for.md", "text": "https://wpnews.pro/news/how-to-download-german-federal-court-decisions-bgh-bverfg-bag-as-json-and-for.txt", "jsonld": "https://wpnews.pro/news/how-to-download-german-federal-court-decisions-bgh-bverfg-bag-as-json-and-for.jsonld"}}