---
title: "Building footprints with heights and volumes (GeoJSON, sync)"
description: "Building footprints with heights and volumes, synchronously, as a GeoJSON FeatureCollection - the endpoint a Grasshopper / Rhino / CAD client extrudes locally.\n\nSource: the materialised `bo_buildings_vol` table (one row per cadastral AV footprint, 2.63 M buildings nationwide, integrated volume cascade roofer LoD2.2 → footprint prism → GWR → flat prism; rebuilt weekly) LEFT JOINed with the roofer LoD2.2 roof statistics (`building_footprint_rf`).\n\nSelect buildings by exactly one of:\n- **point + radius** - `lat`, `lng`, `radius_m` (1–500, default 100): every footprint within `radius_m` metres (exact test in LV95);\n- **bbox** - `bbox=minLng,minLat,maxLng,maxLat` (WGS84, at most ~1.5 km per side): every footprint intersecting the box;\n- **parcel** - `egrid=CH…`: buildings whose point-on-surface lies inside the parcel (parcel geometry from the serving parcel table).\n\n`crs=2056` returns LV95 metre coordinates (2 decimals) instead of WGS84 (7 decimals). `max_features` defaults to 1000 (hard cap 2000); `capped` tells you when the area held more.\n\nMeasured on production: 150 m radius in central Zürich → 22 buildings in ~80 ms; 500 m → ~800 buildings in ~0.6 s. 10 s statement timeout → 504. Results are Redis-cached for 24 h (`X-Cache: HIT|MISS`) and served `Cache-Control: private, max-age=3600` (token-gated, so never `public`).\n\nAuth: `token` header, or `?token=` on the GET so a URL can be pasted into a browser or a Grasshopper HTTP component. Errors are always JSON with a real status code (this is a new surface; no legacy plain-text mode)."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.aireon.ch/llms.txt
> Use this file to discover all available pages before exploring further.

Path: RES API (public) › Building3D

`GET /res_api/building_footprints`

Building footprints with heights and volumes, synchronously, as a GeoJSON FeatureCollection - the endpoint a Grasshopper / Rhino / CAD client extrudes locally.

Source: the materialised `bo_buildings_vol` table (one row per cadastral AV footprint, 2.63 M buildings nationwide, integrated volume cascade roofer LoD2.2 → footprint prism → GWR → flat prism; rebuilt weekly) LEFT JOINed with the roofer LoD2.2 roof statistics (`building_footprint_rf`).

Select buildings by exactly one of:
- **point + radius** - `lat`, `lng`, `radius_m` (1–500, default 100): every footprint within `radius_m` metres (exact test in LV95);
- **bbox** - `bbox=minLng,minLat,maxLng,maxLat` (WGS84, at most ~1.5 km per side): every footprint intersecting the box;
- **parcel** - `egrid=CH…`: buildings whose point-on-surface lies inside the parcel (parcel geometry from the serving parcel table).

`crs=2056` returns LV95 metre coordinates (2 decimals) instead of WGS84 (7 decimals). `max_features` defaults to 1000 (hard cap 2000); `capped` tells you when the area held more.

Measured on production: 150 m radius in central Zürich → 22 buildings in ~80 ms; 500 m → ~800 buildings in ~0.6 s. 10 s statement timeout → 504. Results are Redis-cached for 24 h (`X-Cache: HIT|MISS`) and served `Cache-Control: private, max-age=3600` (token-gated, so never `public`).

Auth: `token` header, or `?token=` on the GET so a URL can be pasted into a browser or a Grasshopper HTTP component. Errors are always JSON with a real status code (this is a new surface; no legacy plain-text mode).

## Authentication

Requires one of the following:

- `ResApiToken`, apiKey, in header, header `token`
- `ResApiTokenQuery`, apiKey, in query

## Query parameters

- `lat` (`getBuildingFootprints.query.lat`; number, optional): WGS84 latitude of the search centre (with `lng`, `radius_m`).
- `lng` (`getBuildingFootprints.query.lng`; number, optional): WGS84 longitude of the search centre.
- `radius_m` (`getBuildingFootprints.query.radius_m`; number, optional): Search radius in metres (clamped to 500).
  - min 1; max 500; default `100`
- `bbox` (`getBuildingFootprints.query.bbox`; string, optional): `minLng,minLat,maxLng,maxLat` in WGS84, at most ~1.5 km per side.
  - pattern `^-?[0-9.]+,-?[0-9.]+,-?[0-9.]+,-?[0-9.]+$`
- `egrid` (`getBuildingFootprints.query.egrid`; string, optional): Parcel EGRID; returns the buildings on that parcel.
  - pattern `^CH[0-9]{12}$`
- `crs` (`getBuildingFootprints.query.crs`; integer, optional): Output coordinate system: 4326 (WGS84 degrees) or 2056 (LV95 metres).
  - one of `4326`, `2056`; default `4326`
