Dokumentation: Seiten auswählen

API-Leitfaden (v1)

Versionierte, öffentliche API. Referenz: ADR-0019. Interaktiv ausprobieren: /docs/api. Maschinenlesbar: GET /api/v1/openapi.json.

Abdeckung und Grenzen

Der Report-Kernflow ist über UI, REST-API, MCP und Report-Skill verfügbar. Vollständige AI-Parität bleibt ein Ziel (ADR-0018). Konto, Team, Gemeinde-Überblick und Standortvergleich erfordern eine bestehende Browser-Sitzung; der Standortvergleich zusätzlich Beta-Gates. Admin-API-Endpunkte erfordern einen API-Key mit admin-Scope; MCP deckt dort Modell, Budget und Nutzung ab. Die übrigen öffentlichen Werkzeuge haben eigene REST-Endpunkte, aber keine eigenen MCP-Tools oder Skills; nicht alle stehen in diesem OpenAPI-Schema. Die Zugangsmatrix beschreibt den jeweiligen Umfang.

Basis

https://www.landnutzen.at/api/v1

Pfad-versioniert (/api/v1). Breaking Changes → /api/v2; neue Felder werden additiv innerhalb v1 ergänzt (Contract bleibt stabil).

Authentifizierung und Report-Quota

Die API funktioniert ohne Key. Der Reportpfad unterscheidet drei strikt getrennte Modi:

ModusWieTageslimit
Anonymkein Key und keine sicher auflösbare bestehende Kontositzung10 pro pseudonymem Request-IP-Bucket
Sessionbestehende gleich-originäre Browser-Sitzung eines vorhandenen Users10 pro pseudonymem Account-Bucket
API-KeyAuthorization: Bearer ln_… oder X-API-Key: ln_…eigenes in der Datenbank hinterlegtes Limit

Der Session-Modus verwendet ausschließlich die vorhandene LandNutzen- Browser-Sitzung. Er ist kein neues Cookie-Auth-Verfahren für headless oder Cross-Origin-Clients; diese verwenden weiterhin einen API-Key. Kann eine Sitzung nicht sicher aufgelöst werden oder existiert der zugehörige User nicht mehr, gilt der anonyme IP-Bucket; eine Sessionstörung überspringt die Bucket-Prüfung nicht.

Ein angebotener API-Key wird immer vor einer Sitzung geprüft. Gespeichert wird nur ein SHA-256-Hash des Keys, nie der Klartext. Ein ungültiger oder widerrufener Key antwortet mit 401 und fällt weder auf Cookie-Auth noch auf anonymen Zugriff zurück. Die Key-Ausstellung erfolgt durch die Plattform (node scripts/create-admin-key.mjs, siehe Admin-Dashboard); eine Self-Service-Ausstellung ist nicht implementiert, das Admin-Dashboard enthält keine Schlüsselverwaltung. Zugang zur API mit eigenem Key läuft über die Zugangs-/Pilotanfrage unter /pilot.

Endpunkt-Übersicht

Maßgeblich ist das maschinenlesbare Schema GET /api/v1/openapi.json (interaktiv: /docs/api). Die Tabelle ergänzt die tatsächlichen Werkzeugrouten (Code-Abgleich 08.10.2026); nicht alle stehen im OpenAPI-Schema. Der Standort-Check gehört zur Basis /api; sein OpenAPI-Pfad überschreibt dafür den allgemeinen Server /api/v1 ausdrücklich. Für die Aufrufe unten gelten jeweils die vollständigen Pfade der Tabelle.

