API reference
Notifications and protocols
Your notifications, and an organization's notification protocols.
See Notifications and Caity by phone for how events, channels, quiet hours and protocols work.
GET /v1/me/notifications/devices
The apps registered for push on your phones: one entry per app per phone (deviceId is the phone's install id), with appId, platform, and the name, model, osVersion and appVersion the app sent. No push tokens.
Auth: user access token or platform agent key
Response 200
{
devices: {
deviceId: string
appId: string
platform: "ios" | "android"
name?: string
model?: string
osVersion?: string
appVersion?: string
createdAt?: number
updatedAt?: number
}[]
}Errors
| Status | Message |
|---|---|
403 | Notifications belong to people. |
PUT /v1/me/notifications/devices/:deviceId
Registers or refreshes a mobile app's Expo push token on this phone (token, platform, appId, optional name, model, osVersion, appVersion). A mobile app's token ties the registration to its sign-in, so signing the app out removes it, and appId must be that app. People only, not assistants.
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). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
token | string | Yes | ||
platform | "ios" | "android" | Yes | ||
appId | "home" | "caity" | "tasks" | "brain" | "mail" | "drive" | "photos" | "git" | "cloud" | "maps" | "tenant" | "admin" | "docs" | "account" | "authenticator" | "mirage" | "health" | "weather" | "marketing" | "food" | No | "caity" | |
name | any JSON | Yes | ||
model | any JSON | Yes | ||
osVersion | any JSON | Yes | ||
appVersion | any JSON | Yes |
Response 200
{
ok: true
}Errors
| Status | Message |
|---|---|
400 | Invalid device ID |
400 | appId does not match the signed-in app |
403 | Notifications belong to people. |
403 | Register devices from the mobile app. |
DELETE /v1/me/notifications/devices/:deviceId
Removes an app's push registration on this phone (appId, default caity). Signing the app out removes it too. People only, not assistants.
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). |
| Query parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
appId | "home" | "caity" | "tasks" | "brain" | "mail" | "drive" | "photos" | "git" | "cloud" | "maps" | "tenant" | "admin" | "docs" | "account" | "authenticator" | "mirage" | "health" | "weather" | "marketing" | "food" | No | "caity" |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
403 | Notifications belong to people. |
403 | Register devices from the mobile app. |
GET /v1/me/notifications/live-activities
Your iPhone Live Activity registrations: per phone and app (maps or home), the push-to-start entry (kind: start) and each running flight activity (kind: activity, with orgId, hex, watchId or local), the APNs environment and, on the push-to-start entry, the flight activities the app last reported running (running). No tokens.
Auth: user access token or platform agent key
Response 200
{
liveActivities: {
kind: "start" | "activity"
installId: string
appId: string
activityId: string
environment: "production" | "development"
orgId?: string
hex?: string
watchId?: string
local?: boolean
running?: string[]
createdAt?: number
updatedAt?: number
}[]
}Errors
| Status | Message |
|---|---|
403 | Notifications belong to people. |
PUT /v1/me/notifications/live-activities/start/:installId
Registers the Maps or Home app's push-to-start token on this iPhone (token in hex, appId, environment production or development, bundleId, and running: the hexes of the flight activities running in the app, sent again whenever they change), so a flight watch can start a Live Activity at takeoff. From the signed-in iPhone app only; tied to its sign-in.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:installId | The phone's install id (the same for every app on it). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | Yes | |
appId | "maps" | "home" | Yes | |
environment | "production" | "development" | Yes | |
bundleId | string | Yes | |
running | string[] | No | up to 20 items; each matches ^~?[0-9a-fA-F]{6}$ |
Response 200
{
ok: true
}Errors
| Status | Message |
|---|---|
400 | appId does not match the signed-in app |
400 | Invalid install ID |
403 | Notifications belong to people. |
403 | Register devices from the mobile app. |
403 | Register Live Activities from the iPhone app. |
DELETE /v1/me/notifications/live-activities/start/:installId
Removes the app's push-to-start token on this phone (appId). Signing the app out removes it too.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:installId | The phone's install id (the same for every app on it). |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
appId | "maps" | "home" | Yes |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | appId does not match the signed-in app |
400 | Invalid install ID |
403 | Notifications belong to people. |
403 | Register devices from the mobile app. |
403 | Register Live Activities from the iPhone app. |
PUT /v1/me/notifications/live-activities/:activityId
Registers a running flight Live Activity's update token (token, appId, environment, bundleId, installId, orgId, hex, and watchId or local: true for one started with Track live). Needs maps:read in the org; from the signed-in iPhone app only.
Auth: user access token or platform agent key · Scope: maps:read
| Path parameter | Description |
|---|---|
:activityId | ActivityKit's id for a running Live Activity on the phone. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | Yes | |
appId | "maps" | "home" | Yes | |
environment | "production" | "development" | Yes | |
bundleId | string | Yes | |
installId | string | Yes | |
orgId | string | Yes | 1–64 characters |
hex | string | Yes | matches ^~?[0-9a-fA-F]{6}$ |
watchId | string | No | 1–64 characters |
local | boolean | No |
Response 200
{
ok: true
}Errors
| Status | Message |
|---|---|
400 | appId does not match the signed-in app |
400 | Invalid install ID |
400 | Invalid activity ID |
403 | Notifications belong to people. |
403 | Register devices from the mobile app. |
403 | Register Live Activities from the iPhone app. |
DELETE /v1/me/notifications/live-activities/:activityId
The activity ended or was dismissed on the phone: no more updates (installId, appId).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:activityId | ActivityKit's id for a running Live Activity on the phone. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
installId | string | Yes | |
appId | "maps" | "home" | Yes |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | appId does not match the signed-in app |
400 | Invalid install ID |
403 | Notifications belong to people. |
403 | Register devices from the mobile app. |
403 | Register Live Activities from the iPhone app. |
GET /v1/me/notifications
Your notifications, newest first (cursor, limit): title, body, link, read, and whether one waits for an acknowledgement (escalating alerts). app: only that mobile app's notices (home: every app's). People only.
Auth: user access token or platform agent key
| Query parameter | Type | Required | Notes |
|---|---|---|---|
cursor | string | No | up to 2,000 characters |
limit | integer | No | 1–100; coerced from a string |
app | "home" | "caity" | "tasks" | "brain" | "mail" | "drive" | "photos" | "git" | "cloud" | "maps" | "tenant" | "admin" | "docs" | "account" | "authenticator" | "mirage" | "health" | "weather" | "marketing" | "food" | No |
Response 200
{
notices: {
noticeId: string
orgId?: string
event: string
title: string
body?: string
url?: string
read?: boolean
requireAck?: boolean
ackedAt?: number
createdAt?: number
}[]
cursor: null | string
}Errors
| Status | Message |
|---|---|
403 | Notifications belong to people. |
POST /v1/me/notifications/read
Marks notifications read (noticeIds, up to 100).
Auth: user access token or platform agent key
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
noticeIds | string[] | Yes | 1–100 items; each up to 64 characters |
Response 200
{
ok: true
}Errors
| Status | Message |
|---|---|
403 | Notifications belong to people. |
POST /v1/me/notifications/:noticeId/ack
Acknowledges a notification: its escalation (later texts or calls) stops. acked: false when it already was.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:noticeId | Notification id (nte_…). |
Response 200
{
acked: boolean
}Errors
| Status | Message |
|---|---|
403 | Notifications belong to people. |
GET /v1/orgs/:orgId/notify/protocols/templates
Ready-made notification protocols (production on-call, meeting guard, invitation chaser, VIP mail, service desk SLA, agent jobs).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
templates: {
id: string
name: string
description: string
rules: {
events: ("issue.sla_breached" | "deployment.ready" | "deployment.failed" | "maps.incident" | "maps.flight" | "assistant.briefing" | "account.new_sign_in" | "domain.verified" | "domain.failed" | "secret.rotation_due" | "issue.assigned" | "issue.mentioned" | "calendar.invite_unanswered" | "calendar.meeting_soon" | "page.mentioned" | "mail.vip" | "maps.watch" | "office.mention" | "video.captions" | "food.receipt" | "food.use_soon" | "agent.job_done" | "agent.job_failed" | "pipeline.failed" | "pipeline.approval" | "security.git_key" | "security.git_clone" | "security.repo_access" | "ops.alarm" | "marketing.approval" | "marketing.journey" | "mirage.report" | "feedback.bug")[]
match?: {
[key: string]: string[]
}
steps: {
afterMinutes: number
channels: object
}[]
beforeEvent?: boolean
roles?: ("owner" | "admin" | "developer" | "viewer")[]
userIds?: string[]
overrideQuietHours?: boolean
}[]
}[]
}GET /v1/orgs/:orgId/notify/protocols
The organization's notification protocols with their rules and what each is attached to.
Auth: user access token or platform agent key · Scope: org:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
protocols: {
protocolId: string
orgId: string
name: string
description?: string
enabled: boolean
rules: {
events: ("issue.sla_breached" | "deployment.ready" | "deployment.failed" | "maps.incident" | "maps.flight" | "assistant.briefing" | "account.new_sign_in" | "domain.verified" | "domain.failed" | "secret.rotation_due" | "issue.assigned" | "issue.mentioned" | "calendar.invite_unanswered" | "calendar.meeting_soon" | "page.mentioned" | "mail.vip" | "maps.watch" | "office.mention" | "video.captions" | "food.receipt" | "food.use_soon" | "agent.job_done" | "agent.job_failed" | "pipeline.failed" | "pipeline.approval" | "security.git_key" | "security.git_clone" | "security.repo_access" | "ops.alarm" | "marketing.approval" | "marketing.journey" | "mirage.report" | "feedback.bug")[]
match?: {
[key: string]: string[]
}
steps: {
afterMinutes: number
channels: object
}[]
beforeEvent?: boolean
roles?: ("owner" | "admin" | "developer" | "viewer")[]
userIds?: string[]
overrideQuietHours?: boolean
}[]
createdBy: string
updatedAt?: number
attachments: {
resourceType: "org" | "project" | "agent" | "calendar" | "mailbox" | "space"
resourceId: string
resourceLabel?: string
}[]
}[]
}POST /v1/orgs/:orgId/notify/protocols
Creates a protocol from { template } or { name, description?, enabled?, rules } (rules: events, optional match on event attributes, steps with minutes and channels, roles, overrideQuietHours, beforeEvent). Owners and admins.
Auth: user access token or platform agent key · Scope: org:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 201
{
protocol: {
attachments: []
protocolId: string
orgId: string
name: string
description?: string
enabled: boolean
rules: {
events: ("issue.sla_breached" | "deployment.ready" | "deployment.failed" | "maps.incident" | "maps.flight" | "assistant.briefing" | "account.new_sign_in" | "domain.verified" | "domain.failed" | "secret.rotation_due" | "issue.assigned" | "issue.mentioned" | "calendar.invite_unanswered" | "calendar.meeting_soon" | "page.mentioned" | "mail.vip" | "maps.watch" | "office.mention" | "video.captions" | "food.receipt" | "food.use_soon" | "agent.job_done" | "agent.job_failed" | "pipeline.failed" | "pipeline.approval" | "security.git_key" | "security.git_clone" | "security.repo_access" | "ops.alarm" | "marketing.approval" | "marketing.journey" | "mirage.report" | "feedback.bug")[]
match?: {
[key: string]: string[]
}
steps: {
afterMinutes: number
channels: ("email" | "sms" | "push" | "voice" | "inapp")[]
}[]
beforeEvent?: boolean
roles?: ("owner" | "admin" | "developer" | "viewer")[]
userIds?: string[]
overrideQuietHours?: boolean
}[]
createdBy: string
updatedAt?: number
}
}GET /v1/orgs/:orgId/notify/protocols/:protocolId
One protocol with its attachments.
Auth: user access token or platform agent key · Scope: org:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:protocolId | Notification protocol id (npr_…). |
Response 200
{
protocol: {
protocolId: string
orgId: string
name: string
description?: string
enabled: boolean
rules: {
events: ("issue.sla_breached" | "deployment.ready" | "deployment.failed" | "maps.incident" | "maps.flight" | "assistant.briefing" | "account.new_sign_in" | "domain.verified" | "domain.failed" | "secret.rotation_due" | "issue.assigned" | "issue.mentioned" | "calendar.invite_unanswered" | "calendar.meeting_soon" | "page.mentioned" | "mail.vip" | "maps.watch" | "office.mention" | "video.captions" | "food.receipt" | "food.use_soon" | "agent.job_done" | "agent.job_failed" | "pipeline.failed" | "pipeline.approval" | "security.git_key" | "security.git_clone" | "security.repo_access" | "ops.alarm" | "marketing.approval" | "marketing.journey" | "mirage.report" | "feedback.bug")[]
match?: {
[key: string]: string[]
}
steps: {
afterMinutes: number
channels: ("email" | "sms" | "push" | "voice" | "inapp")[]
}[]
beforeEvent?: boolean
roles?: ("owner" | "admin" | "developer" | "viewer")[]
userIds?: string[]
overrideQuietHours?: boolean
}[]
createdBy: string
updatedAt?: number
attachments: {
resourceType: "org" | "project" | "agent" | "calendar" | "mailbox" | "space"
resourceId: string
resourceLabel?: string
}[]
}
}PUT /v1/orgs/:orgId/notify/protocols/:protocolId
Replaces a protocol's name, description, on/off and rules. Owners and admins.
Auth: user access token or platform agent key · Scope: org:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:protocolId | Notification protocol id (npr_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | Yes | 1–80 characters; trimmed |
description | string | No | up to 300 characters |
enabled | boolean | No | |
rules | object[] | Yes | 1–20 items |
rules[].events | [] | Yes | at least 1 item |
rules[].match | object | No | values: string[] (up to 20 items, each up to 200 characters) |
rules[].steps | object[] | Yes | 1–6 items |
rules[].steps[].afterMinutes | integer | Yes | 0–10080 |
rules[].steps[].channels | ("inapp" | "push" | "email" | "sms" | "voice")[] | Yes | at least 1 item |
rules[].beforeEvent | boolean | No | |
rules[].roles | ("owner" | "admin" | "developer" | "viewer")[] | No | |
rules[].userIds | string[] | No | up to 50 items; each up to 64 characters |
rules[].overrideQuietHours | boolean | No |
Response 200
{
protocol: {
protocolId: string
orgId: string
name: string
description?: string
enabled: boolean
rules: {
events: ("issue.sla_breached" | "deployment.ready" | "deployment.failed" | "maps.incident" | "maps.flight" | "assistant.briefing" | "account.new_sign_in" | "domain.verified" | "domain.failed" | "secret.rotation_due" | "issue.assigned" | "issue.mentioned" | "calendar.invite_unanswered" | "calendar.meeting_soon" | "page.mentioned" | "mail.vip" | "maps.watch" | "office.mention" | "video.captions" | "food.receipt" | "food.use_soon" | "agent.job_done" | "agent.job_failed" | "pipeline.failed" | "pipeline.approval" | "security.git_key" | "security.git_clone" | "security.repo_access" | "ops.alarm" | "marketing.approval" | "marketing.journey" | "mirage.report" | "feedback.bug")[]
match?: {
[key: string]: string[]
}
steps: {
afterMinutes: number
channels: ("email" | "sms" | "push" | "voice" | "inapp")[]
}[]
beforeEvent?: boolean
roles?: ("owner" | "admin" | "developer" | "viewer")[]
userIds?: string[]
overrideQuietHours?: boolean
}[]
createdBy: string
updatedAt?: number
attachments: {
resourceType: "org" | "project" | "agent" | "calendar" | "mailbox" | "space"
resourceId: string
resourceLabel?: string
}[]
}
}DELETE /v1/orgs/:orgId/notify/protocols/:protocolId
Deletes a protocol and its attachments. Owners and admins.
Auth: user access token or platform agent key · Scope: org:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:protocolId | Notification protocol id (npr_…). |
Response 204 with no body.
POST /v1/orgs/:orgId/notify/protocols/:protocolId/attachments
Attaches the protocol to { type, id, label? }: the whole organization (org) or a Serverless App Service, Issues space, calendar, mailbox or agent. Events about it then follow the protocol. Owners and admins.
Auth: user access token or platform agent key · Scope: org:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:protocolId | Notification protocol id (npr_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
type | "org" | "project" | "space" | "calendar" | "mailbox" | "agent" | Yes | |
id | string | Yes | 1–128 characters |
label | string | No | up to 120 characters |
Response 201
{
ok: true
}DELETE /v1/orgs/:orgId/notify/protocols/:protocolId/attachments/:resourceType/:targetId
Detaches the protocol from that resource. Owners and admins.
Auth: user access token or platform agent key · Scope: org:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:protocolId | Notification protocol id (npr_…). |
:resourceType | What the protocol is attached to: org, project, space, calendar, mailbox or agent; for a group's access, project or repository. |
:targetId | Id of what it's attached to (the org's own id for org, else prj_…, spc_…, cal_…, mbx_…, dev_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Unknown resource type. |