GET /v1/buildings

Föderierte LoD2-Gebäude-Suche per Bounding-Box

stable seit v0.1.0 buildings auth: none

GET /v1/buildings — Gebäude per Bounding-Box

Föderierte GeoJSON-FeatureCollection aller LoD2-Surfaces innerhalb einer WGS84-Bounding-Box. „Föderiert” bedeutet: die API durchsucht alle Bundesländer mit import_finished_at IS NOT NULL parallel und mischt die Ergebnisse. Aus Konsumentensicht: eine API für 16 Bundesländer.

Wichtig — Surface-Level: Jedes Feature ist eine einzelne Surface (Wall/Ground/Roof), nicht ein ganzes Gebäude. Mehrere Surfaces gehören über building_id zum selben Gebäude — zum Rekonstruieren eines Gebäudes nach building_id gruppieren.

Wann verwenden

Wenn du eine bbox > ~1 km² brauchst → eher /v1/tilesets verwenden (3D-Tiles streamen). /v1/buildings ist für detail-orientierte, kleinflächige Queries.

Examples

curl — kleine bbox Frankfurt-Mitte

curl -s "https://api.lodapi.de/v1/buildings?bbox=8.66,50.108,8.665,50.111&limit=50" | jq '.count, .features[0].properties'

Python — bbox + Pagination

import httpx

def fetch_all_buildings(bbox: str, limit: int = 1000):
    cursor = None
    while True:
        params = {"bbox": bbox, "limit": limit}
        if cursor:
            params["cursor"] = cursor
        r = httpx.get("https://api.lodapi.de/v1/buildings", params=params)
        r.raise_for_status()
        data = r.json()
        yield from data["features"]
        cursor = data["lodapi"]["next"]
        if not cursor:
            break

for feature in fetch_all_buildings("8.66,50.108,8.69,50.13"):
    print(feature["id"], feature["properties"]["surface_class"])

TypeScript — Cesium-Anbindung

import * as Cesium from "cesium";

const r = await fetch(
  "https://api.lodapi.de/v1/buildings?bbox=8.66,50.108,8.665,50.111&limit=200"
);
const fc = await r.json();
const ds = await Cesium.GeoJsonDataSource.load(fc, { clampToGround: false });
viewer.dataSources.add(ds);

Parameters

ParameterInTypeRequiredDefaultBeschreibung
bboxquerystringyesWGS84 minLon,minLat,maxLon,maxLat (Komma-separiert)
limitqueryintno1001 ≤ limit ≤ 1000
cursorquerystringnoOpaque cursor aus lodapi.next des vorherigen Calls

Response

200 OK · application/json — GeoJSON-FeatureCollection. Schema-Quelle openapi.json.

{
  "type": "FeatureCollection",
  "bbox": [8.66, 50.108, 8.665, 50.111],
  "count": 47,
  "limit": 100,
  "features": [
    {
      "type": "Feature",
      "id": "DEHE_LOD2_45292_GMLID_1",
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [[[ [8.661, 50.108, 105.2], ... ]]]
      },
      "properties": {
        "surface_id": 12345678,
        "building_id": 987654,
        "gmlid": "DEHE_LOD2_45292_GMLID_1",
        "surface_class": 712,
        "bundesland": "he",
        "lod": "LoD2"
      }
    }
  ],
  "lodapi": {
    "attribution": [
      {
        "source": "HLBG",
        "license": "DL-DE/Zero 2.0",
        "url": "https://www.govdata.de/dl-de/zero-2-0",
        "tiles_count": 1
      }
    ],
    "next": "aGU6MTIzNDU2Nzg="
  }
}

Attribution

Jede Antwort enthält lodapi.attribution[] mit einem Eintrag pro Bundesland, das in den features[] vorkommt. Die Felder:

FeldBedeutung
sourceBehörden-/Geobasis-Stelle (z.B. „HLBG”, „BezReg Köln”)
licenseDL-DE/Zero 2.0, CC BY 4.0 oder DL-DE BY 2.0
urlLizenz-URL für Verweis im UI
tiles_countnicht verwendet bei /v1/buildings (immer 1)

Frontend-Pflicht: Bei license != DL-DE/Zero 2.0 muss der source-String sichtbar in der Map-Footer-Zeile stehen (siehe Attribution-Guide).

Cursor-Pagination

/v1/buildings verwendet opaque cursor pagination statt OFFSET, weil OFFSET auf großen PostGIS-bbox-Resultaten pathologisch langsam ist. Der Cursor ist ein base64-codiertes <bundesland>:<surface_id>-Tupel — clients sollten ihn als opak behandeln.

Achtung: Der Cursor ist federation-aware (breaking change ggü. Phase-1-Clients, siehe README). Cursor aus altem Format führen zu 400.

Stolperdrähte

Verwandte Endpoints

Verwandt

Bereit?

Hol dir deinen API-Key.

1.000 Calls und 1 GB Tile-Daten kostenlos pro Monat — ohne Kreditkarte, ohne Ablaufdatum.