GruppePfadZugriff
ReportGET/POST /api/v1/report, GET /api/v1/report/{id}, GET /api/v1/report/{id}/pdf, GET /api/v1/report/{id}/sources/pdfreport: wie unter „Authentifizierung und Report-Quota“; gespeicherte Reports über die nicht erratbare ID; PDF mit eigenem Tageslimit
Report, bedingtGET /api/v1/report/{id}/dxfnur im Schema, wenn der DXF-Export freigeschaltet ist (siehe unten)
Report, KontoPOST /api/v1/report/{id}/claimbestehende Browser-Sitzung
Konto und OrganisationGET/DELETE /api/v1/me, GET /api/v1/me/reports, GET /api/v1/org/{slug}, GET/POST /api/v1/org/{slug}/invitations, GET /api/v1/gemeinde/{slug}bestehende Browser-Sitzung (Session-Kontext)
Standortvergleich (Beta)/api/v1/org/{slug}/workspace/sites, …/sites/{id}, …/sites/{id}/refresh, …/compareSitzung, Beta-Organisation; Pfade stehen nur im Schema, wenn der Betriebsschalter gesetzt ist, sonst 404
Standort-CheckPOST /api/tools/standort-check (Basis /api, nicht /api/v1)ohne Key, 30 Anfragen pro Tag; signierte Standort- und Regionsnachweise aus der Adressauswahl erforderlich
PV-ErtragsrechnerPOST /api/tools/pv-ertrag (nicht im OpenAPI-Schema)ohne Key; standardmäßig 30 Anfragen pro Tag, eigener Eingabevertrag und signierte Standortnachweise
Immobilienmarkt-SignalGET /api/tools/immobilienmarkt (nicht im OpenAPI-Schema)öffentlich ohne Eingabe und ohne Nutzerkontingent
DatenquellenGET /api/v1/data-sources/coverage-matrix, GET /api/v1/data-sources/{slug}/provenance, GET /api/v1/data-sources/pvgis/releases/{releaseId}/evidence/{evidenceSha256}ohne Key
Admin/api/v1/admin/usage, /model, /budget, /impersonate, /data-sources, /metrics, /cost-overviewAPI-Key mit admin-Scope

Zusätzlich existiert GET /api/v1/health/crons (öffentlich, nur Status, Dauer und Auslöser der letzten Cron-Läufe, ohne Fehlertexte); der Pfad steht nicht im OpenAPI-Schema. Der Remote-MCP-Server POST /api/mcp ist in MCP-Server beschrieben.

Endpunkte

GET /api/v1/report

ParameterOrtPflichtBeispiel
addressQueryjaRathausplatz 1, 2230 Gänserndorf
curl "https://www.landnutzen.at/api/v1/report?address=Rathausplatz%201%2C%202230%20Gänserndorf"

POST /api/v1/report

curl -X POST https://www.landnutzen.at/api/v1/report \
  -H "Content-Type: application/json" \
  -d '{"address":"Rathausplatz 1, 2230 Gänserndorf"}'

Erfolg (200) = Report-JSON nach Report-Contract — kein Wrapper. Antwort- Header: X-RateLimit-Limit, X-RateLimit-Remaining, X-Auth-Mode. X-Auth-Mode ist anon, session oder key; Limit und Restwert gehören immer zum tatsächlich verwendeten Bucket. Report-Antworten bleiben Cache-Control: private, no-store.

Der Account-Bucket ist account:v1:<HMAC-SHA-256(AUTH_SECRET, report:account:v1:<users.id>)>. User-ID und E-Mail werden nicht im Rate-Limit gespeichert. Der Prefix trennt Konto-Buckets von anonymen IP- und API-Key-Buckets. Davon unabhängig bleibt reports.ip_hash das Pseudonym der tatsächlichen Request-IP. Bei einer Kontolöschung wird der Account-Bucket explizit entfernt; der allgemeine wöchentliche Prune begrenzt ältere Rate-Limit-Zeilen nach 90 Tagen. Eine interne FK-Lifecycle-Zuordnung bindet auch frühere HMAC-Generationen nach einer AUTH_SECRET-Rotation an das Konto und löscht sie beim User-Delete per Cascade. Details: Report-Quota-Vertrag.

Additiver Reportblock: historische Hitzebelastung

risiko.hitzebelastung ist ein optionaler additiver v1-Block. Er erscheint nur bei einem aktiven, qualifizierten Quellenrelease von geosphere-hora-hitzelayer und enthält historische mittlere Tage pro Jahr der Klimaperiode 1991–2020:

  • hitzetage_30c_jahr, extreme_hitzetage_35c_jahr, tropennaechte_20c_jahr, hitzewellentage_kysely_jahr;
  • vollständige Release-, Lizenz- und Rasterprovenienz einschließlich source_release_id, release_key, resolution_m: 1000, native_crs: EPSG:3416 und CC BY 4.0.

Kein aktives Release, keine konkrete Rasterabdeckung oder unvollständige Provenienz bedeuten: Der Block fehlt. Bestehende Reports bleiben kompatibel; es gibt weder einen HORA-Live-Provideraufruf noch eine Prognose oder Ampel. Der bestehende SPARTACUS-v3-Klima-Block zeigt unverändert das abgeschlossene Referenzjahr 2025. Vollständiger Quellen- und Reportvertrag.

