Buildings¶
Building endpoints provide access to building-level records in the Solar Lake Enterprise dataset.
Use these endpoints to:
- Retrieve a single building by
building_id - Resolve a building by a WGS84 coordinate
- Fetch many buildings in one request (IDs or points)
- Efficiently retrieve only the fields you need via projection (
options.select)
Authentication: All requests require
subscription_keyas a query parameter.
See authentication for details.
API Base URL¶
https://api.sle.urbananalytica.de
Building object¶
A building record includes:
- Address fields (
street,house_number,postcode,locality,county,state) - Administrative identifiers (
building_id,postcode,ags) - H3 references (
h3_4…h3_10) - Building characteristics (
building_type,building_area,roof_type,roof_area,building_height,heritage_protection) - PV & solar metrics (
pv,radiation,suitable_roof_area,building_kwh,building_kwp,building_panels,building_co2) - Economic indicators (
earnings,costs,amortization,total_earnings) - Grid/neighborhood metrics (
grid_count_buildings,grid_share_owned,grid_share_2020s,grid_population, …) - Roof-segment arrays (
roof_ids,roof_areas,roof_directions,roof_geoms, …) - Geometry as GeoJSON
coordinates→ Pointgeometry→ Polygon (building footprint)
For a detailed field-level specification, see the Building data model page.
1) Get building by ID¶
Retrieve the full building record for a given building_id.
Endpoint¶
GET /building
Query parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
| subscription_key | string | ✓ | 90-character API key |
| building_id | string | ✓ | 24-character building ID |
Example¶
curl "https://api.sle.urbananalytica.de/building?building_id=0009c4da348d4cc82f2d3448&subscription_key=YOUR_KEY"
Example response (simplified)¶
{
"building_id": "0009c4da348d4cc82f2d3448",
"street": "Hauptstraße",
"house_number": "12",
"postcode": "90461",
"locality": "Nürnberg",
"ags": "09564000",
"pv": false,
"roof_area": 120,
"heritage_protection": false,
"deal_size_class": "super",
"coordinates": {
"type": "Point",
"coordinates": [11.42, 48.69]
},
"geometry": {
"type": "Polygon",
"coordinates": [[[...]]]
}
}
2) Get building by coordinates¶
Resolve a building for a WGS84 point using containment-first matching with a limited nearest-building fallback.
Endpoint¶
GET /building-coordinates
Query parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
| subscription_key | string | ✓ | 90-character API key |
| lon | number | ✓ | Longitude (WGS84) |
| lat | number | ✓ | Latitude (WGS84) |
Description¶
This endpoint applies a two-step strategy to match a building to the input coordinate:
- Try an exact match by checking whether the point lies inside a building footprint.
- If no building contains the point, search for buildings within 2 meters of the point.
- Return the fallback match only when exactly one building is found within that 2 meter radius.
- If no building is within 2 meters, or if multiple buildings are within 2 meters, return no match.
Response¶
The GET response model is unchanged. It returns the building object on success and does not expose a match_type field.
If no unambiguous match can be resolved, the endpoint returns 404 Not Found.
Typical use cases¶
- User clicks on a map → resolve building
- Backend enrichment from coordinates
- QA/debugging
Examples¶
Exact match¶
The point lies inside a building footprint, so the building is returned immediately.
curl "https://api.sle.urbananalytica.de/building-coordinates?lon=7.1202&lat=51.481&subscription_key=YOUR_KEY"
{
"building_id": "ef863e08dd25e9e571995158",
"postcode": "90461",
"ags": "09564000",
"pv": false
}
Fallback match¶
The point is not inside any footprint, but exactly one building is within 2 meters, so that nearest building is returned.
{
"building_id": "ef863e08dd25e9e571995158",
"postcode": "90461",
"ags": "09564000",
"pv": false
}
No match¶
No building is returned when:
- no building is within 2 meters, or
- multiple buildings are within 2 meters and the fallback result would be ambiguous.
In these cases, GET /building-coordinates returns 404 Not Found.
3) Get buildings by IDs (batch)¶
Batch lookup of multiple buildings.
Endpoint¶
POST /buildings
Query parameters¶
| Parameter | Type | Required |
|---|---|---|
| subscription_key | string | ✓ |
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
| building_ids | array[string] | ✓ | List of 24-character building IDs |
| options.select | array[string] | Fields to include (projection) |
The API always includes
building_idin the response, even if not listed inselect.
Example¶
curl -X POST "https://api.sle.urbananalytica.de/buildings?subscription_key=YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"building_ids": [
"00cbacac2e8d30e5579d3dc1",
"0159c5881baa4c4037f58699"
],
"options": {
"select": ["building_id", "postcode", "roof_area", "pv"]
}
}'
Response shape¶
{
"requested": 2,
"returned": 2,
"missing_ids": [],
"items": [
{
"building_id": "00cbacac2e8d30e5579d3dc1",
"postcode": "90461",
"roof_area": 120,
"pv": false
}
]
}
4) Get buildings by coordinates (batch)¶
Resolve multiple WGS84 points in a single request.
Endpoint¶
POST /buildings-coordinates
Query parameters¶
| Parameter | Type | Required |
|---|---|---|
| subscription_key | string | ✓ |
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
| points | array[object] | ✓ | List of WGS84 points |
| points[].lon | number | ✓ | Longitude in WGS84 |
| points[].lat | number | ✓ | Latitude in WGS84 |
| points[].address | object | Optional address information for validation | |
| points[].address.street | string | Street | |
| points[].address.house_number | string | House number | |
| points[].address.postcode | string | Postcode | |
| points[].address.locality | string | Locality | |
| options.select | array[string] | Building fields to include |
Address validation works independently of
options.select. Address fields used internally for validation are not added to the returnedbuildingobject unless explicitly selected.
Description¶
This endpoint uses the same coordinate resolution strategy as GET /building-coordinates, but applies it independently to each input point.
The response echoes the original request coordinates so clients can match every result back to the input data:
- matched points are returned as
items[].input_point - unresolved points are returned as
missing_points
Use these echoed coordinates for client-side merging instead of relying on response order.
A point resolves to a nearby building when:
- the point is not inside any building footprint,
- the nearest building is within 2 meters, and
- that fallback candidate is unambiguous because it is the only building within 2 meters.
Matching logic¶
For each input point, the API evaluates matches in this order:
- Return the building immediately if the point lies inside a building footprint.
- Otherwise search for buildings within 2 meters of the point.
- Return a fallback match only if exactly one building is found within 2 meters.
- Otherwise return no match for that point.
Points without a match are listed in missing_points.
Optional address validation¶
Each point may include an optional address object. All address fields are optional. The coordinates remain the only input used to resolve the building; the supplied address does not influence building selection. It is normalized and compared only after a building has been resolved from the coordinates, as a plausibility check rather than a geocoding or postal-address verification service.
Address validation is supported only by POST /buildings-coordinates; GET /building-coordinates remains a coordinate-only lookup. address_validation is returned only when usable address information was supplied.
{
"points": [
{
"lon": 11.12625,
"lat": 49.43996,
"address": {
"street": "Valznerweiherstr.",
"house_number": "98",
"postcode": "90480",
"locality": "Nürnberg"
}
}
],
"options": {
"select": [
"building_id",
"pv",
"roof_area"
]
}
}
Response shape¶
{
"requested": 1,
"returned": 1,
"missing_points": [],
"items": [
{
"input_point": {
"lon": 11.12625,
"lat": 49.43996
},
"match_type": "inside",
"address_validation": {
"assessment": "exact",
"street_match": true,
"house_number_match": true,
"postcode_match": true,
"locality_match": true
},
"building": {
"building_id": "8975053b459c1bffec6f021f",
"pv": false,
"roof_area": 72
}
}
]
}
Response¶
Each result item contains:
input_point→ the original coordinate from the requestmatch_type→ how the building was resolved:insidenearest_within_2m
address_validation→ optional address plausibility result, returned only when usable address information was suppliedbuilding→ the matched building object
match_type is only available on POST /buildings-coordinates. It is not part of the GET endpoint response.
For address validation field results:
true→ the supplied field matches after normalizationfalse→ the supplied field does not matchnull→ the field was not supplied
The overall assessment can be:
exact→ street and house number match, and all other supplied fields matchprobable→ street and house number match, but postcode or locality differsdifferent→ street or house number differsinsufficient→ street or house number was not supplied
Examples¶
Exact match case¶
The point lies inside a building footprint.
{
"requested": 1,
"returned": 1,
"missing_points": [],
"items": [
{
"input_point": {
"lon": 7.1202,
"lat": 51.481
},
"match_type": "inside",
"building": {
"building_id": "ef863e08dd25e9e571995158",
"postcode": "90461",
"ags": "09564000",
"pv": false
}
}
]
}
Address validation case¶
The address is checked after the coordinate-based building match has been resolved.
{
"requested": 1,
"returned": 1,
"missing_points": [],
"items": [
{
"input_point": {
"lon": 11.576,
"lat": 48.137
},
"match_type": "inside",
"address_validation": {
"assessment": "probable",
"street_match": true,
"house_number_match": true,
"postcode_match": false,
"locality_match": true
},
"building": {
"building_id": "00cbacac2e8d30e5579d3dc1",
"pv": false,
"roof_area": 124
}
}
]
}
Fallback match case¶
The point is outside all footprints, but exactly one building is within 2 meters.
{
"requested": 1,
"returned": 1,
"missing_points": [],
"items": [
{
"input_point": {
"lon": 7.120215,
"lat": 51.481012
},
"match_type": "nearest_within_2m",
"building": {
"building_id": "ef863e08dd25e9e571995158",
"postcode": "90461",
"ags": "09564000",
"pv": false
}
}
]
}
No match case¶
No item is returned for a point when:
- no building is within 2 meters, or
- multiple buildings are within 2 meters and the fallback result would be ambiguous.
{
"requested": 1,
"returned": 0,
"missing_points": [
{
"lon": 7.1203,
"lat": 51.4812
}
],
"items": []
}
Notes¶
- Each result item includes the original
input_pointfor reliable client-side mapping back to the request. missing_pointscontains the original request coordinates that could not be resolved.match_typedistinguishes direct containment matches from the nearest-building fallback.- The endpoint guarantees a response for all input points:
- Points that cannot be resolved (including coordinates outside Germany) are returned in
missing_points.
- Points that cannot be resolved (including coordinates outside Germany) are returned in
Error handling¶
422 – Validation Error¶
Returned when query parameters or request bodies are invalid.
403 – Access Denied¶
Returned when subscription_key is missing or invalid.
Empty results¶
Batch endpoints return:
returned = 0- A list of
missing_idsormissing_points
This is not an error and should be handled as "not found".
Related endpoints¶
- Bounding-box building loading → see
endpoints/bounding-boxes.md - Bulk extraction by region (
POST /query/buildings) → seeendpoints/queries.md - API conventions (WGS84, GeoJSON, projection, pagination) → see
conventions.md