Access: Zone create and update require
org_type= Airspace Manager, Admin+. Reads are open to authenticated organisations. See Access control. Manager and Monitor delegation routes are shortcuts to the Resource Memberships API.
Manages airspace zones. Zones are created and owned by the platform or organisations with org_type = Airspace Manager. Airspace Zone Memberships (Manager/Monitor) are managed via the Resource Memberships API.
Data Models: Airspace Zone
Enums: airspace_restriction_type, airspace_zone_type. See Enums.
Airspace Zone Endpoints Summary
| Endpoint | Method | Operation Name | Description |
|---|---|---|---|
/airspaces | POST | Create Zone | Create a new airspace zone |
/airspaces/bulk | POST | Bulk Create Zones | Create multiple airspace zones in one request |
/airspaces | GET | Get Zones | List all airspace zones |
/airspaces/sync/check | GET | Sync Check | Check whether zone catalog needs refresh |
/airspaces/sync | GET | Sync Zones | Download zone catalog sync payload |
/airspaces/\{zone_uuid\} | GET | Get One Zone | Get specific zone details |
/airspaces/\{zone_uuid\} | PUT | Update Zone | Update a zone |
/airspaces/\{zone_uuid\} | DELETE | Delete Zone | Soft delete a zone |
/airspaces/\{zone_uuid\}/invitations | POST | Invite Organisation | Delegate manager/monitor access to another org |
/airspaces/\{zone_uuid\}/invitations | GET | Get Zone Invitations | View pending manager/monitor invites |
/airspaces/\{zone_uuid\}/invitations/accept | POST | Accept Zone Invite | Accept or decline a zone membership invite |
/airspaces/\{zone_uuid\}/memberships/\{membership_uuid\} | DELETE | Revoke Org Membership | Remove an organisation’s link to this zone |
Create Zone
POST /airspaces
Create a new airspace restriction zone. Only accessible by platform admins or orgs with org_type = Airspace Manager.
Request Body:
{
"zone_name": "Northern Sector Restricted Zone",
"restriction_type": 1,
"airspace_zone_type": 1,
"zone_envelope": {
"type": "Polygon",
"coordinates": [
[
[
77.12345,
28.56789
],
[
77.1245,
28.5678
],
[
77.1246,
28.5667
],
[
77.1234,
28.5666
],
[
77.12345,
28.56789
]
]
]
},
"min_height": 0,
"max_height": 400,
"active_from": null,
"active_to": null
}| Field | Type | Description |
|---|---|---|
restriction_type | int | airspace_restriction_type enum |
airspace_zone_type | int | airspace_zone_type enum (RED, YELLOW, etc.) |
zone_envelope | GeoJSON Polygon | Geographic boundary of the zone |
active_from / active_to | timestamp (nullable) | Validity window for temporary restrictions |
Responses:
- 201 Created:
{
"message": "Airspace zone created successfully",
"data": {
...
}
}- 400 Bad Request:
{
"error": "'restriction_type' must be a valid airspace restriction type enum"
}- 409 Conflict:
{
"error": "An airspace zone with this name already exists"
}- 422 Unprocessable Entity:
{
"error": "'zone_envelope' must be a valid closed GeoJSON Polygon"
}Bulk Create Zones
POST /airspaces/bulk
Create multiple airspace restriction zones in a single batch operation (useful for large-scale geometry updates).
Request Body:
{
"zones": [
{
"zone_name": "Red Zone A",
"restriction_type": 1,
"airspace_zone_type": 1,
"zone_envelope": {
"type": "Polygon",
"coordinates": [
...
]
}
},
{
"zone_name": "Red Zone B",
"restriction_type": 1,
"airspace_zone_type": 1,
"zone_envelope": {
"type": "Polygon",
"coordinates": [
...
]
}
}
]
}Responses:
- 201 Created:
{
"message": "Bulk zone creation successful",
"data": {
"total_created": 2,
"zones": [
...
]
}
}- 400 Bad Request:
{
"error": "'zones' array must not be empty"
}Get Zones
GET /airspaces
List all active airspace restriction zones. Open to all authenticated organisations: Airspace Managers, asset owners, and any other org type can call this endpoint. Returns zone_envelope geometry in-line (no separate constraint call needed).
Query Parameters:
| Param | Type | Description |
|---|---|---|
restriction_type | int (optional) | Filter by airspace_restriction_type |
airspace_zone_type | int (optional) | Filter by airspace_zone_type |
page | int (optional) | Page number (default: 1) |
limit | int (optional) | Records per page (default: 25) |
Responses:
- 200 OK:
{
"data": [
{
"zone_uuid": "4f39caae-2a73-426e-bb0c-239e25a01a14",
"zone_udai_id": "UDAI-ZONE-0301",
"zone_name": "Northern Sector Restricted Zone",
"org_owner_uuid": "550e8400-0000-41d4-a716-446655440000",
"restriction_type": 1,
"airspace_zone_type": 1,
"constraint_uuid": "b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e",
"min_height": 0,
"max_height": 400,
"zone_envelope": {
"type": "Polygon",
"coordinates": [
[
[
77.12345,
28.56789
],
[
77.1245,
28.5678
],
[
77.1246,
28.5667
],
[
77.1234,
28.5666
],
[
77.12345,
28.56789
]
]
]
},
"active_from": null,
"active_to": null,
"status": 1,
"created_at": "2025-07-04T09:00:00Z",
"updated_at": "2025-07-04T12:00:00Z"
}
],
"pagination": {
"total_records": 1,
"total_pages": 1,
"current_page": 1,
"per_page": 25,
"has_next": false,
"has_previous": false
}
}Sync Check
GET /airspaces/sync/check
Returns the platform high-water mark for airspace zone changes so an adapter can decide whether a sync is needed.
Access: MemberPlus (authenticated organisation member).
Query Parameters:
| Param | Type | Description |
|---|---|---|
after_change_id | long (optional) | Client’s last applied change ID. Defaults to 0. Must be ≥ 0. |
Responses:
- 200 OK:
{
"current_change_id": 1842,
"client_change_id": 1800,
"has_changes": true,
"full_sync_required": false
}| Field | Type | Description |
|---|---|---|
current_change_id | long | Latest change ID on the server |
client_change_id | long | Echo of the client’s after_change_id |
has_changes | bool | true when current_change_id > client_change_id |
full_sync_required | bool | true when the client’s change ID is below the retained history minimum: caller must run mode=full |
- 400 Bad Request:
after_change_idis negative.
Adapter flow: Call sync check on a timer. If
full_sync_required, runGET /airspaces/sync?mode=full. Else ifhas_changes, runGET /airspaces/sync?mode=diff\&after_change_id=\{client_change_id\}.
Sync Zones
GET /airspaces/sync
Downloads either a full zone catalog snapshot page or an incremental change page. Used by the Windows adapter (and other offline caches) to keep a local zone map current.
Access: MemberPlus.
Query Parameters:
| Param | Type | Description |
|---|---|---|
mode | string (required) | full for a stable snapshot page, or diff for incremental changes |
snapshot_change_id | long (optional) | Full mode only. Pins the snapshot watermark; defaults to current high-water mark. Must be between 0 and current_change_id. |
after_zone_id | int (optional) | Full mode cursor. Return zones with zone_id greater than this value. Defaults to 0. |
after_change_id | long (required for diff) | Diff mode: return changes strictly after this change ID |
until_change_id | long (optional) | Diff mode upper bound; defaults to current high-water mark. Must be between after_change_id and current inclusive. |
limit | int (optional) | Page size. Default 500, max 500. |
Full mode (mode=full)
Stable keyed pagination over the active zone catalog. Page through with after_zone_id / next_zone_id until has_more is false. Record snapshot_change_id as the client’s baseline before applying subsequent diffs.
Response (200 OK):
{
"mode": "full",
"snapshot_change_id": 1842,
"next_zone_id": 500,
"has_more": true,
"zones": [
{
"zone_id": 1,
"zone_uuid": "4f39caae-2a73-426e-bb0c-239e25a01a14",
"zone_udai_id": "UDAI-ZONE-0301",
"zone_version": 3,
"zone_name": "Northern Sector Restricted Zone",
"org_owner_uuid": "550e8400-0000-41d4-a716-446655440000",
"restriction_type": 1,
"airspace_zone_type": 1,
"constraint_uuid": "b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e",
"min_height": 0,
"max_height": 400,
"active_from": null,
"active_to": null,
"status": 1,
"created_at": "2025-07-04T09:00:00Z",
"updated_at": "2025-07-04T12:00:00Z",
"zone_envelope": {
"type": "Polygon",
"coordinates": [
[
[
77.12345,
28.56789
],
[
77.1245,
28.5678
],
[
77.1246,
28.5667
],
[
77.1234,
28.5666
],
[
77.12345,
28.56789
]
]
]
}
}
]
}Diff mode (mode=diff)
Returns change log entries between after_change_id and until_change_id. Each change includes an operation (upsert / delete) and, for upserts, a full zone snapshot.
Response (200 OK):
{
"mode": "diff",
"from_change_id": 1800,
"to_change_id": 1842,
"next_change_id": 1842,
"has_more": false,
"changes": [
{
"change_id": 1841,
"operation": "upsert",
"zone_uuid": "4f39caae-2a73-426e-bb0c-239e25a01a14",
"zone_version": 4,
"zone": {
"zone_id": 1,
"zone_uuid": "4f39caae-2a73-426e-bb0c-239e25a01a14",
"zone_udai_id": "UDAI-ZONE-0301",
"zone_version": 4,
"zone_name": "Northern Sector Restricted Zone",
"org_owner_uuid": "550e8400-0000-41d4-a716-446655440000",
"restriction_type": 1,
"airspace_zone_type": 1,
"constraint_uuid": "b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e",
"min_height": 0,
"max_height": 400,
"active_from": null,
"active_to": null,
"status": 1,
"created_at": "2025-07-04T09:00:00Z",
"updated_at": "2025-07-04T12:30:00Z",
"zone_envelope": {
"type": "Polygon",
"coordinates": [
[
[
77.12345,
28.56789
],
[
77.1245,
28.5678
],
[
77.1246,
28.5667
],
[
77.1234,
28.5666
],
[
77.12345,
28.56789
]
]
]
}
}
},
{
"change_id": 1842,
"operation": "delete",
"zone_uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"zone_version": 2,
"zone": null
}
]
}Error responses:
- 400 Bad Request: Invalid
mode, missingafter_change_idfor diff, out-of-rangelimit/ IDs, or bad snapshot bounds. - 409 Conflict: change history for the requested
after_change_idhas been pruned:
{
"error": "FULL_SYNC_REQUIRED",
"message": "The requested change history is no longer available"
}Caller must discard local state and re-run mode=full.
Get One Zone
GET /airspaces/{zone_uuid}
Responses:
- 200 OK:
{
"data": {
"zone_uuid": "4f39caae-2a73-426e-bb0c-239e25a01a14",
"zone_udai_id": "UDAI-ZONE-0301",
"zone_name": "Northern Sector Restricted Zone",
"restriction_type": 1,
"airspace_zone_type": 1,
"zone_envelope": {
"type": "Polygon",
"coordinates": [
[
[
77.12345,
28.56789
],
[
77.1245,
28.5678
],
[
77.1246,
28.5667
],
[
77.1234,
28.5666
],
[
77.12345,
28.56789
]
]
]
},
"min_height": 0,
"max_height": 400,
"active_from": null,
"active_to": null,
"memberships": [
{
"org_uuid": "550e8400-0000-41d4-a716-446655440000",
"org_udai_id": "UDAI-ORG-801",
"membership_type": 1
},
{
"org_uuid": "9f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"org_udai_id": "UDAI-ORG-102",
"membership_type": 2
}
],
"status": 1,
"created_at": "2025-07-04T09:00:00Z",
"updated_at": "2025-07-04T12:00:00Z"
}
}- 404 Not Found:
{
"error": "Airspace zone not found"
}- 410 Gone:
{
"error": "Airspace zone has been deactivated"
}Update Zone
PUT /airspaces/{zone_uuid}
Request Body:
{
"zone_name": "string",
"restriction_type": "int",
"airspace_zone_type": "int",
"zone_envelope": "GeoJSON Polygon",
"min_height": "double",
"max_height": "double",
"active_from": "timestamp",
"active_to": "timestamp"
}Responses:
- 200 OK:
{
"message": "Airspace zone updated successfully",
"data": {
...
}
}- 400 Bad Request:
{
"error": "'restriction_type' must be a valid enum value"
}- 404 Not Found:
{
"error": "Airspace zone not found"
}- 422 Unprocessable Entity:
{
"error": "'zone_envelope' must be a valid closed GeoJSON Polygon"
}Soft Delete Zone
DELETE /airspaces/{zone_uuid}
Soft deletes an airspace zone (marks it inactive) and removes its associated constraint.
Responses:
- 200 OK:
{
"message": "Airspace zone deleted successfully",
"data": null
}- 403 Forbidden:
{
"error": "Only Airspace Manager organisations can create/update/delete zones"
}- 404 Not Found:
{
"error": "Airspace zone not found"
}Zone Memberships & Invitations
The following routes are fully implemented shortcut endpoints under /airspaces/.... Internally they delegate to the unified Resource Memberships API service layer.
POST /airspaces/{zone_uuid}/invitations
Invite another organisation to manage or monitor this zone.
- Implementation mapping:
POST /resource-invitationswithresource_type=3andresource_uuid=\{zone_uuid\}
GET /airspaces/{zone_uuid}/invitations
View all pending or past membership invitations for this zone.
- Implementation mapping:
GET /resource-invitations?resource_type=3&resource_uuid=\{zone_uuid\}
POST /airspaces/{zone_uuid}/invitations/accept
Accept or decline a pending membership invitation for this zone.
- Implementation mapping:
POST /resource-invitations/accept
DELETE /airspaces/{zone_uuid}/memberships/{membership_uuid}
Revoke an organisation’s membership (Manager/Monitor) for this zone.
- Implementation mapping:
DELETE /resource-memberships/\{membership_uuid\}