Der Produktionsreadback belegt sowohl die aktive Quellenbasis als auch getrennt den öffentlichen, nicht persistierenden API-Consumer auf Merge 08d55c3. Das Fehlen des optionalen Blocks bleibt bei fehlender Rasterabdeckung oder einem fail-closed Release-/Rechte-Gate ein vertragskonformes Ergebnis.

Bedingter DXF-Export eines gespeicherten Reports

GET /api/v1/report/{id}/dxf ist kein allgemeiner Katasterdownload. Der Pfad wird nur dann im OpenAPI-Schema veröffentlicht, wenn parcel_dxf im Code release_bound und DXF_EXPORT_ENABLED exakt true ist. Produktion läuft seit dem nachgewiesenen #412-Cutover mit true. Der tatsächlich ausgeführte Rollback auf false ließ GET und OPTIONS mit 404 private, no-store antworten und entfernte den Pfad aus dem Schema. Flagwechsel werden auf Vercel erst nach einem Redeploy wirksam; Aktivierung, Rollback und finale Wiederaktivierung liefen deshalb auf demselben geprüften Commit jeweils bis Ready und wurden danach gegen Route plus OpenAPI rückgelesen. Das deploymentabhängige OpenAPI-Dokument wird mit Cache-Control: no-store ausgeliefert. Die Daten-Pointer blieben bei allen drei Zuständen unverändert.

Ein freigeschalteter Aufruf bleibt an den vorhandenen wertschöpfenden Report, seinen Public-Release, dieselbe Koordinate und den qualifizierten bev-parzellen/export-Pointer gebunden. Er exportiert vollständige, unveränderte Pilot-Originalpolygone in voller Stützpunktdichte als ASCII-R12- DXF in EPSG:31287. Sichtbare BEV-Attribution, Quelle, CC BY 4.0, Bearbeitungshinweis, Nicht-Unterstützung und Vermessungsgrenze sind Pflicht. Eigentümerdaten, ein eigenständiges BEV-Produkt, nationale Katasterabdeckung, Clipping oder Vereinfachung sind ausgeschlossen.

  • 200: qualifizierte DXF-Datei;
  • 400: ungültiges Report-ID-Format;
  • 403 report_context_mismatch: Der gespeicherte Report ist nicht an den erforderlichen wertschöpfenden Nicht-BEV- und Public-Release-Kontext gebunden;
  • 404: Report fehlt, ist abgelaufen oder das Flag ist aus;
  • 429: DXF-Tageslimit;
  • 503: Export-Release, Geometriezustand oder räumlicher Nutzungszweck passt nicht;
  • 500 dxf_failed: Der Renderer konnte die qualifizierte Geometrie nicht als DXF erzeugen; die Antwort bleibt private, no-store.

Der Consumer ist produktiv aktiviert. Der Produktionsnachweis belegt Dunkelzustand, positiven und negativen Live-Readback, GDAL-Parser, Pointerkonstanz, Rollback und finale Wiederaktivierung. NÖGIS #413 und ein eigenständiger Parzellenpass bleiben davon getrennt offen.

POST /api/tools/standort-check

Öffentlicher Standort-Datenpass ohne Report-Persistenz (Vertrag: Standort-Check v1). Der Pfad hat im OpenAPI-Schema einen eigenen Server mit der Basis https://www.landnutzen.at/api, nicht /api/v1. Er braucht keinen Key; die Auth-Modi des Reportpfads gelten hier nicht.

curl -X POST https://www.landnutzen.at/api/tools/standort-check \
  -H "Content-Type: application/json" \
  -d '{"address":"…","coordinates":{"lat":0,"lon":0},"locationProof":"…","regionCode":"AT-3","regionProof":"…"}'