- `max_features` (`getBuildingFootprints.query.max_features`; integer, optional)
  - min 1; max 2000; default `1000`
- `token` (`getBuildingFootprints.query.token`; string, optional): RES API token as a query parameter (alternative to the `token` header).

## Code samples

### cURL

```bash
curl --request GET \
  --url https://res.aireon.ch/res_api/building_footprints \
  --header 'token: <token>'
```

### TypeScript

```typescript
const url = 'https://res.aireon.ch/res_api/building_footprints';
const options = {method: 'GET', headers: {token: '<token>'}};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "https://res.aireon.ch/res_api/building_footprints"

headers = {"token": "<token>"}

response = requests.get(url, headers=headers)

print(response.text)
```

## Responses

### 200

Footprints in the requested area.

#### Example

```json
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": 0,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          null
        ]
      },
      "properties": {
        "res_building_id": 0,
        "egid": 0,
        "objid": "string",
        "address": "string",
        "zip": 0,
        "city": "string",
        "canton": "string",
        "foot_area_m2": 0,
        "vol_m3": 0,
        "vol_src": "roofer_lod22",
        "height_m": 0,
        "h_ground_masl": 0,
        "h_roof_70p_masl": 0,
        "h_roof_max_masl": 0,
        "h_roof_min_masl": 0,
        "h_ridge_masl": 0,
        "roof_type": "string",
        "roof_planes": 0,
        "rf_state": "ok",
        "pc_vintage": 0,
        "floors": 0,
        "year": 0,
        "gstat": 0
      }
    }
  ],
  "numberReturned": 0,
  "capped": true,
  "timeStamp": "2019-08-24T14:15:22Z",
  "crs": {
    "type": "string",
    "properties": {
      "name": "string"
    }
  },
  "query": {},
  "source": {
    "table": "string",
    "roofer_table": "string",
    "vol_src_counts": {
      "property1": 0,
      "property2": 0
    },
    "height_definition": "string"
  }
}
```

- `type` (`getBuildingFootprints.response.200.type`; string, required)
- `features` (`getBuildingFootprints.response.200.features`; array<object>, required)
  - `type` (`getBuildingFootprints.response.200.features.type`; string, required)
  - `id` (`getBuildingFootprints.response.200.features.id`; integer, required): res_building_id - the suite-wide stable building key (also the feature id in the bo_buildings_vol vector tiles).
  - `geometry` (`getBuildingFootprints.response.200.features.geometry`; object, required): A GeoJSON geometry object (Polygon or MultiPolygon here).
    - `type` (`getBuildingFootprints.response.200.features.geometry.type`; string, required)
      - one of `"Polygon"`, `"MultiPolygon"`, `"Point"`, `"LineString"`, `"MultiLineString"`, `"MultiPoint"`, `"GeometryCollection"`
    - `coordinates` (`getBuildingFootprints.response.200.features.geometry.coordinates`; array<unknown>, required)
  - `properties` (`getBuildingFootprints.response.200.features.properties`; object, required)
    - `res_building_id` (`getBuildingFootprints.response.200.features.properties.res_building_id`; integer, optional)
    - `egid` (`getBuildingFootprints.response.200.features.properties.egid`; integer | null, optional): Federal building identifier (GWR EGID).
    - `objid` (`getBuildingFootprints.response.200.features.properties.objid`; string | null, optional): Cadastral (AV) object id - not unique.
    - `address` (`getBuildingFootprints.response.200.features.properties.address`; string | null, optional)
    - `zip` (`getBuildingFootprints.response.200.features.properties.zip`; integer | null, optional)
    - `city` (`getBuildingFootprints.response.200.features.properties.city`; string | null, optional)
    - `canton` (`getBuildingFootprints.response.200.features.properties.canton`; string | null, optional)
    - `foot_area_m2` (`getBuildingFootprints.response.200.features.properties.foot_area_m2`; number | null, optional): Footprint area in m² (computed in LV95).
    - `vol_m3` (`getBuildingFootprints.response.200.features.properties.vol_m3`; number | null, optional): Building volume in m³ from the integrated cascade.
    - `vol_src` (`getBuildingFootprints.response.200.features.properties.vol_src`; string | null, optional): Which estimator produced `vol_m3` (roofer LoD2.2 solid → footprint prism from measured height → GWR volume → GWR floors × 3 m → flat 3 m prism).
      - one of `"roofer_lod22"`, `"footprint_prism"`, `"gwr_gvol"`, `"gwr_floors_prism"`, `"flat_prism"`, `"none"`, `null`
    - `height_m` (`getBuildingFootprints.response.200.features.properties.height_m`; number | null, optional): Building height in metres: roof 70th percentile minus ground for roofer buildings, otherwise the height the volume estimator used.
    - `h_ground_masl` (`getBuildingFootprints.response.200.features.properties.h_ground_masl`; number | null, optional): Ground elevation at the footprint, m a.s.l. (roofer only).
    - `h_roof_70p_masl` (`getBuildingFootprints.response.200.features.properties.h_roof_70p_masl`; number | null, optional): Roof elevation, 70th percentile of LiDAR roof points, m a.s.l. (roofer only).
    - `h_roof_max_masl` (`getBuildingFootprints.response.200.features.properties.h_roof_max_masl`; number | null, optional)
    - `h_roof_min_masl` (`getBuildingFootprints.response.200.features.properties.h_roof_min_masl`; number | null, optional)
    - `h_ridge_masl` (`getBuildingFootprints.response.200.features.properties.h_ridge_masl`; number | null, optional)
    - `roof_type` (`getBuildingFootprints.response.200.features.properties.roof_type`; string | null, optional): slanted | horizontal | unknown (roofer classification).
    - `roof_planes` (`getBuildingFootprints.response.200.features.properties.roof_planes`; integer | null, optional)
    - `rf_state` (`getBuildingFootprints.response.200.features.properties.rf_state`; string | null, optional): Roofer status: ok = LoD2.2 solid available; novol = reconstructed without a valid volume; norecon = not reconstructed.
      - one of `"ok"`, `"novol"`, `"norecon"`, `null`
    - `pc_vintage` (`getBuildingFootprints.response.200.features.properties.pc_vintage`; integer | null, optional): swissSURFACE3D point-cloud vintage year used by the roofer.
    - `floors` (`getBuildingFootprints.response.200.features.properties.floors`; integer | null, optional): GWR floor count.
    - `year` (`getBuildingFootprints.response.200.features.properties.year`; integer | null, optional): GWR construction year.
    - `gstat` (`getBuildingFootprints.response.200.features.properties.gstat`; integer | null, optional): GWR building status code (1004 = existing).
