# Klaracase MCP tool guide

This page is the long half of the Klaracase MCP tool contract. Each tool description (the text `tools/list` sends your client) carries what you need to choose and call a tool: purpose, how it differs from its siblings, arguments with types and limits, refusal codes and credit price. This page explains the answer: what each field means, and what a null, absent, capped or flagged value claims.

Read the tool description first; it is authoritative for what a tool does and costs. Read this page when you need to interpret a field. There is one section per tool.

A standing rule runs through every section: a flag or a labelled key never claims a payload it does not carry, and a missing field is a statement about our record, never about the decision.

Operator tokens may receive an additional `diagnostics` block; customer tokens do not, and nothing in this guide depends on it.

### The envelope on every answer

Every answer, success or refusal, carries:

- `api_version`: the SemVer of the MCP surface when the payload was built. Re-read it per call; a minor version can change what a field means or what a call costs.
- `changelog_url`: the public changelog, which says what moved between versions.
- `credits`: `{metered, cost, credits_remaining}`. On `metered: true`, `cost` is what this call took (0 for a repeat the tool deduplicated) and `credits_remaining` is the balance after. On `metered: false` both are null: nothing was charged and there is no balance to report. Never read a null as zero.
- `ignored_parameters`: present only when you sent an argument the tool does not declare. It was accepted and ignored; if a filter you sent is named here, the answer is unfiltered on that axis.

### Refusals, rate limit and daily volume cap

A refusal carries a closed `error_code`, a `message` and the envelope. Each section lists its codes. Some malformed arguments are refused in validation prose with no code. `insufficient_credits` means the balance cannot pay for the call.

TOKEN ABILITIES. An API token carries abilities, and each tool needs one: `search` for `search_decisions`, `cross_type_search`, `list_facets` and `corpus_coverage`; `read` for `get_decision`; `graph` for `get_citation_graph`; `datapackage` for `assemble_datapackage`; `citation-check` for `check_citations`. A token without the ability is refused with `error_code: "token_ability_missing"` and `required_ability`, the ability it lacks. Nothing ran and nothing was charged. Create a token with that ability in the web app (Settings, API tokens); a token created there carries every ability unless you narrowed it. A connection made through the OAuth sign-in of an AI client carries every ability.

TOKEN ORGANIZATION AND EXPIRY. A token acts for the organization it was created for, and its calls are charged there. If you leave that organization, the token stops working (HTTP 403, `error_code: "token_org_membership_lost"`). If that organization requires two-factor sign-in of all members and your account has not set it up, every call is refused (HTTP 403, `error_code: "two_factor_required"`) and nothing is charged; the token works again once you set it up in Settings, Two-factor authentication. A token expires after the life chosen when it was created, at most 365 days; an expired token gets HTTP 401.

RATE LIMIT. Per token, 60 requests per minute by default (deployment-configurable). Exceeding it returns a JSON-RPC error with code -32000, HTTP 429 and `data.retry_after_seconds`. Nothing ran and nothing was charged: wait that long and retry. It says nothing about the corpus.

DAILY VOLUME CAP. Metered tools that serve corpus rows or full texts count what they serve to your organization per calendar day. `search_decisions`, `cross_type_search`, `get_citation_graph` and `assemble_datapackage` count in unit `rows`; `get_decision` counts full texts in unit `documents`. At the cap, the tool refuses with `error_code: "volume_cap"` and:

- `unit`: `rows` or `documents`;
- `cap`: your organization's daily cap in that unit, set by your plan;
- `resets_at`: ISO 8601, the next midnight Europe/Berlin;
- `retry_after_seconds`: the wait until `resets_at`.

The check runs before any work: nothing ran and nothing was charged. Wait and retry, or ask your organization admin about a larger plan. It is never a finding about the corpus; never report it as an absence of case law. `check_citations`, `list_facets` and `corpus_coverage` are not volume-governed.

FLOOR BANDS. Counts that reveal corpus size are served as `{value, is_floor}`: below 100 exact, otherwise floored down to at most two significant digits, with `is_floor: true` (12000 means "at least 12,000").

## search_decisions

Hybrid (semantic plus keyword) search over German court decisions. Phrase the query as German legal concepts ("Widerrufsrecht Fernabsatzvertrag Wertersatz Verbraucher"). For how far back each court reaches, call `corpus_coverage`.

### Paging

Up to 20 rows per call. `limit` defaults to 20, which is also the hard cap, so it can only narrow. Reach further rows with `page` (1-based, maximum 10); pages are disjoint and share the query's one charge. A short or empty page means the ranked window ran out, not the corpus. Narrow with filters rather than paging deep.

### How much is there

- `total_available` (floor band): INDEXED PASSAGES matching your query corpus-wide, counted on the LEXICAL ARM ONLY (`total_available_basis: "matching_indexed_passages_lexical_arm"`). It is NOT an upper bound on the rows this response served, and is often smaller: the served list is the UNION of several retrieval arms and only the lexical one is counted, so `total_available: 1` beside thirteen served decisions is no contradiction. Passages, not decisions. `null` in `mode="semantic"` (no lexical arm): "not measurable", never zero. It moves with release-to-release retrieval settings, so never diff it across dates.
- `candidate_pool`: distinct decisions this call ranked and can page through. A per-request window, not a corpus figure: it scales with `limit` (echoed in the response as the limit the search ran with). Compare pools only at a pinned `limit`. It can exceed `total_available`, because the semantic arm adds decisions the lexical count never saw.
- `pool_exhaustive`: true only when the window provably held every match. False means unproven, the usual case.
- `truncated`: false ONLY when `pool_exhaustive` is true AND this page reached the end of the pool. `truncated: false` guarantees nothing matching remains.
- `payload_truncated`: this answer was shortened to fit your client's size budget: snippets, `leitsatz` and `leitsatz_summary` cut to about 300 characters with "…", the scalar `snippet` null (the text is in `snippets[0].text`), lowest-ranked rows possibly dropped. Locators, `cited_norms` and `instanzenzug` are never cut. `guidance` names the remedy (lower `limit` and page at it, narrow, or call `get_decision`).
- `filters_applied`: the filters the search RAN WITH, `{argument: value}`, on every filtered answer; absent when nothing was filtered. It is not an echo: a `cited_norm` naming no instrument is dropped and not listed, and `cited_norm` shows the canonical form used. `filters_applied_sections` names the section each argument narrowed; here always `["decisions"]`.

### Rows and locators

Rows carry `id`, `aktenzeichen`, `court`, `date`, `document_type`, `title`, `fundstelle`, `rn_range`, `rn_source`, `chunk_title`, `snippets` (`{text, rn}`) and the scalar `snippet`, plus the fields below. Any row field may be null or absent; that is a statement about our record, never about the decision. Read a missing field as "not recorded here", never as "none".

