---
title: "Building volume statistics inside an arbitrary drawn polygon"
description: "The polygon counterpart of `/res_api/bldg_vol_bbox`: instead of a circular buffer it evaluates the ACTUAL polygon in PostGIS, so the count matches exactly what the user drew. A building belongs to the polygon when its footprint CENTROID (`building_footprint_rf.geom`) is inside - no double counting across neighbouring polygons, no boundary bleed. Volumes are `rf_volume_lod22` (roofer LoD2.2).\n\nThe outer ring is closed automatically, must have ≥ 3 distinct vertices and ≤ 10,000, and its geodesic area is gated to 2,500..250,000 m² (mirroring the footprint client's drawing limits) by a cheap area-only query BEFORE the footprint count runs. The response mirrors `/bldg_vol_bbox` field-for-field so density clients render it unchanged; `density.bbox_area_m2` is the polygon's own area.\n\nAuth quirk inherited from `/bldg_vol_bbox`: a MISSING `token` header is a **400**, a WRONG one is a **401** (not 401/403). Real status codes, JSON bodies, no `X-RES-API-Version` needed. Not cached."
---

> 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) › Parcel

`POST /res_api/bldg_vol_polygon`

The polygon counterpart of `/res_api/bldg_vol_bbox`: instead of a circular buffer it evaluates the ACTUAL polygon in PostGIS, so the count matches exactly what the user drew. A building belongs to the polygon when its footprint CENTROID (`building_footprint_rf.geom`) is inside - no double counting across neighbouring polygons, no boundary bleed. Volumes are `rf_volume_lod22` (roofer LoD2.2).

