API reference
Maps and flight watches
Live aircraft, flight history, saved maps and places, flight watches, notification groups and web push.
See Maps.
GET /v1/hooks/maps/shared/:token
A map shared by link, with its places. No authentication; owner and organization aren't included.
Auth: none
| Path parameter | Description |
|---|---|
:token | A secret from a link: an issue automation rule's incoming-webhook token (shown once when issued), a map's share link, a notification recipient's confirm and unsubscribe link, a Drive public link (/l/<token>), or a Mirage interaction's token (itk_…, sent with the interaction, good for 15 minutes), or the token in the link to a file of a message Mirage sent to Discord, or a Marketing link's sealed token (a tracked click, the open pixel, unsubscribe and the preference centre, a double opt-in confirmation); or a Food recipe's public link (/r/<token>) or a household's calendar feed. |
Response 200
{
list: {
places: {
placeId: string
listId: string
name: string
note?: string
lat: number
lon: number
address?: string
color?: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon?: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
createdAt: number
updatedAt: number
}[]
listId: string
name: string
description?: string
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
sharing: "org" | "link" | "private"
placeCount: number
createdAt: number
updatedAt: number
}
}GET /v1/hooks/maps/p/:token
An event's public position page (the link texts and emails give recipients outside the platform): the event's title, time, time zone and position, and until when the page follows the aircraft. No authentication; no watch, organization or recipient details. 410 once the link has expired (7 days).
Auth: none
| Path parameter | Description |
|---|---|
:token | A secret from a link: an issue automation rule's incoming-webhook token (shown once when issued), a map's share link, a notification recipient's confirm and unsubscribe link, a Drive public link (/l/<token>), or a Mirage interaction's token (itk_…, sent with the interaction, good for 15 minutes), or the token in the link to a file of a message Mirage sent to Discord, or a Marketing link's sealed token (a tracked click, the open pixel, unsubscribe and the preference centre, a double opt-in confirmation); or a Food recipe's public link (/r/<token>) or a household's calendar feed. |
Response 200
{
label: string
at: number
timeZone: string
lat: number
lon: number
lost: boolean
liveUntil: number
live: boolean
expiresAt: number
}GET /v1/hooks/maps/p/:token/live
Where that event's aircraft is now (position, altitude, speed, track), from the live picture, for 2 hours after the event: aircraft is null while it isn't seen, live: false after that. Only that one aircraft. No authentication; rate-limited per link.
Auth: none
| Path parameter | Description |
|---|---|
:token | A secret from a link: an issue automation rule's incoming-webhook token (shown once when issued), a map's share link, a notification recipient's confirm and unsubscribe link, a Drive public link (/l/<token>), or a Mirage interaction's token (itk_…, sent with the interaction, good for 15 minutes), or the token in the link to a file of a message Mirage sent to Discord, or a Marketing link's sealed token (a tracked click, the open pixel, unsubscribe and the preference centre, a double opt-in confirmation); or a Food recipe's public link (/r/<token>) or a household's calendar feed. |
Response 200
{
live: false
aircraft: null
} | {
live: true
aircraft: null
} | {
live: true
aircraft: {
at: number
lat: number
lon: number
alt: null | number
gs: null | number
track: null | number
onGround: boolean
icon: "unknown" | "helicopter" | "heavy" | "jet" | "turboprop" | "light" | "glider" | "balloon" | "drone" | "ground"
}
}GET /v1/hooks/maps/notify/:token
A notification recipient's status (pending, active, unsubscribed) and group name. No authentication: the token is the recipient's own.
Auth: none
| Path parameter | Description |
|---|---|
:token | A secret from a link: an issue automation rule's incoming-webhook token (shown once when issued), a map's share link, a notification recipient's confirm and unsubscribe link, a Drive public link (/l/<token>), or a Mirage interaction's token (itk_…, sent with the interaction, good for 15 minutes), or the token in the link to a file of a message Mirage sent to Discord, or a Marketing link's sealed token (a tracked click, the open pixel, unsubscribe and the preference centre, a double opt-in confirmation); or a Food recipe's public link (/r/<token>) or a household's calendar feed. |
Response 200
{
status: "active" | "pending" | "unsubscribed"
group: string
email?: string
phone?: string
}POST /v1/hooks/maps/notify/:token/confirm
Confirms a recipient (double opt-in). No authentication.
Auth: none
| Path parameter | Description |
|---|---|
:token | A secret from a link: an issue automation rule's incoming-webhook token (shown once when issued), a map's share link, a notification recipient's confirm and unsubscribe link, a Drive public link (/l/<token>), or a Mirage interaction's token (itk_…, sent with the interaction, good for 15 minutes), or the token in the link to a file of a message Mirage sent to Discord, or a Marketing link's sealed token (a tracked click, the open pixel, unsubscribe and the preference centre, a double opt-in confirmation); or a Food recipe's public link (/r/<token>) or a household's calendar feed. |
Response 200
{
status: "active" | "pending" | "unsubscribed"
group: string
email?: string
phone?: string
}POST /v1/hooks/maps/notify/:token/unsubscribe
Unsubscribes a recipient (RFC 8058 one-click: mail clients post here from the List-Unsubscribe header). No authentication.
Auth: none
| Path parameter | Description |
|---|---|
:token | A secret from a link: an issue automation rule's incoming-webhook token (shown once when issued), a map's share link, a notification recipient's confirm and unsubscribe link, a Drive public link (/l/<token>), or a Mirage interaction's token (itk_…, sent with the interaction, good for 15 minutes), or the token in the link to a file of a message Mirage sent to Discord, or a Marketing link's sealed token (a tracked click, the open pixel, unsubscribe and the preference centre, a double opt-in confirmation); or a Food recipe's public link (/r/<token>) or a household's calendar feed. |
Response 200
{
status: "active" | "pending" | "unsubscribed"
group: string
email?: string
phone?: string
}POST /v1/hooks/maps/location
A background location report from the Maps app with the phone's key (Authorization: Bearer si_loc_…; the body as for …/report). The key writes only its phone's fix and works only while that phone's sign-in does: 401 otherwise, and the phone's location is deleted. 204 when dropped (one report per 20 s is stored).
Auth: none
Response 200
{
ok: true
validUntil?: number
}Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Send JSON. |
401 | Unauthorized |
GET /v1/orgs/:orgId/maps/config
What the apps need to draw: the ADS-B source and its credit line, preset areas, event types, channels (mobile, web, email, sms, call: available or not, and their labels), what a new watch gets by default for the caller (defaults: events, channels, smsEvents), the Mapbox public token for the native map with the Referer it may need (mapbox), and for texts whether the SMS account is still in the provider's sandbox and where the caller's own texts go (masked). For circling and approach alerts: aircraft classes, enabled aircraft presets, the org's locations, circling sensitivity presets and approach defaults. units: the caller's units for measurements (the org's setting with their own on top; /settings).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
provider: {
id: string
label: string
attribution: string
terms: string
lookups: {
registration: boolean
callsign: boolean
type: boolean
hexBatch: number
}
}
providers: ["adsblol", "adsbfi", "airplaneslive", "opensky", "adsbexchange"]
sources: {
id: string
label: string
attribution: string
use: "all" | "last_resort"
}[]
areas: {
id: string
label: string
source: string
}[]
events: {
needsPoint?: true
type: "emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead"
label: string
}[]
aircraftClasses: {
id: "helicopter" | "heavy" | "jet" | "turboprop" | "light" | "glider" | "balloon" | "drone"
label: string
}[]
presets: [] | {
id: string
label: string
}[]
locations: {
locationId: string
name: string
lat: number
lon: number
siteRadiusM: number
}[]
circling: {
sensitive: {
turns: 0.75
radiusKm: 3
windowMinutes: 10
}
normal: {
turns: 1
radiusKm: 2
windowMinutes: 8
}
strict: {
turns: 2
radiusKm: 1.5
windowMinutes: 8
}
}
approachDefaults: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
deliveryLabels: {
failed: string
sent: string
duplicate: string
quiet: string
cooldown: string
no_recipients: string
}
channels: {
mobile: true
web: true
email: boolean
sms: boolean
call: boolean
}
channelLabels: {
[key: string]: string
}
defaults: {
events: {
emergency: boolean
takeoff: boolean
landing: boolean
signal_lost: boolean
signal_resumed: boolean
area_enter: boolean
area_leave: boolean
orbit: boolean
road_follow: boolean
road_switch: boolean
road_repeat: boolean
road_leave: boolean
interchange: boolean
threshold: boolean
approach: boolean
overhead: boolean
}
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
mapbox: {
token: null | string
referer: null | string
}
sms: {
sandbox: boolean | null
phone: null | string
phoneSettings: null | string
}
units: {
speed: string
altitude: string
distance: string
}
}GET /v1/orgs/:orgId/maps/settings
Maps settings: the units measurements show in (speed kt | km/h | mph, altitude ft | m, distance nm | km | mi). units is what the caller sees, org.units the org's setting and mine.units the caller's own (each only what it sets; unset is knots, feet, nautical miles).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
units: {
speed: "kt" | "km/h" | "mph"
altitude: "m" | "ft"
distance: "nm" | "km" | "mi"
}
org: {
units: {
speed?: "kt" | "km/h" | "mph"
altitude?: "m" | "ft"
distance?: "nm" | "km" | "mi"
}
}
mine: null | {
units: {
speed?: "kt" | "km/h" | "mph"
altitude?: "m" | "ft"
distance?: "nm" | "km" | "mi"
}
}
canEditOrg: boolean
}PUT /v1/orgs/:orgId/maps/settings
The org's units, for everyone without their own (org owners and admins, or a key, with maps:write). A unit left out goes back to the default.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
units: {
speed: "kt" | "km/h" | "mph"
altitude: "m" | "ft"
distance: "nm" | "km" | "mi"
}
org: {
units: {
speed?: "kt" | "km/h" | "mph"
altitude?: "m" | "ft"
distance?: "nm" | "km" | "mi"
}
}
mine: null | {
units: {
speed?: "kt" | "km/h" | "mph"
altitude?: "m" | "ft"
distance?: "nm" | "km" | "mi"
}
}
canEditOrg: boolean
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
PUT /v1/orgs/:orgId/maps/settings/me
The caller's own units, in every org, over the org's ({ units: null } follows the org again). People only.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
units: {
speed: "kt" | "km/h" | "mph"
altitude: "m" | "ft"
distance: "nm" | "km" | "mi"
}
org: {
units: {
speed?: "kt" | "km/h" | "mph"
altitude?: "m" | "ft"
distance?: "nm" | "km" | "mi"
}
}
mine: null | {
units: {
speed?: "kt" | "km/h" | "mph"
altitude?: "m" | "ft"
distance?: "nm" | "km" | "mi"
}
}
canEditOrg: boolean
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
GET /v1/orgs/:orgId/maps/aircraft
Live aircraft inside bbox (west,south,east,north), from the flight poller's latest snapshot: position, barometric altitude (null on the ground), ground speed, track, vertical rate, callsign, registration, type, squawk, icon class and, with trails=1, the last 15 minutes of track. Also returns the source, its credit line and the areas polled. Views outside the polled areas are added to the poller's areas for a few minutes.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
bbox | string | No | |
trails | string | No |
Response 200
{
issues?: string[]
pending: boolean
at: null
provider: null
coverage: []
aircraft: []
sources?: undefined
} | {
issues?: string[]
pending: boolean
at: number
provider: {
label: string
id: string
attribution: string
}
sources?: {
label: string
id: string
attribution: string
}[]
coverage: {
lat: number
lon: number
radiusNm: number
}[]
aircraft: {
type?: string
at: number
hex: string
source?: string
desc?: string
lat: number
lon: number
alt: null | number
onGround: boolean
altGeom?: number
gs?: number
track?: number
vs?: number
callsign?: string
registration?: string
category?: string
squawk?: string
emergency?: string
icon: "unknown" | "helicopter" | "heavy" | "jet" | "turboprop" | "light" | "glider" | "balloon" | "drone" | "ground"
operator?: string
road?: string
trail?: ([number, number, number, null | number, null | number, null | number])[]
}[]
}Errors
| Status | Message |
|---|---|
400 | bbox is west,south,east,north in degrees. |
GET /v1/orgs/:orgId/maps/aircraft/nearest
The nearest aircraft in the air to a point, and the next two (the phone's nearest-aircraft widget): which way each is from the point (bearingDeg, compass), how far (rangeM), its altitude (ft), speed (kt), track and phase, and, while it descends, when it should land (landing.at, unix seconds) and at which airport when one lies ahead on its track. The point is rounded to about 100 m and never stored or logged; like a map view, an area outside the polled ones is covered for a few minutes from now (pending until it is). units: the caller's Maps units, for showing the numbers.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
lat | number | Yes | -90–90; coerced from a string | |
lon | number | Yes | -180–180; coerced from a string | |
radiusKm | number | No | 50 | 1–200; coerced from a string |
Response 200
{
units: {
speed: string
altitude: string
distance: string
}
radiusKm: number
aircraft: {
hex: string
callsign?: string
registration?: string
type?: string
desc?: string
operator?: string
icon: "unknown" | "helicopter" | "heavy" | "jet" | "turboprop" | "light" | "glider" | "balloon" | "drone" | "ground"
at: number
rangeM: number
bearingDeg: number
compass: "S" | "N" | "NE" | "E" | "SE" | "SW" | "W" | "NW"
alt: null | number
gs?: number
track?: number
vs?: number
phase: "lost" | "taxi" | "climbing" | "cruise" | "descending" | "landed"
landing: null | {
at: number
airport: null | {
name: string
code?: string
}
}
}[]
issues?: string[]
at: null | number
provider: null | {
label: string
id: string
attribution: string
}
sources?: {
label: string
id: string
attribution: string
}[]
pending: boolean
}GET /v1/orgs/:orgId/maps/aircraft/search
Aircraft in the live snapshot by ICAO hex, registration or callsign (q; exact matches first, then prefixes).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
q | string | No | "" |
Response 200
{
aircraft: {
trail?: undefined
type?: string
at: number
hex: string
source?: string
desc?: string
lat: number
lon: number
alt: null | number
onGround: boolean
altGeom?: number
gs?: number
track?: number
vs?: number
callsign?: string
registration?: string
category?: string
squawk?: string
emergency?: string
icon: "unknown" | "helicopter" | "heavy" | "jet" | "turboprop" | "light" | "glider" | "balloon" | "drone" | "ground"
operator?: string
road?: string
}[]
}GET /v1/orgs/:orgId/maps/aircraft/:hex
One aircraft wherever it is, with its recent track: live from the snapshot (live: true), else its last known position and the track before it from recorded positions (live: false, lastSeen), or aircraft: null when nothing is known. When it isn't live the poller looks it up by hex for a few minutes (pending).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:hex | ICAO 24-bit aircraft address, 6 hex digits (7c6b2d). |
Response 200
{
at: null | number
provider: null | {
label: string
id: string
attribution: string
}
aircraft: null | {
type?: string
at: number
hex: string
source?: string
desc?: string
lat: number
lon: number
alt: null | number
onGround: boolean
altGeom?: number
gs?: number
track?: number
vs?: number
callsign?: string
registration?: string
category?: string
squawk?: string
emergency?: string
icon: "unknown" | "helicopter" | "heavy" | "jet" | "turboprop" | "light" | "glider" | "balloon" | "drone" | "ground"
operator?: string
road?: string
trail?: ([number, number, number, null | number, null | number, null | number])[]
}
live: boolean
lastSeen: null | number
pending?: boolean
}Errors
| Status | Message |
|---|---|
404 | Aircraft not found |
GET /v1/orgs/:orgId/maps/aircraft/:hex/track
Recorded track of a watched aircraft over the last hours (0.25–24, default 6): points [seconds, lon, lat, altitude ft | null, ground speed kt, track°], oldest first. Positions are recorded only while a watch covers the aircraft (kept 14 days).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:hex | ICAO 24-bit aircraft address, 6 hex digits (7c6b2d). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
hours | string | No | 6 |
Response 200
{
points: ([number, number, number, null | number, null | number, null | number])[]
distanceNm: number
recorded: boolean
registration?: string
callsign?: string
type?: string
hex: string
from: number
to: number
}Errors
| Status | Message |
|---|---|
404 | Aircraft not found |
GET /v1/orgs/:orgId/maps/lists
Saved maps the caller can see: their own, and those shared with the organization or by link. With places=1, each map includes its places.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
places | string | No |
Response 200
{
lists: {
listId: string
orgId: string
ownerId: string
name: string
description?: string
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
sharing: "org" | "link" | "private"
shareToken?: string
placeCount: number
createdAt: number
updatedAt: number
places?: {
placeId: string
listId: string
name: string
note?: string
lat: number
lon: number
address?: string
color?: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon?: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
createdBy: string
createdAt: number
updatedAt: number
}[]
}[]
}POST /v1/orgs/:orgId/maps/lists
Creates a saved map: name, optional description, pin color (chart-1…chart-5, foreground), icon and sharing (private, org, link).
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 201
{
list: {
listId: string
orgId: string
ownerId: string
name: string
description?: string
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
sharing: "org" | "link" | "private"
shareToken?: string
placeCount: number
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
GET /v1/orgs/:orgId/maps/lists/:listId
A saved map with its places.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:listId | Saved map id (mls_…); under marketing a list (mkl_…); under me/food a shopping list (fls_…). |
Response 200
{
list: {
places: {
placeId: string
listId: string
name: string
note?: string
lat: number
lon: number
address?: string
color?: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon?: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
createdBy: string
createdAt: number
updatedAt: number
}[]
listId: string
orgId: string
ownerId: string
name: string
description?: string
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
sharing: "org" | "link" | "private"
shareToken?: string
placeCount: number
createdAt: number
updatedAt: number
}
}PATCH /v1/orgs/:orgId/maps/lists/:listId
Renames a map or changes its description, pin style or sharing. sharing: "link" returns a shareToken for the public link; rotateLink: true replaces it; any other sharing turns the link off. Owner, or an org admin for shared maps.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:listId | Saved map id (mls_…); under marketing a list (mkl_…); under me/food a shopping list (fls_…). |
Response 200
{
list: {
listId: string
orgId: string
ownerId: string
name: string
description?: string
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
sharing: "org" | "link" | "private"
shareToken?: string
placeCount: number
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
DELETE /v1/orgs/:orgId/maps/lists/:listId
Deletes a map and its places.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:listId | Saved map id (mls_…); under marketing a list (mkl_…); under me/food a shopping list (fls_…). |
Response 200
{
ok: true
}POST /v1/orgs/:orgId/maps/lists/:listId/places
Adds a place: name, lat, lon, optional note, address, and its own pin color and icon.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:listId | Saved map id (mls_…); under marketing a list (mkl_…); under me/food a shopping list (fls_…). |
Response 201
{
place: {
placeId: string
listId: string
name: string
note?: string
lat: number
lon: number
address?: string
color?: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon?: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
createdBy: string
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
PATCH /v1/orgs/:orgId/maps/lists/:listId/places/:placeId
Changes a place; moveTo moves it to another of your maps.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:listId | Saved map id (mls_…); under marketing a list (mkl_…); under me/food a shopping list (fls_…). |
:placeId | Place id (plc_…). |
Response 200
{
place: {
placeId: string
listId: string
name: string
note?: string
lat: number
lon: number
address?: string
color?: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
icon?: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
createdBy: string
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
DELETE /v1/orgs/:orgId/maps/lists/:listId/places/:placeId
Removes a place.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:listId | Saved map id (mls_…); under marketing a list (mkl_…); under me/food a shopping list (fls_…). |
:placeId | Place id (plc_…). |
Response 200
{
ok: true
}GET /v1/orgs/:orgId/maps/watches
Flight watches the caller can see (their own and those shared with the organization).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
watches: {
name: string
visibility: "org" | "private"
targets: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
exclude: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
}[]
limitToAreas: boolean
events: {
emergency?: boolean
takeoff?: boolean
landing?: boolean
signal_lost?: boolean
signal_resumed?: boolean
area_enter?: boolean
area_leave?: boolean
orbit?: boolean
road_follow?: boolean
road_switch?: boolean
road_repeat?: boolean
road_leave?: boolean
interchange?: boolean
threshold?: boolean
approach?: boolean
overhead?: boolean
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: number
maxAltitudeFt: null | number
loiterMinutes: null | number
ignoreAirportsKm: number
}
approach: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
roads: {
corridorM: number
headingToleranceDeg: number
minSeconds: number
minShare: number
repeatMinutes: number
endAfterSeconds: number
maxAltitudeFt: number
minSpeedKt: number
classes: ("primary" | "motorway" | "trunk")[]
}
thresholds: {
altitudeAboveFt?: number
altitudeBelowFt?: number
speedAboveKt?: number
speedBelowKt?: number
climbAboveFpm?: number
descentAboveFpm?: number
squawks?: string[]
}
}
notify: {
membershipNotices: boolean
liveActivity: boolean
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
cooldownMinutes: number
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allow: ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
timeZone?: string
}
identity: {
mode: "any" | "pin_first"
pinnedHex: null | string
}
lifetime: {
startsAt: null | number
endsAt: null | number
maxNotifications: null | number
maxFlights: null | number
schedule: null | {
days: number[]
start: string
end: string
timeZone: string
}
forHours?: number
}
log: {
enabled: boolean
retentionDays: null | number
}
paused: boolean
watchId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
notificationsSent: number
flightsCompleted: number
endedAt?: number
endedReason?: "time" | "notifications" | "flights"
personal?: boolean
status: "active" | "waiting" | "paused" | "ended" | "off_schedule" | "waiting_location"
}[]
}POST /v1/orgs/:orgId/maps/watches
Creates a flight watch: name, targets ({ kind: hex | registration | callsign | type, value }, a trailing * matches prefixes; no_callsign, any (value *) and class (helicopter, light, turboprop, jet, heavy, glider, balloon, drone) match inside areas only and need one; preset names an aircraft preset), exclude (the same shape: aircraft matching any never match, e.g. callsign POL3* except POL31), areas ({ kind: "preset", id: "au-vic" }, circles { center: [lon, lat], radiusKm }, polygons { ring: [[lon, lat], …] }, an org location { kind: "location", locationId, radiusKm } or { kind: "near_me", radiusKm } around the owner's phone, which makes the watch personal: private, the owner's only, no groups or people), limitToAreas, events (on/off per event type; approach and overhead need a location or near-me area), settings (signal, orbit with maxAltitudeFt, loiterMinutes and ignoreAirportsKm, approach, roads, thresholds), notify (channels: mobile, web, email, sms, call, with the older push read as mobile and web; includeOwner, groupIds, userIds (org members), smsEvents, smsFormat, smsPrefix, cooldownMinutes, timeZone, quietHours), identity (mode: any or pin_first; pinnedHex), lifetime (startsAt, endsAt or forHours, maxNotifications, maxFlights, schedule with days, start, end, timeZone) and log (enabled, retentionDays, null for forever). Type targets match inside the watch's areas. Left out, every event is on and channels are the caller's defaults (GET …/maps/config → defaults). The maker gets a confirmation by push when they're a recipient. See Maps → Flight watches for every setting and its default.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 201
{
watch: {
name: string
visibility: "org" | "private"
targets: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
exclude: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
}[]
limitToAreas: boolean
events: {
emergency?: boolean
takeoff?: boolean
landing?: boolean
signal_lost?: boolean
signal_resumed?: boolean
area_enter?: boolean
area_leave?: boolean
orbit?: boolean
road_follow?: boolean
road_switch?: boolean
road_repeat?: boolean
road_leave?: boolean
interchange?: boolean
threshold?: boolean
approach?: boolean
overhead?: boolean
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: number
maxAltitudeFt: null | number
loiterMinutes: null | number
ignoreAirportsKm: number
}
approach: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
roads: {
corridorM: number
headingToleranceDeg: number
minSeconds: number
minShare: number
repeatMinutes: number
endAfterSeconds: number
maxAltitudeFt: number
minSpeedKt: number
classes: ("primary" | "motorway" | "trunk")[]
}
thresholds: {
altitudeAboveFt?: number
altitudeBelowFt?: number
speedAboveKt?: number
speedBelowKt?: number
climbAboveFpm?: number
descentAboveFpm?: number
squawks?: string[]
}
}
notify: {
membershipNotices: boolean
liveActivity: boolean
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
cooldownMinutes: number
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allow: ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
timeZone?: string
}
identity: {
mode: "any" | "pin_first"
pinnedHex: null | string
}
lifetime: {
startsAt: null | number
endsAt: null | number
maxNotifications: null | number
maxFlights: null | number
schedule: null | {
days: number[]
start: string
end: string
timeZone: string
}
forHours?: number
}
log: {
enabled: boolean
retentionDays: null | number
}
paused: boolean
watchId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
notificationsSent: number
flightsCompleted: number
endedAt?: number
endedReason?: "time" | "notifications" | "flights"
personal?: boolean
status: "active" | "waiting" | "paused" | "ended" | "off_schedule" | "waiting_location"
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
GET /v1/orgs/:orgId/maps/watches/:watchId
A flight watch with every setting, defaults filled in. A near-me watch without a current location reads status: "waiting_location".
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
Response 200
{
watch: {
name: string
visibility: "org" | "private"
targets: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
exclude: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
}[]
limitToAreas: boolean
events: {
emergency?: boolean
takeoff?: boolean
landing?: boolean
signal_lost?: boolean
signal_resumed?: boolean
area_enter?: boolean
area_leave?: boolean
orbit?: boolean
road_follow?: boolean
road_switch?: boolean
road_repeat?: boolean
road_leave?: boolean
interchange?: boolean
threshold?: boolean
approach?: boolean
overhead?: boolean
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: number
maxAltitudeFt: null | number
loiterMinutes: null | number
ignoreAirportsKm: number
}
approach: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
roads: {
corridorM: number
headingToleranceDeg: number
minSeconds: number
minShare: number
repeatMinutes: number
endAfterSeconds: number
maxAltitudeFt: number
minSpeedKt: number
classes: ("primary" | "motorway" | "trunk")[]
}
thresholds: {
altitudeAboveFt?: number
altitudeBelowFt?: number
speedAboveKt?: number
speedBelowKt?: number
climbAboveFpm?: number
descentAboveFpm?: number
squawks?: string[]
}
}
notify: {
membershipNotices: boolean
liveActivity: boolean
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
cooldownMinutes: number
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allow: ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
timeZone?: string
}
identity: {
mode: "any" | "pin_first"
pinnedHex: null | string
}
lifetime: {
startsAt: null | number
endsAt: null | number
maxNotifications: null | number
maxFlights: null | number
schedule: null | {
days: number[]
start: string
end: string
timeZone: string
}
forHours?: number
}
log: {
enabled: boolean
retentionDays: null | number
}
paused: boolean
watchId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
notificationsSent: number
flightsCompleted: number
endedAt?: number
endedReason?: "time" | "notifications" | "flights"
personal?: boolean
status: "active" | "waiting" | "paused" | "ended" | "off_schedule" | "waiting_location"
}
}PATCH /v1/orgs/:orgId/maps/watches/:watchId
Changes a watch: fields sent replace the stored ones (nested objects whole). Owner, or an org admin for shared watches.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
Response 200
{
watch: {
name: string
visibility: "org" | "private"
targets: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
exclude: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
}[]
limitToAreas: boolean
events: {
emergency?: boolean
takeoff?: boolean
landing?: boolean
signal_lost?: boolean
signal_resumed?: boolean
area_enter?: boolean
area_leave?: boolean
orbit?: boolean
road_follow?: boolean
road_switch?: boolean
road_repeat?: boolean
road_leave?: boolean
interchange?: boolean
threshold?: boolean
approach?: boolean
overhead?: boolean
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: number
maxAltitudeFt: null | number
loiterMinutes: null | number
ignoreAirportsKm: number
}
approach: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
roads: {
corridorM: number
headingToleranceDeg: number
minSeconds: number
minShare: number
repeatMinutes: number
endAfterSeconds: number
maxAltitudeFt: number
minSpeedKt: number
classes: ("primary" | "motorway" | "trunk")[]
}
thresholds: {
altitudeAboveFt?: number
altitudeBelowFt?: number
speedAboveKt?: number
speedBelowKt?: number
climbAboveFpm?: number
descentAboveFpm?: number
squawks?: string[]
}
}
notify: {
membershipNotices: boolean
liveActivity: boolean
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
cooldownMinutes: number
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allow: ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
timeZone?: string
}
identity: {
mode: "any" | "pin_first"
pinnedHex: null | string
}
lifetime: {
startsAt: null | number
endsAt: null | number
maxNotifications: null | number
maxFlights: null | number
schedule: null | {
days: number[]
start: string
end: string
timeZone: string
}
forHours?: number
}
log: {
enabled: boolean
retentionDays: null | number
}
paused: boolean
watchId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
notificationsSent: number
flightsCompleted: number
endedAt?: number
endedReason?: "time" | "notifications" | "flights"
personal?: boolean
status: "active" | "waiting" | "paused" | "ended" | "off_schedule" | "waiting_location"
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
POST /v1/orgs/:orgId/maps/watches/:watchId/pause
Pauses a watch: the poller stops evaluating it and nothing is sent.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
Response 200
{
watch: {
name: string
visibility: "org" | "private"
targets: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
exclude: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
}[]
limitToAreas: boolean
events: {
emergency?: boolean
takeoff?: boolean
landing?: boolean
signal_lost?: boolean
signal_resumed?: boolean
area_enter?: boolean
area_leave?: boolean
orbit?: boolean
road_follow?: boolean
road_switch?: boolean
road_repeat?: boolean
road_leave?: boolean
interchange?: boolean
threshold?: boolean
approach?: boolean
overhead?: boolean
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: number
maxAltitudeFt: null | number
loiterMinutes: null | number
ignoreAirportsKm: number
}
approach: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
roads: {
corridorM: number
headingToleranceDeg: number
minSeconds: number
minShare: number
repeatMinutes: number
endAfterSeconds: number
maxAltitudeFt: number
minSpeedKt: number
classes: ("primary" | "motorway" | "trunk")[]
}
thresholds: {
altitudeAboveFt?: number
altitudeBelowFt?: number
speedAboveKt?: number
speedBelowKt?: number
climbAboveFpm?: number
descentAboveFpm?: number
squawks?: string[]
}
}
notify: {
membershipNotices: boolean
liveActivity: boolean
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
cooldownMinutes: number
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allow: ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
timeZone?: string
}
identity: {
mode: "any" | "pin_first"
pinnedHex: null | string
}
lifetime: {
startsAt: null | number
endsAt: null | number
maxNotifications: null | number
maxFlights: null | number
schedule: null | {
days: number[]
start: string
end: string
timeZone: string
}
forHours?: number
}
log: {
enabled: boolean
retentionDays: null | number
}
paused: boolean
watchId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
notificationsSent: number
flightsCompleted: number
endedAt?: number
endedReason?: "time" | "notifications" | "flights"
personal?: boolean
status: "active" | "waiting" | "paused" | "ended" | "off_schedule" | "waiting_location"
}
}POST /v1/orgs/:orgId/maps/watches/:watchId/resume
Resumes a paused watch.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
Response 200
{
watch: {
name: string
visibility: "org" | "private"
targets: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
exclude: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
}[]
limitToAreas: boolean
events: {
emergency?: boolean
takeoff?: boolean
landing?: boolean
signal_lost?: boolean
signal_resumed?: boolean
area_enter?: boolean
area_leave?: boolean
orbit?: boolean
road_follow?: boolean
road_switch?: boolean
road_repeat?: boolean
road_leave?: boolean
interchange?: boolean
threshold?: boolean
approach?: boolean
overhead?: boolean
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: number
maxAltitudeFt: null | number
loiterMinutes: null | number
ignoreAirportsKm: number
}
approach: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
roads: {
corridorM: number
headingToleranceDeg: number
minSeconds: number
minShare: number
repeatMinutes: number
endAfterSeconds: number
maxAltitudeFt: number
minSpeedKt: number
classes: ("primary" | "motorway" | "trunk")[]
}
thresholds: {
altitudeAboveFt?: number
altitudeBelowFt?: number
speedAboveKt?: number
speedBelowKt?: number
climbAboveFpm?: number
descentAboveFpm?: number
squawks?: string[]
}
}
notify: {
membershipNotices: boolean
liveActivity: boolean
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
cooldownMinutes: number
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allow: ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
timeZone?: string
}
identity: {
mode: "any" | "pin_first"
pinnedHex: null | string
}
lifetime: {
startsAt: null | number
endsAt: null | number
maxNotifications: null | number
maxFlights: null | number
schedule: null | {
days: number[]
start: string
end: string
timeZone: string
}
forHours?: number
}
log: {
enabled: boolean
retentionDays: null | number
}
paused: boolean
watchId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
notificationsSent: number
flightsCompleted: number
endedAt?: number
endedReason?: "time" | "notifications" | "flights"
personal?: boolean
status: "active" | "waiting" | "paused" | "ended" | "off_schedule" | "waiting_location"
}
}POST /v1/orgs/:orgId/maps/watches/:watchId/restart
Starts an ended watch again (it ended at its end time, or after its notification or flight limit) with its counters at zero. A watch whose end time has passed needs a new one (or none) first.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
Response 200
{
watch: {
name: string
visibility: "org" | "private"
targets: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
exclude: {
kind: "any" | "type" | "hex" | "callsign" | "registration" | "preset" | "no_callsign" | "class"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
}[]
limitToAreas: boolean
events: {
emergency?: boolean
takeoff?: boolean
landing?: boolean
signal_lost?: boolean
signal_resumed?: boolean
area_enter?: boolean
area_leave?: boolean
orbit?: boolean
road_follow?: boolean
road_switch?: boolean
road_repeat?: boolean
road_leave?: boolean
interchange?: boolean
threshold?: boolean
approach?: boolean
overhead?: boolean
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: number
maxAltitudeFt: null | number
loiterMinutes: null | number
ignoreAirportsKm: number
}
approach: {
lookaheadMinutes: number
minClosingKt: number
maxAltitudeFt: null | number
overheadKm: number
}
roads: {
corridorM: number
headingToleranceDeg: number
minSeconds: number
minShare: number
repeatMinutes: number
endAfterSeconds: number
maxAltitudeFt: number
minSpeedKt: number
classes: ("primary" | "motorway" | "trunk")[]
}
thresholds: {
altitudeAboveFt?: number
altitudeBelowFt?: number
speedAboveKt?: number
speedBelowKt?: number
climbAboveFpm?: number
descentAboveFpm?: number
squawks?: string[]
}
}
notify: {
membershipNotices: boolean
liveActivity: boolean
smsEvents: null | ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
cooldownMinutes: number
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allow: ("emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead")[]
}
timeZone?: string
}
identity: {
mode: "any" | "pin_first"
pinnedHex: null | string
}
lifetime: {
startsAt: null | number
endsAt: null | number
maxNotifications: null | number
maxFlights: null | number
schedule: null | {
days: number[]
start: string
end: string
timeZone: string
}
forHours?: number
}
log: {
enabled: boolean
retentionDays: null | number
}
paused: boolean
watchId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
notificationsSent: number
flightsCompleted: number
endedAt?: number
endedReason?: "time" | "notifications" | "flights"
personal?: boolean
status: "active" | "waiting" | "paused" | "ended" | "off_schedule" | "waiting_location"
}
}POST /v1/orgs/:orgId/maps/watches/:watchId/test
Sends the caller a sample alert on the watch's channels that reach them and returns what each did: mobile (devices: phones with the Maps app, queued), web (sent, devices), email (sent), sms (sent, or skipped with why) and call (skipped). People only; maps:write, or the watch's owner.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
Response 200
{
mobile?: {
devices: number
queued: boolean
}
web?: {
sent: number
devices: number
}
email?: {
sent?: boolean
skipped?: string
}
sms?: {
sent?: boolean
error?: string
skipped?: string
}
call?: {
skipped: string
}
}GET /v1/orgs/:orgId/maps/watches/:watchId/flights
Flights the watch logged, newest first: airframe (hex, registration, callsign, type), start (takeoff or first_seen) and end (landing, lost, left, watch_ended, schedule), status (in_progress, completed, ended), distance, highest altitude, events and roads followed. hex filters to one airframe; pass the returned cursor for older ones.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
limit | string | No | 50 | |
hex | string | No | ||
cursor | string | No |
Response 200
{
flights: {
flightId: string
watchId: string
hex: string
registration?: string
callsign?: string
type?: string
desc?: string
status: "in_progress" | "completed" | "ended"
endReason?: string
startedAt: number
endedAt?: number
startedBy: "takeoff" | "first_seen"
start: {
lat: number
lon: number
alt: null | number
}
end?: {
lat: number
lon: number
alt: null | number
}
maxAlt: null | number
distanceNm: number
events: {
type: "emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead"
at: number
title: string
text: string
}[]
roads: {
label: string
from: number
to?: number
}[]
points?: ([number, number, number, null | number, null | number, null | number])[]
}[]
cursor: null | string
}GET /v1/orgs/:orgId/maps/watches/:watchId/flights/:flightId
One logged flight with its track (points: [seconds, lon, lat, altitude ft | null, ground speed kt, track°]).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
:flightId | Logged flight id (fgl_…). |
Response 200
{
flight: {
flightId: string
watchId: string
hex: string
registration?: string
callsign?: string
type?: string
desc?: string
status: "in_progress" | "completed" | "ended"
endReason?: string
startedAt: number
endedAt?: number
startedBy: "takeoff" | "first_seen"
start: {
lat: number
lon: number
alt: null | number
}
end?: {
lat: number
lon: number
alt: null | number
}
maxAlt: null | number
distanceNm: number
events: {
type: "emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead"
at: number
title: string
text: string
}[]
roads: {
label: string
from: number
to?: number
}[]
points?: ([number, number, number, null | number, null | number, null | number])[]
}
}GET /v1/orgs/:orgId/maps/watches/:watchId/flights/:flightId/export
A logged flight as a file: format=gpx (track and events as waypoints), kml (line and time-stamped track) or csv (one row per position, events alongside).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
:flightId | Logged flight id (fgl_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
format | string | No | "gpx" |
Response 200 with no body.
Errors
| Status | Message |
|---|---|
400 | format is gpx, kml or csv. |
DELETE /v1/orgs/:orgId/maps/watches/:watchId
Deletes a watch and its flight logs. Its events expire after 30 days.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
Response 200
{
ok: true
}GET /v1/orgs/:orgId/maps/watches/:watchId/events
A watch's events, newest first (kept 30 days): type, aircraft, position, text, and what happened to the notification (sent with channels, quiet, no_recipients, failed). Pass the returned cursor for older ones.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:watchId | Flight watch id (fwt_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
limit | string | No | 50 | |
cursor | string | No |
Response 200
{
events: {
eventId: string
watchId: string
type: "emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead" | "recipients_added" | "recipients_removed" | "watch_started"
at: number
hex: string
title: string
text: string
aircraft: {
registration?: string
callsign?: string
type?: string
desc?: string
}
position?: {
lat: number
lon: number
alt: null | number
gs?: number
vs?: number
track?: number
}
data?: {
[key: string]: unknown
}
delivery?: {
status: "failed" | "sent" | "duplicate" | "quiet" | "cooldown" | "no_recipients"
channels?: ("email" | "sms" | "call" | "mobile" | "push" | "web")[]
recipients?: number
errors?: string[]
duplicates?: {
recipients: number
of: string[]
}
}
}[]
cursor: null | string
}GET /v1/orgs/:orgId/maps/events
Recent events across the watches the caller can see, newest first.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
limit | string | No | 50 |
Response 200
{
events: {
eventId: string
watchId: string
type: "emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold" | "approach" | "overhead" | "recipients_added" | "recipients_removed" | "watch_started"
at: number
hex: string
title: string
text: string
aircraft: {
registration?: string
callsign?: string
type?: string
desc?: string
}
position?: {
lat: number
lon: number
alt: null | number
gs?: number
vs?: number
track?: number
}
data?: {
[key: string]: unknown
}
delivery?: {
status: "failed" | "sent" | "duplicate" | "quiet" | "cooldown" | "no_recipients"
channels?: ("email" | "sms" | "call" | "mobile" | "push" | "web")[]
recipients?: number
errors?: string[]
duplicates?: {
recipients: number
of: string[]
}
}
}[]
}GET /v1/orgs/:orgId/maps/incidents
Emergency incidents and warnings (Australia), from the incidents poller's picture: filtered to a view (bbox), hazards (hazards=bushfire,flood) and a minimum level (minLevel); sorted by distance from near=lon,lat (adds distanceKm), else most severe first; areas=0 leaves out warning areas (lists); limit. feeds carries each feed's credit line and licence. Answers 304 to a matching If-None-Match.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
updatedAt: null | number
feeds: {
sourceId: string
label: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA" | "AU"
attribution: string
licence: string
licenceUrl?: string
homepage?: string
count: number
ok: boolean
checkedAt?: number
changedAt?: number
error?: string
}[]
incidents: {
id: string
sourceId: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
kind: "warning" | "incident"
hazard: "other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal"
level: "none" | "advice" | "watch_and_act" | "emergency_warning"
status?: string
statusClass: "unknown" | "active" | "contained" | "controlled"
title: string
category?: string
location?: string
lga?: string
action?: string
description?: string
size?: string
agency?: string
resources?: number
updated: number
published?: number
url?: string
point: [number, number]
polygons?: [number, number][][][]
distanceKm?: number
}[]
total: number
etag: string
}Response 304 with no body.
GET /v1/orgs/:orgId/maps/incidents/feeds
The emergency feeds in use: credit lines, licences, when each was last read and whether it's working.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
updatedAt: null | number
feeds: {
sourceId: string
label: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA" | "AU"
attribution: string
licence: string
licenceUrl?: string
homepage?: string
count: number
ok: boolean
checkedAt?: number
changedAt?: number
error?: string
}[]
}GET /v1/orgs/:orgId/maps/incidents/:incidentId
One incident (or its last version if it has ended) with its history of changes, newest first.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:incidentId | Incident id as listed (<feed>:<the agency's id>, e.g. vic:ESTA:261009192), URL-encoded. |
Response 200
{
incident: null | {
id: string
sourceId: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
kind: "warning" | "incident"
hazard: "other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal"
level: "none" | "advice" | "watch_and_act" | "emergency_warning"
status?: string
statusClass: "unknown" | "active" | "contained" | "controlled"
title: string
category?: string
location?: string
lga?: string
action?: string
description?: string
size?: string
agency?: string
resources?: number
updated: number
published?: number
url?: string
point: [number, number]
polygons?: [number, number][][][]
}
ended: boolean
history: {
at: number
change: string
incident: {
url?: string
status?: string
kind: "warning" | "incident"
level: "none" | "advice" | "watch_and_act" | "emergency_warning"
title: string
description?: string
location?: string
id: string
size?: string
category?: string
action?: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
sourceId: string
published?: number
resources?: number
updated: number
hazard: "other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal"
statusClass: "unknown" | "active" | "contained" | "controlled"
lga?: string
agency?: string
point: [number, number]
}
}[]
feed?: {
sourceId: string
label: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA" | "AU"
attribution: string
licence: string
licenceUrl?: string
homepage?: string
count: number
ok: boolean
checkedAt?: number
changedAt?: number
error?: string
}
}GET /v1/orgs/:orgId/maps/zones/config
Hazards, levels, zone events, states and a new zone's defaults for the caller.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
hazards: {
id: "other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal"
label: string
icon: string
glyph: "car" | "tree" | "info" | "cyclone" | "smoke" | "flame" | "grass" | "burn" | "house" | "drop" | "bolt" | "sun" | "wave" | "quake" | "slope" | "hazard" | "buoy" | "cross" | "plug" | "paw"
group: string
}[]
hazardGroups: {
id: string
label: string
}[]
levels: {
id: "none" | "advice" | "watch_and_act" | "emergency_warning"
label: string
callToAction: null | string
token: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground" | "primary" | "destructive" | "muted-foreground" | "background" | "incident" | "map-horizon" | "map-sky" | "map-space" | "incident-foreground" | "warning-advice" | "warning-advice-foreground" | "warning-watch" | "warning-watch-foreground" | "warning-emergency" | "warning-emergency-foreground"
foreground: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground" | "primary" | "destructive" | "muted-foreground" | "background" | "incident" | "map-horizon" | "map-sky" | "map-space" | "incident-foreground" | "warning-advice" | "warning-advice-foreground" | "warning-watch" | "warning-watch-foreground" | "warning-emergency" | "warning-emergency-foreground"
}[]
statuses: {
id: "unknown" | "active" | "contained" | "controlled"
label: string
}[]
events: {
type: "new" | "closed" | "updated" | "escalated" | "downgraded"
label: string
}[]
states: {
id: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
label: string
}[]
defaults: {
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
smsEvents: null | ("new" | "closed" | "updated" | "escalated" | "downgraded")[]
events: {
new: boolean
closed: boolean
updated: boolean
escalated: boolean
downgraded: boolean
}
}
}GET /v1/orgs/:orgId/maps/zones
Watch zones: areas where emergency incidents and warnings alert (those the caller can see).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
zones: {
name: string
visibility: "org" | "private"
areas: {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
} | {
kind: "state"
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
}[]
hazards: ("other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal")[]
minLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
events: {
new?: boolean
closed?: boolean
updated?: boolean
escalated?: boolean
downgraded?: boolean
}
notify: {
smsEvents: null | ("new" | "closed" | "updated" | "escalated" | "downgraded")[]
smsMinLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allowLevels: ("none" | "advice" | "watch_and_act" | "emergency_warning")[]
}
timeZone?: string
}
paused: boolean
zoneId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
alertsSent: number
personal?: boolean
status: "active" | "paused" | "waiting_location"
}[]
}POST /v1/orgs/:orgId/maps/zones
Creates a watch zone: areas (circle, polygon, location, near_me or state; up to 10), hazards (empty: all), minLevel, events and notify (channels, people, groups, smsEvents, smsMinLevel, quiet hours with allowLevels). Channels left out get the caller's defaults.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 201
{
zone: {
name: string
visibility: "org" | "private"
areas: {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
} | {
kind: "state"
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
}[]
hazards: ("other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal")[]
minLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
events: {
new?: boolean
closed?: boolean
updated?: boolean
escalated?: boolean
downgraded?: boolean
}
notify: {
smsEvents: null | ("new" | "closed" | "updated" | "escalated" | "downgraded")[]
smsMinLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allowLevels: ("none" | "advice" | "watch_and_act" | "emergency_warning")[]
}
timeZone?: string
}
paused: boolean
zoneId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
alertsSent: number
personal?: boolean
status: "active" | "paused" | "waiting_location"
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
GET /v1/orgs/:orgId/maps/zones/:zoneId
One watch zone, with its status (active, paused or waiting_location for a near-me zone without a current location).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:zoneId | Watch zone id (izn_…). |
Response 200
{
zone: {
name: string
visibility: "org" | "private"
areas: {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
} | {
kind: "state"
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
}[]
hazards: ("other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal")[]
minLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
events: {
new?: boolean
closed?: boolean
updated?: boolean
escalated?: boolean
downgraded?: boolean
}
notify: {
smsEvents: null | ("new" | "closed" | "updated" | "escalated" | "downgraded")[]
smsMinLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allowLevels: ("none" | "advice" | "watch_and_act" | "emergency_warning")[]
}
timeZone?: string
}
paused: boolean
zoneId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
alertsSent: number
personal?: boolean
status: "active" | "paused" | "waiting_location"
}
}PATCH /v1/orgs/:orgId/maps/zones/:zoneId
Changes a watch zone (its owner, or an org admin for org zones): fields sent replace the stored ones.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:zoneId | Watch zone id (izn_…). |
Response 200
{
zone: {
name: string
visibility: "org" | "private"
areas: {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
} | {
kind: "state"
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
}[]
hazards: ("other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal")[]
minLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
events: {
new?: boolean
closed?: boolean
updated?: boolean
escalated?: boolean
downgraded?: boolean
}
notify: {
smsEvents: null | ("new" | "closed" | "updated" | "escalated" | "downgraded")[]
smsMinLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allowLevels: ("none" | "advice" | "watch_and_act" | "emergency_warning")[]
}
timeZone?: string
}
paused: boolean
zoneId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
alertsSent: number
personal?: boolean
status: "active" | "paused" | "waiting_location"
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
POST /v1/orgs/:orgId/maps/zones/:zoneId/pause
Pauses a watch zone: nothing is checked or sent until it's resumed.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:zoneId | Watch zone id (izn_…). |
Response 200
{
zone: {
name: string
visibility: "org" | "private"
areas: {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
} | {
kind: "state"
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
}[]
hazards: ("other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal")[]
minLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
events: {
new?: boolean
closed?: boolean
updated?: boolean
escalated?: boolean
downgraded?: boolean
}
notify: {
smsEvents: null | ("new" | "closed" | "updated" | "escalated" | "downgraded")[]
smsMinLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allowLevels: ("none" | "advice" | "watch_and_act" | "emergency_warning")[]
}
timeZone?: string
}
paused: boolean
zoneId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
alertsSent: number
personal?: boolean
status: "active" | "paused" | "waiting_location"
}
}POST /v1/orgs/:orgId/maps/zones/:zoneId/resume
Resumes a paused watch zone.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:zoneId | Watch zone id (izn_…). |
Response 200
{
zone: {
name: string
visibility: "org" | "private"
areas: {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
} | {
kind: "location"
locationId: string
radiusKm: number
} | {
kind: "near_me"
radiusKm: number
} | {
kind: "state"
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
}[]
hazards: ("other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal")[]
minLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
events: {
new?: boolean
closed?: boolean
updated?: boolean
escalated?: boolean
downgraded?: boolean
}
notify: {
smsEvents: null | ("new" | "closed" | "updated" | "escalated" | "downgraded")[]
smsMinLevel: "none" | "advice" | "watch_and_act" | "emergency_warning"
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
includeOwner: boolean
groupIds: string[]
userIds: string[]
smsFormat: "full" | "short"
smsPrefix: boolean
quietHours?: null | {
start: string
end: string
timeZone: string
allowLevels: ("none" | "advice" | "watch_and_act" | "emergency_warning")[]
}
timeZone?: string
}
paused: boolean
zoneId: string
orgId: string
ownerId: string
createdAt: number
updatedAt: number
lastEventAt?: number
alertsSent: number
personal?: boolean
status: "active" | "paused" | "waiting_location"
}
}POST /v1/orgs/:orgId/maps/zones/:zoneId/test
Sends the caller a sample alert on the zone's channels that reach them; per-channel results.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:zoneId | Watch zone id (izn_…). |
Response 200
{
mobile?: {
devices: number
queued: boolean
}
web?: {
sent: number
devices: number
}
email?: {
sent?: boolean
skipped?: string
}
sms?: {
sent?: boolean
error?: string
skipped?: string
}
call?: {
skipped: string
}
}GET /v1/orgs/:orgId/maps/zones/:zoneId/events
A watch zone's alerts, newest first (limit, cursor): the change, the incident as it was, the distance and what was sent. Kept 30 days (7 for near-me zones).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:zoneId | Watch zone id (izn_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
limit | string | No | 50 | |
cursor | string | No |
Response 200
{
events: {
eventId: string
zoneId: string
type: "new" | "closed" | "updated" | "escalated" | "downgraded"
at: number
incidentId: string
title: string
text: string
from?: "none" | "advice" | "watch_and_act" | "emergency_warning"
incident: {
url?: string
status?: string
kind: "warning" | "incident"
level: "none" | "advice" | "watch_and_act" | "emergency_warning"
title: string
description?: string
location?: string
id: string
size?: string
category?: string
action?: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
sourceId: string
published?: number
resources?: number
updated: number
hazard: "other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal"
statusClass: "unknown" | "active" | "contained" | "controlled"
lga?: string
agency?: string
point: [number, number]
}
distanceKm?: number
delivery?: {
status: "failed" | "sent" | "duplicate" | "quiet" | "no_recipients"
channels?: string[]
recipients?: number
errors?: string[]
duplicates?: {
recipients: number
}
}
}[]
cursor: null | string
}DELETE /v1/orgs/:orgId/maps/zones/:zoneId
Deletes a watch zone. Its alerts expire on their own.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:zoneId | Watch zone id (izn_…). |
Response 200
{
ok: true
}GET /v1/orgs/:orgId/maps/zone-events
Recent zone alerts across the zones the caller can see.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
limit | string | No | 50 |
Response 200
{
events: {
eventId: string
zoneId: string
type: "new" | "closed" | "updated" | "escalated" | "downgraded"
at: number
incidentId: string
title: string
text: string
from?: "none" | "advice" | "watch_and_act" | "emergency_warning"
incident: {
url?: string
status?: string
kind: "warning" | "incident"
level: "none" | "advice" | "watch_and_act" | "emergency_warning"
title: string
description?: string
location?: string
id: string
size?: string
category?: string
action?: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
sourceId: string
published?: number
resources?: number
updated: number
hazard: "other" | "bushfire" | "grass_fire" | "burn_off" | "structure_fire" | "vehicle_fire" | "fire" | "flood" | "storm" | "cyclone" | "tree_down" | "heat" | "tsunami" | "earthquake" | "landslide" | "hazmat" | "smoke" | "rescue" | "medical" | "accident" | "power" | "animal"
statusClass: "unknown" | "active" | "contained" | "controlled"
lga?: string
agency?: string
point: [number, number]
}
distanceKm?: number
delivery?: {
status: "failed" | "sent" | "duplicate" | "quiet" | "no_recipients"
channels?: string[]
recipients?: number
errors?: string[]
duplicates?: {
recipients: number
}
}
}[]
}GET /v1/orgs/:orgId/maps/locations
The org's alert locations: locationId, name, lat, lon, siteRadiusM (within it counts as on site), address, note, icon, color, ownerId.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
locations: {
locationId: string
orgId: string
name: string
lat: number
lon: number
siteRadiusM: number
address?: string
note?: string
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
ownerId: string
createdAt: number
updatedAt: number
}[]
}POST /v1/orgs/:orgId/maps/locations
Creates an alert location: name, lat, lon, siteRadiusM (50–5,000 m, default 300), optional address, note, icon, color. Up to 50 per organization.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 201
{
location: {
locationId: string
orgId: string
name: string
lat: number
lon: number
siteRadiusM: number
address?: string
note?: string
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
ownerId: string
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
GET /v1/orgs/:orgId/maps/locations/:locationId
One alert location.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:locationId | Location id: a platform location, or under Maps an org's alert location (mlc_…). |
Response 200
{
location: {
locationId: string
orgId: string
name: string
lat: number
lon: number
siteRadiusM: number
address?: string
note?: string
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
ownerId: string
createdAt: number
updatedAt: number
}
}PATCH /v1/orgs/:orgId/maps/locations/:locationId
Changes an alert location; fields sent replace the stored ones. Moving it moves every watch that uses it. Its owner or an org admin.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:locationId | Location id: a platform location, or under Maps an org's alert location (mlc_…). |
Response 200
{
location: {
locationId: string
orgId: string
name: string
lat: number
lon: number
siteRadiusM: number
address?: string
note?: string
icon: "map-pin" | "star" | "heart" | "home" | "briefcase" | "utensils" | "coffee" | "plane" | "helicopter" | "flag" | "camera" | "car" | "tent" | "hospital" | "shield"
color: "chart-1" | "chart-2" | "chart-3" | "chart-4" | "chart-5" | "foreground"
ownerId: string
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
DELETE /v1/orgs/:orgId/maps/locations/:locationId
Deletes an alert location. 409, naming them, while watches use it. Its owner or an org admin.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:locationId | Location id: a platform location, or under Maps an org's alert location (mlc_…). |
Response 200
{
ok: true
}GET /v1/orgs/:orgId/maps/locations/:locationId/watches
Watches that alert near a location (watchId, name), those the caller can see.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:locationId | Location id: a platform location, or under Maps an org's alert location (mlc_…). |
Response 200
{
watches: {
watchId: string
name: string
}[]
}GET /v1/orgs/:orgId/maps/groups
Notification groups with counts of active, pending and unsubscribed recipients.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
groups: {
counts: {
active: number
pending: number
unsubscribed: number
}
canEdit: boolean
groupId: string
orgId: string
name: string
ownerId: string
createdAt: number
updatedAt: number
}[]
}POST /v1/orgs/:orgId/maps/groups
Creates a notification group (name).
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 201
{
group: {
groupId: string
orgId: string
name: string
ownerId: string
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
GET /v1/orgs/:orgId/maps/groups/:groupId
A group and, for its owner and org admins, its recipients.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:groupId | Notification group id (ngr_…). |
Response 200
{
group: {
members: {
memberId: string
groupId: string
kind: "user" | "contact"
userId?: string
name?: string
email?: string
phone?: string
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
status: "active" | "pending" | "unsubscribed"
createdAt: number
confirmedAt?: number
unsubscribedAt?: number
}[]
canEdit: boolean
groupId: string
orgId: string
name: string
ownerId: string
createdAt: number
updatedAt: number
}
}PATCH /v1/orgs/:orgId/maps/groups/:groupId
Renames a group.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:groupId | Notification group id (ngr_…). |
Response 200
{
group: {
groupId: string
orgId: string
name: string
ownerId: string
createdAt: number
updatedAt: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
DELETE /v1/orgs/:orgId/maps/groups/:groupId
Deletes a group and its recipients. Watches that used it stop sending to them.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:groupId | Notification group id (ngr_…). |
Response 200
{
ok: true
}POST /v1/orgs/:orgId/maps/groups/:groupId/members
Adds a recipient: an organization member ({ kind: "user", userId }, active at once) or anyone ({ kind: "contact", name?, email?, phone? } with phone in E.164), who is asked to confirm first and stays pending until they do. channels limits what they get.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:groupId | Notification group id (ngr_…). |
Response 201
{
member: {
memberId: string
groupId: string
kind: "user" | "contact"
userId?: string
name?: string
email?: string
phone?: string
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
status: "active" | "pending" | "unsubscribed"
createdAt: number
confirmedAt?: number
unsubscribedAt?: number
}
invited: boolean
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
PATCH /v1/orgs/:orgId/maps/groups/:groupId/members/:memberId
Changes a recipient's name or channels.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:groupId | Notification group id (ngr_…). |
:memberId | Recipient id (nmb_…). |
Response 200
{
member: {
memberId: string
groupId: string
kind: "user" | "contact"
userId?: string
name?: string
email?: string
phone?: string
channels: ("email" | "sms" | "call" | "mobile" | "web")[]
status: "active" | "pending" | "unsubscribed"
createdAt: number
confirmedAt?: number
unsubscribedAt?: number
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
POST /v1/orgs/:orgId/maps/groups/:groupId/members/:memberId/resend
Asks a pending recipient to confirm again (at most three times, an hour apart).
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:groupId | Notification group id (ngr_…). |
:memberId | Recipient id (nmb_…). |
Response 200
{
invited: boolean
}DELETE /v1/orgs/:orgId/maps/groups/:groupId/members/:memberId
Removes a recipient.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:groupId | Notification group id (ngr_…). |
:memberId | Recipient id (nmb_…). |
Response 200
{
ok: true
}GET /v1/orgs/:orgId/maps/push
Where the caller's alerts can go: the web push public key (VAPID), browsers with web push (subscriptions) and phones that get Maps alerts (phones: deviceId, appId maps, or home on phones without the Maps app, name, model, platform, appVersion, updatedAt).
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
publicKey: string
subscriptions: {
subId: string
label?: string
host: string
createdAt: number
lastUsedAt?: number
}[]
phones: {
deviceId: string
appId: "maps" | "home"
name?: string
model?: string
platform: string
appVersion?: string
updatedAt?: number
}[]
}POST /v1/orgs/:orgId/maps/push/test
Sends the caller a sample alert on their phones (Maps app) and browsers: mobile (devices, queued) and web (sent, devices).
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
mobile?: {
devices: number
queued: boolean
}
web?: {
sent: number
devices: number
}
email?: {
sent?: boolean
skipped?: string
}
sms?: {
sent?: boolean
error?: string
skipped?: string
}
call?: {
skipped: string
}
}POST /v1/orgs/:orgId/maps/push/subscriptions
Subscribes a device to web push: the browser's PushSubscription (endpoint, keys.p256dh, keys.auth) and an optional label. People only; up to 20 devices.
Auth: user access token or platform agent key · Scopes: maps:read, maps:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 201
{
subId: string
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
DELETE /v1/orgs/:orgId/maps/push/subscriptions/:subId
Removes one of the caller's devices.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:subId | Push subscription id, as listed by GET /v1/orgs/:orgId/maps/push. |
Response 200
{
ok: true
}GET /v1/me/maps/location
Your location for near-me alerts: sharing, the phones sharing (devices: deviceId, platform, name, mode foreground or background, retentionHours, enabledAt, lastReportAt), the current fix (current: lat, lon to 3 decimals, accuracyM, at, deviceName, validUntil, or null) and the near-me watches using it (usedBy). From the Maps or mobile apps only.
Auth: user access token or platform agent key
Response 200
{
sharing: boolean
devices: {
lastReportAt?: number
mode: "foreground" | "background"
retentionHours: number
enabledAt: number
name?: string
deviceId: string
platform: string
}[]
current: null | {
deviceId: string
mode: string
validUntil: number
deviceName?: string
lat: number
lon: number
accuracyM: number
at: number
}
usedBy: {
orgId: string
watchId: string
name: string
}[]
}Errors
| Status | Message |
|---|---|
403 | Your location is yours: open it in the Maps app. |
PUT /v1/me/maps/location/devices/:deviceId
Turns sharing on for this phone or changes it: platform, name, mode (foreground: counts 30 minutes after each report; background: retentionHours 1, 6 or 24 after the last report). A background phone gets its report key (key, si_loc_…) once. Mobile app tokens only, tied to their sign-in.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:deviceId | Device id: an agent's (dev_…); under /v1/me/notifications a phone's install id; under /v1/me/sign-in-approvals a phone that approves sign-ins (apd_…); under /v1/me/vault the id a device made for its vault (22 base64url characters). |
Response 200
{
key?: string
device: {
lastReportAt?: number
mode: "foreground" | "background"
retentionHours: number
enabledAt: number
name?: string
deviceId: string
platform: string
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
403 | Your location is yours: open it in the Maps app. |
403 | Phones share their location from the Maps app. |
POST /v1/me/maps/location/devices/:deviceId/report
Reports this phone's location: lat, lon, accuracyM, at (ms; at most 10 minutes old), source (foreground, significant, region, open). Stored to 3 decimals, accuracy at least 50 m, one current fix per phone; 204 when dropped (one report per 20 s). Mobile app tokens only.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:deviceId | Device id: an agent's (dev_…); under /v1/me/notifications a phone's install id; under /v1/me/sign-in-approvals a phone that approves sign-ins (apd_…); under /v1/me/vault the id a device made for its vault (22 base64url characters). |
Response 200
{
ok: true
validUntil?: number
}Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Send JSON. |
403 | Your location is yours: open it in the Maps app. |
403 | Phones share their location from the Maps app. |
DELETE /v1/me/maps/location/devices/:deviceId
Stops sharing on one phone: its fix and key are deleted.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:deviceId | Device id: an agent's (dev_…); under /v1/me/notifications a phone's install id; under /v1/me/sign-in-approvals a phone that approves sign-ins (apd_…); under /v1/me/vault the id a device made for its vault (22 base64url characters). |
Response 200
{
ok: boolean
}Errors
| Status | Message |
|---|---|
403 | Your location is yours: open it in the Maps app. |
DELETE /v1/me/maps/location
Deletes your location everywhere: every phone's fix, the phones and their keys. Near-me watches wait until a phone shares again.
Auth: user access token or platform agent key
Response 200
{
devices: number
ok: true
}Errors
| Status | Message |
|---|---|
403 | Your location is yours: open it in the Maps app. |
GET /v1/me/maps/location/activity
Your own log of turning sharing on, background on, stopping, deleting and phones removed at sign-out (action, at, deviceName), kept 90 days. Never coordinates.
Auth: user access token or platform agent key
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
limit | string | No | 50 |
Response 200
{
activity: {
deviceName?: string
action: string
at: number
}[]
}Errors
| Status | Message |
|---|---|
403 | Your location is yours: open it in the Maps app. |