The German law API

Every federal statute and hundreds of thousands of court decisions, as clean JSON. Full-text search, semantic case search, norm lookup and citation resolution. No key, no sign-up, open CORS. Built and run by Nulegal GmbH.

Quick start

Every endpoint is a plain GET that returns JSON. Try it in your terminal:

curl
curl "https://recht.nulegal.eu/v1/search?q=k%C3%BCndigung&limit=3"

Basics

API basics
Base URLhttps://recht.nulegal.eu
AuthNone. No key or token required.
FormatJSON (UTF-8). Query strings must be URL-encoded.
CORSOpen (*) for GET, POST, OPTIONS. Call it directly from the browser.
CachingResponses send Cache-Control: public, max-age=3600. Please cache on your side.
Personal dataNot permitted. Do not include names, case facts or other personal data in queries or request bodies, including /v1/resolve. Requests are logged. See the Terms of Use.

Full-text search

GET/v1/search

Search across all federal statutes. Ranks by relevance, pins curated matches for common terms and returns a plain-text snippet for each hit.

Full-text search parameters
ParameterTypeDescription
qstring, requiredSearch term. Minimum 2 characters. Accepts a keyword (kündigung), a citation (§ 823 BGB) or a natural-language question.
limitintegerNumber of results, 1 to 100. Default 20.
repealedbooleanInclude norms of repealed statutes, matched against their last known text. Default false: search returns law in force. Results are additive — everything the default search returns is still there, ranked among the repealed matches. Repealed provisions stay addressable at their own URL regardless of this parameter, and /v1/norm resolves them (and ?asof= versions) unconditionally.
mstringSearch mode: auto (default), fast or deep.

Example

curl
curl "https://recht.nulegal.eu/v1/search?q=k%C3%BCndigung&limit=2"
JavaScript
const r = await fetch(
  "https://recht.nulegal.eu/v1/search?q=" + encodeURIComponent("kündigung") + "&limit=2"
);
const { results } = await r.json();
console.log(results[0].ref, results[0].jurabk, results[0].url);
Response
{
  "query": "kündigung",
  "results": [
    {
      "jurabk": "KSchG",
      "slug": "kschg",
      "ref": "§ 1",
      "ref_norm": "1",
      "heading": "Sozial ungerechtfertigte Kündigungen",
      "rank": 0.48,
      "snippet": "Kündigung des Arbeitsverhältnisses gegenüber einem …",
      "law_url": "KSchG",
      "url": "https://recht.nulegal.eu/gesetze/KSchG/1"
    }
  ]
}

Curated pages

Some questions no single statute answers. “Wie viel Schmerzensgeld nach einem Unfall?” is one: § 253 BGB grants a “billige Entschädigung in Geld” and names no amount. For those queries the response carries an extra pages array next to results — curated pages on this site that do answer the question, each with the figures it shows, so you can answer without a second request. results is unaffected, and pages is absent for the vast majority of queries, so existing clients need no change. Every entry carries "type": "page", which is how you tell one apart from a norm hit if you merge the two lists.

Response
{
  "query": "schmerzensgeld nach unfall wie viel",
  "results": [ … ],
  "pages": [
    {
      "type": "page",
      "kind": "schmerzensgeldtabelle",
      "title": "Schmerzensgeldtabelle: Verkehrsunfall",
      "url": "https://recht.nulegal.eu/schmerzensgeldtabelle?kontext=verkehrsunfall",
      "description": "199 Entscheidungen deutscher Gerichte mit zugesprochenem Schmerzensgeld (Verkehrsunfall): Median 4.500 €, Spanne …",
      "stats": { "n": 199, "median_eur": 4500.0, "min_eur": 100.0, "max_eur": 500000.0 },
      "updated": "2026-07-27"
    }
  ]
}
Fields of a curated page match
FieldTypeDescription
typestringAlways page.
kindstringStable identifier of the page family, e.g. schmerzensgeldtabelle. New kinds may be added over time; treat an unknown kind as a generic page.
titlestringDisplay title, German, including the selected facet.
urlstringAbsolute URL, same convention as results[].url.
descriptionstringOne paragraph answering the query, with the figures the page shows.
statsobject, optionalMachine-readable version of those figures. Keys depend on kind.
updatedstring, optionalISO date the underlying data was last built.

The same match drives the hint shown above the results on /suche, so the website and the API never disagree about which page answers a query.

Case-law search

GET/v1/case-search

Semantic search over court decisions. A natural-language question in, decisions out. Hits carry the best-matching paragraph number (rn) and a snippet.

Case-law search parameters
ParameterTypeDescription
qstring, requiredQuestion or keyword. Minimum 2 characters.
limitintegerNumber of results, 1 to 20. Default 10.

Example

