# HTTP API

> Every endpoint of the team server, grouped by area, with who may call it. Generated from the API contract.

<!-- Generated by `bun run docs:api` from shared/src/api. Do not edit by hand. -->

The team server has 231 HTTP endpoints. Each one is declared once in [`shared/src/api/`](https://github.com/trina-app/trina-ax/blob/main/shared/src/api/index.ts), with zod schemas for its query, body and response. The server validates every request against it, and the web app calls endpoints by name.

> **Note:** The API serves the Trina AX apps. It is not yet a stable public API for other programs, and it follows the [version rules](/docs/develop/versioning.md).

## Calling the API

- Endpoints live under the team's own address, for example `https://team.example.com/api/health`.
- The web app signs in with a session cookie. Requests from other origins are refused unless the origin is in `MYCEL_PUBLIC_ORIGINS`.
- Live updates and answers stream over a WebSocket at `GET /api/ws`.
- The [MCP connector](/docs/agents/mcp-connector.md) adds `/mcp`, `/oauth/*` and `/.well-known/*` outside this list.

| Who | Means |
|---|---|
| Anyone | No session needed |
| Signed in | Any active member |
| Admin | An admin or the owner |
| Owner | The owner only |
| Owner + password | The owner, who enters their password again (updates, restores) |

## Setup, sign-in and account

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/setup` | Anyone | Is first-run setup still needed (no owner yet)? |
| `POST` | `/api/setup` | Anyone | Create the team and its owner (only while no user exists; needs the setup token). Signs the owner in. |
| `POST` | `/api/auth/login` | Anyone | Sign in with username + password (argon2id). Rate-limited per IP and per account. |
| `POST` | `/api/auth/logout` | Signed in | End this session and clear the cookie. |
| `POST` | `/api/auth/password` | Signed in | Change own password; ends every other session of this person. |
| `GET` | `/api/me` | Signed in | The signed-in person, groups, team name. |
| `PATCH` | `/api/me` | Signed in | Profile, language, theme and composer preferences. |
| `GET` | `/api/me/usage` | Signed in | My own usage this day / week / month (never anyone else's) and the usage limits that apply to me. |
| `GET` | `/api/me/sessions` | Signed in | Own signed-in devices. |
| `DELETE` | `/api/me/sessions/:id` | Signed in | Sign out one of own devices. |
| `GET` | `/api/invites/:token` | Anyone | What an invite link is for (team name, role, still valid?). |
| `GET` | `/api/password-resets/:token` | Anyone | What a password reset link is for (whose account, still valid?). |
| `POST` | `/api/password-resets/:token` | Anyone | Set a new password with a one-time reset link; ends every other session and signs in. |
| `POST` | `/api/invites/:token/accept` | Anyone | Create the account from an invite link and sign in. |

## Chats and projects

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/questions/frequent` | Signed in | Own repeated questions from current branches in the last 30 days; bounded sample, never other people’s prompts. |
| `GET` | `/api/chats` | Signed in | Own chats, newest first (search with q, trash with trash=1). |
| `POST` | `/api/chats` | Signed in | New empty chat (optionally inside a project). |
| `GET` | `/api/engines` | Signed in | Whether the caller may pick the engine / model, the team default, and the engines + models they may pick. |
| `GET` | `/api/chats/:id` | Signed in | One own chat. |
| `GET` | `/api/chats/:id/queue` | Signed in | Own chat queue snapshot; advisory rank and epoch/revision for reconnect recovery. |
| `PATCH` | `/api/chats/:id` | Signed in | Rename, move to a project, change engine/model. |
| `DELETE` | `/api/chats/:id` | Signed in | Move to chat trash (purged after 7 days). Stops a running turn. |
| `POST` | `/api/chats/:id/restore` | Signed in | Bring a chat back from the trash. |
| `GET` | `/api/chats/:id/messages` | Signed in | Active branch of the conversation, paged backwards. |
| `POST` | `/api/chats/:id/messages` | Signed in | Save the message, create the empty answer, queue the turn. Send the X-Mycel-Window header so browser tools reach this window. |
| `POST` | `/api/chats/:id/stop` | Signed in | Stop the running or queued turn of this chat. |
| `GET` | `/api/chats/:id/messages/:messageId/sources` | Signed in | The files the AI read or saw passages of for this answer, each checked against the viewer's access now (no name or path for the others). |
| `POST` | `/api/chats/:id/messages/:messageId/regenerate` | Signed in | New answer to the same user message (sibling of :messageId, an assistant message). |
| `POST` | `/api/chats/:id/messages/:messageId/edit` | Signed in | Edited copy of user message :messageId as a new branch, then answer it. |
| `POST` | `/api/chats/:id/branch` | Signed in | Switch the visible branch ("< 2/3 >"); returns the newest page of the new path. |
| `GET` | `/api/chats/:id/requests` | Signed in | Open ask_user / browser site cards of the running turn of this chat. |
| `POST` | `/api/turns/:id/connect` | Signed in | Finish a connect_service card: add the connection with a sealed key, after a sign-in, or skip |
| `POST` | `/api/turns/:id/answer` | Signed in | Answer an ask_user card or a browser site confirmation of an own running turn. |
| `GET` | `/api/projects` | Signed in | Projects whose folder the caller can read. |
| `POST` | `/api/projects` | Signed in | New project: personal (users/<me>/projects/<slug>), on an existing folder the caller can write, or a new projects/<slug> with participants (admin or owner). |
| `GET` | `/api/projects/:id` | Signed in | One project. |
| `PATCH` | `/api/projects/:id` | Signed in | Edit name / instructions (the creator or an admin, with write access to the folder; audited, readers notified). folderPath: admins only, never under users/. |
| `POST` | `/api/projects/:id/share` | Signed in | Copy a personal project's folder into a team folder and point the project at it (the personal folder stays). |
| `DELETE` | `/api/projects/:id` | Signed in | Delete the project (the creator or an admin; chats stay, without project; the folder stays). |

## Memories

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/memories` | Signed in | Own memories, newest first. |
| `POST` | `/api/memories` | Signed in | Add a memory of one's own (same limits as the AI's remember). |
| `PATCH` | `/api/memories/:id` | Signed in | Correct the text of one of the own memories. |
| `DELETE` | `/api/memories/:id` | Signed in | Forget one memory. |
| `DELETE` | `/api/memories` | Signed in | Forget everything. |

## Skills

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/skills/popular` | Signed in | Last 30 days of usage counts for currently readable skills, with no user identities or prompts. |
| `GET` | `/api/skills` | Signed in | Skills the caller can use: skills/**/*.md with a name header that the caller can read, and their own personal skills (users/<caller>/skills/), by name. |
| `GET` | `/api/skills/issues` | Signed in | Skill entries the caller can read that do not load: an invalid SKILL.md (also a name that is not its folder name) or a legacy file with a broken header. |
| `GET` | `/api/skills/overview` | Signed in | The skills folders the caller manages / can suggest into, and how many suggestions wait. |
| `GET` | `/api/skills/suggestions` | Signed in | My suggestions, or (scope=review) the suggestions for skills folders I manage. Nobody else sees them. |
| `GET` | `/api/skills/suggestions/:id` | Signed in | One suggestion: its suggester and the managers of its target folder only (404 for anyone else). |
| `POST` | `/api/skills/suggestions` | Signed in | Suggest as skill: from an answer in my chat or a file in my folder; stored on the server (not in skills/); the managers of the target folder are told. |
| `POST` | `/api/skills/suggestions/:id/approve` | Signed in | Register: a manager of the target folder writes it under skills/ (audited, version history); the suggester is told. |
| `POST` | `/api/skills/suggestions/:id/reject` | Signed in | Turn down: a manager of the target folder turns it down; the suggester is told. |
| `GET` | `/api/admin/skill-changes` | Admin | Every create / edit / move / delete under skills/ (people and AI), newest first. |
| `GET` | `/api/admin/skill-managers` | Admin | Who manages team skills: the write rules for people and groups on skills/ and its folders. |
| `PUT` | `/api/admin/skill-managers` | Admin | "Manages team skills" on / off for a person or group on skills/ or a subfolder: adds or removes their write rule there (audited, like Admin > folder access). |

## Scheduled tasks

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/schedule-templates` | Signed in | Dormant templates; listing creates no scheduled work. |
| `POST` | `/api/schedule-templates` | Signed in | Explicitly create a private-output scheduled template, idempotent per user/request. |
| `GET` | `/api/schedules` | Signed in | Own scheduled tasks and the team time zone they run in. |
| `PATCH` | `/api/schedules/:id` | Signed in | Pause or resume one of the own scheduled tasks. |
| `POST` | `/api/schedules/:id/run` | Signed in | Run one of the own tasks once now, with the rules of a scheduled run; its schedule and on/off stay as they are. |
| `POST` | `/api/schedules/:id/edit` | Signed in | Check an edit of an own free-text task and show its schedule card (nothing changes yet). |
| `PUT` | `/api/schedules/:id` | Signed in | Save an edit: a free-text task with the answer to its card, a template with its time and folders. |
| `DELETE` | `/api/schedules/:id` | Signed in | Delete one of the own scheduled tasks. |
| `GET` | `/api/schedules/:id/review` | Signed in | The schedule card of an own task nobody confirmed (needsReview), to check it again. |
| `POST` | `/api/schedules/:id/review` | Signed in | Answer that card with one of its options: resume (confirmed, runs again with the addresses and connections it showed) or keep it paused. |
| `GET` | `/api/admin/schedule-reviews` | Admin | Scheduled tasks paused until their owners confirm them again (metadata only). |

## Connected folders

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/admin/connected` | Owner | Connected folders and their last sync. |
| `POST` | `/api/admin/connected` | Owner + password | Connect a folder of the server Mac as connected/<name> (everyone can read it; first sync starts). |
| `POST` | `/api/admin/connected/:id/sync` | Owner | Start a sync now (runs in the background). |
| `DELETE` | `/api/admin/connected/:id` | Owner | Disconnect: the mirrored files go away, anything people added stays. |

## Files

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/files/tree` | Signed in | List a folder (only what the caller may see; ancestors of visible folders shown for navigation). |
| `GET` | `/api/files/content` | Signed in | Text content for preview / editing. |
| `PUT` | `/api/files/content` | Signed in | Save a text file from the file screen (hash-based conflict copy, version history). |
| `GET` | `/api/files/download` | Signed in | Stream a file (Range supported, never loaded whole into memory). |
| `GET` | `/api/files/hwp-preview` | Signed in | Authorized HWP/HWPX raster page. Pages are 1-based. Original download stays available. |
| `GET` | `/api/files/preview` | Signed in | JPEG preview of a HEIC / HEIF photo (converted on the server, cached). No converter or a failed conversion: 503 unavailable with params.reason no_preview. |
| `POST` | `/api/files/upload` | Signed in | Upload one file up to 50 MB into a folder (write access). |
| `POST` | `/api/files/mkdir` | Signed in | Create a folder (name rules + collision check). |
| `POST` | `/api/files/move` | Signed in | Move / rename (write access at both ends; folders.path follows). Group / project / rule folders: admin or owner only, never into users/ (400). Into users/<me>/ when others lose sight of it: 409 audience_narrowed unless confirm. |
| `POST` | `/api/files/copy` | Signed in | Copy a readable file into a writable folder (sharing a personal file). dryRun: {viewersAdded} only (also 201). |
| `DELETE` | `/api/files` | Signed in | Move a file or folder to the trash (30 days). Group / project / rule folders: admin or owner only. |
| `GET` | `/api/files/history` | Signed in | Version history of a file. |
| `GET` | `/api/files/history/:versionId/download` | Signed in | Download an old version (read access to its path). |
| `POST` | `/api/files/restore` | Signed in | Restore an old version of a file. |
| `GET` | `/api/files/trash` | Signed in | Trash items the caller could restore (write access to the original path). |
| `POST` | `/api/files/trash/:id/restore` | Signed in | Put a trashed item back (write access to the original path; " (restored)", in the team language, is added when the name is taken). |
| `DELETE` | `/api/files/trash/:id` | Admin | Delete a trashed item for good (admin or owner). |
| `POST` | `/api/uploads` | Signed in | Attach a file (≤ 50 MB) to an own chat: stored in users/<me>/.attachments/<chatId>/. |
| `GET` | `/api/uploads/:id/thumbnail` | Signed in | Small JPEG/PNG thumbnail of an image attachment (a team file: the image itself, up to 2 MB, while the caller can read it). |
| `POST` | `/api/attachments/team-file` | Signed in | Attach a team-folder file the caller can read to an own chat, as a reference (re-checked on every send and turn). |
| `GET` | `/api/files/find` | Signed in | Files whose name contains q, among the files the caller can read (newest first). |
| `GET` | `/api/files/search` | Signed in | Lines that contain q (literal text, any case) in the files the caller can read, office documents through their text cache. Rate limited per person. |
| `GET` | `/api/files/recent` | Signed in | Recently changed files the caller can read (for the attach picker). |
| `POST` | `/api/upload-sessions` | Signed in | Start a chunked upload (8 MB chunks). Expires after 24 h. |
| `PUT` | `/api/upload-sessions/:id/chunks/:n` | Signed in | Store chunk n (0-based). Re-sending a stored chunk is a no-op. |
| `GET` | `/api/upload-sessions/:id` | Signed in | Which chunks arrived (to resume after a disconnect). |
| `POST` | `/api/upload-sessions/:id/complete` | Signed in | Verify sha256 and move the file into place. |
| `DELETE` | `/api/upload-sessions/:id` | Signed in | Drop an unfinished upload. |

## Artifacts

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/chats/:id/artifacts` | Signed in | Artifacts of an own chat, all versions, without content. |
| `GET` | `/api/artifacts/:id` | Signed in | One artifact version with content (own chats only). |

## Jobs

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/jobs/:id` | Signed in | Own job (jobs of nobody, e.g. system backups: the owner). Result when done. |
| `POST` | `/api/jobs/:id/cancel` | Signed in | Cancel a queued or running own job. |
| `POST` | `/api/transcribe` | Signed in | Voice input / recordings up to 50 MB (larger: upload session with target transcribe). Result: TranscribeResult. |

## In-app browser

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/browser/calls` | Signed in | Long-poll fallback: pending browser.call for this window (waits up to waitMs). |
| `POST` | `/api/browser/results` | Signed in | Long-poll fallback: browser.result. |

## Admin

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/admin/users` | Admin | All members, and with ?noAi=1 who cannot use AI now ("No AI"). |
| `POST` | `/api/admin/users` | Admin | Add a member with a temporary password (alternative to an invite). |
| `PATCH` | `/api/admin/users/:id` | Admin | Role, groups, disable (ends their sessions). Only the owner changes admins. |
| `DELETE` | `/api/admin/users/:id` | Owner | Owner only. Remove a member: sessions end now, chats and memories are purged after the chat retention period; the personal folder goes to the owner or is deleted. |
| `POST` | `/api/admin/users/:id/reset-password` | Admin | New temporary password (given, or a memorable one is made); the person must change it at next sign-in; valid 7 days; audited. |
| `POST` | `/api/admin/users/:id/reset-link` | Admin | One-time password reset link (24 h) to hand over; ends their sessions when used; audited. |
| `POST` | `/api/admin/transfer-ownership` | Owner + password | Make another member the owner (password re-entry); the old owner becomes admin. |
| `GET` | `/api/admin/invites` | Admin | Open and used invite links. |
| `POST` | `/api/admin/invites` | Admin | New invite link (copy it; no mail in v1). |
| `DELETE` | `/api/admin/invites/:id` | Admin | Revoke an unused invite. |
| `GET` | `/api/admin/groups` | Admin | Groups with members. |
| `POST` | `/api/admin/groups` | Admin | New group. |
| `PATCH` | `/api/admin/groups/:id` | Admin | Rename / change members. |
| `DELETE` | `/api/admin/groups/:id` | Admin | Delete a group (its folder rules go too). |
| `GET` | `/api/admin/folders` | Admin | Folders that carry rules, with their rules (= /api/admin/folder-rules of the design). |
| `POST` | `/api/admin/folders` | Admin | Put rules on a folder (creates it on disk if asked). |
| `PUT` | `/api/admin/folders/:id/rules` | Admin | Replace the rules of a folder; audited; affected chats get fresh engine sessions. |
| `DELETE` | `/api/admin/folders/:id` | Admin | Remove all rules of a folder (the folder on disk stays). |
| `POST` | `/api/admin/folder-rules/preview` | Admin | "Who sees what" for proposed rules, before saving. |
| `GET` | `/api/admin/access/folder` | Admin | One team folder: every active person's access, the folder and rule it comes from, and counts. Not for users/. |
| `GET` | `/api/admin/access/people/:id` | Admin | One person: their access to every team folder (rule, top-level, group, project, connected) and why. |
| `POST` | `/api/admin/access/new-person` | Admin | The same for someone about to be invited with this role and these groups (nothing is saved). |
| `GET` | `/api/admin/access/tree` | Admin | One level of the team folder for the admin tree: each child folder with who sees it, from where, and its risks. users/ is one row, never listed. |
| `POST` | `/api/admin/access/edit-preview` | Admin | What saving these rules on one folder would change: who loses and gains access there and below, what "follow the folder above" gives now, warnings, and the hash of the rules now. Nothing is saved. |
| `GET` | `/api/admin/engines` | Admin | Engine install/login/lockdown status, models, defaults, concurrency. |
| `GET` | `/api/admin/engines/api-config` | Owner | The team API engine settings (the key is never returned, only whether one is set). |
| `PUT` | `/api/admin/engines/api-config` | Owner | Set the team API engine: OpenAI-compatible base URL, model, label; key: a new one, null to remove, absent to keep. |
| `PATCH` | `/api/admin/engines` | Admin | Defaults, concurrency, enable/disable, who else may pick the engine, Claude-limit fallback to Codex. |
| `POST` | `/api/admin/engines/:id/check` | Admin | Re-check one engine now (bounded, no model call unless needed). |
| `GET` | `/api/admin/budgets` | Admin | Budgets with current spend. |
| `POST` | `/api/admin/budgets` | Admin | New budget. |
| `PATCH` | `/api/admin/budgets/:id` | Admin | Change a budget. |
| `DELETE` | `/api/admin/budgets/:id` | Admin | Delete a budget. |
| `GET` | `/api/admin/settings` | Admin | Team settings. |
| `PATCH` | `/api/admin/settings` | Admin | Change team settings (team name change also renames the relay address: owner only). |
| `PUT` | `/api/admin/team-icon` | Admin | Set the team logo (tab icon, home-screen app icon): PNG, JPEG or WebP up to 1 MiB, 32–4096 px a side; audited. |
| `DELETE` | `/api/admin/team-icon` | Admin | Remove the team logo: back to the default icon; audited. |
| `GET` | `/api/admin/speech-host` | Admin | How this server turns video and audio sound into text itself: its cores, piece length and measured speed. |
| `GET` | `/api/admin/speech-key` | Admin | Whether the OpenRouter key for voice input is set (last 4 characters only, never the key). |
| `PUT` | `/api/admin/speech-key` | Admin | Set (sealed in the browser) or remove (null) the OpenRouter key for voice input; asks for the password again. |
| `GET` | `/api/admin/usage` | Admin | Usage and cost per person / engine / model / day / group / AI connection / skill. Skill rows attribute the entire turn and may overlap. |
| `GET` | `/api/admin/audit` | Admin | Admin actions, file changes, tool calls, sign-ins. |

## AI connections

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/admin/credentials` | Admin | AI connections of the team (and that members have their own), with state and this month's use. Never a secret. |
| `POST` | `/api/admin/credentials` | Owner + password | Add a Claude subscription token or an API key (sealed in the browser); checked without spending tokens. Already connected: 409 saying where (DuplicateCredentialParams); with moveFrom, a member's personal copy moves to the team. |
| `PATCH` | `/api/admin/credentials/:id` | Owner | Rename, order, switch off, assign to groups / people, monthly limit. |
| `POST` | `/api/admin/credentials/:id/secret` | Owner + password | Put a new token / key on an existing connection (same kind). |
| `DELETE` | `/api/admin/credentials/:id` | Owner | Remove a connection (usage history stays). |
| `POST` | `/api/admin/credentials/:id/check` | Admin | Check a connection again now, without spending tokens. |
| `POST` | `/api/admin/credential-logins` | Owner + password | Start a ChatGPT sign-in for the team (device code); progress on WebSocket credential.login. |
| `GET` | `/api/admin/credential-logins/:id` | Owner | State of a sign-in this owner started. |
| `DELETE` | `/api/admin/credential-logins/:id` | Owner | Stop a sign-in. |
| `PATCH` | `/api/admin/credential-settings` | Owner | Personal connections and explicit shared-subscription consent. |
| `GET` | `/api/credentials/sealing-key` | Signed in | Public key the browser seals a token / key with before sending it. |
| `GET` | `/api/me/credentials` | Signed in | My own AI connections (when the team allows them). |
| `POST` | `/api/me/credentials` | Signed in | Add my own Claude token or API key; used for my turns first. |
| `DELETE` | `/api/me/credentials/:id` | Signed in | Remove one of my own connections. |
| `POST` | `/api/me/credential-logins` | Signed in | Start my own ChatGPT sign-in. |
| `GET` | `/api/me/credential-logins/:id` | Signed in | State of my sign-in. |
| `DELETE` | `/api/me/credential-logins/:id` | Signed in | Stop my sign-in. |

## Google Drive

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/integrations/google-drive` | Signed in | Own Google Drive connection; never a token. |
| `POST` | `/api/integrations/google-drive/authorize` | Signed in | Start personal Google authorization in a system browser. |
| `GET` | `/api/integrations/google-drive/flows/:id` | Signed in | Poll the flow started by this same signed-in session. |
| `POST` | `/api/integrations/google-drive/flows/:id/complete` | Signed in | Confirm the Google account shown by this own authorization flow. |
| `DELETE` | `/api/integrations/google-drive/flows/:id` | Signed in | Cancel this own authorization flow. |
| `DELETE` | `/api/integrations/google-drive` | Signed in | Immediately disable own Drive access, then attempt Google revocation. |

## MCP and HTTP connections

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/integrations` | Signed in | My personal connections and the team connections I may use. Never a key or token. |
| `POST` | `/api/integrations` | Signed in | A personal connection (403 when the team turned personal connections off). Checked right away; status says how it went. |
| `PATCH` | `/api/integrations/:id` | Signed in | Change a connection: the owner of a personal one, an admin for a team one. A new address drops the stored key. |
| `DELETE` | `/api/integrations/:id` | Signed in | Delete a connection (OAuth: revocation is tried, the local tokens go first). |
| `POST` | `/api/integrations/:id/refresh` | Signed in | Check the connection now; MCP: save its current tool list. |
| `POST` | `/api/integrations/:id/authorize` | Signed in | Start signing in at an MCP server (OAuth with PKCE) in a browser window. |
| `POST` | `/api/integrations/:id/tools` | Signed in | Turn one tool of an MCP connection on or off for the AI (whoever manages the connection). New tools are on. |
| `GET` | `/api/integrations/flows/:id` | Signed in | Poll a sign-in started by this same session. |
| `GET` | `/api/admin/integrations` | Admin | Every team connection, with who may use it. |
| `POST` | `/api/admin/integrations` | Admin | A team connection; access says who may use it (default: nobody until set). |
| `GET` | `/api/integration-requests` | Signed in | Requests from admins to connect a service as my own connection, still waiting for me. |
| `GET` | `/api/integration-requests/:id` | Signed in | One request to me, in any state (404 for anyone else, admins included). |
| `POST` | `/api/integration-requests/:id/complete` | Signed in | Connect it as my own connection, with my key, or made for signing in next (MCP OAuth: the request is connected when the sign-in finishes). Only the member it asks. |
| `POST` | `/api/integration-requests/:id/decline` | Signed in | Decline a waiting request to me. |
| `GET` | `/api/admin/integration-requests` | Admin | Requests admins sent to members, with their state. Never a key. |
| `POST` | `/api/admin/integration-requests` | Admin | Ask a member to connect a service as their own connection (a notice and a link for them; waits 7 days). |
| `POST` | `/api/admin/integration-requests/:id/withdraw` | Admin | Withdraw a waiting request. |

## Notifications

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/notifications/:id` | Signed in | Read an own notification without marking read; current-access filtered and never cached. |
| `GET` | `/api/notifications` | Signed in | Own metadata-only inbox, retained for 30 days. |
| `POST` | `/api/notifications/:id/read` | Signed in | Mark an own notification read. |
| `GET` | `/api/notification-preferences` | Signed in | Own inbox event preferences. OS push opt-in is separate. |
| `PATCH` | `/api/notification-preferences` | Signed in | Change own inbox event preferences. |

## Push notifications

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/push` | Signed in | Own push opt-in and current-session binding; disabled until the server is configured. |
| `POST` | `/api/push/subscriptions` | Signed in | Explicitly consent to an encrypted push subscription bound to this login session. |
| `PATCH` | `/api/push` | Signed in | Own opt-in preference; turning off removes own subscriptions and queued deliveries. |
| `DELETE` | `/api/push/subscriptions/:id` | Signed in | Remove an own current-session subscription. |

## MCP connector (app connections)

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/connectors/remote/requests/:id` | Signed in | Inspect an OAuth request, bound to this user and login session. |
| `POST` | `/api/connectors/remote/requests/:id` | Signed in | Explicitly allow or deny an external app connection. |
| `GET` | `/api/connectors/remote` | Signed in | List only this user’s external connections. |
| `DELETE` | `/api/connectors/remote/:id` | Signed in | Revoke an own external connection and all of its tokens. |

## System

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/health` | Anyone | Liveness for the menubar app, relay and update check. No private data. |
| `GET` | `/api/admin/diagnostics` | Owner | Relay, disk, engine keys, queue, pf anchor, sandbox, backups. |
| `GET` | `/api/admin/update` | Owner | Current / available version. |
| `POST` | `/api/admin/update` | Owner + password | Back up the DB, switch app/current, restart; roll back if the health check fails. |
| `GET` | `/api/admin/backups` | Owner | Backups in .system/backups/. |
| `POST` | `/api/admin/backup` | Owner | Back up now (VACUUM INTO + team folder manifest diff). |
| `POST` | `/api/admin/restore` | Owner + password | Restore a backup (everything after it is lost; the UI shows how much). |
| `POST` | `/api/admin/export` | Owner | Export chats / memories / files (optionally password-encrypted with age). |
| `GET` | `/api/admin/connection` | Owner | Relay / direct connection state (from the relay client, component F). |
| `GET` | `/api/connect-info` | Signed in | Office-network address and certificate fingerprint for the desktop app (pinning). |
| `POST` | `/api/connect-info/lan-failure` | Signed in | The desktop app could not use the office address (shown in Diagnostics). |
| `PUT` | `/api/admin/connection` | Owner + password | Change the connection mode. |
| `GET` | `/api/admin/storage` | Admin | Storage use of the team disk (statfs), what uses it, the plan's disk when there is one. |
| `GET` | `/api/admin/plan` | Admin | The plan (plan.json): limits, what the team uses of them, where to change it. null without a plan file. |
| `GET` | `/api/managed/notices` | Signed in | The operator's notices (notices.json) meant for the caller's role, in the caller's language. |

## Office Mac updates

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/admin/office-update` | Admin | Office mode automatic updates: version, channel, next window, last check (null outside office mode). |
| `POST` | `/api/admin/office-update` | Admin | Office mode: update now, or turn automatic updates off / on. |

## Plugins

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/admin/plugins` | Admin | Installed plugins, the official catalog for this server and the trust status. |
| `POST` | `/api/admin/plugins/inspect` | Admin | Check an uploaded .trinaplugin (signature, files, platform) and return what installing it asks for. Installs nothing. |
| `POST` | `/api/admin/plugins/inspect-source` | Admin | The same check for a catalog package or a file in the server import folder. |
| `POST` | `/api/admin/plugins/install` | Admin | Install (or update to) the inspected package after the admin approved its permissions; optionally enable it for the company. |
| `POST` | `/api/admin/plugins/:id/enable` | Admin | Turn an installed plugin on for the whole company. |
| `POST` | `/api/admin/plugins/:id/disable` | Admin | Turn it off for the company (stays installed). |
| `POST` | `/api/admin/plugins/:id/rollback` | Admin | Go back to the previously installed version (verified again). |
| `DELETE` | `/api/admin/plugins/:id` | Admin | Remove the plugin and its files. Documents and edited copies of skills stay. |

## Dev environment

| Method | Path | Who | What it does |
|---|---|---|---|
| `GET` | `/api/projects/:id/dev-env` | Signed in | Dev environment (experiment) of a project: setting, availability, the box state; for people who can read the folder. |
| `PUT` | `/api/projects/:id/dev-env` | Admin | Turn the dev environment of a project on or off, who may use it, network and limits; turning on needs the current warning accepted (audited). |
| `POST` | `/api/projects/:id/dev-env/box` | Signed in | Stop or restart the project box (people who may use it, and admins; audited). |
| `POST` | `/api/projects/:id/dev-env/preview` | Signed in | A short-lived link to a dev server port of the box, on the separate preview origin (read access to the folder; audited). |
| `GET` | `/api/projects/:id/dev-env/activity` | Signed in | Box audit of a project: AI commands, changed files, box and preview events (read access to the folder). |