Der Body akzeptiert ausschließlich diese fünf Felder. locationProof und regionProof sind signierte Nachweise aus der gewählten Antwort des Adressvorschlags GET /api/geo/suggest; Freitext ohne Auswahl wird abgewiesen (400). Die Antwort enthält je Quellenkarte Zustand (Treffer, Nullbefund, Abdeckungslücke, veraltet, gesperrt, Fehler), Quelle, Datenstand und Lizenz. Sie umfasst 13 Karten: 12 sind freigegeben, die Karte local-climate-zone (Lokale Klimazone) ist nicht freigegeben und kommt mit dem Zustand not_configured (lib/tools/site-check.ts, Stand 07.10.2026). Adresse, Koordinate und Nachweise werden nicht gespeichert, die Antwort trägt Cache-Control: private, no-store.

  • Limit: 30 Anfragen pro Tag und pseudonymem IP-Bucket (X-RateLimit-Limit, X-RateLimit-Remaining; 429 rate_limit_exceeded mit Retry-After: 86400).
  • Fehler: 400 (unter anderem input_invalid, address_selection_required, coords_invalid, location_selection_unverified, region_selection_unverified, invalid_json), 415 unsupported_media_type (nur application/json), 429 rate_limit_exceeded, 503 source_matrix_unavailable.
  • Messung: Jede bestätigte Prüfung zählt kennungsfrei als Start, Endzustand und Serverlauf der Tag-90-Kennzahl (seit 04.10.2026). Eigene Prüfläufe mit interner Markierung zählen getrennt (ADR-0079, siehe Admin-Dashboard).

GET /api/v1/data-sources/coverage-matrix

Öffentliche, maschinenlesbare Coverage- und Rechtematrix (Vertrag: Coverage-/Rechtematrix v1), ohne Key. Ein dokumentierter Status ist keine Verfügbarkeitsfreigabe: Erst qualifizierte Release-, Rechte-, Freshness-, Coverage- und Consumer-Gates öffnen eine Zelle.

  • Felder: schemaVersion, matrixVersion, evidenceUpdatedAt, scope, summary, regions (alle 9 Bundesländer), lanes, cells.
  • Caching: ETag und If-None-Match (304), Cache-Control: public, max-age=0, must-revalidate; 503, wenn das Coverage-/Rechte-Ledger nicht lesbar ist.
  • Beispielstand (Abruf 07.10.2026): matrixVersion 2026-10-04.site-check-zoning-vorarlberg-lane-v1, 42 Lanes, 378 Zellen, 9 Bundesländer. Die Zahlen ändern sich mit jeder Matrixversion; maßgeblich ist die Live-Antwort.

Tageslimits

Alle Limits sind pseudonyme Tageszähler (rate_limits); Defaults laut Code, Stand 07.10.2026 (die Report-Limits sind im Abschnitt „Authentifizierung und Report-Quota“ erklärt).

PfadZählerLimit pro Tag
GET/POST /api/v1/reportIP-, Konto- oder Key-Bucket10 (anonym), 10 (Konto), Key: daily_limit
GET /api/v1/report/{id}/pdf und GET /api/v1/report/{id}/sources/pdfgemeinsamer pdf:-Bucket je IP300 insgesamt
GET /api/v1/report/{id}/dxfdxf: je IP300
POST /api/tools/standort-checktool:site-check je IP30
POST /api/v1/org/{slug}/workspace/sites/{id}/refreshje Organisation75 (3 × 25 Standorte)
POST /api/v1/access-requestsje IP20

Die Hilfsendpunkte der Oberfläche außerhalb von /api/v1 haben eigene Limits (Adressvorschläge GET /api/geo/suggest 300, PV-Ertragsrechner 30, Karten-GeoJSON 300, WMS-Kacheln 3.000 pro Tag); sie sind nicht Teil der öffentlichen API-Zusage. 429 antwortet mit Retry-After: 86400.

Fehler-Envelope

Stabil bei jedem Nicht-2xx:

{ "error": { "code": "address_missing", "message": "…" } }
StatuscodeBedeutung
400address_missing / invalid_jsonEingabe fehlt/ungültig
401unauthorizedAPI-Key ungültig oder widerrufen
422address_not_foundkein unterstützter österreichischer Adresstreffer; Eingabe korrigieren, kein Report, keine Speicherung
429rate_limitedTageslimit erreicht (Retry-After)
500internalunerwarteter Fehler
503geocoding_unavailableAdresssuche vorübergehend nicht verfügbar; später erneut versuchen

Die Zeilen gelten für GET/POST /api/v1/report; 422 und 503 entstehen, bevor Quellen abgefragt werden, und zählen wie jede Anfrage zum Tageslimit. Die übrigen Endpunkte nennen ihre Codes im OpenAPI-Schema.

Admin: Werkzeug-KPIs

