API
Health, identity and locations
Liveness, the caller's identity and the active locations.
Start here to find out who a token belongs to (GET /v1/me), which organizations and roles it has, and which locations resources can be created in.
Every route below, with its parameters, request and response, errors and samples, is in the API reference.
| Route | What it does |
|---|---|
GET /health | Liveness check. No authentication. |
GET /health/deep | Liveness check including a read of the serving region's database replica; returns the region. No authentication. |
GET /v1/hooks/people/:userId/avatar | A person's avatar for <img src> anywhere: a redirect to the image (good for an hour), cached for ten minutes; 404 when they have none. The avatarUrl in profiles carries a version (?v=), so a new image is a new URL. No authentication. |
GET /v1/hooks/people/:userId/banner | A person's banner image for <img src> anywhere, as the avatar's hook: a redirect to the image, cached for ten minutes; 404 when they have none. bannerUrl carries a version. No authentication. |
GET /v1/festive | Festive themes' yearly periods in force (periods, in priority order: id, name, when, themes, defaultTheme, regions). No session needed; cached for five minutes. During a period every app and the phone wear its default theme unless the person chose another or Off (/v1/me/preferences/festive). |
GET /v1/me | The caller: the signed-in user (with organizations and roles), or the key (API or platform agent key) with its organization and scopes. |
GET /v1/locales | The languages people can choose (locales: locale, label, spelling, weekStart), in order: English (Australia), the default, and English (US). Choose one with PATCH /v1/me/profile (locale). |
GET /v1/me/org-access | Your organizations whose Cactive One access has ended (never subscribed, cancelled or unpaid), with the reason for each ({ ended: { [orgId]: reason } }). Their apps answer 402 with code: "access_ended" until an administrator fixes billing. |
GET /v1/me/permissions | What the person may do in a space, app by app (docs/specs/onboarding/permissions.md): space is personal or one of their organisations. Each app: whether they reach it, why not, their level (No access, View, Edit, Manage) and why, in words; in an organisation, also the apps it hides from everyone's app switcher (hidden, launcher keys), which they still reach. |
GET /v1/locations | Active locations, for location pickers. Any authenticated caller. |
POST /v1/me/controls/:control | Applies what you chose in a setting's prompt after a 403 setting_required: fix change (the change the refusal described, worked out here) or once (Caity's own settings, for one request of hers: request, 15 minutes at most), with its scope and, for an app, app. Only you, signed in to one of the platform's apps; never a key, the phone assistant or a task. An organisation's settings and second checks aren't changed here. Audited. |
POST /v1/me/access-requests | Asks the organisation's owners and admins to change a control that blocks you (control, scope, optional app, subject and a note of up to 300 characters); they're notified and answer in Tenant. Answers 202 with the request. |
GET /v1/me/preferences | Your preferences, the same in every app and on every device: apps, the app switcher's order (order, tile keys such as cloud or mail:contacts) and the apps you hid (hidden), or null for the default switcher. People only. |
PUT /v1/me/preferences | Saves your app switcher (apps: { order, hidden }, up to 100 keys each; apps added later appear at the end). apps: null restores the default. People only. |
GET /v1/me/preferences/widgets | The phone's widgets: what the Dynamic Island and the Lock Screen show, ranked per surface; null until the person arranges them. |
PUT /v1/me/preferences/widgets | Saves the phone's widgets (at most 16 KB as JSON); every phone signed in to the account follows. |
GET /v1/me/preferences/calendar | Calendar's settings (week start, working hours, other time zones, new-event defaults, overlays, hidden calendars); null until changed. |
PUT /v1/me/preferences/calendar | Saves Calendar's settings; the answer is what was saved (cleaned). Every device and the phone follow. |
GET /v1/me/preferences/festive | The festive theme chosen for a period's year (docs/specs/design/festive-themes.md); null until one is chosen. |
PUT /v1/me/preferences/festive | Saves it ({ instance, choice }: a theme id, off or on; null clears it); every app and the phone follow. |
GET /v1/me/account/devices | Your phones and tablets with the apps signed in on each (and whether each gets push), browsers, command-line machines and Apple devices' sign-ins; thisSession is the calling app's. Only you, in a phone app (a token with audience mobile); every change is audited in your organizations. |
GET /v1/me/account/account-chooser | Whether web apps' sign-ins ask which account to use (on); off by default, the account in use continues. Only you, in a phone app. |
PUT /v1/me/account/account-chooser | Turns the account chooser on or off ({ "on": true }), as ID's Devices & sessions does. Only you, in a phone app. |
DELETE /v1/me/account/devices/apps/:sessionId | Signs one app on a phone out: its tokens stop at once and it stops receiving push. thisPhone says whether it was the calling app's own sign-in. |
DELETE /v1/me/account/devices/phones/:installId | Signs every app on a phone out and removes its push registrations. |
DELETE /v1/me/account/devices/browsers/:sessionId | Signs a browser out, with the app sign-ins started from it. |
DELETE /v1/me/account/devices/cli/:sessionId | Signs a command-line machine out and revokes the git keys it made (keysRevoked). |
DELETE /v1/me/account/devices/apple/:grantId | Signs an Apple device out of Mail, Calendar and Contacts: its refresh token stops now, its access token within a minute. |
GET /v1/me/account/apple | Apple devices: your mailboxes, app passwords (never the secret), the devices that sync and the devices signed in with a profile. Where Apple devices aren't offered (appleDevices false on GET /me/profile), this and the other Apple device routes answer 404. |
POST /v1/me/account/apple/passwords | Makes an app password (name, mailboxIds, empty for every mailbox, optional expiresInDays) after a fresh step-up for account_credential (403 step_up otherwise). The password is returned once. |
DELETE /v1/me/account/apple/passwords/:appPasswordId | Revokes an app password: devices using it are signed out within a minute. |
PUT /v1/me/account/apple/devices/:deviceId/wipe | Asks an iPhone or iPad (ActiveSync) to remove this account's mail, calendars and contacts at its next sync (on: true), or withdraws that (on: false). |
DELETE /v1/me/account/apple/devices/:deviceId | Forgets a device and what it synced: its next sync starts over. |
GET /v1/me/account/age | Your date of birth (or null) and what it means for social features. |
PUT /v1/me/account/age | Saves your date of birth (dateOfBirth, YYYY-MM-DD) once; after that only support corrects it (409). |
GET /v1/me/account/orgs/:orgId | An organization you belong to: its members with their roles, and its groups with their people and whether you may change them (the organization's owners and admins, and the group's own owners). |
PUT /v1/me/account/orgs/:orgId/groups/:teamId/members/:userId | Adds a member to a group or makes them an owner or member of it (role). The group's owners and the organization's owners and admins; what the group grants is checked too. |
DELETE /v1/me/account/orgs/:orgId/groups/:teamId/members/:userId | Takes a member out of a group (the group's owners and the organization's owners and admins). |
GET /v1/me/account/sign-ins | The last 90 days of sign-ins and failed attempts, newest first: device, place, address, how, and whether the browser is still signed in. |
GET /v1/me/account/permissions | Personal and each organisation: what the person can do in each app and why, and what Caity can do for them there. |
GET /v1/me/account/first-run | The account's first run as this phone app shows it (?app=, the app's id): due, its steps, the invites waiting, how the person signs in. |
POST /v1/me/account/first-run/steps/:step | Continue (done) or Skip on one of the first run's steps. |
POST /v1/me/account/first-run/later | "Finish later": sign-ins stop showing the first run; Account offers to pick it up. |
POST /v1/me/account/first-run/dismiss | Account's "Get Set Up" card: Not Now (the card goes; the run stays). |
POST /v1/me/account/first-run/invites/:inviteId/join | Joins an organisation from an invite to the person's proved address (the Organisation step), audited in it. |
POST /v1/me/account/join | Joins an organisation with a join code (code: as typed, or its link) at the code's role; the first run's Organisation step is then done. Every code that doesn't work gets the same answer; a person may try 10 an hour (429 after). |
GET /v1/me/account/domain-offers | Organisations open to the person's proved address's verified domain (docs/tenant/domains.md → Joining by domain). |
POST /v1/me/account/domain-offers/:orgId/join | Joins one of them at its role, audited in it; the first run's Organisation step is then done. |
POST /v1/me/account/domain-offers/:orgId/decline | No Thanks: the offer isn't made again. |
GET /v1/me/account/connected-apps | Apps you allowed to act for you (MCP clients, organizations' own apps), with their permissions and last use. |
DELETE /v1/me/account/connected-apps/:clientId | Removes a connected app and its refresh tokens: it stops reaching your account at once. |
GET /v1/me/account/passkeys | Your passkeys: name, when added and last used. Never the public key. |
DELETE /v1/me/account/passkeys/:credentialId | Removes a passkey. 409 when it's your only way in (no password and no other passkey). Passkeys are added at ID. |
GET /v1/me/account/linked-sign-ins | Your Apple and Google sign-ins: the address (or that it's hidden), when linked and last used, and lastWay, the one that's your only way in. Never the provider's account id. |
DELETE /v1/me/account/linked-sign-ins/:provider | Unlinks apple or google. 409 when it's your only way in (no password, passkey or other link). Linking happens at ID. |
GET /v1/me/account/password | Whether your account has a password (hasPassword). |
PUT /v1/me/account/password | Sets a new password (12 to 256 characters); with one already set, current must be it (wrong ones count toward the sign-in lockout, 429 while locked); a first one needs a fresh step-up for account_credential (403 step_up otherwise; the app confirms at ID's /step-up/phone). Every other sign-in ends (signedOut); this app stays. |
GET /v1/me/account/phones | Your phone numbers (verified or not, primary, notifications on), the most you may add (max) and whether two-step sign-in by text is on. |
POST /v1/me/account/phones | Adds a number (number, optional label) and texts it a code; sent: false with a reason when the text couldn't go. |
POST /v1/me/account/phones/verify | Verifies the number a code went to (code). |
POST /v1/me/account/phones/:phoneId/resend | Texts a new code to an unverified number (once every 30 seconds, five an hour). |
DELETE /v1/me/account/phones/:phoneId | Removes a number. Removing the last verified one turns two-step sign-in by text off. |
PUT /v1/me/account/phones/:phoneId/primary | Makes a verified number the primary one: texts, calls and sign-in codes go to it. |
PUT /v1/me/account/phones/:phoneId/notifications | Whether a number gets notification texts and calls (on). |
POST /v1/me/account/two-step/code | Texts a code to your primary number, to turn two-step sign-in by text on or off. |
PUT /v1/me/account/two-step | Turns two-step sign-in by text on or off (on) with the texted code. |
GET /v1/me/account/assistant | Caity by phone: your settings, whether a PIN is set and a number verified, and each organization with the permissions your role there lets the assistant hold (scopes, with their words) and its defaults. |
PUT /v1/me/account/assistant | Saves Caity by phone: on or off, the organizations it acts in with their permissions (never more than your role allows), the default organization, texts and calls, the PIN for calls, transcripts, retention and the briefing time. |
PUT /v1/me/account/assistant/pin | Sets the PIN for calls (pin, confirm): 4 to 8 digits, not all the same or in a row. |
GET /v1/me/account/encryption-keys | Your own encryption keys (Health, your Drive and Photos) with their use in the last 30 days. Metadata only, never material. |
GET /v1/me/account/encryption-keys/:keyId | One of your keys: versions, use, and the last 50 events of what used it. |
GET /v1/me/account/photo-tokens | Photos' personal tokens (a Shortcut, Mac sync, MCP): name, scopes and last use. Never the token. |
DELETE /v1/me/account/photo-tokens/:tokenId | Removes a Photos token: whatever uses it stops at once. |
GET /v1/me/profile | You: your profile (name, email, avatarUrl, bannerUrl, banner and accent colours, about (your About Me), effect, username, kind (personal, or org for an account made through an organization's invite) and usernameChangeAt (when it can change next, or null), locale (the language you chose, or null)), the language to use (locale: your choice, else en-US for a US Accept-Language, else en-AU), the languages you can choose (locales) and each organization with your scopes there, so native apps offer only the organizations an app can open, and whether Apple devices (Exchange accounts) are offered (appleDevices). People only. |
PATCH /v1/me/profile | Changes your profile, the one people see across the platform (Mirage's cards, members and messages; every app's account menu): name, about (About Me, Markdown as in Mirage), banner and accent (hex colours such as #5865f2) effect (a profile effect's id from GET /v1/me/profile/effects; choosing one needs a paid plan, Cactive One Pro or Max or a paid organisation seat, else 403) and locale (your language for dates, numbers and spelling in every app, email and text: one of GET /v1/locales, such as en-AU or en-US). null clears a field (not the name). Returns user and the fields that changed; name changes are recorded in your organizations' audit logs. People only, not assistants. |
POST /v1/me/profile/avatar/uploads | Where to upload a new avatar: give its type (PNG, JPEG, WebP or GIF) and size in bytes (up to 2 MB). PUT the image to url with headers within 15 minutes (exactly that type and size), then make it your avatar with PUT /v1/me/profile/avatar. People only. |
PUT /v1/me/profile/avatar | Makes an uploaded image (uploadId) your avatar once it's checked: there, up to 2 MB and really a PNG, JPEG, WebP or GIF, whatever it was uploaded as. Anything else is deleted (400 or 413). The previous image is deleted. Returns user with the new avatarUrl. People only. |
DELETE /v1/me/profile/avatar | Removes your avatar (people see your initials) and deletes the image. People only. |
POST /v1/me/profile/banner/uploads | Where to upload a new banner image (cropped to 5:2, 1500 × 600, first): give its type (PNG, JPEG, WebP or GIF) and size in bytes (up to 4 MB). PUT the image to url with headers within 15 minutes, then make it your banner with PUT /v1/me/profile/banner. People only. |
PUT /v1/me/profile/banner | Makes an uploaded image (uploadId) your banner once it's checked: there, up to 4 MB and really a PNG, JPEG, WebP or GIF. Anything else is deleted (400 or 413). The previous image is deleted. Returns user with the new bannerUrl. People only. |
DELETE /v1/me/profile/banner | Removes your banner image (your banner colour shows) and deletes the image. People only. |
GET /v1/me/profile/effects | The profile effects (effects: effectId, name, renderer, colors), in order. Choosing and showing one need a paid plan: GET /v1/me/profile says whether you have one (effectsIncluded) and which you chose (effectChoice), kept while it isn't shown. People only. |
GET /v1/me/profile/username/check | Whether a username (name) could be yours: available, or the reason it can't (taken, reserved, or not 2–32 lowercase letters, numbers, underscores and single full stops). A name held for someone answers as taken. Checks and claims share an allowance of 60 an hour; past it, reason says so. People only. |
PUT /v1/me/profile/username | Claims or changes your username (username, unique regardless of case). After a change the next waits 30 days (429); your previous name is held for you for 14 days. Accounts made through an organization's invite have none (403); a taken name is 409; past the hourly allowance of lookups, 429. Recorded in your organizations' audit logs. People only, not assistants. |