- LOCATOR COVERAGE IS PARTIAL. `rn_range` exists only where Randnummern were parsed (often null on older and OCR'd texts); `chunk_title` is a law heading, effectively always null on decisions. Cite `fundstelle` (court, date, Aktenzeichen).
- `title` is a static string listing at most four file numbers; beyond four it lists three plus `u. a. (+N)`. The docket you searched for may hide there. Cite from `get_decision`'s `metadata.file_numbers`.
- A RANDNUMMER IS CITABLE ONLY WHEN `rn_source` SAYS `printed`. Indexed numbers come from publisher anchors, which also count front matter. At serve time they are compared with the number printed in the passage: `printed` (agree), `source_anchor_unverified` (disagree) or `unknown` (nothing printed to check). `rn_range` reads `"Rn. 41-45"` only on `printed` and the bare `"41-45"` otherwise, and `fundstelle` then omits ", Rn. N". The bare numbers still re-fetch the passage through `get_decision`.

### Relevance and order

Each row carries `confidence` (`high`, `medium`, `low`): the band of its relevance to your query as the relevance model, which reads your query and each passage together, measured it. `null` means "not measured on this request", never "low": every row is null in keyword mode (asked for or auto-selected) and when the relevance model was unavailable (rows then keep retrieval order). `top_confidence` bands the best row (null when not measured or empty). A large `total_available` beside a `low` `top_confidence` means much text matches your words and little answers your question.

Neither field reorders anything. Rows arrive in served order, best first: the relevance model's order whenever it ran, otherwise retrieval order. Of two rows whose relevance is practically equal, a narrow court-tier tie-break lets the higher-instance court lead, at any position in the list, on this tool and on `cross_type_search`, under any filter. So never re-sort rows by `confidence`. Exact ties are ordered by `id` so pages stay disjoint; that order means nothing.

### Mode

`mode` in the response names the mode that ran. Unset does not guarantee hybrid: a query that is a precise identifier throughout (a §-citation such as "§ 573 Abs. 2 Nr. 2 BGB", an Aktenzeichen, an ECLI, a bare abbreviation like "BGB") goes to keyword retrieval. "§ 573 BGB Eigenbedarfskündigung" stays hybrid, because it carries a substantive word. Pass `mode="hybrid"` to override.

- KEYWORD MODE REQUIRES EVERY TOKEN, so each extra term narrows the pool (an unknown term is dropped rather than emptying it). Responses say `keyword_mode: "all_terms_required"` and add a `hint` when the pool came back smaller than `limit`; `pool_exhaustive: true` there covers the conjunction only. A query that is a citation throughout is matched EXACTLY, with no typo tolerance, so "§ 550a BGB" never matches docket 55/02; its `hint` points at `cited_norm` and `corpus_coverage` as checks before reporting an absence. Everyday words keep typo tolerance ("Eigenbedarfskuendigung" still finds "Eigenbedarfskündigung").
- `mode="semantic"` has no lexical arm (`total_available` null) and is still ordered by the relevance model. If a hybrid answer looks off-topic, retry the string in semantic mode before reporting that nothing exists: on a long descriptive query the keyword arm can crowd out semantic candidates.

### Query expansion

On hybrid queries the server may ADD curated German legal-register terms from a versioned dictionary ("Bagatelldelikt" to "Sachen von geringem Wert"). The terms are added, never substituted (your words are retrieved unchanged in their own pass); this dictionary step is deterministic and uses no model; it never fires on precise identifiers (Aktenzeichen, §/Art. citations, ECLI, quoted phrases). `query_expansion` is on EVERY response, never null:

- fired: `{status: "applied", applied: true, original_query, added_terms, note}`; read it before quoting results, since it names words the ranking saw that you did not type;
- not fired: `{status: "abstained"|"skipped", applied: false, reason, note}`. `abstained`: the dictionary read the query and added nothing; `skipped`: it did not run. `reason` is one of `no_entry_matched`, `entry_blocked`, `caller_opted_out`, `disabled`, `not_hybrid_mode`, `precise_identifier`, `empty_query`, `bridge_error`, `not_recorded`, `unknown`.

`bridge: false` switches it off for one call.

### Headnote, cited norms and Verfahrensgang

Present where an extraction produced them (about 38% of the corpus); absent fields are omitted, never fabricated.

- `leitsatz` is the decision's own Leitsatz section text, read at serve time (whitespace normalised, spelling unchanged, a budget cut marked "…"). `leitsatz_source` on it: `official_headnote` (the headnote the court published; quote it as the court's), `source_document` (a Leitsatz section, possibly a portal's editorial headnote) or `orientierungssatz` (a section headed Orientierungssatz, a documentation-service note, not court text). Treat any other value as unverified.
- `leitsatz_summary` is a model's summary, labelled `leitsatz_summary_source: "model_generated_unverified"`. It can name a norm the decision never cites; never present it as the court's words. A decision with no stored Leitsatz section serves the summary only, with no `leitsatz`.
- `cited_norms`: a de-duplicated summary of cited norms, one entry per norm, with extraction artefacts dropped (Randnummer pseudo-norms like `§ 43 Nr. 5 RdNr`, `§ 1246 Nr. 104 LS`, tokens naming no instrument like `§ 3 VI`, multi-citation tokens). Not the full Normenkette and not the filter vocabulary: filter with `cited_norm`.
- `instanzenzug`: `instanzenzug_source: "model_extracted_unverified"`, model-extracted prose known to name the wrong court on some rows. Never repeat it as established history or derive an Aktenzeichen from it. `instanzenzug_form`: `"locator"` (every stage names an Aktenzeichen), `"narrative"` (none does) or `"mixed"`.
- `instanzenzug_graph`: where the form is not `"locator"` and the citation graph holds the decision's procedural edges, an array of `{reference_canonical, target_artifact_id}`, the dockets the prose withholds. Entries come partly from a parser, partly from a model, with no per-entry flag, and can bind a LATER decision (which `get_citation_graph` withholds as `forward_date`). Read an entry as "a decision somewhere in this case's chain" and confirm it with `get_decision`. A null `target_artifact_id` means the instance is outside the corpus; the docket is real. When the only locator was the decision's own docket, the list is absent and `instanzenzug_graph_withheld_reason: "self_reference"` says so.

### `frequently_cited_by_results`

Decisions cited by at least two served rows but not themselves served: a hint that a leading decision sits below the window, never a relevance claim. Entries: `artifact_id`, `court`, `aktenzeichen`, `date`, `cited_by_count` (served rows citing it), `cited_by` (their ids); at most five, ordered by `cited_by_count` then id. Computed over the rows this response carries. Empty is ordinary and proves nothing. Only resolved citations count.

### Fortgeltung, dates and ECLI

- `fortgeltung_checked: false` on every row: Rechtskraft and Fortgeltung are NOT checked. A decision may have been quashed; the absence of a note is no evidence it stands.
- `date_source: "suspect_lower_court"` (with `date_note`): on this scan the stored date sits beside the APPEALED judgment and no own date could be recovered, so date-range membership is approximate. Absence means "not flagged", not "verified".
- `date_confidence` (`unverified` or `repaired`, with a German `date_confidence_note`): the docket year contradicts the stored year. On `unverified`, `title` and `fundstelle` print the docket year plus "(Datum ungesichert)" instead of the day; cite the day only after reading the decision. `repaired`: recovered from a date the court printed about itself. No key: never in that census.
- `ecli_date_disagrees_with_source: true` with a German `ecli_advisory`: the source's own ECLI and date disagree; both are served unchanged; rely on the date fields. We read every German ECLI's year, and the ordinal's date block for BGH, BVerwG, BSG, BPatG and BAG only. Absence is no claim that an ECLI was checked.

### Zero results

`filter_vocabulary` is added to an EMPTY result under a `court` or `document_type` filter. Per argument: `checked: true`, `matched_values`, `unmatched_values`, `declared_but_unindexed_values`, `suggestions` (always arrays).

- `unmatched_values`: the value matched NOTHING in the index. "LAG Hessen" is absent because the court is indexed as "Hessisches Landesarbeitsgericht", so the zero says nothing about what it decided. Never report "no case law" while a value sits here; retry with a suggestion or `branch`.
- `matched_values`: the value exists, so the zero is a real answer for it.
- `declared_but_unindexed_values`: our schema offers the value but the index holds no row under it (`document_type: "Schlussanträge"`, reserved for CJEU Advocate-General opinions, none held today). Drop the filter.
- `suggestions` prefer the parent court over a chamber.
- Absent block or entry: unchecked, never verified.

`filter_vocabulary.court.related_values` appears on ANY answer when a court value shares your court's name across a hyphen: `LSG Niedersachsen` (1988 to 2002) beside `LSG Niedersachsen-Bremen`, after a 2002 merger. Entries carry `value` and `indexed_passages`, with a `related_values_note`. A full answer under one value misses the other's decisions.

`filter_vocabulary.cited_norm` (empty result under `cited_norm`): `value` (canonical token filtered), `indexed_passages`, `coarser_alternatives` (`{norm, indexed_passages}`). `indexed_passages > 0`: the norm is not the cause; rephrase the query. `0` with alternatives: retry with the coarser norm, a strict superset (a decision citing `§ 823 Abs. 2 BGB` also carries `§ 823 BGB`). `0` without: drop `cited_norm`. `checked: false`: unreadable, no conclusion.

`filter_diagnostics` (empty result under a date or `branch` filter). `date_range`: `requested`, measured `coverage` (`earliest`/`latest` by month, `scope`, `as_of`) and a `verdict`: `range_below_coverage_floor` (ends before the corpus starts; not an absence of case law), `range_above_coverage`, `range_within_coverage` (the date filter does not explain the zero). `branch`: `in_corpus` and a floored `indexed_decisions`. Absent means unchecked. Cached daily.

### Refusals and price

`search_timeout` (retryable) and `index_unavailable` (nothing searched) are failures, not an empty corpus. Also `insufficient_credits`, `query_too_long` (over 500 characters) and `volume_cap` (unit `rows`). Validation prose, no code: an unknown `branch`, `document_type` or `mode`, a bad or inverted date range, `page` outside 1 to 10. Needs the `search` ability (`token_ability_missing` otherwise).

1 credit per distinct query, not per call: idempotent within the billing period on query, every filter and mode, invariant to `page` and `limit`. A repeat reports `cost: 0`.

### Arguments

- `query` (string, required, 2 to 500 characters). Longer input is rejected, not truncated; use `check_citations` for a long text.
- `court` (string). The indexed vocabulary is MIXED (abbreviated "BGH", spelled-out "Verwaltungsgericht des Saarlandes") and chamber-level ("OLG Frankfurt 6. Zivilsenat"); a court value matches all its chambers. Get values from `list_facets(field="court_name")`. A court not in the corpus returns zero: a coverage gap.
- `branch` (enum): the COURT JURISDICTION that decided, never the subject area. "ordentlich" (BGH/OLG/LG/AG), "verwaltung" (BVerwG/OVG/VG), "sozial" (BSG/LSG/SG), "arbeit" (BAG/LAG/ArbG), "finanz" (BFH/FG), "verfassung" (BVerfG), "patent" (BPatG only; BGH patent decisions are "ordentlich"), "unbekannt".
- `document_type` (enum): "Urteil", "Beschluss", "Verfügung", "Sonstige", "Gerichtsbescheid", "Schlussanträge".
- `cited_norm` (string, one canonical §-token, e.g. "§ 906 BGB"). Matches decisions whose extracted Normenkette cites it. Canonicalized ("§906 BGB" works); spellings of one law are one filter ("§ 3 AsylG" matches "§ 3 AsylVfG", "Art. 6 MRK" matches "Art. 6 EMRK"); subdivisions nest ("§ 823 BGB" matches "§ 823 Abs. 1 BGB"). Only extracted citations count, so a missing decision may still cite the norm. An "i.V.m." compound is one token.
- `date_from`, `date_to` (YYYY-MM-DD, inclusive; `date_to` not earlier). Scanned decisions, chiefly pre-1960, can carry a wrong stored date, so range membership is approximate for them; see `date_source` and `date_confidence`.
- `mode`: "hybrid" (default), "keyword", "semantic"; auto-selected when unset.
- `limit` (default 20, hard cap 20).
- `bridge` (boolean, default true): allow the query expansion.
- `page` (1-based, default 1, maximum 10).

## cross_type_search

Hybrid search over BOTH German statutes and court decisions in one call, split into `sections.laws` and `sections.decisions`. No commentary. Use it when a question spans norm and case law; for decisions alone prefer `search_decisions`.

### Filters apply to one section each

No filter narrows both sections. `jurisdiction` narrows the laws section only and never empties `sections.decisions`. `court`, `branch`, `document_type`, `cited_norm`, `date_from` and `date_to` narrow the decisions section only. `filters_applied` works as on `search_decisions`; `filters_applied_sections` names, per argument, the sections it ran on. A section it does not name was searched UNFILTERED on that axis.

### Rows

Decision rows follow the `search_decisions` row contract (locators, the `rn_source` rule, headnote, norms, Verfahrensgang, `fortgeltung_checked: false`, date and ECLI disclosures); read that section. An `official_headnote` is readable verbatim via `get_decision(section: "Leitsatz")`.

Law rows:

- A LAW ROW IS ONE § OR ARTIKEL. One statute can fill several rows (§ 543 and § 626 BGB side by side), and `id` is the statute-level id, which repeats: never deduplicate law rows on `id`. `title` names the statute; `chunk_title` (the § heading, e.g. "§ 626 Fristlose Kündigung aus wichtigem Grund") with `breadcrumb` (its path inside the statute, e.g. "… Untertitel 1 Dienstvertrag") identifies the row. Cite the §, never the bare statute.
- AT MOST ONE ROW PER NORMATIVE UNIT. An Anlage whose heading names its anchor ("Anlage 41 (zu § 10 Absatz 5)") is served under that §, so a §'s annexes share one slot. `laws_folded_by_unit` counts law rows dropped that way (absent when none); it changes order only, and drops nothing retrieval failed to reach.
- THE LAW INDEX IS § GRANULAR. A query that is one subdivided norm and nothing else (`§ 2325 Abs. 3 BGB`) is answered on the lexical arm from its bare § (`§ 2325 BGB`); a version marker (`a.F.`) is kept, and the semantic arm keeps your whole query. Anything else (`§§` lists, `i.V.m.` compounds, prose) passes unchanged. Check the Absatz in the served text; we never filter to it.
- `law_type` (`GESETZ`, `RICHTLINIE`, `VERORDNUNG`, …) and `jurisdiction` (`DE`, `EU`, `XI`) carry the `list_facets` values; null means "we do not carry it", never "domestic". Law rows only.
- A law row has no `rn_range` and no `snippets[].rn`. An EU-legislation Artikel serves `article_range` ("Art. 69") with `snippets[].article`; both are absent on other rows.

### Relevance and order

Every row carries `confidence` (`high`, `medium`, `low`; null = not measured on this request, never "low"; null on every row in keyword mode or when the relevance model was unavailable). The answer carries `top_confidence`. Neither reorders anything.

The two sections are independent retrievals: never rank a law row against a decision row. Within each section rows arrive in served order, best first: the relevance model's order whenever it ran, including semantic mode. On the laws section, the statutes this response's own decisions cite may then lift the § the case law applies; this is deterministic, only re-orders rows retrieval returned, and does nothing when the decisions are off-target. On every section, of two rows whose relevance is practically equal, a narrow court-tier tie-break lets the higher-instance court lead, at any position, on this tool and on `search_decisions`, under any filter. Never re-sort by `confidence`.

### Server-side additions

`query_expansion` works as on `search_decisions`, on both sections, with the same two shapes and `reason` values. The laws section can also receive two additions. First, candidates retrieved against a short German doctrinal phrase that a language model generates from a query in everyday language: for this step the text of your query is sent to that model, a purpose the privacy policy (Datenschutzerklärung, `/privacy`) discloses. Second, a keyword retrieval of your own words (no model) against per-§ lists of everyday phrases. Both only ADD candidates; the relevance model still scores everything against YOUR words. `bridge: false` switches all three additions off, and your query is then not sent for the doctrinal phrase.

### Totals

At most 10 rows per section. `section_totals.laws` and `section_totals.decisions` each carry:

- `total_available` (floor band): matching indexed passages for that section, counted on the LEXICAL ARM ONLY (`total_available_basis: "matching_indexed_passages_lexical_arm"`). It is NOT an upper bound on the rows the section served, and is often smaller: the served list is the UNION of several retrieval arms, so 1 beside ten rows is no contradiction. Passages, not documents. `null` in semantic mode. Never diff it across dates.
- `candidate_pool`: distinct documents the section ranked. Can exceed `total_available`; scales with `limit`; never quote it as how much exists.
- `truncated`, THREE-VALUED: false only when the window provably held every match and the rows reached the end; true when the section ran and was cut; NULL when the section was not searched at all, with the section's skip reason beside it. Null means "we did not look", never "nothing more".

Top-level `total_available` sums both sections. Top-level `truncated`: true if either section that ran was cut, null if neither was cut but one never ran, false only when both ran uncut. The response echoes the effective per-section `limit` (defaulted or capped at 10). No `page` argument. `payload_truncated` works as on `search_decisions`.

An empty decisions section under `cited_norm` adds `filter_vocabulary.cited_norm`, read as on `search_decisions`.

### `frequently_cited_by_results` and `norms_cited_by_decision_results`

`frequently_cited_by_results` works as on `search_decisions`, over the decisions section only.

`norms_cited_by_decision_results`: §§ the served decisions cite in common, a hint that the laws section may miss the governing norm, never a relevance claim. §-level entries (Abs. and Satz variants collapsed): `canonical`, `cited_by_count`, `cited_by` (citing decision ids), `in_laws_results` (whether the § is among served law rows), `law_artifact_id` (null where no served citation of it resolved). At least two citing decisions, at most five entries, by `cited_by_count` then `canonical`. `in_laws_results: false` is a pointer to look, not a verdict. It counts over the decisions this response could serve at the widest `limit`, so below `limit: 10` a `cited_by` id may be one you were not served; `in_laws_results` still refers to your served law rows. The laws re-ordering counts over a wider set, so a lifted law row may name a § this block omits.

The laws section finds a concept only where the legislator used it as a word: "Bemessungszeitraum" (§ 2b BEEG) works; judge-made doctrines like "Verkehrssicherungspflicht" (§ 823 BGB) or "Störerhaftung" (§ 97 UrhG, § 7 TMG) never appear in statute text. Then `in_laws_results: false` is the honest signal, and this block often names the governing norm. The block is bounded by extraction: a norm the decision argues in a shape the extractor misses (§ 311 Abs. 2 BGB, culpa in contrahendo) can be absent. Treat it as evidence present, never as the full Normenkette.

### Refusals and price

`insufficient_credits`, `unauthenticated`, `no_billable_organization`, `search_timeout`, `index_unavailable`, `query_too_long`, `volume_cap` (unit `rows`), `token_ability_missing` (needs `search`). Validation prose, no code: bad date range, unknown enum, `limit` below 1.

1 credit per distinct query: idempotent within the billing period on query, filters and mode, invariant to `limit`.

### Arguments

- `query` (required, 2 to 500 characters; precise identifiers switch to keyword mode as on `search_decisions`).
- `jurisdiction` (max 50): laws only. `DE`, `EU` (EU secondary law and Treaties; the only way to reach Richtlinien and Verordnungen), `XI` (international). Counts via `list_facets(field="jurisdiction")`.
- `court` (max 100), `branch` (enum as on `search_decisions`; no effect on laws), `document_type` (enum), `cited_norm` (max 120; canonicalized, spellings unified, subdivisions nest), `date_from`/`date_to` (YYYY-MM-DD, `date_to` not earlier; scanned-date caveat applies): decisions only.
- `mode`: "hybrid" (default), "keyword" (not ordered by the relevance model), "semantic" (no lexical arm); precise identifiers auto-select keyword.
- `limit`: per section, default 5, hard cap 10.
- `bridge` (default true): allow all server-side additions.

## list_facets

List the indexed values of a facetable field, so you filter on values the INDEX holds instead of guessing. A value is listed because a decision was indexed under it, never because we verified the thing it names exists. Fields: `court_name`, `court_branch`, `document_type`, `jurisdiction`, `law_type`, `cited_norms`.

### Response

`{field, applies_to, values: {"BGH": {value, is_floor}, …}, total_values, truncated, value_limit, count_basis}`, plus `guidance`, `as_of`, and where relevant `prefix`, `norm`, `candidates_considered`, `candidates_probed`. `values` is always an object, `{}` when empty. `guidance` explains an empty list; an unreachable index is reported there as an availability failure, never as an empty corpus.

- PREFIX: `prefix` keeps values that START WITH it, case-insensitively. A trailing space is significant: `"AG "` lists the Amtsgerichte without `AGH Niedersachsen`, `"AG"` keeps both. A whitespace-only prefix is ignored and not echoed. Works on every field; ordering stays most-cited first; echoed as `prefix`.
- An undeclared argument is accepted, ignored and named in `ignored_parameters`: the answer is then unfiltered.
- COMPLETENESS: `total_values` is how many values THIS RESPONSE carries. `truncated` says the list is short of the vocabulary (hit `value_limit`, or cut to the size budget); false means complete for that field and scope. It describes the enumeration, not your prefix. A large vocabulary (`court_name`; its live size is `corpus_coverage.courts_total`) is served as its largest-count head with `truncated: true`; use `prefix` for the rest. Search filters accept ANY exact value, listed or not.
- APPLICABILITY: `court_name`, `court_branch`, `document_type` exist on decisions; `jurisdiction`, `law_type` on laws (`applies_to` says which). `jurisdiction` with `type: "decision"` is empty by scope, not by corpus. `XI` is a deliberate non-ISO code for non-EU international instruments (CISG, CMR, EPÜ). A branch is a court jurisdiction: "patent" is the Bundespatentgericht.
- COUNTS are floor bands of `indexed_passages` (`count_basis`), not decisions: one decision spans many passages (roughly 3 to 4 per decision). Use them for relative order and existence; for decision totals call `corpus_coverage`. Enumerated fields are cached daily.
- `as_of`: when the vocabulary was measured. For enumerated fields, the cache write time (up to 24 hours old); for a `cited_norms` family, the call instant.

### The norm facet is family-scoped

`field: "cited_norms"` REQUIRES `norm` and lists that norm's family: the norm plus its indexed subdivisions ("§ 543 BGB", "§ 543 Abs. 2 S. 1 Nr. 3 BGB", …) with passage counts, most-cited first, decisions only; `norm` is echoed canonicalized. Spellings of one law are one family ("§ 34 BauGB" and "§ 34 BBauG" list the same members, each count including the other spelling). Use it to SEE a family, not to find a filter spelling: `cited_norm` on the coarse norm already matches every subdivision. An empty `cited_norm` search carries `filter_vocabulary.cited_norm`, and `corpus_coverage.filter_coverage_caveats` states what the norm layer covers.

FAMILY COMPLETENESS IS REPORTED. Every candidate token is confirmed against the live index, so `truncated: false` means the whole family. `candidates_considered` (derived) and `candidates_probed` (confirmed) differing means `truncated: true` and guidance opening INCOMPLETE LISTING: a sample. An unreadable derivation returns an ERROR, never an empty family, so only an empty family with `truncated: false` supports "absent from the Normenkette". `§§` group tokens are never members.

THE FAMILY IS COMPLETE OVER WHAT IS INDEXED, NOT OVER WHAT EXISTS IN THE STATUTE. `cited_norms` keeps the chain a decision was indexed under, including subdivisions the current text lacks. So each value carries one presence flag, from our stored CURRENT consolidated text of that §:

- § present: `absatz_absent_in_current_text`. TRUE when the text declares Absatz markers and the cited one is not among them, or it declares no Absatz at all while the token names Abs. 2 or higher, the same oracle that makes `check_citations` answer `discrepancy` / `absatz_absent`. A flag on the TEXT, not a verdict: an Absatz a later reform removed is marked too. FALSE means not contradicted, including where no check was possible: a § we hold no text for, and Abs. 1 of a § that declares no Absatz. Never a confirmation.
- § absent: `section_absent_in_current_text: true` and no Absatz flag; `section_repealed_on` when the repeal date is known. The tokens still filter.
- undetermined (the instrument resolves to no single law we hold): neither key, and no claim either way.

`Nr.` and `Satz` ordinals are never checked.

### Refusals and price

`unrecognisable_norm_token`, `norm_family_unavailable`, `unauthenticated`, `no_billable_organization`, `token_ability_missing` (needs `search`). Validation prose, no code: a bad `field`, `type` or `prefix`, a missing `norm` (`field "cited_norms" needs a norm to scope to, e.g. norm="§ 543 BGB"`). Free: 0 credits.

### Arguments

- `field` (enum, required), as above.
- `type` (`decision` or `law`): scope the counts; a mismatched scope returns an empty list with guidance. Ignored for `cited_norms`.
- `norm`: required with `cited_norms`, ignored otherwise (e.g. "§ 543 BGB", "Art. 5 GG").
- `prefix`: case-insensitive, trailing space significant.

## get_decision

Fetch one decision's full text or a slice (a named `section` or a Randnummer window), plus metadata.

### Identifiers and text

`id` accepts exactly three forms: the internal UUID, an Aktenzeichen in normal spacing and casing ("VIII ZR 271/17"; not "viii zr 271/17" or "1StR100/20"), or a full ECLI (exact, case-insensitive). Nothing partial is normalized. An Aktenzeichen shared by several decisions is refused with candidates (id, court, date) unless `court` and/or `date` narrow it. `metadata.file_numbers` is the authoritative file-number set; `joined_proceeding_note` fires when it holds more than one. This tool serves no `leitsatz_source`: ask `search_decisions` about headnote provenance.

`full_text` is cut to `max_chars`. `text_length` is ALWAYS the whole judgment (the same number `assemble_datapackage` reports); on a slice, `served_text_length` is the slice's length (absent on a plain fetch). `truncated` means your `max_chars` cut the text. On a slice, `max_chars` caps the slice. If `ocr_note` is present, the text is a scanned original with recognition errors, and structured metadata outranks strings in `full_text`.

### Slices

`rn_from`/`rn_to` and/or `section` (Tenor, Leitsatz, Tatbestand, Gründe; case-insensitive, "gruende" and "leitsaetze" work) return a slice. The response echoes `requested_range`, `returned_range` (with the served `section`) and `available_range`. Every response also carries `available_sections` (empty list when none can be served), `available_range` and `has_rn_anchors`.

### Randnummer citability

`rn_source` is on every response and inside `returned_range` and `available_range`. Indexed numbers come from publisher anchors that also count front matter; at serve time the number printed at the head of the served text is compared:

- `printed`: agree; write "Rn. X".
- `source_anchor_unverified` (disagree) or `unknown` (nothing printed): re-fetch by those numbers, but never cite them as "Rn.". `rn_source_note` explains, and the header line reads "source paragraphs X-Y (printed Randnummer not verified)".
- `inline_glued_unverified`: the text prints its Randnummern glued to the sentence ("…Randnummer81Entgegen…") but we hold no anchors; `rn_inline_marker` gives the first marker and its offset, `has_rn_anchors` is false, and `rn_from`/`rn_to` cannot select them. Read the number off the text.

`rn_source_basis` appears only when the verdict is not a read of the served text: `parser_sequence_reading` (the court's own number, confirmed from the inline marker at parse time, citable, though the served text no longer shows the marker), `parser_hypothesis_reading` (a marker whose digit boundary was guessed; not citable), `chunk_bytes_refute_anchor` (beside `source_anchor_unverified`: a printed number somewhere in the described text contradicts its stored anchor; matters most on a whole-text fetch). Absent: `rn_source` is a read of the served text. On a whole-text fetch, inline markers are removed from `full_text`, and `rn_inline_markers_removed` counts them (absent when none).

### Ranges snap to block boundaries

Whole blocks overlapping your window are returned, so `returned_range` is often WIDER than `requested_range` (Rn. 12-13 can return Rn. 10-18) and `returned_range_note` says so. Read the span off `returned_range`, never off your request or the `[…, Rn. X-Y]` block headers inside the text. After a `max_chars` cut, `returned_range` names the last Randnummer the served text carries; where the cut falls inside one block, `rn_to` collapses onto `rn_from`; where it removed a Randnummer you named, `returned_range_note` names it and how to fetch it. A section slice of Tenor or Leitsatz usually has null Rn bounds, meaning "not Rn-numbered", not "empty".

On a passage whose stored anchors its own served bytes refute, `returned_range` is read off the printed text (a consecutive run of bare line-head numbers, or null with a note), and `rn_from`/`rn_to` still select by the stored anchors, whose span `available_range` names. So a number you read back into a request can reach a wider window than you were shown.

`available_range_scope` names what `available_range` covers: `"decision"` or a section name. A refusal naming a `section` quotes that section's range; otherwise the range is decision-wide, so under `section: "Gründe"` its lower half may lie in the Tatbestand and be refused.

### Sections need a heading

A section is cut at a real heading LINE (Entscheidungsgründe, Tatbestand, Tenor, Leitsatz, numbered variants) to the next heading; the heading may open the line with text after a colon or dash ("Tenor: Das angefochtene Urteil wird aufgehoben."). A word inside a sentence never anchors. A recorded official publication head also anchors the Leitsatz; if it cannot be located in the stored text, the refusal is `official_headnote_not_located`. `Orientierungssatz` anchors the Leitsatz family, and `returned_range.section_heading` names the spelling anchored. A recorded headnote section with no anchoring heading is refused `document_leitsatz_not_located`. Many LAG, FG and VG decisions have no usable headings: section requests are refused with the available list. Empty `available_sections`: fetch the whole text.

### Fortgeltung, procedural outcomes, ECLI

`fortgeltung_checked: false` always: this decision may have been quashed. Verify its status before relying on it.

`procedural_outcomes` appears when a later decision in the chain decided a Rechtsmittel against this one: per deciding decision, `pointer_de` (German to render), `decided_by` (court, date, Aktenzeichen, id), `rechtsmittel_outcome` (`aufgehoben`, `aufgehoben_und_zurueckverwiesen`, `teilweise_aufgehoben`, `abgeaendert`, `zurueckgewiesen`, `verworfen`, `unparsed`), `outcome_source: "tenor_pattern"` and `outcome_evidence` (the Tenor sentence, verbatim; quote it). `unparsed`: the Tenor was read, the formula not recognised. A procedural fact, never a treatment label. Coverage is partial, so absence means nothing: never "not quashed" or "still good law".

`metadata` carries `ecli_date_disagrees_with_source: true` and `ecli_advisory` when the ECLI's date contradicts the decision's; rely on the date fields.

### Refusals and price

`max_chars_below_minimum`, `not_found`, `not_found_under_filter`, `ambiguous_aktenzeichen`, `rn_range_not_found`, `section_not_found`, `sections_unavailable`, `official_headnote_not_located`, `document_leitsatz_not_located`, `unauthenticated`, `no_billable_organization`, `insufficient_credits`, `backend_unavailable`, `volume_cap` (unit `documents`), `token_ability_missing` (needs `read`).

1 credit per decision per calendar month; further reads of that decision in the month, any section or range, report `cost: 0`.

### Arguments

- `id` (required): UUID, Aktenzeichen or ECLI.
- `max_chars` (default 40000, minimum 500).
- `rn_from`, `rn_to` (optional; inclusive; `rn_to` at least `rn_from`).
- `section` (optional): Tenor, Leitsatz, Tatbestand, Gründe; the canonical name is echoed in `returned_range.section`. Check `available_sections` first.
- `court` (optional, Aktenzeichen only): short form, matched as a whole-word prefix of the stored senate-level name ("BGH" reaches every senate, never "BGHSt"); an exact stored value pins one decision.
- `date` (optional, YYYY-MM-DD, Aktenzeichen only).

## get_citation_graph

Citation edges around ONE decision: `references` (outgoing, decisions it cites) and `referenced_by` (incoming). Edges are extracted and deduplicated; a missing edge does not mean no citation.

### Edge fields

Every edge carries `resolution_status`, `reference_canonical`, `reference_role`, `in_corpus`, `reference_canonicals`, `reference_roles`, `target_artifact_id` (the cited decision's id, null where none was bound), `occurrences` (stored reference rows the edge collapses), `hop`, `from_artifact_id`, `loops_to_source`, `withheld_reason` and `canonical_key_conflict` (both null when there is nothing to say), and a `corpus` block. `referenced_by` rows add `to_artifact_id`. `in_corpus: false` edges are real citations we could not resolve to a corpus decision; they appear only in `references`, because an incoming edge is found by its resolved target.

- `resolution_status`: `resolved`, `unresolved_ambiguous`, `unresolved_pending`, `unresolved_no_match`, `unresolved_out_of_coverage`. `unresolved_ambiguous` serves up to 5 `ambiguous_candidates` (`artifact_id`, `court`, `date` for display, `dates` = every date across versions; compare a cited date with `dates`); it is over-determined, not missing. `unresolved_out_of_coverage` is a DISCLOSED BOUNDARY: court and year are readable and the year lies outside what we index for that court (a 2007 BAG citation; the BAG corpus starts in 2010). It uses the coverage map `check_citations` uses, only when court and year are both readable; otherwise `unresolved_pending`. Report "outside our indexed range", never "does not exist".
- `unresolved_reason`, on unresolved edges where one was stored: e.g. `foreign_court_docket`, `out_of_coverage`, `journal_fundstelle`, `ambiguous_docket`. Absent when none; never on a resolved edge. A coverage word agrees with the status: `out_of_coverage` with `unresolved_out_of_coverage`, `in_range_unresolved` with the others.
- `reference_role`: `legal_basis`, `cited`, `decisive`, `discussed`, `procedural`. `reference_roles` lists every role (a Vorinstanz can be cited procedurally and substantively: one edge, two roles); `reference_role` is the primary one by fixed precedence (`procedural`, `decisive`, `discussed`, `legal_basis`, `cited`). `procedural` marks an instance-chain pointer, ranked first among `in_corpus: false` edges. NO role is a treatment label: `decisive` means weight in the reasoning, not approval; never infer overruling or which way a court ruled.
- `hop`: 1 direct, 2 neighbour of a neighbour. `from_artifact_id` is always the CITING decision and `target_artifact_id` the CITED one, whichever direction you fetched; use them to reconcile the two views. `to_artifact_id` is the node an incoming edge was discovered from (the source at depth 1).
- `loops_to_source: true` marks a depth-2 edge pointing back at the source (a true edge, served, not "cites itself"); false otherwise.
- `corpus`: the decision at the FAR end. Its Aktenzeichen field is `az` (same as `aktenzeichen` elsewhere). It carries `ecli_date_disagrees_with_source` and `ecli_advisory` where the ECLI's date contradicts the decision's.

### Identity and folding

ONE ROW PER DISTINCT DECISION, per direction, per node: several spellings or roles of one cited decision are one row, so row counts are decision counts. At depth 2 one decision can appear once per discovering node.

A bound edge is keyed on the cited decision, `target_artifact_id`, and its `reference_canonical` is built from that decision's own court and docket, so one decision always prints one canonical you may quote and cache. An unbound edge (null `target_artifact_id`) is keyed on its normalised spelling (`BGH, Urteil vom 08.04.2009 - VIII ZR 231/07`, `BGH, VIII ZR 231/07` and `VIII ZR 231/07` are one key). A docket names a proceeding, so two edges can share a docket with two different `target_artifact_id` values: two citations, not a duplicate.

An unresolved spelling merges into a resolved edge only when the resolver, run on that spelling with its own date and court, returns the same decision; a shared docket is never enough (`B 13 R 135/11 B` and `B 13 R 135/11 R` stay apart). A bound and an unbound edge never fold together; an `unresolved_ambiguous` row keeps its own edge, and no prefix or letter is stripped to force a match.

`reference_canonicals` is the evidence: the distinct spellings the citing document printed for this citation. `occurrences` is the arithmetic and is never below the number of spellings.

Two spellings of one citation are two rows in the stored population and one row in the served list, so a page can serve fewer rows than `references_total`; nothing is missing. `references_total_note` explains the gap in prose where it applies.

The incoming list is never folded by spelling. Where two unbound spellings share one key but name two different decisions, both edges are served with `canonical_key_conflict` holding the key: a resolver fault to report, not a duplicate. A bound edge always reads `canonical_key_conflict: null`.

### Withheld edges

Rows impossible on their face are served in neither list: a row naming the citing decision itself (its own docket, or on scans its letterhead docket one character away) and a resolved row binding a LATER-dated decision. Where only a real citation's binding was withdrawn, the row stays as an `in_corpus: false` edge with `withheld_reason`: `text_date_contradiction` (the citing text prints a date the bound decision lacks) or `text_court_contradiction` (it names a different court). `references_withheld_reasons` counts, per reason, every edge of the decision carrying one, removed or still served: `self_reference`, `self_reference_ocr_variant`, `forward_date`, `text_date_contradiction`, `text_court_contradiction`. `{}` when none; the same on every page.

### Totals

`references_total` (every outgoing reference after withholding, each cited decision once) splits into `references_resolved_total` (distinct resolved corpus decisions) and `references_unresolved_total` (distinct unresolved references). `referenced_by_total` counts distinct resolved citing decisions. All four describe the SOURCE decision's hop-1 neighbourhood (`totals_scope: "source_decision_hop_1"`), identical on every `page`, `direction` and depth; `direction: "incoming"` can show an empty `references` beside `references_total: 10`. `served_references_total` and `served_referenced_by_total` count the rows served; `served_direction` names what you asked for. Quote totals, never row counts, for how widely a decision is cited.

THE RESOLVED TOTALS ARE FLOORS: citing decisions outside the corpus and citations we could not bind are missing, most of all for landmark constitutional decisions cited by reporter (`BVerfGE 90, 22`). Say "at least N decisions in the indexed corpus cite this".

### Caps, paging and depth

Per direction at most `per_direction_cap` (25) distinct resolved decisions, ranked by confidence, plus at most `unresolved_cap` (25) unresolved outgoing edges. `truncated` (with `truncation_notice`) is true when a cap cut or depth-2 nodes were dropped.

`page` walks the source's lists 25 distinct decisions at a time in a stable order; pages are disjoint. `pagination` reports `page`, `page_size`, `max_page`, `references_pages`, `referenced_by_pages`, `has_more_references`, `has_more_referenced_by`, `applies_at_depth` and `reachable_distinct_max` (500 per direction; the most-cited decisions exceed it, so paging ends before the list). A direction you did not ask for reports 0 pages: "not served", not "empty". Follow the `has_more_*` flag, not the row count: folding can make a page short. The cursor follows rows actually served: a row dropped for size is served first on the next page; `references_served_so_far` / `referenced_by_served_so_far` is the cursor and `references_shed_by_budget` / `referenced_by_shed_by_budget` counts what was deferred (absent for an unserved direction), so page counts are floors. `pagination.unreachable_reason: "max_page"` names the bound where rows remain. `page` is defined at depth 1 only.

Depth 2 expands under `node_cap` (50 distinct neighbours besides the source), enforced: `nodes_omitted` counts decisions cut and `truncated` goes true. It is a bounded, breadth-first sample. At depth 1 `nodes_omitted` is 0.

`procedural_outcomes` at the top level is a neutral pointer about the SOURCE decision, with the same fields and caveats as on `get_decision`; absence means nothing, and `fortgeltung_checked` stays false.

### Size truncation

`payload_truncated`, always present, is a different signal from `truncated`: this answer was shortened to fit your client's budget. Shed in order: (1) `reference_canonicals` to its head and `reference_roles` to the primary role; (2) `ambiguous_candidates` emptied; (3) whole rows from the end of the longer list, never below one per direction. `reference_canonical`, `reference_role`, `target_artifact_id` and `corpus` are never touched. Rows that lost detail name it in `payload_truncated_fields`. `truncation` carries `reason: "response_budget"`, `shed_fields`, `edges_dropped`, `references_returned` / `references_dropped`, `referenced_by_returned` / `referenced_by_dropped` and `guidance`. Remedy: one `direction` at a time, then `page`.

### Refusals and price

`not_found`, `ambiguous_aktenzeichen`, `invalid_direction`, `page_undefined_at_this_depth` (`page > 1` with `depth: 2`), `unauthenticated`, `no_billable_organization`, `insufficient_credits`, `backend_unavailable`, `volume_cap` (unit `rows`), `token_ability_missing` (needs `graph`). 2 credits per call.

### Arguments

- `id` (required): UUID (preferred) or Aktenzeichen with normal spacing; ambiguous returns candidates.
- `direction`: "outgoing", "incoming", "both" (default).
- `depth`: 1 (default) or 2 (capped at 50 neighbours).
- `court`, `date` (optional, Aktenzeichen only): disambiguators; a landmark can share its Aktenzeichen with a later ancillary decision.
- `page` (default 1, maximum 20; depth 1 only).

## assemble_datapackage

Up to 10 decisions plus their outgoing citation edges in one JSON package, for grounded LLM context. For one decision use `get_decision`; for one decision's complete, paged edges use `get_citation_graph`.

### Text

Each decision carries EXACTLY ONE text key: `excerpt` (about 700 characters) by default; with `full_text: true`, `full_text` (the whole stored judgment) or `full_text_excerpt` (a slice), the latter with `full_text_returned_chars` and `truncated_reason` (`max_chars` or `budget_shedding`). Every decision carries `text_length` (the whole judgment, as `get_decision` reports it) and `truncated` (true whenever less than the whole judgment was served). An `excerpt` starts at the first substantive section (Leitsatz, else Tenor, else Gründe); `excerpt_span` names it, or `document_start`. Where `excerpt_span` is `Leitsatz`, `leitsatz_source` says who wrote it (`official_headnote`, `source_document`, `orientierungssatz`, as on `search_decisions`); absent otherwise or where provenance cannot be established. `max_chars` is a ceiling the response budget outranks; the echoed `max_chars` is the cap that ran.

### Response budget

An oversized result would be rejected whole, so the package sheds in fixed order, stopping when it fits: (1) text shortened, down to a span-anchored excerpt of about 300 characters; (2) `citation_edges` capped to N rows per source, down to one; (3) whole decisions dropped from the END of your `ids`. Never an error; at least one decision survives. `payload_truncated` is always present; when true, `truncation` carries `reason`, `excerpt_mode_applied`, `excerpt_chars_applied`, `edges_capped` (rows per source, null if untouched), `dropped_seed_ids` (pass them as `ids` in a second call; repeat until empty) and `fits_budget` (false only when one decision's single edge row is itself over budget: use `include_citations: false` or `get_decision`). `truncation_notice` says it in German. Package-level `truncated` is true when any text was cut, any edge dropped, or anything shed.

### Citation edges

`citation_edges` are the included decisions' OUTGOING citations, deduplicated. `in_corpus: true` edges resolve to a corpus decision and carry a `corpus` block; `in_corpus: false` edges are real citations we could not identify, with `corpus: null`, never corpus-verified: their `reference_canonical` is what the judgment says, not something we confirmed. `resolution_status`, `ambiguous_candidates` (`artifact_id`, `court`, `date`, `dates`) and `unresolved_reason` mean exactly what they mean on `get_citation_graph`. A resolved edge row is one distinct decision, all its spellings in `reference_canonicals`.

### Caps and `edge_accounting`

Per source decision, `per_source_resolved_target_cap` distinct resolved targets and `per_source_unresolved_edge_row_cap` unresolved edge rows. `edge_accounting` has one row per source: `from_artifact_id`, `unit` (edge rows), `edges_total` (a property of the decision; `get_citation_graph` reports the same), `edges_included`, `edges_resolved_included`, `edges_unresolved_included`, `edges_resolved_total`, `edges_unresolved_total`, `targets_resolved_included`, `targets_resolved_total` (distinct resolved decisions; they agree with the resolved `edges_*` half).

`edges_total` minus `edges_included` can be positive while `truncated` is false: duplicate spellings of one citation were merged into one served edge, and nothing is missing. When a cap dropped edges, `truncated` is true; fetch the rest with `get_citation_graph`. `requested`, `included` and `deduped` count ids sent, decisions held and duplicates collapsed; `requested - deduped - included` decisions were dropped by the budget and are named in `truncation.dropped_seed_ids`.

### Fortgeltung and ECLI

Every decision carries `fortgeltung_checked: false`; keep it when you feed rows to a model. A decision whose ECLI date contradicts its own date carries `ecli_date_disagrees_with_source: true` and `ecli_advisory`; rely on the date fields.

### Refusals and price

`ids_unresolved` (an id not found or ambiguous; the whole call fails with guidance), `max_chars_below_minimum`, `unauthenticated`, `no_billable_organization`, `insufficient_credits`, `backend_unavailable`, `volume_cap` (unit `rows`), `token_ability_missing` (needs `datapackage`). 5 credits per call, keyed on the resolved ids plus `include_citations`, `full_text` and `max_chars`; the same package again in the billing month costs 0.

### Arguments

- `ids` (array, required, 1 to 10): UUIDs (preferred) or Aktenzeichen. Ten is served, never refused for size. Duplicates collapse. ORDER MATTERS: the budget drops from the END.
- `include_citations` (default true).
- `full_text` (default false): whole judgments instead of excerpts; token-heavy.
- `max_chars` (default 60000, minimum 500, maximum 200000): per-decision cap when `full_text` is true.

## corpus_coverage

What the corpus holds: per-branch and per-court decision counts with the earliest and latest `decision_date` held, measured over the decision store. Read it before a search to tell a coverage gap from a non-existent concept. A `branch` is a COURT JURISDICTION, never a subject area: `patent` is the Bundespatentgericht, and patent decisions of ordinary courts count under `ordentlich`.

### Shape

`{total_decisions, branches: [{branch, count, earliest, latest, instance_mix, top_courts}], courts: [{court, branch, count, earliest, latest}], courts_returned, courts_total, corpus_floors, coverage_ranges, filter_coverage_caveats, law_coverage, as_of}`, with `court_founding_year`, `court_founding_basis` and `has_dates_below_floor` on the rows. Counts are floor bands. Dates are `YYYY-MM` or null, never day precision.

- `courts` IS CAPPED BY `top` AND NOTHING ELSE IS. Compare `courts_returned` with `courts_total`; never read `courts` as the full list. `corpus_floors` is one derived sentence over the whole scope.
- `court_founding_year` is when the COURT was constituted (BGH 1950, BAG 1954), a plausibility floor on dates, NOT our ingestion boundary. `earliest` is the earliest plausible decision we HOLD. For ingestion read `coverage_ranges`; the two can differ by decades (BGH founded 1950, non-criminal senates ingested from 2000).
- `court_founding_basis`: `"court_floor"` or `"branch_wide_weakest_court_floor"` (one year governs the row), `"per_court_floors_mixed"` (members floored individually; `court_founding_year` null; see per-court rows), `"no_floor_asserted"` (unchecked). `has_dates_below_floor: true` marks a row where implausible dates were excluded from `earliest`; with a null year only under `"per_court_floors_mixed"`.
- `instance_mix: {federal, appellate, first_instance_and_regional, other, note}` splits a branch across the Instanzenzug (`other` for courts outside the rank table). The corpus leans toward the published top; first instance is a selection, never a Vollerhebung. Read the numbers and the `note` from the payload; they move as the corpus grows. The `note` is the branch's own conclusion (possibly that first-instance claims are not supportable) and is the caveat to relay.
- `top_courts`: each branch's up to five busiest courts, with counts and dates. Small courts that never reach `courts` are named here, e.g. the Vergabekammern, Anwaltsgerichtshöfe, Berufsgerichte für Heilberufe, Schifffahrtsobergerichte and Truppendienstgerichte under `branch: "unbekannt"`, which reflects our court normalisation, not the decisions.
- `filter_coverage_caveats`: known blind spots of the `cited_norm` and `document_type` filters on the early corpus.

### `coverage_ranges`: the ingestion boundary

`{note, scope, verified_at, source, ranges}`; each range is `{bucket, court, label, from, until, sources, exhaustive, ocr, note, holdings_earliest}`. The first nine come from our version-controlled coverage map; `holdings_earliest` is measured. `from`/`until` are inclusive ISO dates (null `until` = open-ended). Scoped to `branch` (`scope` names it; "all" without a branch).

`from` IS THE CONTRACT, `holdings_earliest` THE MEASUREMENT (month precision). They differ where a snapshot reaches below the window: the BVerwG is ingested from 2002 and held from 1997. An `out_of_coverage` verdict uses whichever reaches further back. Null `holdings_earliest`: nothing held. The BUCKET is the unit: the BGH is `BGH_STRAFRECHT` from 1950-10-02 and `BGH_OTHER` (Zivil-, Familien- und sonstige Senate) from 2000-01-01; the BVerwG is two rows over one bucket, read as their union. `exhaustive: false`: a selection. `ocr: true`: OCR text; check verbatim quotes against the original. Below a `from`, say "outside the range we ingest", never "the citation may be wrong". `check_citations` serves this range on the finding as `coverage_boundary`.

### `law_coverage`

`{note, eu, international}`. The statute texts behind `check_citations` are German federal law plus the instruments in `eu` and `international`, derived on every call; do not rely on a remembered list. No Landesrecht is covered, so a Land-law citation reads `not_found` with `coverage.status: "out_of_scope"`, `coverage.scope: "no_state_law"` and a German sentence. In Verwaltungs- and Baurecht the governing norm is often a Landesgesetz: a scope boundary, not an error.

### Caching, refusals, price

Cached for a day. `as_of` is the cache write time (up to 24 hours old); identical counts with the same `as_of` are one measurement. Free: 0 credits. Refusals: `unauthenticated`, `no_billable_organization`, `token_ability_missing` (needs `search`); an out-of-set `branch` or a `top` outside 1 to 100 is refused in prose.

### Arguments

- `branch` (optional): ordentlich, verwaltung, sozial, arbeit, finanz, verfassung, patent, unbekannt.
- `top` (default 20, maximum 100): per-court rows, busiest first. Branch rows are never capped.

## check_citations

Check every court-decision and statute citation in a pasted German legal text against the corpus: one verdict per citation, with Unicode codepoint offsets into your exact input.

### Synchronous and corpus-only

One call, no polling. Input is capped at 20,000 characters. The external register stage (dejure.org) is skipped here: corpus misses read `external_status: "skipped"`, so `not_found` is weaker evidence than a check that also asked the register. Longer documents, the external register stage and re-checks run in the Citation Check of the Klaracase web app; a public REST API is planned. Typically well under a few seconds.

INPUT GATE. Before any charge, a deterministic gate counts five legal-signal categories: (1) a `§` or spelled-out norm ("Paragraf 536", "Artikel 5"); (2) a German court; (3) an Aktenzeichen-shaped docket; (4) two or more German legal-prose markers ("Abs.", "Urteil", "vgl."); (5) two or more English legal markers. It needs TWO OR MORE. "Nach § 573 Abs. 2 Nr. 1 BGB ist die Kündigung wirksam." hits one and is refused `not_german_legal_text` at any length. Send the surrounding sentences or the cited decision; do not pad.

### Verdicts: a closed set of seven

Only `discrepancy` asserts that something IS wrong. Never invent an eighth word.

- `verified_corpus`: matches a real decision or statute § in our corpus. Not a claim that it is correct law, still good law, or supports its proposition.
- `verified_external`: confirmed by the external register; not produced here, but possible on a reused earlier run.
- `not_found`: not in our corpus. Never "fabricated": an ingestion backlog exists inside our coverage windows. `evidence.reason: "statute_unknown"`: the abbreviation matches no law we index ("we could not find this law", not "it does not exist"). `evidence.reason: "section_absent_in_current_text"`: the § is not in the current text of a law we hold; where corpus decisions cite that §, the verdict is `discrepancy` instead, with `evidence.citing_passages` and `evidence.section_absence_advisory` (it may have been struck, renumbered or recodified). Where § presence cannot be read: `unverifiable`, `section_presence_unreadable`.
  LAND LAW: a real Land-law citation (`§ 47 BauO LSA`, `Art. 6 BayBO`) reads `evidence.reason: "state_law_out_of_scope"`, `coverage: {status: "out_of_scope", scope: "no_state_law", instrument, state}` and a `coverage_advisory`. Relay: the statute is real, we cannot check Landesrecht, nothing is said about correctness. A trailing Landeskürzel places a citation alone (`§ 45 Abs 1 BG LSA`: `instrument: "BG"`, `state: "LSA"`; the advisory adds that the reading rests on that code); behind a federal instrument it names the authority (`Art. 12 GG BE` is the Grundgesetz). Unknown instrument: `coverage.status: "unknown"`, no advisory, no evidence either way. `coverage` is null where no coverage question arises.
- `out_of_coverage`: an attested boundary (below a court's ingestion range, or a jurisdiction outside scope), not a defect. Relay both halves: outside our indexed range, AND existence not confirmed. `coverage_boundary: {bucket, label, from, until, source}` is the deciding range from our coverage map, with a German `coverage_advisory`; quote its `from`, never `court_founding_year`. It is null on the two out-of-scope arms (foreign jurisdiction, CJEU case number). `external_status: "skipped"`. Never used for an unfound statute.
- `ambiguous`: several corpus decisions match; candidates in `evidence`, with a German `ambiguity_advisory`, which names the one candidate a stated date fits, as a pointer only (`matched_decision` stays null). If your sentence states court AND date and exactly one candidate contradicts neither while all others contradict something, it RESOLVES: `verified_corpus`, `matched_decision` set, `evidence.pass: "stated_court_and_date"`, candidates kept. `evidence.candidates_not_persisted` counts candidates the storage cap dropped; `evidence.attribution.candidates_compared` counts those compared; `candidates_remaining` is a deprecated alias due to be dropped. Each candidate carries `conflict_axis` (`none`, `court`, `date`, `document_type` and `_and_` composites of the last three); `evidence.attribution.conflict_axes` is the histogram and `evidence.attribution.conflict_axis` the best-fitting candidate's axis. `candidates_conflicting` is a bare count.
- `unverifiable`: a tooling limit, not a statement about the citation. Two legal-fact cases: `evidence.reason: "statute_superseded_instrument"` with `coverage: {status: "superseded", scope: "current_consolidated_text_only", instrument, successor, superseded_on}` and a `coverage_advisory` (`§ 181 BBauG`: replaced by the `BauGB` on 1987-07-01, numbers do not carry over; relay successor and date, and never read a `BauGB` verdict as covering the `BBauG`); and `evidence.reason: "cost_schedule_number_unchecked"` for `Nr. 3104 VV RVG`, `Nr. 1211 KV GKG` and the FamGKG, GNotKG, GvKostG and JVKostG schedules (canonical `Nr. 3104 RVG-VV`, `Nr. 1211 GKVerz`, `Nr. <n> <instrument>-KV`), whose evidence names `instrument`, `schedule`, `schedule_number` and `instrument_in_corpus`. The number is not checked, so relay `subdivision_advisory`; `check_scope` reads `{subdivision: "unchecked", article_text_available: null, article_text_read: false, court: "not_applicable"}`; grouped under `no_statement` in `reason_counts`.
- `discrepancy`: found, and it CONTRADICTS the citation (wrong court or date, `Urteil` for a `Beschluss`, a nonexistent Absatz, a repealed §); typed reason in `evidence`. `attribution_document_type` compares your decision word with the stored `document_type` (`evidence.attribution.prose_document_type` / `record_document_type`; `document_type_match` joins `attribution.outcome` on agreement); only `Urteil`, `Beschluss`, `Gerichtsbescheid`, `Verfügung` are compared. On a shared Aktenzeichen where your prose contradicts every candidate: `attribution.outcome: "all_candidates_conflict"`, typed reason = the best-fitting candidate's axis, plus `ambiguity_advisory` and the candidate list.

### `check_scope`

Every finding carries `check_scope` with four keys: was the named thing actually checked?

- `subdivision`: the Absatz question. `checked`, `unchecked`, or `not_applicable` (no Absatz cited: every `case` finding, a bare `§ 823 BGB`, a `Nr.`-only citation).
- `article_text_available`: do we hold a text for the resolved § or Artikel? A corpus property; `null`, never `false`, when no law was resolved (every `case` finding).
- `article_text_read`: did this check load that text? `false` beside `not_applicable` means nothing asked.
- `court`: was the court your prose names compared? `checked`, `unchecked` (unreadable place, no court on the record, several courts of that type in the Land, or an unknown court such as `Anwaltsgerichtshof Hamm`) or `not_applicable` (statute finding, or no court named). `unchecked` never reads `court_match` and never changes the verdict; relay it as "not checked".

A cited Absatz that was NOT checked never reads `verified_*`: it reads `unverifiable` (`Art. 69 Abs. 3 EPÜ` without stored Absatz markers). Satz, Nr. and lit. are not on this axis: `§ 573 Abs. 1 Nr. 2 BGB` is `checked` and stays `verified_corpus`.

### `subdivision_check`

Five values, finer than `check_scope.subdivision` and never in disagreement with it:

- `absatz_verified`: an Absatz alone was cited and confirmed.
- `absatz_unverified`: undecidable (no text held, or a § without numbered Absätze cited as `Abs. 1`). Unknown, never "zero".
- `absatz_absent`: the check RAN and the Absatz is not in the § (numbered Absätze without it, or none while `Abs. 2` or higher is cited), read against the CURRENT text: `discrepancy` / `absatz_absent`. `evidence.absatz_cited_by_resolved_references` counts corpus references citing that § and Absatz; non-zero usually marks a repealed or renumbered Absatz (`§ 299 Abs. 3 StGB`, repealed 20.11.2015). A description, never a defence.
- `absatz_unchecked`: an Absatz on a translated instrument (the EPÜ) with no stored markers: `unchecked`, verdict `unverifiable`.
- `not_checked`: nothing below the § was checked (no subdivision, or a Satz/Nr./lit./Alt./Halbs. qualifier, which nothing checks), even beside a confirmed Absatz.

Satz, Nr. and lit. are never verified, so `verified_corpus` then attests only the § and its Absatz. Relay the German `subdivision_advisory` ("Abs. 1 bestätigt; Nr. 2 nicht geprüft") rather than "fully verified". It speaks only about what lies below the §, and is `null` when there is nothing to report. The run's `notes` repeat the caveat once, with a count.

### Advisories that are never verdicts

RECHTSMITTEL. A `case` finding whose decision had its Rechtsmittel decided carries `evidence.advisory` with `type: "rechtsmittel_entschieden"`, `pointer_de`, `decided_by`, `rechtsmittel_outcome` (as on `get_decision`), `outcome_source: "tenor_pattern"` and `outcome_evidence` (quote it). The verdict is unchanged; never count it as a defect or a treatment label. Absence means nothing.

PRE-REFORM NUMBERING. A `statute` finding citing a § a major reform moved carries `evidence.advisory` with `type: "possible_pre_reform_numbering"`, a German `note`, `successor_precision` (`"provision"` or `"statute"`), `reform` and `effective`. Gated on the date the citing SENTENCE states: before `effective`, `successor` with `successor_applies: true`; on or after it, or undated with a confirmed Absatz, no advisory; otherwise `successor_if_pre_reform` with `successor_applies: "unknown"`. `reference_date` dates sentences that name no date; `evidence.citation_date_source` reads `"sentence"`, `"reference_date"` or `"none"` (then `evidence.citation_date` is absent). Where the old § or its instrument is gone (§ 564b BGB; AGBG, VerbrKrG, KO), `successor_applies: true` regardless of date. Example: "§ 455 BGB" is `verified_corpus` though the Eigentumsvorbehalt moved to § 449 BGB on 01.01.2002. Never call it a wrong citation; the register is partial, so absence confirms nothing.

### Run status, retention and losses

`partial` and `unverified_count` are on every answer. If the external stage ran out of time, the run still ends `status: "complete"`, but unreached citations read `external_status: "unavailable"` with `evidence.external.reason: "stage_budget_exhausted"`; `partial: true` and `unverified_count` (out of `progress.citations_total`) say so, as do `notes`. Never relay such a run as checked. The re-check runs in the Citation Check of the web app; calling this tool again returns the same run for identical text in the billing period, and any other text is a new, charged check.

RETENTION. Findings are deleted 90 days after a run was created. A purged run stays `status: "complete"` with `findings: []`, `findings_unavailable_reason: "retention_purged"`, `findings_purged_at`, no `unique_citations`, and its counts preserved. Both keys are `null` on a run holding findings. Never relay a purged run as "no citations". This tool reuses only current-month runs, so it never returns one itself.

LOSSES. A citation the grammar cannot read to the end is DROPPED, not mis-reported: `extraction.dropped_unreadable` counts, `extraction.dropped_unreadable_texts` quotes them, `notes` says so. `extraction.dropped == dropped_unreadable + dropped_refused_collision`; `dropped_unreadable == dropped_truncation + dropped_trailing_noun + dropped_stacked_subdivision`. `extraction.possible_citations_unparsed` counts docket-shaped text never admitted, and numbered annex or schedule entries before a law we hold (`Anm. zu Nr. 1008 VV RVG`, `Anlage 1 Nr. 5 BKatV`), with sites in `extraction.possible_citations_unparsed_texts`. Contract-clause look-alikes (`§ 13 MV` in a lease is clause 13 of the Mietvertrag; also `AV`, `GV`, `BV`, `TV`, `AGB`) are REFUSED and listed in `extraction.refused_contract_collision` (`text`, offsets, `instrument`, German `advisory`), with no finding and no verdict; a document naming the statute (`§ 93a AO`, "Mitteilungsverordnung") still resolves. Each loss entry carries `text`, `start_offset`, `end_offset` and `offsets_unavailable_reason` (both offsets `null` when unknown, never `-1`). Lists cap at 25; counters do not. Name these passages to the user: the check is incomplete there. `extraction.detected = progress.citations_total + extraction.dropped`, the marks on the page, never a recall claim.

### Response shape and units

`status`, `progress`, `verdict_counts`, `reason_counts`, `unique_citations`, `findings` (offsets in Unicode codepoints; UTF-16 callers convert), `extraction`, `notes`, `partial`, `unverified_count`, `payload_truncated` and the envelope. `findings` and `progress.citations_total` count OCCURRENCES; `verdict_counts`, `reason_counts`, `unique_citations` and `progress.unique_citations_total` count DISTINCT citations. Say "citations", not "mentions".

A resolved `case` finding is keyed on `matched_decision.artifact_id`, so several spellings of one decision count once and two decisions of one proceeding count twice. Otherwise, and on every statute or EU finding, the key is `canonical` (`BGH, Urteil vom 08.04.2009 - VIII ZR 231/07` and `VIII ZR 231/07` both serve `canonical: "BGH VIII ZR 231/07"`). Never group on `raw_text`.

`unique_citations`, in reading order, has seven keys per entry: `key_basis` (`matched_decision` or `canonical`), `target_artifact_id` (null on the canonical arm), `canonical`, `spellings`, `occurrences` (never below the number of spellings), `verdict`, `reference_type` (`case`, `statute`, `eu_regulation`, `eu_directive`). Statute and EU entries always use `canonical`; two Artikel of one regulation are two citations, while `Art. 7 VO (EG) Nr. 261/2004` and `Art. 7 Fluggastrechte-VO` are one. `matched_decision` is null on statute and EU findings; the resolved law is `evidence.law_artifact_id`, and an EU law bound through its instrument number carries `evidence.binding_provenance: {"via": "eu_instrument_number"}`. `findings` stays one entry per occurrence.

German advisory strings are finished sentences to render: `coverage_advisory`, `ambiguity_advisory`, `subdivision_advisory`, `ecli_advisory`, `evidence.advisory`, `evidence.section_absence_advisory`. `matched_decision` carries `ecli_date_disagrees_with_source` and `ecli_advisory` where its ECLI date contradicts its own.

SIZE. `payload_truncated` (always present, distinct from `partial`) says this answer was shortened; `truncation` names what and `guidance` the remedy. Shed order: advisory sentences, then `evidence` reduced to its `reason`, then tail findings. Rows name their loss in `payload_truncated_fields`; `verdict_counts`, `progress` and `unique_citations` still cover the whole run.

### Refusals and price

`text_too_long`, `not_german_legal_text`, `insufficient_credits`, `unauthenticated`, `no_billable_organization`, `backend_unavailable`, `token_ability_missing` (needs `citation-check`). Validation prose, no code: `text` under 50 characters, a `reference_date` that is not an ISO calendar day.

Credits = max(2, ceil(characters / 5,000)) on the normalized text, computed server-side: 2 up to 10,000 characters, 4 at the 20,000 cap. Charged before the check, idempotent on identical text within the billing period (a repeat returns the existing run at 0). The web app prices longer documents on its own scale. Quote the reported `credits.cost`.

### Arguments

- `text` (required, 50 to 20,000 characters): must pass the input gate; offsets refer to this exact string.
- `reference_date` (optional, `YYYY-MM-DD`): the document date, applied to statute citations whose sentence names none; a sentence's own date wins. It gates only the pre-reform advisory and changes no verdict.