GET /api/v1/admin/metrics erfordert einen API-Key mit admin-Scope und liefert ausschließlich die kennungsfreien Aggregate aus ADR-0042: das gewählte rollierende Tagesfenster sowie Status und Kennzahlen des festen 14-Tage-Ausgangswerts.

ParameterWerteStandard
days1, 7, 14, 3014
toolstabile öffentliche Tool-ID oder allall

Die Antwort enthält Funnel-, Qualitäts-, Laufzeit-, Kosten-, Regions- und Providerzusammenfassungen sowie den Tagesverlauf. baselineSnapshot wird davon getrennt während D+1 bis einschließlich D+14 nach dem gemeinsamen Funnel-/Server-Anker fortgeschrieben. Mit Ablauf von D+14 ist er vollständig und bleibt ab D+15 unverändert. Der Snapshot bewahrt die Funnel-, Fehler-, Provider-, Runtime-, Laufzeit- und Kostendimensionen einschließlich Zählern und Summen, enthält aber weder Tag noch Region und bleibt unabhängig von der 30-Kalendertage-Retention der Tageswerte erhalten. Es gibt keinen Rohereignis-Endpunkt. Antworten tragen Cache-Control: private, no-store. Ist die Aggregation nicht verfügbar, antwortet der Endpunkt ehrlich mit 503 metrics_unavailable statt mit einer leeren Erfolgsantwort. internal weist eigene Prüfläufe im Fenster getrennt aus (available, funnelStarts, funnelCompletes, funnelHonestTerminals, serverRuns; ADR-0079); sie sind in keinem anderen Feld enthalten, der Tagesverlauf trägt sie als internalFunnelTerminals und internalServerRuns.

Ein ungültiges days ergibt 400 invalid_window, eine unbekannte Werkzeug-ID 400 invalid_tool; ohne Admin-Key antwortet die Route mit 401, ohne admin-Scope mit 403.