curl
curl "https://recht.nulegal.eu/v1/case-search?q=wann%20darf%20mein%20chef%20mir%20k%C3%BCndigen&limit=2"
Response
{
  "query": "wann darf mein chef mir kündigen",
  "results": [
    {
      "court": "BAG",
      "decided": "2011-11-24",
      "aktenzeichen": "2 AZR 429/10",
      "doktyp": "Urteil",
      "rn": null,
      "snippet": "Kündigung noch nach Fristablauf wirksam …",
      "source": "rii",
      "url": "https://recht.nulegal.eu/rechtsprechung/bag/2011-11-24/2-azr-429-10"
    }
  ]
}

When a result comes from an Open-Database-Licence source, the response adds an attribution array. If present, show it alongside the results.

More endpoints

The same API also resolves single norms and citations:

More endpoints
EndpointDescription
GET /v1/norm/{law}/{ref}One norm with full text and version metadata. Optional ?asof=YYYY-MM-DD for a historical version.
GET /v1/preview/{law}/{ref}One norm as a short snippet. Powers the citation badge preview.
GET /v1/law/{law}A law with its table of norms.
GET /v1/case/{doknr|ecli}One decision by juris document number or ECLI, with its cited norms.
GET /v1/norm/{law}/{ref}/citing-casesFederal decisions that cite a given norm.
GET /v1/suggest?q=Typeahead suggestions for laws and norms.
POST /v1/resolveResolve up to 100 raw citation strings to structured norms.

A repealed statute, or a provision that was removed from one, has no text in force. /v1/norm, /v1/preview and /v1/resolve then answer with the last known text rather than an empty one, and label it: status is repealed or in_force (the law's own status, as /v1/law reports it), text_status is current or historical, and version.valid_to carries the date the text stopped being observed. Treat text_status: "historical" as "this is not the law in force today". ?asof= is unaffected: a date after the repeal still answers a 404, because nothing applied then.

An interactive reference with every parameter is at /docs (OpenAPI).

Link to a decision (permalinks)

Want to link to a court decision from your site, newsletter or app without knowing our URLs? Build a link from what a citation already gives you — court, date, docket number (Aktenzeichen). A unique match answers with a 301 redirect to the decision page; if several decisions share the docket number you get a small picker page; if we do not have the decision you get a 404 with pointers to external sources.

Decision permalink endpoints
EndpointDescription
GET /finde?gericht=&datum=&az=Resolver with three optional parts. gericht takes full names or common abbreviations (BGH, OLG Köln, VG Berlin, EuGH), any casing. datum takes 2023-06-26 or 26.06.2023. az is the docket number, any of the German or European formats. Give as much as you have — the docket number alone is often enough. Try it: a worked example.
GET /az/{aktenzeichen}Short form when the docket number is all you have, e.g. /az/VI ZR 496/15 or /az/C-311/18.
GET /rechtsprechung/bverfge/{band}-{seite}Resolve a BVerfGE citation from the court’s amtliche Sammlung: /rechtsprechung/bverfge/30-173 for BVerfGE 30, 173. The pin-cite form works too (/rechtsprechung/bverfge/30-173-177 for “BVerfGE 30, 173 (177)”) and redirects to the canonical address first. Where the Sammlung prints more than one decision at a page, the citation gets a picker page instead of a guessed redirect.

Example

curl
curl -I "https://recht.nulegal.eu/finde?gericht=BGH&datum=26.06.2023&az=VIa%20ZR%20335%2F21"
# HTTP/1.1 301 Moved Permanently
# location: /rechtsprechung/bgh/2023-06-26/via-zr-335-21

These are HTML endpoints meant for links, not JSON. All of them are stable: a link that resolves today keeps resolving.

Deep links to a Randnummer or Absatz

Decision pages carry a permanent anchor per paragraph (Randnummer): append #rd_N to the decision URL. Norm pages carry one per numbered subsection (Absatz): append #abs-N to the norm URL. The page highlights the targeted passage and shows its permalink right there, ready to copy.

URL
https://recht.nulegal.eu/rechtsprechung/bgh/2023-06-26/via-zr-335-21#rd_13
https://recht.nulegal.eu/gesetze/BGB/823#abs-2

Both fragment formats are permanent, under the same discipline as the resolver endpoints above. Decision texts are immutable, so a #rd_N link keeps pointing at the same passage forever. Norm texts follow the legislature: #abs-N always resolves to paragraph N of the current version, which an amendment may renumber or repeal, so cite the passage in text alongside the link where permanence matters. /v1/case-search already returns the best-matching Randnummer per hit (rn) and a ready deep link in url. The full stability promise, in German, is documented at /vernetzung.

Usage and fair use

Looking to embed citations on your own site instead? See the citation badge — or let Vernetzung link every legal citation in your pages automatically (API, WordPress plugin, or a one-line script tag).