The outer ring is closed automatically, must have ≥ 3 distinct vertices and ≤ 10,000, and its geodesic area is gated to 2,500..250,000 m² (mirroring the footprint client's drawing limits) by a cheap area-only query BEFORE the footprint count runs. The response mirrors `/bldg_vol_bbox` field-for-field so density clients render it unchanged; `density.bbox_area_m2` is the polygon's own area.

Auth quirk inherited from `/bldg_vol_bbox`: a MISSING `token` header is a **400**, a WRONG one is a **401** (not 401/403). Real status codes, JSON bodies, no `X-RES-API-Version` needed. Not cached.

## Authentication

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

## Request body

_Required._

- `polygon` (`getBuildingVolumePolygon.polygon`; object, optional)
  - `type` (`getBuildingVolumePolygon.polygon.type`; string, required)
  - `coordinates` (`getBuildingVolumePolygon.polygon.coordinates`; array<array<array<number>>>, required): GeoJSON rings, WGS84 `[lng, lat]`.
- `ring` (`getBuildingVolumePolygon.ring`; array<array<number>>, optional): Outer ring as `[[lng, lat], …]`. Closed automatically if the last vertex differs from the first.
- `coordinates` (`getBuildingVolumePolygon.coordinates`; array<array<number>>, optional): Alias of `ring`.

## Example requests

### GeoJSON Polygon

```json
{
  "polygon": {
    "type": "Polygon",
    "coordinates": [
      [
        [
          8.54,
          47.376
        ],
        [
          8.545,
          47.376
        ],
        [
          8.545,
          47.379
        ],
        [
          8.54,
          47.379
        ],
        [
          8.54,
          47.376
        ]
      ]
    ]
  }
}
```

### Bare ring

```json
{
  "ring": [
    [
      8.54,
      47.376
    ],
    [
      8.545,
      47.376
    ],
    [
      8.545,
      47.379
    ],
    [
      8.54,
      47.379
    ]
  ]
}
```

## Code samples

### cURL

```bash
curl --request POST \
  --url https://res.aireon.ch/res_api/bldg_vol_polygon \
  --header 'Content-Type: application/json' \
  --header 'token: <token>' \
  --data '
{
  "polygon": {
    "type": "Polygon",
    "coordinates": [
      [
        [
          8.54,
          47.376
        ],
        [
          8.545,
          47.376
        ],
        [
          8.545,
          47.379
        ],
        [
          8.54,
          47.379
        ],
        [
          8.54,
          47.376
        ]
      ]
    ]
  }
}
'
```

### TypeScript

```typescript
const url = 'https://res.aireon.ch/res_api/bldg_vol_polygon';
const options = {
  method: 'POST',
  headers: {'Content-Type': 'application/json', token: '<token>'},
  body: JSON.stringify({
    polygon: {
      type: 'Polygon',
      coordinates: [
        [
          [8.54, 47.376],
          [8.545, 47.376],
          [8.545, 47.379],
          [8.54, 47.379],
          [8.54, 47.376]
        ]
      ]
    }
  })
};

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/bldg_vol_polygon"

payload = { "polygon": {
        "type": "Polygon",
        "coordinates": [[[8.54, 47.376], [8.545, 47.376], [8.545, 47.379], [8.54, 47.379], [8.54, 47.376]]]
    } }
headers = {
    "Content-Type": "application/json",
    "token": "<token>"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
```

## Responses

### 200

Building volume statistics for the polygon.

#### Example

```json
{
  "success": true,
  "input": {
    "vertex_count": 4,
    "polygon_area_m2": 125874.3
  },
  "statistics": {
    "total_building_count": 87,
    "buildings_with_volume": 85,
    "buildings_without_volume": 2,
    "total_volume_m3": 412350.5,
    "avg_volume_m3": 4851.2,
    "min_volume_m3": 120.4,
    "max_volume_m3": 38210.9,
    "total_footprint_area_m2": 31240.7
  },
  "density": {
    "bbox_area_m2": 125874.3,
    "volume_density_bbox_m3_per_m2": 3.2759,
    "volume_density_footprint_m3_per_m2": 13.1991
  }
}
```

- `success` (`getBuildingVolumePolygon.response.200.success`; boolean, optional)
- `input` (`getBuildingVolumePolygon.response.200.input`; object, optional)
  - `vertex_count` (`getBuildingVolumePolygon.response.200.input.vertex_count`; integer, optional): Distinct vertices of the closed ring.
  - `polygon_area_m2` (`getBuildingVolumePolygon.response.200.input.polygon_area_m2`; number, optional): Geodesic area of the polygon.
- `statistics` (`getBuildingVolumePolygon.response.200.statistics`; object, optional)
  - `total_building_count` (`getBuildingVolumePolygon.response.200.statistics.total_building_count`; integer, optional)
  - `buildings_with_volume` (`getBuildingVolumePolygon.response.200.statistics.buildings_with_volume`; integer, optional)
  - `buildings_without_volume` (`getBuildingVolumePolygon.response.200.statistics.buildings_without_volume`; integer, optional)
  - `total_volume_m3` (`getBuildingVolumePolygon.response.200.statistics.total_volume_m3`; number, optional)
  - `avg_volume_m3` (`getBuildingVolumePolygon.response.200.statistics.avg_volume_m3`; number | null, optional)
  - `min_volume_m3` (`getBuildingVolumePolygon.response.200.statistics.min_volume_m3`; number | null, optional)
  - `max_volume_m3` (`getBuildingVolumePolygon.response.200.statistics.max_volume_m3`; number | null, optional)
  - `total_footprint_area_m2` (`getBuildingVolumePolygon.response.200.statistics.total_footprint_area_m2`; number, optional)
- `density` (`getBuildingVolumePolygon.response.200.density`; object, optional)
  - `bbox_area_m2` (`getBuildingVolumePolygon.response.200.density.bbox_area_m2`; number, optional): Named for compatibility with `/res_api/bldg_vol_bbox`; here it is the polygon's own area (m²).
  - `volume_density_bbox_m3_per_m2` (`getBuildingVolumePolygon.response.200.density.volume_density_bbox_m3_per_m2`; number, optional): total_volume_m3 / polygon area, 4 dp.
  - `volume_density_footprint_m3_per_m2` (`getBuildingVolumePolygon.response.200.density.volume_density_footprint_m3_per_m2`; number, optional): total_volume_m3 / total footprint area, 4 dp.

### 400

Missing token (`Missing Token`), no `polygon`/`ring`/`coordinates`, fewer than 3 vertices, non-numeric vertices, more than 10,000 vertices, or an area outside 2,500..250,000 m² (the message carries the measured area).

#### Example

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

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

### 401

Wrong token.

#### Example

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

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

### 500

PostGIS error - `{"error":"Server error","message":"…"}`.

#### Example

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

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


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