Der Standort-Check (tool=site-check) wird seit dem Deploy vom 04.10.2026 gezählt (Abschluss nach bestätigter Prüfanfrage) und misst seit Migration 0065 (#650) Laufzeit und Bundesland je Prüfung (server_run); bis 04.10.2026 war er nicht instrumentiert. Sein 14-Tage-Ausgangswert ist am 06.10.2026 neu verankert: Fortschreibung 07.10. bis 20.10.2026, unveränderlich ab 21.10.2026 (docs/evidence/interne-prueflaeufe-2026-10-06.md, Abschnitt 7).

Admin: Kosten pro Tool-Abschluss, Lead und Source Release

GET /api/v1/admin/cost-overview erfordert einen API-Key mit admin-Scope (Tag-90-Gate, docs/ROADMAP-90-TAGE-PLATTFORM.md, Abschnitt „Exit-Gates Tag 90“; Vertrag docs/contracts/admin-cost-overview-v1.md).

ParameterWerteStandard
days7, 14, 2828

Liefert ratios.toolCompletion, ratios.qualifiedLead und ratios.activeSourceRelease, je mit status ∈ "measured" (gemessene direkte Kosten + konfigurierte Infrastrukturkosten), "direct_only" (Infrastruktur nicht konfiguriert), "not_meaningful" (Nenner unter dokumentierter Mindestgröße), "not_captured" (Aggregation insgesamt fehlgeschlagen; der Lead-Nenner ist seit PAY-02 gemessen und trägt diesen Status nicht mehr dauerhaft) oder "cost_incomplete" (nicht zugeordnete Providerkosten im Fenster). Der Tool-Abschluss-Nenner zählt pv-yield und seit 04.10.2026 site-check. Direkte Kosten stammen ausschließlich aus MET-01; Infrastrukturkosten sind nie live abgerufen, sondern ein optionaler ENV-Konfigurationswert mit Pflichtangabe von Quelle und Datum (docs/API-ECONOMICS.md). budgetAlerts zeigt den Status des erzwungenen LLM-Budget-Caps (ADR-0017) sowie ehrliche Nicht-Verifizierbarkeits- Hinweise für Vercel Spend Management und Neon-Billing-Alerts. internalRuns (available, qualifiedCompletions, otherCompletions) weist eigene Prüfläufe als „davon intern“ aus; sie zählen nie in einem Nenner (ADR-0079).

Antworten tragen Cache-Control: private, no-store. Fehlt der Admin-Key, antwortet die Route mit 401; ein Key ohne admin-Scope erhält 403; ein ungültiges days ergibt 400 invalid_window. Ist die Aggregation nicht verfügbar, antwortet der Endpunkt mit 503 cost_overview_unavailable statt einer leeren Erfolgsantwort.

Admin: Datenquellen und Drift-Policy

GET /api/v1/admin/data-sources erfordert einen API-Key mit admin-Scope. Der bestehende Quellenkatalog, letzte technische Lauf und aktive Release bleiben unverändert; DATA-02 ergänzt ausschließlich additive v1-Felder:

{
  "generatedAt": "2026-08-25T10:47:00.000Z",
  "monitoring": {
    "cronName": "monitor-data-source-drift",
    "lastCheckedAt": "2026-08-25T10:47:00.000Z",
    "lastRunId": 123,
    "lastAlertDelivery": { "status": "sent" },
    "monitoredSources": 9,
    "counts": { "fresh": 8, "due": 1, "stale": 0, "failed": 0, "unknown": 0 }
  },
  "sources": [
    {
      "slug": "basemap-orthofoto",
      "activePointer": { "releaseId": "…", "pointerVersion": 2 },
      "monitoring": {
        "releaseId": "…",
        "pointerVersion": 2,
        "state": "due",
        "severity": "warning",
        "findings": [{ "code": "freshnessDue" }],
        "thresholds": { "dueLeadMinutes": 120 },
        "alert": { "status": "sent" }
      }
    }
  ]
}

Das Beispiel ist ein Schemaausschnitt, kein Produktionsreadback. Legacy- Quellen ohne Active Pointer erhalten monitoring: null. Freigegebene Teilabdeckung und bekannte Warnungen bleiben eine akzeptierte Baseline; erst relevante Änderungen, veraltete Frische oder fehlende Evidenz erzeugen due, stale, failed oder unknown.

Alle Antworten tragen Cache-Control: private, no-store. Fehlt der Admin-Key, antwortet die Route mit 401; ein Key ohne admin-Scope erhält 403. Ist der Quellen- oder Historienvertrag nicht vollständig lesbar, lautet die Antwort 503 data_sources_unavailable; ein leerer oder erfunden gesunder Status wird nicht ausgegeben. Der vollständige Contract ist in GET /api/v1/openapi.json unter /admin/data-sources dokumentiert.

Ehrliche Datenlage

Nicht verfügbare oder unsichere Datenschichten stehen in jedem Report unter meta.degraded (Layer, Grund, Fallback). Die Widmung ist eine Indikation (nicht rechtsverbindlich), Kostenrahmen sind Grob-Schätzungen. Quellen/Lizenzen je Report unter sources — siehe Datenquellen & Lizenzen.

Standortvergleich: parallele Anlagen

POST /api/v1/org/{slug}/workspace/sites begrenzt neue Anlagen auf 25 Standorte je Organisation, auch bei parallelen Requests (#597, ADR-0068). Der günstige Vorabzähler reserviert keinen Platz. Nach der Quellenabfrage prüft der Store unter einer organisationsbezogenen Transaktionssperre erneut. Ein unterlegener Request erhält wie eine bereits volle Organisation HTTP 409 site_limit_reached; technische DB-Fehler bleiben HTTP 500 workspace_unavailable. Andere Organisationen teilen diese Sperre nicht. Keine Idempotenzzusage: Wiederholungen sind Gegenstand von #596. Bestehender Überbestand wird nicht gelöscht; dessen separate Bestandsprüfung und die bestehende Listenbegrenzung sind in ADR-0068 dokumentiert.

Quellenanhang als PDF

GET /api/v1/report/{id}/sources/pdf liefert Quellen, Lizenzen, Langlinks und gespeicherte Provenienz desselben Report-Snapshots als separaten PDF-Download. Es werden keine Daten neu abgerufen. Erfolgreiche Antworten verwenden Content-Type: application/pdf, Content-Disposition: attachment und Cache-Control: private, no-store.

Fehler: 400 bei ungültigem ID-Format, 404 bei unbekanntem oder abgelaufenem Report, 429 beim gemeinsamen PDF-Tageslimit (mit Retry-After: 86400) und 500 bei fehlgeschlagener PDF-Erzeugung. Zugriff und ID-Vertrag entsprechen dem Haupt-PDF.