- `numberReturned` (`getBuildingFootprints.response.200.numberReturned`; integer, required)
- `capped` (`getBuildingFootprints.response.200.capped`; boolean, required): True when more buildings matched than `max_features`; narrow the area or tile the request. Capped answers are not cached.
- `crs` (`getBuildingFootprints.response.200.crs`; object, required): GeoJSON named CRS: `urn:ogc:def:crs:EPSG::4326` (default) or `urn:ogc:def:crs:EPSG::2056` when `crs=2056` was requested.
  - `type` (`getBuildingFootprints.response.200.crs.type`; string, optional)
  - `properties` (`getBuildingFootprints.response.200.crs.properties`; object, optional)
    - `name` (`getBuildingFootprints.response.200.crs.properties.name`; string, optional)
- `query` (`getBuildingFootprints.response.200.query`; object, required): The normalised filter that was applied (mode point|bbox|egrid with its parameters).
- `source` (`getBuildingFootprints.response.200.source`; object, required)
  - `table` (`getBuildingFootprints.response.200.source.table`; string, optional)
  - `roofer_table` (`getBuildingFootprints.response.200.source.roofer_table`; string, optional)
  - `vol_src_counts` (`getBuildingFootprints.response.200.source.vol_src_counts`; map<integer>, optional)
  - `height_definition` (`getBuildingFootprints.response.200.source.height_definition`; string, optional)
- `timeStamp` (`getBuildingFootprints.response.200.timeStamp`; string, optional)
  - format `date-time`

### 400

Invalid request.

#### Example

```json
{
  "error": "string",
  "message": "string"
}
```

- `error` (`getBuildingFootprints.response.400.error`; string, required): Human-readable error description.
- `message` (`getBuildingFootprints.response.400.message`; string, optional): Optional underlying error message.

### 401

Authentication missing or invalid.

#### Example

```json
{
  "error": "string",
  "message": "string"
}
```

- `error` (`getBuildingFootprints.response.401.error`; string, required): Human-readable error description.
- `message` (`getBuildingFootprints.response.401.message`; string, optional): Optional underlying error message.

### 403

Authenticated but not permitted.

#### Example

```json
{
  "error": "string",
  "message": "string"
}
```

- `error` (`getBuildingFootprints.response.403.error`; string, required): Human-readable error description.
- `message` (`getBuildingFootprints.response.403.message`; string, optional): Optional underlying error message.

### 500

Server error.

#### Example

```json
{
  "error": "string",
  "message": "string"
}
```

- `error` (`getBuildingFootprints.response.500.error`; string, required): Human-readable error description.
- `message` (`getBuildingFootprints.response.500.message`; string, optional): Optional underlying error message.

### 504

The PostGIS query exceeded the 10 s statement timeout - narrow the area.

#### Example

```json
{
  "error": "string",
  "detail": "string"
}
```

- `error` (`getBuildingFootprints.response.504.error`; string, optional)
- `detail` (`getBuildingFootprints.response.504.detail`; string, optional)


Source: https://docs.aireon.ch/res/get-building-footprints/index.md
