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, or a notification recipient's confirm and unsubscribe link. |
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, or a notification recipient's confirm and unsubscribe link. |
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, or a notification recipient's confirm and unsubscribe link. |
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, or a notification recipient's confirm and unsubscribe link. |
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, or a notification recipient's confirm and unsubscribe link. |
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, or a notification recipient's confirm and unsubscribe link. |
Response 200
{
status: "active" | "pending" | "unsubscribed"
group: string
email?: string
phone?: string
}GET /v1/orgs/:orgId/maps/config
What the app needs to draw: the ADS-B source and its credit line, preset areas, event types and channels; for texts, whether the SMS account is still in the provider's sandbox and where the signed-in person's own texts go (masked).
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: {
type: "emergency" | "takeoff" | "landing" | "signal_lost" | "signal_resumed" | "area_enter" | "area_leave" | "orbit" | "road_follow" | "road_switch" | "road_repeat" | "road_leave" | "interchange" | "threshold"
label: string
}[]
channels: {
push: true
email: boolean
sms: boolean
call: boolean
}
sms: {
sandbox: boolean | null
phone: null | string
phoneSettings: null | string
}
}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/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 from the live snapshot with its recent track; 404 when it hasn't been seen in the last 90 seconds.
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: 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])[]
}
provider: {
label: string
id: string
attribution: string
}
}Errors
| Status | Message |
|---|---|
404 | Aircraft not found |
404 | Not seen in the last 90 seconds |
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.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
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
}[]
}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_…). |
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_…). |
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_…). |
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_…). |
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_…). |
: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_…). |
: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: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
exclude: {
kind: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
}[]
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
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: 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: {
channels: ("email" | "call" | "push" | "sms")[]
includeOwner: boolean
groupIds: string[]
membershipNotices: boolean
smsFormat: "full" | "short"
smsPrefix: boolean
cooldownMinutes: number
timeZone?: string
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")[]
}
}
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"
status: "active" | "paused" | "waiting" | "ended" | "off_schedule"
}[]
}POST /v1/orgs/:orgId/maps/watches
Creates a flight watch: name, targets ({ kind: hex | registration | callsign | type, value }, a trailing * matches prefixes), 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 } or polygons { ring: [[lon, lat], …] }), limitToAreas, events (on/off per event type), settings (signal, orbit, roads, thresholds), notify (channels, includeOwner, groupIds, 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. 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: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
exclude: {
kind: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
}[]
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
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: 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: {
channels: ("email" | "call" | "push" | "sms")[]
includeOwner: boolean
groupIds: string[]
membershipNotices: boolean
smsFormat: "full" | "short"
smsPrefix: boolean
cooldownMinutes: number
timeZone?: string
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")[]
}
}
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"
status: "active" | "paused" | "waiting" | "ended" | "off_schedule"
}
}Errors
| Status | Message |
|---|---|
400 | Send JSON. |
GET /v1/orgs/:orgId/maps/watches/:watchId
A flight watch with every setting, defaults filled in.
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: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
exclude: {
kind: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
}[]
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
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: 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: {
channels: ("email" | "call" | "push" | "sms")[]
includeOwner: boolean
groupIds: string[]
membershipNotices: boolean
smsFormat: "full" | "short"
smsPrefix: boolean
cooldownMinutes: number
timeZone?: string
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")[]
}
}
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"
status: "active" | "paused" | "waiting" | "ended" | "off_schedule"
}
}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: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
exclude: {
kind: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
}[]
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
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: 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: {
channels: ("email" | "call" | "push" | "sms")[]
includeOwner: boolean
groupIds: string[]
membershipNotices: boolean
smsFormat: "full" | "short"
smsPrefix: boolean
cooldownMinutes: number
timeZone?: string
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")[]
}
}
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"
status: "active" | "paused" | "waiting" | "ended" | "off_schedule"
}
}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: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
exclude: {
kind: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
}[]
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
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: 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: {
channels: ("email" | "call" | "push" | "sms")[]
includeOwner: boolean
groupIds: string[]
membershipNotices: boolean
smsFormat: "full" | "short"
smsPrefix: boolean
cooldownMinutes: number
timeZone?: string
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")[]
}
}
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"
status: "active" | "paused" | "waiting" | "ended" | "off_schedule"
}
}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: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
exclude: {
kind: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
}[]
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
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: 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: {
channels: ("email" | "call" | "push" | "sms")[]
includeOwner: boolean
groupIds: string[]
membershipNotices: boolean
smsFormat: "full" | "short"
smsPrefix: boolean
cooldownMinutes: number
timeZone?: string
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")[]
}
}
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"
status: "active" | "paused" | "waiting" | "ended" | "off_schedule"
}
}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: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
exclude: {
kind: "type" | "hex" | "callsign" | "registration" | "no_callsign"
value: string
}[]
areas: {
kind: "preset"
id: string
} | {
kind: "circle"
center: [number, number]
radiusKm: number
label?: string
} | {
kind: "polygon"
ring: [number, number][]
label?: string
}[]
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
}
settings: {
signal: {
lostAfterSeconds: number
lowAltitudeFt: number
}
orbit: {
turns: number
radiusKm: number
windowMinutes: 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: {
channels: ("email" | "call" | "push" | "sms")[]
includeOwner: boolean
groupIds: string[]
membershipNotices: boolean
smsFormat: "full" | "short"
smsPrefix: boolean
cooldownMinutes: number
timeZone?: string
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")[]
}
}
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"
status: "active" | "paused" | "waiting" | "ended" | "off_schedule"
}
}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: "completed" | "ended" | "in_progress"
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"
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: "completed" | "ended" | "in_progress"
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"
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" | "recipients_added" | "recipients_removed"
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" | "quiet" | "cooldown" | "no_recipients"
channels?: ("email" | "call" | "push" | "sms")[]
recipients?: number
errors?: 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" | "recipients_added" | "recipients_removed"
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" | "quiet" | "cooldown" | "no_recipients"
channels?: ("email" | "call" | "push" | "sms")[]
recipients?: number
errors?: 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" | "call" | "push" | "sms")[]
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" | "call" | "push" | "sms")[]
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" | "call" | "push" | "sms")[]
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
The web push public key (VAPID) and the caller's subscribed devices.
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
}[]
}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
}