# Sites and zones

> A site is one of the customer’s plants. Its zones and muster points come as GeoJSON, and its privacy level decides which positions the API can see.

Page: https://safeonuba.com/en/developers/concepts/sites · SafeOnuba API v1 (`api_version: "2026-09-24"`), in preview: the contract may change.

A **site** is a plant: a location with its perimeter, its zones and its muster points. Your customer can have one or several, and everything else hangs from them: every alert, every evacuation and every event carries its own.

## Sites

`GET /v1/sites` returns the sites your client has access to. Any scope will do.

| Field | What it is |
| --- | --- |
| `id` | The site’s UUID. It’s the one you use in the `site_id` filters. |
| `name` | The site’s name. |
| `location` | Location as text, or `null`. |
| `privacy_mode` | The plant’s privacy level. It decides which positions the API can see. |
| `unveil_min_severity` | In “emergencies only”, the minimum severity of an alert from which that person’s position is visible. |

| privacy_mode | What it means |
| --- | --- |
| `continuous` | The plant sees positions continuously, and so does the API. |
| `on_demand` | “Emergencies only”, the default value. A person’s position is only visible with an open alert from `unveil_min_severity` upwards, during an evacuation or with an approved request. |

The API obeys the same rule as the dashboard. [Positions](https://safeonuba.com/en/developers/concepts/positions) explains it in detail.

## Zones and muster points

`GET /v1/sites/{id}/zones` returns a site’s zones in force. It requires `alerts:read`.

Each zone comes with its geometry as a **GeoJSON polygon in WGS84** (`geometry.type: "Polygon"`), so you can draw it straight onto your control room’s plan or map.

| type | What it means |
| --- | --- |
| `work_area` | Work area. |
| `restricted` | Restricted zone. Entering it raises a `restricted_zone_entry` alert. |
| `forbidden` | Off-limits zone. Entering it raises a `forbidden_zone_entry` alert. |
| `assembly_point` | Muster point for an evacuation. It also carries the `assembly_point` object. |
| `privacy` | Privacy zone, such as changing rooms or canteens. It arrives with a name and a type, but without geometry (`geometry: null`). |
| `building` | Building. |

### Privacy zones

Inside a privacy zone, nobody’s position is recorded. The API gives its name and its type, but not its polygon.

### Muster points

Zones of type `assembly_point` also carry:

| Field | What it is |
| --- | --- |
| `serves` | Which evacuations it is valid for: `general`, `tsunami`, `earthquake`. |
| `elevation_m` | Elevation in metres, or `null`. |
| `elevation_source` | Where the elevation comes from: `dem` or `verified`. |
| `vertical` | `true` if it is an elevated refuge, inside a building. |
| `capacity` | Capacity, or `null`. |

During an evacuation, the control room can rule out muster points. That doesn’t change the zones: you see it in the evacuation itself (see [Evacuations and headcount](https://safeonuba.com/en/developers/concepts/evacuations#muster-points)).

## Filtering by site

If your control room only covers one plant, filter by it instead of receiving everything:

- In lists, with the `site_id` parameter (`/v1/alerts`, `/v1/musters`, `/v1/workers`, `/v1/devices`, `/v1/positions/latest`).
- In webhooks, with `filters.site_ids` when you create the destination (see [Webhooks](https://safeonuba.com/en/developers/webhooks#filters)).

Requesting a site that isn’t your customer’s returns `403` or `404`, depending on the route.
