Überblick
Die API liefert amtliche Bodenrichtwerte (BRW) zu einer deutschen Adresse. Die Adresse wird
geokodiert, das Bundesland erkannt und der jeweils zuständige amtliche Geodienst abgefragt —
standardmäßig zum aktuellsten Stichtag, auf Wunsch zu einem historischen (Parameter
stichtag). Basis-URL ist die Domain dieser Seite, alle Antworten sind JSON
(UTF-8). Das Tool ist kostenlos und ohne Key nutzbar; ein API-Key erhöht lediglich die Limits.
Optional je Adresse: das amtliche ALKIS-Flurstück (mit_flurstueck) und ein
rechnerischer Bodenwert (mit_bodenwert) — beides derzeit nur für NW und ST.
Beide Optionen gibt es auch im CSV-Batch.
Hinweis: Bayern (BY) ist derzeit nicht enthalten — Lizenzlage ungeklärt.
Endpunkte
GET /api/v1/abfrage — Einzelabfrage einer Adresse (synchron)
| Parameter | Typ | Beschreibung |
|---|---|---|
| adresse | Query, Pflicht | 5–300 Zeichen, z. B. Domplatz 1, 39104 Magdeburg |
| kompakt | Query, optional | true = schlanke Antwort ohne roh_payload und Geometrie (für Integrationen) |
| mit_flurstueck | Query, optional | true = amtliches ALKIS-Flurstück an der Adresse ergänzen. Nur NW und ST — andere Länder liefern den Bodenrichtwert unverändert, aber kein Flurstück. |
| mit_bodenwert | Query, optional | true = rechnerischer Bodenwert (amtliche Fläche × amtlicher BRW, je Zone anteilig). Impliziert mit_flurstueck. |
| stichtag | Query, optional | JJJJ-MM-TT — historischer Stichtag. Freigegeben für BE, SN, ST, TH. Ohne den Parameter gilt immer der aktuellste Wert. |
Historischer Stichtag. Die Abfrage ist geografisch adressiert: „welcher amtliche Wert galt an diesem Punkt zu diesem Stichtag?“ — nicht „was machte Zone X über die Jahre?“. Zonennummern und -zuschnitte sind über Jahrgänge nicht stabil, ein Join über die Nummer würde verschiedene Flächen vermischen.
Ein nicht vorhandener Stichtag wird nie stillschweigend durch den nächstgelegenen oder aktuellen Wert ersetzt. Stattdessen:
{
"fehler_typ": "stichtag_nicht_verfuegbar",
"stichtag_angefragt": "2016-01-01",
"verfuegbare_stichtage": ["2016-12-31", "2018-12-31", "2020-12-31", "2022-01-01"],
"treffer": []
}
Für ein Land ohne Historie-Freigabe:
fehler_typ: "historie_fuer_land_nicht_verfuegbar". Achtung: die Länder mischen die
Stichtagskonvention — Thüringen führt 2008–2020 als JJJJ-12-31 und erst ab 2022 als
JJJJ-01-01. 2016-01-01 ist dort leer, 2016-12-31 liefert
einen Wert. JJJJ-12-31 und 01.01.(JJJJ+1) sind
verschiedene Ermittlungszeitpunkte (§ 196 Abs. 1 Satz 5 BauGB, geändert zum 23.06.2021)
und werden nicht zusammengelegt.
Bodenwert.
ist_amtlich ist immer false: amtlich sind die beiden Eingangswerte
(Fläche, Bodenrichtwert), die Multiplikation und Flächenaufteilung sind unsere Berechnung.
bodenwert_gesamt_eur ist null, wenn Zonen dieselbe Fläche überdecken —
dann sind die Teilwerte alternative Wertansätze, keine Summanden, und Addieren wäre
fachlich falsch. Der Grund steht maschinenlesbar in abdeckung und im Klartext in
hinweise.
Beispielantwort (gekürzt):
{
"eingabe_adresse": "Domplatz 1, 39104 Magdeburg",
"geocode_status": "ok",
"longitude": 11.6339,
"latitude": 52.1250,
"treffer": [
{
"bodenrichtwert_eur_qm": 250.0,
"stichtag": "2024-12-31",
"bodenrichtwertzone_name": "...",
"quelle": { "land": "ST", "dienst_bezeichnung": "..." },
"attribution": {
"bereitsteller": "(c) GeoBasis-DE / LVermGeo ST (...)",
"lizenz": "dl-de/by-2-0",
"lizenz_uri": "https://www.govdata.de/dl-de/by-2-0"
},
"modified": "Schema normalisiert, Werte unveraendert"
}
],
"fehler": null
}
Jeder Treffer trägt die lizenzpflichtige attribution
(Bereitsteller · Lizenz · URI) und den Änderungshinweis modified.
Diese sind bei jeder Weiterverwendung mitzuführen.
POST /api/v1/batch — CSV-Batch starten (asynchron)
| Parameter | Typ | Beschreibung |
|---|---|---|
| datei | multipart/form-data, Pflicht | CSV, max. 1 MB (siehe CSV-Format) |
| mit_flurstueck | Form-Feld, optional | true = ALKIS-Flurstück je Adresse (nur NW/ST) |
| mit_bodenwert | Form-Feld, optional | true = rechnerischer Bodenwert je Adresse; impliziert mit_flurstueck |
| stichtag | Form-Feld, optional | JJJJ-MM-TT — gilt für den gesamten Lauf, gleiche Regeln wie bei /api/v1/abfrage |
Antwort: { "job_id": "abc123...", "adressen": 12, "status": "wartet", "optionen": {...} }
Die Zusatzoptionen verlängern den Lauf spürbar (je Adresse weitere
amtliche Abrufe). Die XLSX enthält dann die Flurstücks- und Bodenwertspalten sowie das
Detailblatt Bodenwert mit einer Zeile je Teilfläche.
GET /api/v1/batch/{job_id} — Job-Status abfragen
Antwort enthält status (wartet/laeuft/fertig/fehler), verarbeitet, treffer, fehler.
GET /api/v1/batch/{job_id}/download?format=xlsx|json — Ergebnis herunterladen
Liefert die XLSX- bzw. JSON-Datei. Verfügbar, sobald status = fertig.
GET /api/v1/batch/{job_id}/vorschau?limit=20 — Ergebnis-Vorschau (JSON)
GET /api/v1/flurstueck — Flurstück per amtlichem Kennzeichen
| Parameter | Typ | Beschreibung |
|---|---|---|
| kennzeichen | Query, Pflicht | ALKIS-flstkennz, z. B. 150938145050080001__ |
| mit_bodenwert | Query, optional | true = rechnerischer Bodenwert je Flurstück |
Das Land wird aus den ersten beiden Stellen abgeleitet
(05 = NW, 15 = ST); andere Präfixe liefern HTTP 400 mit klarer Meldung.
Das Kennzeichen ist fix 20-stellig und rechts mit Unterstrichen aufgefüllt — kürzere
Eingaben werden serverseitig aufgefüllt.
GET /api/v1/laender — aktive Länder, Limits & Quellenvermerke
Das Feld aufrufer zeigt, welche Limits für Sie gelten (erkannt/anonym) — ideal zum Prüfen Ihres Keys.
datenlage weist je Land aus, was der amtliche Dienst
wirklich hergibt: geometrie (Zonenfläche für die Karte), klartext
(Klartext oder nur amtliche Codes), historie (ist stichtag freigegeben)
und zeitreihe (zusätzlich mit Zonenfläche je Stichtag). Die Listen
historie_laender und zeitreihe_laender geben dasselbe kompakt.
GET /health — Health-Check (status, version, zeit)
Rate-Limit & API-Keys
| Zugang | Adressen/Batch | Anfragen/Stunde | Zählung |
|---|---|---|---|
| anonym | 100 | 5 | pro IP-Adresse |
| mit gültigem API-Key | 500 | 100 | pro Schlüssel |
Der Key wird per Header X-API-Key: <key> übergeben; alternativ
Authorization: Bearer <key>. Jede Antwort enthält die Header
X-RateLimit-Limit und X-RateLimit-Remaining. Firmenkunden hinter einem
gemeinsamen Proxy werden pro Schlüssel gezählt, nicht pro IP.
Einen Test-Key können Sie formlos per E-Mail anfragen: foerster.max97@gmail.com.
CSV-Format für Batch-Uploads
CSV (UTF-8 oder Latin-1), eine Adresse je Zeile. Erste Zeile darf die Kopfzeile
adresse sein (optional). Enthält eine Zeile mehrere Spalten, werden diese zu einer
Adresse zusammengefügt. Duplikate werden entfernt. Maximal 1 MB.
adresse
Domplatz 1, 39104 Magdeburg
Aegidientorplatz 1, 30159 Hannover
Rathausstraße 15, 10178 Berlin
Copy-&-Paste-Beispiele
curl
# Einzelabfrage, ohne Key
curl "https://IHRE-DOMAIN/api/v1/abfrage?adresse=Domplatz%201%2C%2039104%20Magdeburg"
# Einzelabfrage, mit API-Key
curl -H "X-API-Key: IHR_KEY" \
"https://IHRE-DOMAIN/api/v1/abfrage?adresse=Domplatz%201%2C%2039104%20Magdeburg"
# Batch-Upload (mit Key via Bearer)
curl -H "Authorization: Bearer IHR_KEY" \
-F "datei=@adressen.csv" \
"https://IHRE-DOMAIN/api/v1/batch"
Python (requests)
import requests
BASIS = "https://IHRE-DOMAIN"
# ohne Key
r = requests.get(f"{BASIS}/api/v1/abfrage",
params={"adresse": "Domplatz 1, 39104 Magdeburg"})
print(r.json())
# mit Key
kopf = {"X-API-Key": "IHR_KEY"}
r = requests.get(f"{BASIS}/api/v1/abfrage",
params={"adresse": "Domplatz 1, 39104 Magdeburg"},
headers=kopf)
print(r.headers.get("X-RateLimit-Remaining"), r.json())
# Batch mit Key
with open("adressen.csv", "rb") as f:
r = requests.post(f"{BASIS}/api/v1/batch",
files={"datei": f}, headers=kopf)
job = r.json()["job_id"]
JavaScript (fetch)
const BASIS = "https://IHRE-DOMAIN";
// ohne Key
const r1 = await fetch(
`${BASIS}/api/v1/abfrage?adresse=` +
encodeURIComponent("Domplatz 1, 39104 Magdeburg"));
console.log(await r1.json());
// mit Key
const r2 = await fetch(
`${BASIS}/api/v1/abfrage?adresse=` +
encodeURIComponent("Domplatz 1, 39104 Magdeburg"),
{ headers: { "X-API-Key": "IHR_KEY" } });
console.log(r2.headers.get("X-RateLimit-Remaining"), await r2.json());
// Batch mit Key
const fd = new FormData();
fd.append("datei", dateiObjekt); // File aus
const r3 = await fetch(`${BASIS}/api/v1/batch`,
{ method: "POST", body: fd, headers: { "X-API-Key": "IHR_KEY" } });
Fehlercodes
| Code | Bedeutung |
|---|---|
| 400 | Ungültige Eingabe (keine Adressen erkannt oder zu viele Adressen im Batch) |
| 401 | Ungültiger API-Key |
| 404 | Job oder Ergebnis nicht gefunden |
| 413 | Upload zu groß (max. 1 MB) |
| 429 | Rate-Limit überschritten (siehe X-RateLimit-*-Header) |
Fehler werden als JSON { "detail": "..." } mit deutscher Meldung zurückgegeben.
Ein Abruffehler erscheint nie als „0 Treffer“, sondern als Fehler-/Hinweistext im jeweiligen Ergebnis.
Quellenvermerkspflicht
Die gelieferten Werte stammen unverändert aus amtlichen Diensten der Bundesländer und stehen
unter Lizenzen wie dl-de/by-2-0 bzw. dl-de/zero-2.0. Bei jeder Weiterverwendung
der Daten sind die zugehörigen Quellen-/Namensnennungen mitzuführen. Die vollständige Liste liefert
GET /api/v1/laender (Feld quellenvermerke) und steht in jedem Export.
Maschinenlesbar liegt sie je Treffer im Feld attribution vor.
Geocoding: Koordinaten stammen von © OpenStreetMap-Mitwirkenden (ODbL), ermittelt über Nominatim / Photon — bei Weitergabe von Koordinaten mitzuführen.