REST API
A műveletek leírása angolul marad. A magyar szöveg anyanyelvi ellenőrzésre vár.
Használd a REST API-t saját programodból. Az alábbi mezőket, típusokat és jogosultságokat a kódból olvassuk ki.
Base URL: https://api.srvo.app/api/v1. Self-host: use your server origin with /api/v1.
Authentication: Authorization: Bearer <API key>. See API keys. OAuth connections use the MCP resource and are refused on REST; see Connect AI apps. Session requests use the same policy.
Pagination: cursor and limit, default 50, maximum 200. Follow nextCursor until null. Per-operation schemas below define which lists support pagination.
Idempotency and confirmation headers appear on the operations that accept them. Rate-limited errors include Retry-After when available. Budgets depend on runtime configuration; there is no fixed universal request rate.
Errors: { error: { code: “VALIDATION” / “TIMEOUT” / “UNAUTHENTICATED” / “FORBIDDEN” / “NOT_FOUND” / “CONFLICT” / “STALE_PREVIEW” / “RATE_LIMITED” / “MODULE_DISABLED” / “QUOTA_EXCEEDED” / “AI_NOT_CONFIGURED” / “VOICE_BUSY” / “VOICE_CAP” / “VOICE_OFF” / “NOT_AVAILABLE” / “ATTACHMENT_TYPE” / “ATTACHMENT_TOO_LARGE” / “ATTACHMENT_LIMIT” / “ATTACHMENT_NOT_READY” / “ATTACHMENT_UNREADABLE” / “ATTACHMENT_PARSE_DISABLED” / “INTERNAL”, key: string, params?: object, current?: object, fieldErrors?: object, retryAfter?: integer } }.
- 400: Validation error
- 401: Not signed in
- 403: Forbidden or module disabled
- 404: Not found (also for records you can’t see)
- 409: Conflict or stale preview
- 429: Rate limited
ai
GET /ai/credits
Read workspace Sergio credits
Capability: ai.credits.read. Kind: read.
No input fields.
Output: { plan: string, planCredits: integer, used: integer, held: integer, mode: “payg” / “hard”, notice: “none” / “low” / “overPlan” / “capNear” / “exhausted”, nextReset: string, spendCapCents?: integer, extraCents?: integer, upgrade?: { plan: string, savingCents: integer } }.
POST /ai/credits
Set Sergio credit mode and monthly spending cap
Capability: ai.credits.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| mode | body | “payg” / “hard” | yes |
| spendCapEuros | body | integer | yes |
Output: { plan: string, planCredits: integer, used: integer, held: integer, mode: “payg” / “hard”, notice: “none” / “low” / “overPlan” / “capNear” / “exhausted”, nextReset: string, spendCapCents?: integer, extraCents?: integer, upgrade?: { plan: string, savingCents: integer } }.
GET /ai/credits/usage
Read your chat message credits and your UTC daily and monthly totals. Current streaming answer is not settled yet.
Capability: ai.credits.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| conversationId | query | string | yes |
Output: { messages: array
boards
POST /metrics/present
Compute a widget query and return totals, up to 20 groups and a widget block. Pass widget and optional timeZone; no paging.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| timeZone | body | string | no |
| widget | body | { family?: “metric”, id?: string, kind: “kpi” / “progress” / “bar” / “line” / “stacked” / “table” / “donut”, title?: string, tableId: string, metrics: array | yes |
Output: { status: “complete” / “partial” / “stale” / “restricted”, totals: array
POST /metrics/query
Compute sums, averages, counts and percents over a table’s readable rows, optionally grouped by a select/status field or date bucket.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| dateField | body | string | no |
| filters | body | array<{ field: string, op: “eq” / “neq”, value: string or number or boolean } or { field: string, op: “in”, values: array |
no |
| groupBy | body | array<{ field: string } or { date: “day” / “week” / “month” }> | no |
| metrics | body | array<{ op: “sum” / “avg” / “min” / “max” / “countRows” / “countNonNull” / “countDistinct” / “percent”, field?: string, of?: “countRows” / “sum”, numerator?: array |
yes |
| range | body | { preset: “today” / “thisWeek” / “lastWeek” / “thisMonth” / “lastMonth” } or { lastDays: integer } or { from: string, to: string } | no |
| tableId | body | string | yes |
| timeZone | body | string | no |
Output: { status: “complete” / “partial” / “stale” / “restricted”, metrics: array
POST /metrics/validate
Check a metric query against the table’s fields and the caller’s field access, without running it.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| dateField | body | string | no |
| filters | body | array<{ field: string, op: “eq” / “neq”, value: string or number or boolean } or { field: string, op: “in”, values: array |
no |
| groupBy | body | array<{ field: string } or { date: “day” / “week” / “month” }> | no |
| metrics | body | array<{ op: “sum” / “avg” / “min” / “max” / “countRows” / “countNonNull” / “countDistinct” / “percent”, field?: string, of?: “countRows” / “sum”, numerator?: array |
yes |
| range | body | { preset: “today” / “thisWeek” / “lastWeek” / “thisMonth” / “lastMonth” } or { lastDays: integer } or { from: string, to: string } | no |
| tableId | body | string | yes |
| timeZone | body | string | no |
Output: { ok: boolean, restricted: boolean, issues: array
GET /records/{recordId}/activity
Return permission-masked record history. Pass recordId and optional cursor/limit; follow nextCursor for more.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| recordId | path | string | yes |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
POST /tables/{tableId}/records
Create a record in a table.
Capability: boards.records.create. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| Idempotency-Key | header | string | yes |
| fields | body | object | yes |
| id | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { record: { id: string, tableId: string, spaceId: string, version: integer, rank: string, createdBy: string or null, data: object, createdAt: string, updatedAt: string, restrictedFields?: array
GET /tables/{tableId}/export
Export tableId and optional viewId as masked CSV/XLSX. Returns filename, contentType and base64 body over MCP, up to 1 MiB; use REST for larger files. No paging.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| viewId | query | string | no |
| format | query | “csv” / “xlsx” | no |
| locale | query | “en” / “hu” | no |
Output: string.
GET /records/{recordId}
Get one record by id.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| recordId | path | string | yes |
Output: { record: { id: string, tableId: string, spaceId: string, version: integer, rank: string, createdBy: string or null, data: object, createdAt: string, updatedAt: string, restrictedFields?: array
GET /tables/{tableId}/records
List the records of a table, ordered by id, one page at a time.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
POST /records/{recordId}/move
Move a record between readable neighbours and/or patch its group fields in one versioned update.
Capability: boards.records.update. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| recordId | path | string | yes |
| Idempotency-Key | header | string | yes |
| afterId | body | string or null | no |
| baseVersion | body | integer | yes |
| beforeId | body | string or null | no |
| fields | body | object | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { record: { id: string, tableId: string, spaceId: string, version: integer, rank: string, createdBy: string or null, data: object, createdAt: string, updatedAt: string, restrictedFields?: array
POST /trash/purge
Permanently delete trashed records, or empty the trash (recordIds: “all”). Preview first, then commit.
Capability: boards.records.trash. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| Srvo-Confirmation | header | string | no |
| recordIds | body | “all” or array |
yes |
| spaceIds | body | array |
no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { mode: “hidden” / “deleted”, count: integer, spaceCount?: integer } or { preview: { summary: string, counts: object, warnings: array
POST /records/{recordId}/restore
Restore a trashed record at its current version. No preview required.
Capability: boards.records.trash. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| recordId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { record: { id: string, tableId: string, spaceId: string, version: integer, rank: string, createdBy: string or null, data: object, createdAt: string, updatedAt: string, restrictedFields?: array
POST /records/titles
Resolve up to 500 recordIds to visible id/title pairs; unreadable records are omitted. No paging.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| recordIds | body | array |
yes |
Output: { items: array
POST /records/{recordId}/trash
Move a record to the trash (restorable for 30 days in the cloud). Preview first, then commit.
Capability: boards.records.trash. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| recordId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { recordId: string, trashedAt: string, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
PATCH /records/{recordId}
Update some fields of a record. Fields not sent stay as they are.
Capability: boards.records.update. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| recordId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | no |
| fields | body | object | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { record: { id: string, tableId: string, spaceId: string, version: integer, rank: string, createdBy: string or null, data: object, createdAt: string, updatedAt: string, restrictedFields?: array
core
POST /api-keys
Create an API key. The secret is returned once.
Capability: core.self.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| kind | body | “personal” / “workspace” | yes |
| name | body | string | yes |
| scope | body | { mode: “read” / “read-write”, spaces?: array |
yes |
| ttlDays | body | 30 or 90 or 365 or null | yes |
Output: { key: { id: string, ownerMemberId: string, kind: “personal” / “workspace”, name: string, prefix: string, scope: object, expiresAt: string or null, lastUsedAt: string or null, revokedAt: string or null, createdAt: string, createdBy: string, createdByName?: string }, secret: string }.
GET /api-keys
List API key metadata.
Capability: core.self.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | query | “personal” / “workspace” | no |
Output: { items: array
POST /api-keys/{keyId}/revoke
Preview and revoke an API key.
Capability: core.self.read. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| keyId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { id: string, ownerMemberId: string, kind: “personal” / “workspace”, name: string, prefix: string, scope: { mode: “read” / “read-write”, spaces?: array
GET /me/email-preferences
Read my email notification setting (off, batched every 15 minutes, or daily).
Capability: core.self.read. Kind: read.
No input fields.
Output: { notifications: “off” / “batched” / “daily” }.
PUT /me/email-preferences
Change my email notification setting.
Capability: core.self.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| notifications | body | “off” / “batched” / “daily” | yes |
Output: { notifications: “off” / “batched” / “daily” }.
POST /grants
Grant a member or team a capability at tenant, space or exact item scope.
Capability: core.grants.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| capability | body | string | yes |
| effect | body | “allow” / “deny” | no |
| id | body | string | no |
| scope | body | { kind: “tenant” } or { kind: “space”, id: string } or { kind: “item”, id: string } | yes |
| subject | body | { kind: “member”, id: string } or { kind: “team”, id: string } | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { grant: { subject: object, scope: object, capability: string, effect: “allow” / “deny”, id: string, version: integer }, changeId: integer }.
GET /grants
List explicit capability grants in this tenant (owners and admins).
Capability: core.grants.manage. Kind: read.
No input fields.
Output: { items: array
POST /grants/{grantId}/revoke
Revoke an explicit grant and require sync clients to re-authorize.
Capability: core.grants.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| grantId | path | string | yes |
| Idempotency-Key | header | string | no |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { grant: { subject: object, scope: object, capability: string, effect: “allow” / “deny”, id: string, version: integer }, changeId: integer }.
GET /home/tasks
My readable assigned tasks across tables, filtered and paged in SQL.
Capability: core.self.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | query | string | no |
| limit | query | integer | no |
| bucket | query | “all” / “today” / “overdue” / “upcoming” / “no_date” / “done_today” | no |
| timeZone | query | string | no |
Output: { items: array
POST /invites/{inviteId}/cancel
Cancel an open invite (its link stops working).
Capability: core.invites.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| inviteId | path | string | yes |
| Idempotency-Key | header | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { invite: { id: string, email: string, role: “owner” / “admin” / “member” / “limited” / “guest”, teamIds: array
POST /invites
Invite someone by email. The UI returns the link once; MCP never returns invite tokens. Emails it when a provider is set.
Capability: core.invites.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| body | string | yes | |
| locale | body | “en” / “hu” | no |
| role | body | “owner” / “admin” / “member” / “limited” / “guest” | no |
| teamIds | body | array |
no |
| ttlDays | body | integer | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { invite: { id: string, email: string, role: “owner” / “admin” / “member” / “limited” / “guest”, teamIds: array
GET /invites
List invites (pending and expired by default).
Capability: core.invites.manage. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| includeClosed | query | boolean | no |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
POST /invites/{inviteId}/resend
Resend an open invite with a fresh link and expiry (the old link stops working).
Capability: core.invites.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| inviteId | path | string | yes |
| Idempotency-Key | header | string | no |
| ttlDays | body | integer | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { invite: { id: string, email: string, role: “owner” / “admin” / “member” / “limited” / “guest”, teamIds: array
POST /links
Link an editable source to a readable target.
Capability: core.links.write. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| from | body | { module: string, kind: string, id: string } | yes |
| id | body | string | no |
| rank | body | string | no |
| rel | body | string | no |
| to | body | { module: string, kind: string, id: string } | yes |
Output: { link: { id: string, from: object, to: object, rel: string, rank: string, createdBy: string or null, createdAt: string, version: integer }, changeId: integer }.
POST /links/list
List outgoing links and backlinks visible now.
Capability: core.links.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | body | string | no |
| entity | body | { module: string, kind: string, id: string } | yes |
| limit | body | integer | no |
Output: { items: array
DELETE /links/{linkId}
Remove a link, keeping both entities.
Capability: core.links.write. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| linkId | path | string | yes |
| baseVersion | query | integer | yes |
Output: { linkId: string, changeId: integer }.
PATCH /links/{linkId}/rank
Set a link’s ordering rank.
Capability: core.links.write. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| linkId | path | string | yes |
| baseVersion | body | integer | no |
| rank | body | string | yes |
Output: { link: { id: string, from: object, to: object, rel: string, rank: string, createdBy: string or null, createdAt: string, version: integer }, changeId: integer }.
GET /me/capabilities
Read your effective tenant capabilities and per-space grants in this workspace.
Capability: core.self.read. Kind: read.
No input fields.
Output: { capabilities: array
GET /members
List the workspace’s members (people and agents) with role, status, teams and last activity.
Capability: core.members.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | query | “person” / “agent” | no |
| status | query | “invited” / “active” / “suspended” / “removed” | no |
| includeRemoved | query | boolean | no |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
POST /members/{memberId}/reactivate
Reactivate a suspended member.
Capability: core.members.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| memberId | path | string | yes |
| Idempotency-Key | header | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { member: { id: string, kind: “person” / “agent”, name: string, email: string or null, role: string, status: “invited” / “active” / “suspended” / “removed”, teamIds: array
POST /members/{memberId}/remove
Remove a member (offboarding): hand their spaces, private items and views to another member, remove their agents and team memberships, end their access.
Capability: core.members.manage. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| memberId | path | string | yes |
| Idempotency-Key | header | string | no |
| Srvo-Confirmation | header | string | no |
| reassignTo | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { member: { id: string, kind: “person” / “agent”, name: string, email: string or null, role: string, status: “invited” / “active” / “suspended” / “removed”, teamIds: array
POST /members/{memberId}/suspend
Suspend a member: their sessions, keys and agents stop working until reactivated.
Capability: core.members.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| memberId | path | string | yes |
| Idempotency-Key | header | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { member: { id: string, kind: “person” / “agent”, name: string, email: string or null, role: string, status: “invited” / “active” / “suspended” / “removed”, teamIds: array
POST /members/{memberId}/role
Change a member’s role (role ceiling applies; only owners make owners; one owner always stays).
Capability: core.members.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| memberId | path | string | yes |
| Idempotency-Key | header | string | no |
| role | body | “owner” / “admin” / “member” / “limited” / “guest” or string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { member: { id: string, kind: “person” / “agent”, name: string, email: string or null, role: string, status: “invited” / “active” / “suspended” / “removed”, teamIds: array
PUT /modules
Enable or hide a workspace module without deleting its data.
Capability: core.modules.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| enabled | body | boolean | yes |
| module | body | “boards” / “notes” / “track” / “files” / “flows” / “send” | yes |
Output: { module: “boards” / “notes” / “track” / “files” / “flows” / “send”, enabled: boolean }.
POST /notifications/archive
Update my currently readable notifications: archive.
Capability: core.self.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| archived | body | boolean | no |
| ids | body | array |
yes |
Output: { changeIds: array
POST /notifications
Send a custom inbox notification to up to ten workspace members.
Capability: core.notifications.create. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| memberIds | body | array |
yes |
| message | body | string | yes |
| target | body | { kind: “record” / “table” / “view” / “note”, id: string } | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { ok: true }.
GET /notifications
My persisted notifications, rechecked against current target visibility.
Capability: core.self.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | query | string | no |
| limit | query | integer | no |
| state | query | “active” / “archived” / “all” | no |
| unreadOnly | query | boolean | no |
Output: { items: array
POST /notifications/read-all
Update my currently readable notifications: markAllRead.
Capability: core.self.read. Kind: write.
No input fields.
Output: { changeIds: array
POST /notifications/read
Update my currently readable notifications: markRead.
Capability: core.self.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| ids | body | array |
yes |
| read | body | boolean | no |
Output: { changeIds: array
POST /notifications/snooze
Update my currently readable notifications: snooze.
Capability: core.self.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| ids | body | array |
yes |
| until | body | string or null | yes |
Output: { changeIds: array
GET /notifications/unread-count
Count currently readable, active, unsnoozed unread notifications.
Capability: core.self.read. Kind: read.
No input fields.
Output: { unreadCount: integer }.
GET /core/recents
Visible personal recents for records, tables, views and notes, bounded to 50.
Capability: core.self.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| limit | query | integer | no |
Output: { items: array
POST /core/recents
Remember a readable personal navigation target.
Capability: core.self.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | body | string | yes |
| kind | body | “record” / “table” / “view” / “note” | yes |
Output: { changeIds: array
POST /roles
Create a custom role with capability patterns and row/field restrictions.
Capability: core.roles.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| capabilities | body | array |
yes |
| fieldRules | body | array<{ tableId: string, fieldId: string, access: “hidden” / “read” / “edit” }> | no |
| id | body | string | no |
| name | body | string | yes |
| recordRules | body | array<{ tableId: string, access: “read” / “edit”, where: array |
no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { role: { id: string, key: “owner” / “admin” / “member” / “limited” / “guest” or null, builtin: boolean, name: string, capabilities: array
POST /roles/{roleId}/delete
Preview and delete a custom role, reassigning every member when in use.
Capability: core.roles.manage. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| roleId | path | string | yes |
| Idempotency-Key | header | string | no |
| Srvo-Confirmation | header | string | no |
| reassignTo | body | “owner” / “admin” / “member” / “limited” / “guest” or string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { roleId: string, reassigned: integer, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
GET /roles
List the roles: built-in roles with their capabilities, member counts and whether you may assign them.
Capability: core.roles.read. Kind: read.
No input fields.
Output: { items: array
PATCH /roles/{roleId}
Update a custom role. Built-in roles are immutable.
Capability: core.roles.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| roleId | path | string | yes |
| Idempotency-Key | header | string | no |
| baseVersion | body | integer | yes |
| capabilities | body | array |
yes |
| fieldRules | body | array<{ tableId: string, fieldId: string, access: “hidden” / “read” / “edit” }> | no |
| name | body | string | yes |
| recordRules | body | array<{ tableId: string, access: “read” / “edit”, where: array |
no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { role: { id: string, key: “owner” / “admin” / “member” / “limited” / “guest” or null, builtin: boolean, name: string, capabilities: array
GET /scripts/runs/{runId}
Read a SRVO Script run you started: status, output or error, CPU and SDK calls.
Capability: core.scripts.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| runId | path | string | yes |
Output: { runId: string, status: “running” / “ok” / “error”, scriptHash: string, startedAt: string, finishedAt: string or null, output: null or boolean or number or string or array
POST /scripts/runs
Start a read-only SRVO Script run as you. Poll core.scripts.get for the result.
Capability: core.scripts.run. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| args | body | unknown | no |
| source | body | string | yes |
Output: { runId: string, status: “running” / “ok” / “error”, scriptHash: string, startedAt: string, finishedAt: string or null, output: null or boolean or number or string or array
POST /search/query
Search readable records, structure, note titles, member names and own Track entries. Empty queries return no recents.
Capability: core.self.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | body | string | no |
| limit | body | integer | no |
| q | body | string | yes |
| types | body | array<“record” / “table” / “dashboard” / “space” / “folder” / “view” / “note” / “member” / “time_entry”> or string | no |
Output: { groups: array
GET /me
Who am I: workspace, member, role, kind, and for agents the person they act for.
Capability: core.self.read. Kind: read.
No input fields.
Output: { tenantId: string, memberId: string, kind: “user” / “agent” / “integration” / “automation”, name: string, role: string, workspace: { name: string, slug: string or null }, onBehalfOf: string or null, modules: array
GET /taxonomies/{kind}/{id}/access
Who can use a Project, Client or Tag. Grant details need Manage and sharing authority; others see only their own rights.
Capability: core.taxonomies.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
Output: { detailed: false, rights: { view: boolean, use: boolean, contribute: boolean, manage: boolean, delete: boolean }, sharing: { allowed: true } or { allowed: false, reason: “view_only” / “archived” / “source_read_only” / “not_delegated” / “scope_restricted” / “not_allowed” } } or { detailed: true, rights: { view: boolean, use: boolean, contribute: boolean, manage: boolean, delete: boolean }, sharing: { allowed: true } or { allowed: false, reason: “view_only” / “archived” / “source_read_only” / “not_delegated” / “scope_restricted” / “not_allowed” }, grants: array
POST /taxonomies/{kind}/{id}/access/revoke
Remove grants from a Project, Client or Tag. Preview, then confirm. The last manager cannot be removed.
Capability: core.taxonomies.write. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| Idempotency-Key | header | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
| grantIds | body | array |
yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { access: { detailed: false, rights: object, sharing: object } or { detailed: true, rights: object, sharing: object, grants: array
POST /taxonomies/{kind}/{id}/access
Set one member’s, team’s or role’s rights on a Project, Client or Tag (preset or exact rights). Preview, then confirm. Needs Manage and sharing authority.
Capability: core.taxonomies.write. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| Idempotency-Key | header | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
| delegableRights | body | array<“view” / “use” / “contribute” / “manage” / “delete”> | no |
| effect | body | “allow” / “deny” | no |
| preset | body | “member” / “contributor” / “manager” | no |
| rights | body | array<“view” / “use” / “contribute” / “manage” / “delete”> | no |
| subject | body | { kind: “member”, id: string } or { kind: “team”, id: string } or { kind: “role”, id: “owner” / “admin” / “member” / “limited” / “guest” or string } or { kind: “all_members” } | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { access: { detailed: false, rights: object, sharing: object } or { detailed: true, rights: object, sharing: object, grants: array
POST /taxonomies/{kind}/{id}/archive
Archive or unarchive a Project, Client or Tag. Archived entries keep their links and history but cannot be newly used. Needs Manage.
Capability: core.taxonomies.write. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| Idempotency-Key | header | string | yes |
| archived | body | boolean | yes |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “project”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “client”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “tag” }, changeId: integer }.
POST /taxonomies/{kind}/capabilities
What you can do now: create this kind, your rights on one entry, and whether you can edit a source. Advisory; writes recheck.
Capability: core.taxonomies.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | body | string | no |
| source | body | { module: string, kind: string, id: string } | no |
Output: { kind: “project” / “client” / “tag”, policyEpoch: integer, create: { allowed: true } or { allowed: false, reason: “view_only” / “archived” / “source_read_only” / “not_delegated” / “scope_restricted” / “not_allowed” }, entry?: { ref: object, version: integer, rights: object, sharing: object }, source?: { ref: object, version: integer, edit: object } }.
POST /taxonomies/{kind}
Create a Project, Client or Tag. You become its manager; default visibility is members-only (Projects/Clients) or workspace (Tags).
Capability: core.taxonomies.write. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| Idempotency-Key | header | string | yes |
| color | body | “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” | no |
| fields | body | object | no |
| id | body | string | no |
| name | body | string | yes |
| teamIds | body | array |
no |
| visibility | body | “members” / “workspace” / “team” / “private” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “project”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “client”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “tag” }, changeId: integer }.
POST /taxonomies/{kind}/{id}/delete
Move an unreferenced Project, Client or Tag to the trash. Preview lists references; referenced entries must be archived instead. Needs Manage and Delete.
Capability: core.taxonomies.write. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| Idempotency-Key | header | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { ref: { kind: “project” / “client” / “tag”, id: string }, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
GET /taxonomies/{kind}/{id}
Read one Project, Client or Tag with creator/editor details and your current rights.
Capability: core.taxonomies.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
Output: { entry: { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “project”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “client”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “tag” } }.
POST /taxonomies/{kind}/{id}/history/list
Paged history of one Project, Client or Tag under your current View and field masks. Access details need Manage.
Capability: core.taxonomies.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| cursor | body | string | no |
| eventTypes | body | array<“create” / “rename” / “fields” / “contribution_added” / “link_added” / “link_removed” / “visibility” / “access” / “access_effect” / “archive” / “unarchive” / “trash” / “restore” / “delete_requested” / “recovery” / “migration_baseline”> | no |
| limit | body | integer | no |
Output: { items: array
GET /taxonomies/{kind}
List Projects, Clients or Tags you can view. Filters (Made by me, origin, archive, search) apply after access, before paging.
Capability: core.taxonomies.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| query | query | string | no |
| madeByMe | query | boolean | no |
| origin | query | “human” / “ai” / “integration” / “automation” / “import” / “migration” | no |
| archived | query | “active” / “archived” / “all” | no |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
POST /taxonomies/{kind}/picker
Choices for a Project, Client or Tag picker. Viewable entries without Use are returned disabled with a reason.
Capability: core.taxonomies.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| archived | body | “active” / “archived” / “all” | no |
| cursor | body | string | no |
| limit | body | integer | no |
| madeByMe | body | boolean | no |
| origin | body | “human” / “ai” / “integration” / “automation” / “import” / “migration” | no |
| query | body | string | no |
| source | body | { module: string, kind: string, id: string } | no |
Output: { items: array
POST /taxonomies/{kind}/{id}/recover
Make yourself manager of a private Project, Client or Tag that no one can manage. Owner (or owner-delegated admin) only; needs a reason; audited. Private parents stay closed.
Capability: core.taxonomies.write. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| Idempotency-Key | header | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
| reason | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { entry: { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “project”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “client”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “tag” } or null, changeId: integer, version: integer, policyEpoch: integer } or { preview: { summary: string, counts: object, warnings: array
GET /taxonomy-recovery
Private Projects, Clients and Tags that no one can manage any more. Owner (or owner-delegated admin) only; needs a reason and is audited. Returns IDs and creation metadata, never names.
Capability: core.taxonomies.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | query | “project” / “client” / “tag” | no |
| reason | query | string | yes |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
GET /taxonomy-settings
Who may create Projects, Clients and Tags. Owners/admins see the configured roles, members and teams; others see what they can create.
Capability: core.taxonomies.read. Kind: read.
No input fields.
Output: { version: integer, schemaVersion: 1, detailed: false, create: { project: object, client: object, tag: object } } or { version: integer, schemaVersion: 1, detailed: true, creation: { project: object, client: object, tag: object } }.
PATCH /taxonomy-settings
Choose which roles, members and teams may create one taxonomy kind. Human owners/admins only; never changes existing entry access.
Capability: core.taxonomies.write. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
| creationPolicy | body | { roles: array<“owner” / “admin” / “member” / “limited” / “guest” or string>, memberIds: array |
yes |
| taxonomy | body | “project” / “client” / “tag” | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { settings: { version: integer, schemaVersion: 1, detailed: false, create: object } or { version: integer, schemaVersion: 1, detailed: true, creation: object }, policyEpoch: integer, changeId: integer }.
PATCH /taxonomies/{kind}/{id}
Rename a Project, Client or Tag, change a Tag colour, or edit permitted fields. Needs Manage.
Capability: core.taxonomies.write. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
| patch | body | { name?: string, color?: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink”, fields?: object } | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “project”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “client”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “tag” }, changeId: integer }.
POST /taxonomies/{kind}/{id}/visibility
Change who sees a Project, Client or Tag by default: members-only, a team, the workspace, or private. Preview, then confirm.
Capability: core.taxonomies.write. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| kind | path | “project” / “client” / “tag” | yes |
| id | path | string | yes |
| Idempotency-Key | header | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
| teamIds | body | array |
no |
| visibility | body | “members” / “workspace” / “team” / “private” | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { entry: { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “project”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “client”, tableId: string, fields: object } or { id: string, label: string or null, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” or null, createdBy: object, createdFor: object, createdAt: string, editedBy: object, editedAt: string, version: integer, archived: boolean, visibility: “members” / “workspace” / “team” / “private”, rights: object, kind: “tag” } or null, changeId: integer, version: integer, policyEpoch: integer } or { preview: { summary: string, counts: object, warnings: array
POST /teams
Create a team (open or closed), optionally with its first members.
Capability: core.teams.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| id | body | string | no |
| memberIds | body | array |
no |
| name | body | string | yes |
| visibility | body | “open” / “closed” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { team: { id: string, name: string, visibility: “open” / “closed”, memberIds: array
POST /teams/{teamId}/delete
Delete a team that has no spaces left; its memberships go with it.
Capability: core.teams.manage. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| teamId | path | string | yes |
| Idempotency-Key | header | string | no |
| Srvo-Confirmation | header | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { team: { id: string, name: string, visibility: “open” / “closed”, memberIds: array
GET /teams
List teams: open ones, the closed ones you’re in (team managers see all).
Capability: core.teams.read. Kind: read.
No input fields.
Output: { items: array
POST /teams/{teamId}/members
Add a member to a team. Without team management rights you can only join an open team yourself.
Capability: core.teams.join. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| teamId | path | string | yes |
| Idempotency-Key | header | string | no |
| memberId | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { team: { id: string, name: string, visibility: “open” / “closed”, memberIds: array
DELETE /teams/{teamId}/members/{memberId}
Remove a member from a team. Without team management rights you can only leave a team yourself.
Capability: core.teams.join. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| teamId | path | string | yes |
| memberId | path | string | yes |
| Idempotency-Key | header | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { team: { id: string, name: string, visibility: “open” / “closed”, memberIds: array
PATCH /teams/{teamId}
Rename a team or switch it between open and closed.
Capability: core.teams.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| teamId | path | string | yes |
| Idempotency-Key | header | string | no |
| name | body | string | no |
| visibility | body | “open” / “closed” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { team: { id: string, name: string, visibility: “open” / “closed”, memberIds: array
GET /trash/records
Return readable trashed records under live parents. Pass optional cursor/limit; follow nextCursor. Structure trash uses listTrashedItems.
Capability: core.self.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
files
POST /files/{fileId}/download
Sign a five-minute attachment URL after a current permission check.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| versionId | body | string | no |
Output: { url: string, headers: object, expiresAt: string }.
POST /files/{fileId}/copy
Copy a readable file into a writable folder using storage-side copy.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| folderId | body | string or null | no |
| spaceId | body | string | yes |
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } }.
GET /files/{fileId}
Get one visible file’s metadata (name, type, size, folder, status, version). Never returns file bytes or URLs.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } }.
POST /files/{fileId}/move
Move a file after checking its folder permission.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| baseVersion | body | integer | yes |
| confirmToken | body | string | no |
| folderId | body | string or null | no |
| spaceId | body | string | yes |
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } } or { preview: { gains: array
POST /files/{fileId}/purge
Permanently delete a trashed file (bytes are removed after retention). Call without confirmationToken to preview, then with the returned token to commit.
Capability: files.entries.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } } or { preview: { summary: string, counts: object, warnings: array
POST /files/{fileId}/rename
Rename a file after checking its folder permission.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| baseVersion | body | integer | yes |
| name | body | string | yes |
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } }.
POST /files/{fileId}/restore
Restore a file after checking its folder permission.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| baseVersion | body | integer | yes |
| confirmToken | body | string | no |
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } } or { preview: { destination: “privateRoot”, parentId: null, ownerId: string, itemCount: integer }, confirmToken: string }.
POST /files/{fileId}/trash
Trash a file after checking its folder permission.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| baseVersion | body | integer | yes |
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } }.
POST /files/folders
Create a Files folder in the shared item tree.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| name | body | string | yes |
| parentId | body | string or null | no |
| spaceId | body | string | yes |
| visibility | body | “inherit” / “private” | no |
Output: { folder: { id: string, spaceId: string, parentId: string or null, parentVisible?: boolean, name: string, version: number, updatedAt: string, deletedAt: string or null, summary?: object } }.
GET /files/contents/list
List visible folders first, then files, with sorting and paging.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| folderId | query | string or null | no |
| spaceId | query | string | no |
| parentId | query | string or null | no |
| section | query | “all” / “workspace” / “shared” / “private” / “favourites” / “recent” / “sharedWithMe” | no |
| sort | query | “name” / “modified” / “size” | no |
| direction | query | “asc” / “desc” | no |
| offset | query | integer | no |
| limit | query | integer | no |
Output: { folders: array
POST /files/folders/{folderId}/move
Move a Files folder.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| folderId | path | string | yes |
| baseVersion | body | integer | yes |
| confirmToken | body | string | no |
| parentId | body | string or null | yes |
Output: { folder: { id: string, spaceId: string, parentId: string or null, parentVisible?: boolean, name: string, version: number, updatedAt: string, deletedAt: string or null, summary?: object } } or { preview: { gains: array
GET /files/path/{itemId}
Get the folder path (breadcrumb) from the root to a visible file or folder. Ancestors you cannot see come back with null id and name.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
Output: { path: array
POST /files/folders/{folderId}/purge
Permanently delete a trashed Files folder and its contents you can edit (bytes are removed after retention). Call without confirmationToken to preview, then with the returned token to commit.
Capability: files.entries.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| folderId | path | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { folder: { id: string, spaceId: string, parentId: string or null, parentVisible?: boolean, name: string, version: number, updatedAt: string, deletedAt: string or null, summary?: object } } or { preview: { summary: string, counts: object, warnings: array
POST /files/folders/{folderId}/rename
Rename a Files folder.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| folderId | path | string | yes |
| baseVersion | body | integer | yes |
| name | body | string | yes |
Output: { folder: { id: string, spaceId: string, parentId: string or null, parentVisible?: boolean, name: string, version: number, updatedAt: string, deletedAt: string or null, summary?: object } }.
POST /files/folders/{folderId}/restore
Restore a Files folder.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| folderId | path | string | yes |
| baseVersion | body | integer | yes |
| confirmToken | body | string | no |
Output: { folder: { id: string, spaceId: string, parentId: string or null, parentVisible?: boolean, name: string, version: number, updatedAt: string, deletedAt: string or null, summary?: object } } or { preview: { destination: “privateRoot”, parentId: null, ownerId: string, itemCount: integer }, confirmToken: string }.
POST /files/folders/{folderId}/trash
Trash a Files folder.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| folderId | path | string | yes |
| baseVersion | body | integer | yes |
Output: { folder: { id: string, spaceId: string, parentId: string or null, parentVisible?: boolean, name: string, version: number, updatedAt: string, deletedAt: string or null, summary?: object } }.
POST /files/{fileId}/preview
Sign an allowlisted image/PDF preview; other types download as attachments.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| versionId | body | string | no |
Output: { url: string, headers: object, expiresAt: string }.
POST /files/roots/ensure
Create a usable Files root in a writable space, or return the existing root.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| spaceId | body | string | yes |
Output: { folder: { id: string, spaceId: string, parentId: string or null, parentVisible?: boolean, name: string, version: number, updatedAt: string, deletedAt: string or null, summary?: object } }.
POST /shares
Create a Transfer package or file request link. Returns the token once.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| audience | body | “restricted” / “workspace” / “anyone” | no |
| disableDownload | body | boolean | no |
| downloadLimit | body | integer | no |
| expiresInDays | body | integer | no |
| fileIds | body | array |
no |
| folderId | body | string or null | no |
| kind | body | “transfer” / “request” | yes |
| message | body | string | no |
| password | body | string | no |
| recipients | body | array |
no |
| role | body | “viewer” / “commenter” / “editor” | no |
| spaceId | body | string or null | no |
| targetItemId | body | string | no |
| title | body | string | no |
Output: { share: { id: string, kind: “transfer” / “request”, spaceId: string or null, targetItemId?: string, audience?: “restricted” / “workspace” / “anyone”, role?: “viewer” / “commenter” / “editor”, disableDownload?: boolean, folderId: string or null, title: string, message: string, recipients: array
GET /shares/{shareId}
Read one of my shares with its view, download and upload history.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| shareId | path | string | yes |
Output: { share: { id: string, kind: “transfer” / “request”, spaceId: string or null, targetItemId?: string, audience?: “restricted” / “workspace” / “anyone”, role?: “viewer” / “commenter” / “editor”, disableDownload?: boolean, folderId: string or null, title: string, message: string, recipients: array
GET /shares
List my Transfer packages and file requests, newest first.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| kind | query | “transfer” / “request” | no |
| limit | query | integer | no |
Output: { shares: array
GET /shares/item/{targetItemId}
List all live links on an item I can manage.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| targetItemId | path | string | yes |
Output: { shares: array
POST /shares/{shareId}/revoke
Revoke a share now. The public link stops at once.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| shareId | path | string | yes |
Output: { share: { id: string, kind: “transfer” / “request”, spaceId: string or null, targetItemId?: string, audience?: “restricted” / “workspace” / “anyone”, role?: “viewer” / “commenter” / “editor”, disableDownload?: boolean, folderId: string or null, title: string, message: string, recipients: array
POST /shares/{shareId}/update
Update a v2 item link’s audience, role, password, expiry and download setting.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| shareId | path | string | yes |
| audience | body | “restricted” / “workspace” / “anyone” | no |
| disableDownload | body | boolean | no |
| expiresInDays | body | integer | no |
| password | body | string or null | no |
| role | body | “viewer” / “commenter” / “editor” | no |
Output: { share: { id: string, kind: “transfer” / “request”, spaceId: string or null, targetItemId?: string, audience?: “restricted” / “workspace” / “anyone”, role?: “viewer” / “commenter” / “editor”, disableDownload?: boolean, folderId: string or null, title: string, message: string, recipients: array
GET /files/storage/usage
Read workspace storage usage, including versions, trash and pending reservations.
Capability: files.storage.manage. Kind: read.
No input fields.
Output: { usedBytes: number, reservedBytes: number, quotaBytes: number or null }.
GET /files/trash/list
List trashed Files folders and files you could restore. Paginated with offset and limit (max 200); hasMore says whether another page exists.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| offset | query | integer | no |
| limit | query | integer | no |
Output: { folders: array
POST /files/uploads/{uploadId}/abort
Abort a direct upload session owned by the caller.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| uploadId | path | string | yes |
Output: { file?: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null }, parts?: array
POST /files/uploads
Reserve storage and sign a direct upload. Never send file bytes to this endpoint.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| collision | body | “rename” / “replace” | no |
| contentType | body | string | yes |
| folderId | body | string or null | no |
| name | body | string | yes |
| sha256 | body | string | no |
| size | body | integer | yes |
| spaceId | body | string | yes |
Output: { uploadId: string, fileId: string, versionId: string, partSize: number, parts: array
POST /files/uploads/{uploadId}/complete
Complete a direct upload session owned by the caller.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| uploadId | path | string | yes |
| etag | body | string | no |
Output: { file?: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null }, parts?: array
POST /files/uploads/{uploadId}/part
Part a direct upload session owned by the caller.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| uploadId | path | string | yes |
| part | body | { n: integer, etag: string, size: integer } | yes |
Output: { file?: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null }, parts?: array
POST /files/uploads/{uploadId}/urls
Urls a direct upload session owned by the caller.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| uploadId | path | string | yes |
| parts | body | array |
yes |
Output: { file?: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null }, parts?: array
GET /files/{fileId}/versions
List a visible file’s retained versions.
Capability: files.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
Output: { versions: array
POST /files/{fileId}/versions/{versionId}/restore
Restore a clean retained version without overwriting its bytes.
Capability: files.entries.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| fileId | path | string | yes |
| versionId | path | string | yes |
| baseVersion | body | integer | yes |
Output: { file: { id: string, spaceId: string, folderId: string or null, parentVisible?: boolean, name: string, mime: string, size: number, currentVersionId: string or null, version: number, deletedAt: string or null, updatedAt: string, status: “pending” / “scanning” / “ready” / “failed”, scanStatus: “pending” / “clean” / “infected”, createdBy: string or null } }.
flows
POST /flows
Create a disabled flow with an immutable version.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| definition | body | { schemaVersion: 1, id: string, version: integer, name: string, trigger: { type: “record”, event: “created” / “updated” / “matching”, tableId: string, filter?: object, fieldId?: string, from?: object, to?: object } or { type: “track”, clientId?: string, projectId?: string } or { type: “schedule”, cron: string, timeZone: string, hungarianHolidays?: “include” / “skip-non-working-days” } or { type: “webhook”, method: “GET” / “POST” / “PUT” / “PATCH” / “DELETE”, payloadSchema: object } or { type: “inbound-email”, connectionId?: string } or { type: “form-submitted”, formId: string } or { type: “manual” } or { type: “flow”, flowId: string }, entry: string, steps: object } | yes |
| runAs | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, name: string, enabled: boolean, version: integer, definition: { schemaVersion: 1, id: string, version: integer, name: string, trigger: object, entry: string, steps: object }, createdBy: string, runAs: string, trashedAt: string or null, createdAt: string }.
POST /flows/{flowId}/disable
disable a flow.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, name: string, enabled: boolean, version: integer, definition: { schemaVersion: 1, id: string, version: integer, name: string, trigger: object, entry: string, steps: object }, createdBy: string, runAs: string, trashedAt: string or null, createdAt: string }.
POST /flows/{flowId}/email/create
Give an email-triggered flow a new inbound address (replaces the old one). Returns its local part.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { localPart?: string, ok: true }.
POST /flows/{flowId}/email/disable
Remove a flow’s inbound email address.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { localPart?: string, ok: true }.
POST /flows/{flowId}/enable
enable a flow.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, name: string, enabled: boolean, version: integer, definition: { schemaVersion: 1, id: string, version: integer, name: string, trigger: object, entry: string, steps: object }, createdBy: string, runAs: string, trashedAt: string or null, createdAt: string }.
GET /flows/{flowId}
Get a flow definition.
Capability: flows.edit. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
Output: { id: string, name: string, enabled: boolean, version: integer, definition: { schemaVersion: 1, id: string, version: integer, name: string, trigger: object, entry: string, steps: object }, createdBy: string, runAs: string, trashedAt: string or null, createdAt: string }.
GET /flows
List workspace flows.
Capability: flows.edit. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| trash | query | boolean | no |
Output: { items: array
POST /flows/{flowId}/restore
restore a flow.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, name: string, enabled: boolean, version: integer, definition: { schemaVersion: 1, id: string, version: integer, name: string, trigger: object, entry: string, steps: object }, createdBy: string, runAs: string, trashedAt: string or null, createdAt: string }.
POST /flows/{flowId}/runs/clear
Clear terminal run history. Active runs remain.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { ok: true }.
GET /flow-runs/{runId}
Get a run and its redacted step trace.
Capability: flows.edit. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| runId | path | string | yes |
Output: { run: { id: string, flowId: string, version: integer, runAs: string, status: “queued” / “running” / “succeeded” / “failed” / “skipped” / “cancelled”, triggerKind: string, createdAt: number, startedAt: number or null, finishedAt: number or null, error: string or null, counted: boolean }, steps: array
GET /flows/{flowId}/runs
Page through newest flow runs.
Capability: flows.edit. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| status | query | “queued” / “running” / “succeeded” / “failed” / “skipped” / “cancelled” | no |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { items: array
POST /flows/secrets/delete
Delete a vault secret (owners/admins).
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| name | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { ok: true }.
GET /flows/secrets
List vault secret names for HTTP steps. Values are never returned.
Capability: flows.edit. Kind: read.
No input fields.
Output: { items: array
POST /flows/secrets
Create or replace a vault secret (owners/admins). HTTP steps reference it as {{secret.NAME}} and may only send it to the listed https origins.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| name | body | string | yes |
| origins | body | array |
yes |
| value | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { ok: true }.
POST /flows/test
Simulate a definition without writes or run usage.
Capability: flows.edit. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| definition | body | { schemaVersion: 1, id: string, version: integer, name: string, trigger: { type: “record”, event: “created” / “updated” / “matching”, tableId: string, filter?: object, fieldId?: string, from?: object, to?: object } or { type: “track”, clientId?: string, projectId?: string } or { type: “schedule”, cron: string, timeZone: string, hungarianHolidays?: “include” / “skip-non-working-days” } or { type: “webhook”, method: “GET” / “POST” / “PUT” / “PATCH” / “DELETE”, payloadSchema: object } or { type: “inbound-email”, connectionId?: string } or { type: “form-submitted”, formId: string } or { type: “manual” } or { type: “flow”, flowId: string }, entry: string, steps: object } | yes |
| sample | body | null or boolean or number or string or array<null or boolean or number or string or array |
yes |
Output: { status: string, steps: array
POST /flows/{flowId}/trash
trash a flow.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, name: string, enabled: boolean, version: integer, definition: { schemaVersion: 1, id: string, version: integer, name: string, trigger: object, entry: string, steps: object }, createdBy: string, runAs: string, trashedAt: string or null, createdAt: string }.
PATCH /flows/{flowId}
Save a new immutable flow version.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
| definition | body | { schemaVersion: 1, id: string, version: integer, name: string, trigger: { type: “record”, event: “created” / “updated” / “matching”, tableId: string, filter?: object, fieldId?: string, from?: object, to?: object } or { type: “track”, clientId?: string, projectId?: string } or { type: “schedule”, cron: string, timeZone: string, hungarianHolidays?: “include” / “skip-non-working-days” } or { type: “webhook”, method: “GET” / “POST” / “PUT” / “PATCH” / “DELETE”, payloadSchema: object } or { type: “inbound-email”, connectionId?: string } or { type: “form-submitted”, formId: string } or { type: “manual” } or { type: “flow”, flowId: string }, entry: string, steps: object } | yes |
| runAs | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, name: string, enabled: boolean, version: integer, definition: { schemaVersion: 1, id: string, version: integer, name: string, trigger: object, entry: string, steps: object }, createdBy: string, runAs: string, trashedAt: string or null, createdAt: string }.
GET /flows/usage
Get this workspace’s monthly run pool.
Capability: flows.edit. Kind: read.
No input fields.
Output: { used: number, included: number, plan: string, resetsOn: string, timeZone?: string }.
GET /flows/{flowId}/versions
List immutable flow versions.
Capability: flows.edit. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
Output: { items: array
POST /flows/{flowId}/webhook/create
create an inbound webhook. Modes: srvo (signed + secret header), github (X-Hub-Signature-256), linear (Linear-Signature, paste Linear’s secret), path (secret token in the URL). Secrets are shown once.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
| mode | body | “srvo” / “github” / “linear” / “path” | no |
| signingSecret | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { publicId?: string, secret?: string, mode?: “srvo” / “github” / “linear” / “path”, ok: true }.
POST /flows/{flowId}/webhook/disable
disable an inbound webhook.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { publicId?: string, secret?: string, mode?: “srvo” / “github” / “linear” / “path”, ok: true }.
POST /flows/{flowId}/webhook/rotate
rotate an inbound webhook. Modes: srvo (signed + secret header), github (X-Hub-Signature-256), linear (Linear-Signature, paste Linear’s secret), path (secret token in the URL). Secrets are shown once.
Capability: flows.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| flowId | path | string | yes |
| Idempotency-Key | header | string | yes |
| mode | body | “srvo” / “github” / “linear” / “path” | no |
| signingSecret | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { publicId?: string, secret?: string, mode?: “srvo” / “github” / “linear” / “path”, ok: true }.
import
POST /imports/connections/{connectionId}/disconnect
Disconnect your source connection and cancel its active runs.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| connectionId | path | string | yes |
Output: { disconnected: boolean }.
POST /imports/connections/{connectionId}/import
Start an import using your existing source connection.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| connectionId | path | string | yes |
Output: { run: { id: string, provider: “airtable” / “toggl” / “toggl-focus”, protocol?: “mcp”, stayConnected?: boolean, status: “discovering” / “picking” / “extracting” / “ready” / “applying” / “complete” / “cancelled” / “failed” / “partial”, version: integer, timeZone: string, selection: object or null, items?: array
GET /imports/connections
List your source connections without credentials.
Capability: import.plans.apply. Kind: read.
No input fields.
Output: { connections: array
POST /imports/connector/{runId}/cancel
Stop an own import run and delete its token. Committed rows stay.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| runId | path | string | yes |
| baseVersion | body | integer | yes |
Output: { run: { id: string, provider: “airtable” / “toggl” / “toggl-focus”, protocol?: “mcp”, stayConnected?: boolean, status: “discovering” / “picking” / “extracting” / “ready” / “applying” / “complete” / “cancelled” / “failed” / “partial”, version: integer, timeZone: string, selection: object or null, items?: array
POST /imports/connector
Connect Airtable or Toggl with a personal token for one import.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| provider | body | “airtable” / “toggl” / “toggl-focus” | yes |
| timeZone | body | string | yes |
| token | body | string | yes |
Output: { run: { id: string, provider: “airtable” / “toggl” / “toggl-focus”, protocol?: “mcp”, stayConnected?: boolean, status: “discovering” / “picking” / “extracting” / “ready” / “applying” / “complete” / “cancelled” / “failed” / “partial”, version: integer, timeZone: string, selection: object or null, items?: array
GET /imports/connector/{runId}
Get an own import run, its discovery while picking and its plan while ready.
Capability: import.jobs.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| runId | path | string | yes |
| itemId | query | string | no |
Output: { run: { id: string, provider: “airtable” / “toggl” / “toggl-focus”, protocol?: “mcp”, stayConnected?: boolean, status: “discovering” / “picking” / “extracting” / “ready” / “applying” / “complete” / “cancelled” / “failed” / “partial”, version: integer, timeZone: string, selection: object or null, items?: array
POST /imports/connector/{runId}/pick
Choose what to import and where, then fetch it in the background.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| runId | path | string | yes |
| baseVersion | body | integer | yes |
| selection | body | { provider: “airtable”, baseId?: string, bases?: array |
yes |
| spaceId | body | string | no |
| target | body | { kind: “existing”, spaceId: string } or { kind: “section”, audience?: “private” / “workspace”, name?: string } or { kind: “folder”, folderId: string, name?: string } or { kind: “new”, teamId: string, name: string } | no |
Output: { run: { id: string, provider: “airtable” / “toggl” / “toggl-focus”, protocol?: “mcp”, stayConnected?: boolean, status: “discovering” / “picking” / “extracting” / “ready” / “applying” / “complete” / “cancelled” / “failed” / “partial”, version: integer, timeZone: string, selection: object or null, items?: array
POST /imports/connector/{runId}/retry
Retry one failed table without repeating completed tables.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| runId | path | string | yes |
| baseVersion | body | integer | yes |
| itemId | body | string | yes |
Output: { run: { id: string, provider: “airtable” / “toggl” / “toggl-focus”, protocol?: “mcp”, stayConnected?: boolean, status: “discovering” / “picking” / “extracting” / “ready” / “applying” / “complete” / “cancelled” / “failed” / “partial”, version: integer, timeZone: string, selection: object or null, items?: array
POST /imports/connector/{runId}/start
Apply the previewed plan in the background with the reviewed mappings.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| runId | path | string | yes |
| baseVersion | body | integer | yes |
| mappings | body | { tableMappings?: object, fieldMappings?: object } | yes |
Output: { run: { id: string, provider: “airtable” / “toggl” / “toggl-focus”, protocol?: “mcp”, stayConnected?: boolean, status: “discovering” / “picking” / “extracting” / “ready” / “applying” / “complete” / “cancelled” / “failed” / “partial”, version: integer, timeZone: string, selection: object or null, items?: array
POST /imports/files/preview
Preview base64 export files before importing: up to 50 files, 5 MB total and 50,000 rows. Writes no destination data.
Capability: import.plans.apply. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| columns | body | object | no |
| files | body | array<{ name: string, base64: string }> | yes |
| idColumn | body | string | no |
| sheet | body | string | no |
| source | body | “csv” / “xlsx” / “monday” / “nocodb” / “airtable” / “toggl” / “notion” / “trello” / “asana” / “clickup” / “linear” | yes |
| sourceId | body | string | yes |
| spaceId | body | string | no |
| target | body | { kind: “existing”, spaceId: string } or { kind: “section”, audience?: “private” / “workspace”, name?: string } or { kind: “folder”, folderId: string, name?: string } or { kind: “new”, teamId: string, name: string } | no |
| timeZone | body | string | no |
Output: { plan: { version: 1, source: “airtable” / “csv” / “nocodb” / “monday” / “notion” / “trello” / “asana” / “clickup” / “linear”, sourceId: string, pages?: array
POST /imports/jobs/{jobId}/cancel
Stop an owned import after its last committed batch. Keep imported data.
Capability: import.plans.apply. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| jobId | path | string | yes |
| baseVersion | body | integer | yes |
Output: { job: { id: string, spaceId: string, folderId?: string, notesFolderId?: string, planHash: string, status: “running” / “complete” / “rolling_back” / “rolled_back”, cancelled: boolean, hasTrack: boolean, issues: array
GET /imports/jobs/{jobId}
Get an import job and its committed progress.
Capability: import.jobs.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| jobId | path | string | yes |
Output: { job: { id: string, spaceId: string, folderId?: string, notesFolderId?: string, planHash: string, status: “running” / “complete” / “rolling_back” / “rolled_back”, cancelled: boolean, hasTrack: boolean, issues: array
POST /imports/jobs/{jobId}/rollback
Trash objects created by an import, in resumable batches.
Capability: import.jobs.rollback. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| jobId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { job: { id: string, spaceId: string, folderId?: string, notesFolderId?: string, planHash: string, status: “running” / “complete” / “rolling_back” / “rolled_back”, cancelled: boolean, hasTrack: boolean, issues: array
POST /imports/apply
Preview and apply a reviewed import plan in resumable batches.
Capability: import.plans.apply. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| Srvo-Confirmation | header | string | no |
| jobId | body | string | no |
| options | body | { conflictPolicy?: “source_wins”, batchSize?: integer, tableMappings?: object, fieldMappings?: object } | no |
| plan | body | { version: 1, source: “airtable” / “csv” / “nocodb” / “monday” / “notion” / “trello” / “asana” / “clickup” / “linear”, sourceId: string, pages?: array |
no |
| requestId | body | string | no |
| resumeToken | body | string | no |
| target | body | { kind: “existing”, spaceId: string } or { kind: “section”, audience?: “private” / “workspace”, name?: string } or { kind: “folder”, folderId: string, name?: string } or { kind: “new”, teamId: string, name: string } | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { job: { id: string, spaceId: string, folderId?: string, notesFolderId?: string, planHash: string, status: “running” / “complete” / “rolling_back” / “rolled_back”, cancelled: boolean, hasTrack: boolean, issues: array
metrics
POST /metrics/series
Query readable metric series and previous periods with the SRVO Script contract.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| compareTo | body | “previousPeriod” | no |
| filters | body | array<{ field: string, op: “eq” / “neq”, value: string or number or boolean } or { field: string, op: “in”, values: array |
no |
| groupBy | body | array<string or “date:day” / “date:week” / “date:month”> | no |
| metrics | body | array<string or { tableId: string, op: “sum” / “avg” / “min” / “max” / “countRows” / “countNonNull” / “percent”, field?: string, dateField?: string }> | yes |
| range | body | { preset: “thisWeek” / “lastWeek” / “thisMonth” / “lastMonth” } or { lastDays: integer } or { from: string, to: string } | no |
Output: { status: “complete” / “partial” / “stale” / “restricted”, series: array
POST /metrics/check
Validate metric tables, fields, units, ranges and access without aggregating.
Capability: boards.records.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| compareTo | body | “previousPeriod” | no |
| filters | body | array<{ field: string, op: “eq” / “neq”, value: string or number or boolean } or { field: string, op: “in”, values: array |
no |
| groupBy | body | array<string or “date:day” / “date:week” / “date:month”> | no |
| metrics | body | array<string or { tableId: string, op: “sum” / “avg” / “min” / “max” / “countRows” / “countNonNull” / “percent”, field?: string, dateField?: string }> | yes |
| range | body | { preset: “thisWeek” / “lastWeek” / “thisMonth” / “lastMonth” } or { lastDays: integer } or { from: string, to: string } | no |
Output: { ok: boolean, restricted: boolean, issues: array
notes
POST /notes/{pageId}/paragraphs
Append one plain-text paragraph (max 50,000 characters) to the end of a Notes page. Pass the page’s current bodyVersion as baseVersion from getNote; a stale version fails with CONFLICT. Returns the updated page.
Capability: notes.pages.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| baseVersion | body | integer | yes |
| text | body | string | yes |
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
POST /notes
Create a Notes page in a space (or under parentId), or a private quick note. Returns the new page. Send an idempotencyKey to make retries safe.
Capability: notes.pages.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| blocks | body | array<{ id: string, type: “heading”, level: 1 or 2 or 3, text: array |
no |
| icon | body | string or null | no |
| id | body | string | no |
| parentId | body | string or null | no |
| private | body | boolean | no |
| quick | body | boolean | no |
| spaceId | body | string | yes |
| title | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
GET /notes/{noteId}/export
Export noteId as safe Markdown. Returns filename, contentType and base64 body over MCP, up to 1 MiB; use REST for larger files.
Capability: notes.pages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| noteId | path | string | yes |
Output: string.
GET /notes/{noteId}
Read a Notes page and its validated document blocks.
Capability: notes.pages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| noteId | path | string | yes |
Output: { page?: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
GET /notes
List visible pages in a space or this member’s quick notes inbox.
Capability: notes.pages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| spaceId | query | string | no |
| quick | query | “true” / “false” | no |
| after | query | string | no |
| limit | query | integer | no |
Output: { pages: array
POST /notes/{pageId}/move
Move a Notes page and its subpages to another space or parent page. Pass the page’s version as baseVersion. Returns the moved page.
Capability: notes.pages.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| baseVersion | body | integer | yes |
| parentId | body | string or null | yes |
| spaceId | body | string | yes |
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
PATCH /notes/{pageId}
Rename a Notes page. Pass the page’s version as baseVersion; a stale version fails with CONFLICT.
Capability: notes.pages.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| baseVersion | body | integer | yes |
| title | body | string | yes |
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
POST /notes/{pageId}/restore
Restore a trashed Notes page and its subpages. Call without confirmationToken to preview, then again with the returned token to commit.
Capability: notes.pages.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
PUT /notes/{pageId}/body
Replace a Notes page body with the given blocks. Pass the page’s bodyVersion as baseVersion; a stale version fails with CONFLICT. Earlier bodies stay restorable from listNoteVersions. Prefer appendNoteParagraph for small additions.
Capability: notes.pages.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| baseVersion | body | integer | yes |
| blocks | body | array<{ id: string, type: “heading”, level: 1 or 2 or 3, text: array |
yes |
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
POST /notes/{pageId}/trash
Move a Notes page and its subpages to trash. Call without confirmationToken to preview, then again with the returned token to commit.
Capability: notes.pages.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
GET /notes/{pageId}/versions/{versionId}
Read one retained version of a visible Notes page.
Capability: notes.pages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| versionId | path | string | yes |
Output: { version: { id: string, at: string, authorId: string or null, kind: “auto” / “restore”, bodyVersion: integer }, blocks: array
GET /notes/{pageId}/versions
List the retained version metadata of a visible Notes page.
Capability: notes.pages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
Output: { versions: array
POST /notes/{pageId}/versions/{versionId}/restore
Restore a retained snapshot as a new version, preserving the previous body.
Capability: notes.pages.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| pageId | path | string | yes |
| versionId | path | string | yes |
| baseVersion | body | integer | yes |
Output: { page: { id: string, spaceId: string, parentId: string or null, title: string, icon: string or null, rank: string, visibility: “inherit” / “private”, createdBy: string or null, createdAt: string, updatedBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, bodyVersion: integer, blocks: array
send
POST /send/domains
Add a sending domain. Returns the DNS records to add; a background job checks them.
Capability: send.domains.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| clickTracking | body | boolean | no |
| customReturnPath | body | string | no |
| domain | body | string | yes |
| openTracking | body | boolean | no |
| region | body | “eu-central-1” / “eu-west-1” | no |
| tls | body | “opportunistic” | no |
Output: { id: string, domain: string, status: “not_started” / “pending” / “partially_verified” / “verified” / “failed” / “temporary_failure”, records: array
DELETE /send/domains/{domainId}
Remove a sending domain. Its provider identity and DKIM keys are removed in the background.
Capability: send.domains.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| domainId | path | string | yes |
Output: { id: string, deleted: true }.
GET /send/domains/{domainId}
Read one sending domain with its DNS records and check status.
Capability: send.domains.manage. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| domainId | path | string | yes |
Output: { id: string, domain: string, status: “not_started” / “pending” / “partially_verified” / “verified” / “failed” / “temporary_failure”, records: array
GET /send/domains
List sending domains with the DNS records to add and their check status.
Capability: send.domains.manage. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| limit | query | integer | no |
| after | query | string | no |
| before | query | string | no |
Output: { domains: array
PATCH /send/domains/{domainId}
Change a sending domain’s open/click tracking or TLS setting.
Capability: send.domains.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| domainId | path | string | yes |
| clickTracking | body | boolean | no |
| openTracking | body | boolean | no |
| tls | body | “opportunistic” | no |
Output: { id: string, domain: string, status: “not_started” / “pending” / “partially_verified” / “verified” / “failed” / “temporary_failure”, records: array
POST /send/domains/{domainId}/verify
Ask for a fresh DNS check of a sending domain (runs within a minute).
Capability: send.domains.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| domainId | path | string | yes |
Output: { id: string, domain: string, status: “not_started” / “pending” / “partially_verified” / “verified” / “failed” / “temporary_failure”, records: array
POST /send/emails/batch
Send up to 100 emails at once (no attachments or scheduling). Strict: all or nothing; permissive: valid ones go out.
Capability: send.emails.send. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| emails | body | array<{ from: string, to: string or array |
yes |
| validation | body | “strict” / “permissive” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { data: array
POST /send/emails/{emailId}/cancel
Cancel a scheduled email before it goes out.
Capability: send.emails.send. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| emailId | path | string | yes |
Output: { id: string }.
GET /send/emails/{emailId}
Read one email sent through the API: recipients, subject, last event, and the body while kept.
Capability: send.messages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| emailId | path | string | yes |
Output: { id: string, from: string, to: array
GET /send/emails
List emails sent through the API or SMTP, newest first (system mail is never listed).
Capability: send.messages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| limit | query | integer | no |
| after | query | string | no |
| before | query | string | no |
Output: { items: array
PATCH /send/emails/{emailId}
Move a scheduled email to another time (at most 30 days ahead). Only while it is scheduled.
Capability: send.emails.send. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| emailId | path | string | yes |
| scheduledAt | body | string | yes |
Output: { id: string }.
POST /send/emails
Send an email from a verified domain of this workspace (to, cc, bcc ≤ 50, attachments, optional scheduled_at).
Capability: send.emails.send. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| attachments | body | array<{ content?: string, path?: string, filename?: string, contentType?: string, contentId?: string }> | no |
| bcc | body | string or array |
no |
| cc | body | string or array |
no |
| from | body | string | yes |
| headers | body | object | no |
| html | body | string | no |
| replyTo | body | string or array |
no |
| scheduledAt | body | string | no |
| subject | body | string | yes |
| tags | body | array<{ name: string, value: string }> | no |
| text | body | string | no |
| to | body | string or array |
yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string }.
POST /send/emails/raw
Send a ready MIME message (the SMTP relay uses this): envelope sender, recipients (≤ 50) and the message as base64. Its From must be on the sender’s verified domain.
Capability: send.emails.send. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| from | body | string | yes |
| raw | body | string | yes |
| to | body | array |
yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string }.
POST /send/keys
Create a Send API key. The token is returned once.
Capability: send.keys.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| domainIds | body | array |
no |
| name | body | string | yes |
| permission | body | “full_access” / “sending_access” | no |
Output: { key: { id: string, name: string, prefix: string, permission: “full_access” / “sending_access”, domainIds: array
GET /send/keys
List the workspace’s active Send API keys (metadata only, never the token).
Capability: send.keys.manage. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| limit | query | integer | no |
| after | query | string | no |
| before | query | string | no |
Output: { items: array
POST /send/keys/{keyId}/revoke
Revoke a Send API key. It stops working at once.
Capability: send.keys.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| keyId | path | string | yes |
Output: { id: string, name: string, prefix: string, permission: “full_access” / “sending_access”, domainIds: array
GET /send/messages
List outbound emails of this workspace, newest first, with delivery status.
Capability: send.messages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| status | query | “queued” / “sent” / “delivered” / “bounced” / “complained” / “failed” / “suppressed” / “blocked” / “scheduled” / “canceled” | no |
| limit | query | integer | no |
Output: { messages: array
GET /send/status
Whether this server has an email provider set up (without one, mail waits in the queue).
Capability: send.messages.read. Kind: read.
No input fields.
Output: { configured: boolean, provider: string or null }.
POST /send/suppressions
Suppress an email address: mail from this workspace’s Send API skips it from now on.
Capability: send.suppressions.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| body | string | yes | |
| reason | body | “manual” / “unsubscribe” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, email: string, reason: “hard_bounce” / “soft_bounce” / “complaint” / “unsubscribe” / “manual”, source: “srvo” / “api”, createdAt: string }.
POST /send/suppressions/batch/add
Suppress up to 1,000 email addresses at once. Addresses already listed keep their entry.
Capability: send.suppressions.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| emails | body | array |
yes |
| reason | body | “manual” / “unsubscribe” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { data: array
POST /send/suppressions/batch/remove
Remove up to 1,000 email addresses from the suppression list at once.
Capability: send.suppressions.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| emails | body | array |
yes |
Output: { removed: integer }.
GET /send/suppressions/{suppressionId}
Read one suppression entry by its id or by the email address.
Capability: send.messages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| suppressionId | path | string | yes |
Output: { id: string, email: string, reason: “hard_bounce” / “soft_bounce” / “complaint” / “unsubscribe” / “manual”, source: “srvo” / “api”, createdAt: string }.
GET /send/suppressions
List the workspace’s suppressed email addresses, newest first (bounces, complaints, manual).
Capability: send.messages.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| limit | query | integer | no |
| after | query | string | no |
| before | query | string | no |
Output: { items: array
DELETE /send/suppressions/{suppressionId}
Remove an address from the suppression list (by id or address). Mail may reach it again, bounces included.
Capability: send.suppressions.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| suppressionId | path | string | yes |
Output: { id: string, email: string, deleted: true }.
sergio
POST /sergio/conversations
Create a private Sergio conversation
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| scope | body | { kind: “project” / “client”, id: string } | no |
| title | body | string | no |
Output: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: { kind: “project” / “client”, id: string } or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }.
POST /sergio/conversations/{id}/delete
Update your private conversation: delete
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| baseVersion | body | integer | yes |
| forgetLearned | body | boolean | no |
Output: { id: string, version: integer }.
GET /sergio/conversations/{id}
Read your conversation and a page of messages
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| cursor | query | string | no |
| limit | query | integer | no |
Output: { conversation: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: object or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }, messages: array
POST /sergio/conversations/list
List your private Sergio conversations
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | body | string | no |
| limit | body | integer | no |
| pinned | body | boolean | no |
| query | body | string | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
Output: { items: array
POST /sergio/conversations/{id}/move
Update your private conversation: move
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| baseVersion | body | integer | yes |
| forgetLearned | body | boolean | no |
| scope | body | { kind: “project” / “client”, id: string } or null | yes |
Output: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: { kind: “project” / “client”, id: string } or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }.
POST /sergio/conversations/{id}/pin
Update your private conversation: pin
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| baseVersion | body | integer | yes |
| pinned | body | boolean | yes |
Output: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: { kind: “project” / “client”, id: string } or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }.
POST /sergio/conversations/{id}/rename
Update your private conversation: rename
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| baseVersion | body | integer | yes |
| title | body | string | yes |
Output: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: { kind: “project” / “client”, id: string } or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }.
POST /sergio/conversations/{id}/setMemory
Update your private conversation: setMemory
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| baseVersion | body | integer | yes |
| learn | body | boolean | no |
| use | body | boolean | no |
Output: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: { kind: “project” / “client”, id: string } or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }.
POST /sergio/conversations/{id}/unpin
Unpin your private Sergio conversation
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| baseVersion | body | integer | yes |
Output: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: { kind: “project” / “client”, id: string } or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }.
POST /sergio/external/list
Owner-only external coding agent chat list
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | body | string | no |
| limit | body | integer | no |
| pinned | body | boolean | no |
| query | body | string | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
Output: { items: array
POST /sergio/external/poll
Owner-only external coding agent chat poll
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | body | string | no |
| id | body | string | yes |
| limit | body | integer | no |
Output: { conversation: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: object or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }, messages: array
POST /sergio/external/post
Owner-only external coding agent chat post
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| id | body | string | yes |
| text | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, conversationId: string, parentMessageId: string or null, role: “user” / “assistant”, parts: array
POST /sergio/external/read
Owner-only external coding agent chat read
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| cursor | body | string | no |
| id | body | string | yes |
| limit | body | integer | no |
Output: { conversation: { id: string, ownerMemberId: string, title: string, pinned: boolean, archived: boolean, scope: object or null, memoryUse: boolean, memoryLearn: boolean, createdAt: string, updatedAt: string, lastMessageAt: string or null, version: integer }, messages: array
POST /sergio/memory/entries/copyToMine
Read or manage Sergio memory under scope and audience policy: entries.copyToMine
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, memoryId: string, kind: “decision” / “fact” / “preference” / “open_item”, text: string, pinned: boolean, forgotten: boolean, shared: boolean, origin: “learned” / “user” / “promoted”, humanEdited: boolean, state: “active” / “stale” / “audience_narrowed” / “source_in_trash” / “closed”, badges: array<“new” / “pinned” / “stale”>, sources: array
POST /sergio/memory/entries/create
Read or manage Sergio memory under scope and audience policy: entries.create
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, memoryId: string, kind: “decision” / “fact” / “preference” / “open_item”, text: string, pinned: boolean, forgotten: boolean, shared: boolean, origin: “learned” / “user” / “promoted”, humanEdited: boolean, state: “active” / “stale” / “audience_narrowed” / “source_in_trash” / “closed”, badges: array<“new” / “pinned” / “stale”>, sources: array
POST /sergio/memory/entries/forget
Read or manage Sergio memory under scope and audience policy: entries.forget
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, version: integer }.
POST /sergio/memory/entries/list
Read or manage Sergio memory under scope and audience policy: entries.list
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Output: { items: array
POST /sergio/memory/entries/pin
Read or manage Sergio memory under scope and audience policy: entries.pin
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, memoryId: string, kind: “decision” / “fact” / “preference” / “open_item”, text: string, pinned: boolean, forgotten: boolean, shared: boolean, origin: “learned” / “user” / “promoted”, humanEdited: boolean, state: “active” / “stale” / “audience_narrowed” / “source_in_trash” / “closed”, badges: array<“new” / “pinned” / “stale”>, sources: array
POST /sergio/memory/entries/restore
Read or manage Sergio memory under scope and audience policy: entries.restore
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, memoryId: string, kind: “decision” / “fact” / “preference” / “open_item”, text: string, pinned: boolean, forgotten: boolean, shared: boolean, origin: “learned” / “user” / “promoted”, humanEdited: boolean, state: “active” / “stale” / “audience_narrowed” / “source_in_trash” / “closed”, badges: array<“new” / “pinned” / “stale”>, sources: array
POST /sergio/memory/entries/share
Read or manage Sergio memory under scope and audience policy: entries.share
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { text: string, audienceCount: integer, canShare: boolean, reason: “SOURCE_NOT_COMMON” or null, entry?: { id: string, memoryId: string, kind: “decision” / “fact” / “preference” / “open_item”, text: string, pinned: boolean, forgotten: boolean, shared: boolean, origin: “learned” / “user” / “promoted”, humanEdited: boolean, state: “active” / “stale” / “audience_narrowed” / “source_in_trash” / “closed”, badges: array<“new” / “pinned” / “stale”>, sources: array
POST /sergio/memory/entries/unpin
Read or manage Sergio memory under scope and audience policy: entries.unpin
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, memoryId: string, kind: “decision” / “fact” / “preference” / “open_item”, text: string, pinned: boolean, forgotten: boolean, shared: boolean, origin: “learned” / “user” / “promoted”, humanEdited: boolean, state: “active” / “stale” / “audience_narrowed” / “source_in_trash” / “closed”, badges: array<“new” / “pinned” / “stale”>, sources: array
POST /sergio/memory/entries/update
Read or manage Sergio memory under scope and audience policy: entries.update
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, memoryId: string, kind: “decision” / “fact” / “preference” / “open_item”, text: string, pinned: boolean, forgotten: boolean, shared: boolean, origin: “learned” / “user” / “promoted”, humanEdited: boolean, state: “active” / “stale” / “audience_narrowed” / “source_in_trash” / “closed”, badges: array<“new” / “pinned” / “stale”>, sources: array
POST /sergio/memory/explain
Read or manage Sergio memory under scope and audience policy: explain
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Output: { scope: { kind: “project” / “client”, id: string } or { kind: “workspace” }, parts: array
POST /sergio/memory/get
Read or manage Sergio memory under scope and audience policy: get
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Output: { id: string, scope: { kind: “project” / “client”, id: string } or { kind: “workspace” }, audience: “shared” / “member”, summary: string, instructions: string, editable: boolean, paused: boolean, counts: { decision: integer, fact: integer, preference: integer, open_item: integer }, updatedAt: string, updatedBy: string or null, version: integer } or null.
POST /sergio/memory/history/list
Read or manage Sergio memory under scope and audience policy: history.list
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Output: { items: array
POST /sergio/memory/instructions/set
Read or manage Sergio memory under scope and audience policy: instructions.set
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, scope: { kind: “project” / “client”, id: string } or { kind: “workspace” }, audience: “shared” / “member”, summary: string, instructions: string, editable: boolean, paused: boolean, counts: { decision: integer, fact: integer, preference: integer, open_item: integer }, updatedAt: string, updatedBy: string or null, version: integer }.
POST /sergio/memory/pause
Read or manage Sergio memory under scope and audience policy: pause
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, scope: { kind: “project” / “client”, id: string } or { kind: “workspace” }, audience: “shared” / “member”, summary: string, instructions: string, editable: boolean, paused: boolean, counts: { decision: integer, fact: integer, preference: integer, open_item: integer }, updatedAt: string, updatedBy: string or null, version: integer }.
POST /sergio/memory/reevaluate
Read or manage Sergio memory under scope and audience policy: reevaluate
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, version: integer, examined: integer, restored: integer, nextCursor: string or null }.
POST /sergio/memory/reset
Read or manage Sergio memory under scope and audience policy: reset
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, version: integer }.
POST /sergio/memory/resume
Read or manage Sergio memory under scope and audience policy: resume
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, scope: { kind: “project” / “client”, id: string } or { kind: “workspace” }, audience: “shared” / “member”, summary: string, instructions: string, editable: boolean, paused: boolean, counts: { decision: integer, fact: integer, preference: integer, open_item: integer }, updatedAt: string, updatedBy: string or null, version: integer }.
POST /sergio/memory/summary/set
Read or manage Sergio memory under scope and audience policy: summary.set
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, scope: { kind: “project” / “client”, id: string } or { kind: “workspace” }, audience: “shared” / “member”, summary: string, instructions: string, editable: boolean, paused: boolean, counts: { decision: integer, fact: integer, preference: integer, open_item: integer }, updatedAt: string, updatedBy: string or null, version: integer }.
POST /sergio/memory/suppressions/clear
Read or manage Sergio memory under scope and audience policy: suppressions.clear
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| audience | body | “shared” / “member” | no |
| baseVersion | body | integer | no |
| confirmed | body | boolean | no |
| conversationId | body | string | no |
| cursor | body | string | no |
| id | body | string | no |
| instructions | body | string | no |
| kind | body | “decision” / “fact” / “preference” / “open_item” | no |
| limit | body | integer | no |
| scope | body | { kind: “project” / “client”, id: string } | no |
| sources | body | array<{ source: object, sourceVersion: integer }> | no |
| summary | body | string | no |
| summaryEntries | body | array<{ id: string, version: integer }> | no |
| text | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { id: string, scope: { kind: “project” / “client”, id: string } or { kind: “workspace” }, audience: “shared” / “member”, summary: string, instructions: string, editable: boolean, paused: boolean, counts: { decision: integer, fact: integer, preference: integer, open_item: integer }, updatedAt: string, updatedBy: string or null, version: integer }.
POST /sergio/conversations/{id}/messages
Append a user message to your private conversation
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| fileIds | body | array |
no |
| parentMessageId | body | string | no |
| text | body | string | yes |
Output: { id: string, conversationId: string, parentMessageId: string or null, role: “user” / “assistant”, parts: array
POST /sergio/messages/{messageId}/edit
Edit your message: a new version and a fresh answer
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| messageId | path | string | yes |
| text | body | string | yes |
| tier | body | “fast” / “smart” | no |
Output: { runId: string, userMessage: { id: string, conversationId: string, parentMessageId: string or null, role: “user” / “assistant”, parts: array
POST /sergio/messages/{messageId}/retry
Answer again: a new version of a Sergio answer
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| messageId | path | string | yes |
| tier | body | “fast” / “smart” | no |
Output: { runId: string, userMessage: { id: string, conversationId: string, parentMessageId: string or null, role: “user” / “assistant”, parts: array
POST /sergio/conversations/{id}/send
Send a message to Sergio and start streaming the answer
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| fileIds | body | array |
no |
| parentMessageId | body | string | no |
| text | body | string | yes |
| tier | body | “fast” / “smart” | no |
| via | body | “text” / “voice” | no |
Output: { runId: string, userMessage: { id: string, conversationId: string, parentMessageId: string or null, role: “user” / “assistant”, parts: array
POST /sergio/messages/{messageId}/stop
Stop a streaming Sergio answer
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| messageId | path | string | yes |
Output: { runId: string, stopped: boolean }.
POST /sergio/proposals/{proposalId}/decide
Confirm, cancel or undo your Sergio tool proposal using its existing confirmation and undo rules.
Capability: ai.agent.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| proposalId | path | string | yes |
| decision | body | “confirm” / “cancel” / “undo” | yes |
Output: { id: string, actionId: string, state: “pending” / “confirmed” / “cancelled” / “expired” / “undone”, preview: { now: object, after: object }, createdAt: number, expiresAt: number, undoUntil: number or null, canUndo: boolean, undoSupported?: boolean }.
GET /sergio/proposals/{proposalId}
Read your Sergio tool proposal and its current decision state.
Capability: ai.agent.use. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| proposalId | path | string | yes |
Output: { id: string, actionId: string, state: “pending” / “confirmed” / “cancelled” / “expired” / “undone”, preview: { now: object, after: object }, createdAt: number, expiresAt: number, undoUntil: number or null, canUndo: boolean, undoSupported?: boolean }.
srvo
GET /srvo/settings
Read the workspace SRVO default. Unavailable or narrowed dashboards fall back to Overview.
Capability: srvo.settings.read. Kind: read.
No input fields.
Output: { defaultDashboardId: string or null }.
PUT /srvo/settings
Set the workspace SRVO default to a Workspace dashboard or Overview. Human owner/admin only.
Capability: srvo.settings.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| defaultDashboardId | body | string or null | yes |
Output: { defaultDashboardId: string or null }.
structure
POST /dashboards/{dashboardId}/widgets
Add one widget to dashboardId at optional baseVersion. Returns the saved layout; maximum 40 widgets.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| dashboardId | path | string | yes |
| baseVersion | body | integer | no |
| widget | body | { family?: “metric”, id?: string, kind: “kpi” / “progress” / “bar” / “line” / “stacked” / “table” / “donut”, title?: string, tableId: string, metrics: array |
yes |
Output: { dashboardId: string, widgets: array
POST /dashboards
Create a dashboard with title and up to 40 widgets. Optional parentId/spaceId controls inherited access; top level is private. Returns the dashboard.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| parentId | body | string or null | no |
| spaceId | body | string | no |
| title | body | string | yes |
| widgets | body | array<{ family?: “metric”, id?: string, kind: “kpi” / “progress” / “bar” / “line” / “stacked” / “table” / “donut”, title?: string, tableId: string, metrics: array |
no |
Output: { dashboardId: string, widgets: array
POST /dashboards/reports
Create a weekly or monthly report dashboard with up to 40 widgets. Optional range defaults to last full period. Returns dashboard and report metadata; no delivery.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| cadence | body | “weekly” / “monthly” | yes |
| parentId | body | string or null | no |
| range | body | “all” / “thisWeek” / “lastWeek” / “thisMonth” / “lastMonth” / “last7” / “last30” / “last90” / “last365” | no |
| spaceId | body | string | no |
| title | body | string | yes |
| widgets | body | array<{ family?: “metric”, id?: string, kind: “kpi” / “progress” / “bar” / “line” / “stacked” / “table” / “donut”, title?: string, tableId: string, metrics: array |
yes |
Output: { dashboardId: string, widgets: array
POST /dashboards/{dashboardId}/discard
Move a dashboard created by Sergio to the trash while its widgets are unchanged (Undo).
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| dashboardId | path | string | yes |
| baseVersion | body | integer | yes |
Output: { dashboardId: string, trashed: true }.
PATCH /dashboards/{dashboardId}/widgets
Add, update or remove dashboard widgets by dashboardId and optional baseVersion. Returns the saved layout; maximum 40 widgets.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| dashboardId | path | string | yes |
| add | body | array<{ family?: “metric”, id?: string, kind: “kpi” / “progress” / “bar” / “line” / “stacked” / “table” / “donut”, title?: string, tableId: string, metrics: array |
no |
| baseVersion | body | integer | no |
| remove | body | array |
no |
| update | body | array<{ family?: “metric”, id: string, kind: “kpi” / “progress” / “bar” / “line” / “stacked” / “table” / “donut”, title?: string, tableId: string, metrics: array |
no |
Output: { dashboardId: string, widgets: array
GET /dashboards/{dashboardId}
Read a dashboard’s saved widgets (the ones on tables the caller can see) and its version.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| dashboardId | path | string | yes |
Output: { dashboardId: string, widgets: array
PUT /dashboards/{dashboardId}
Replace a dashboard’s widgets (max 40; family metric, module or script). Send the version you read as baseVersion; a newer save returns CONFLICT.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| dashboardId | path | string | yes |
| baseVersion | body | integer | yes |
| widgets | body | array<{ family?: “metric”, id: string, kind: “kpi” / “progress” / “bar” / “line” / “stacked” / “table” / “donut”, title?: string, tableId: string, metrics: array |
yes |
Output: { dashboardId: string, widgets: array
PUT /items/{itemId}/favourite
Add an item to the caller’s favourites (last).
Capability: structure.favourites.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
Output: { itemId: string, favourite: boolean, rank: string or null, changeId: integer }.
DELETE /items/{itemId}/favourite
Remove an item from the caller’s favourites.
Capability: structure.favourites.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
Output: { itemId: string, favourite: boolean, rank: string or null, changeId: integer }.
PUT /views/{viewId}/favourite
Favourite a visible view for this member.
Capability: structure.favourites.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| viewId | path | string | yes |
Output: { viewId: string, favourite: boolean, rank: string or null, changeId: integer }.
DELETE /views/{viewId}/favourite
Remove a personal view favourite.
Capability: structure.favourites.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| viewId | path | string | yes |
Output: { viewId: string, favourite: boolean, rank: string or null, changeId: integer }.
POST /tables/{tableId}/fields/{fid}/convert
Change a field’s type and convert every value. Preview shows how many values convert, need review or are lost; then commit.
Capability: structure.fields.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| fid | path | string | yes |
| Srvo-Confirmation | header | string | no |
| config | body | object | no |
| type | body | “title” / “text” / “long_text” / “number” / “currency” / “select” / “multi_select” / “status” / “checkbox” / “date” / “duration” / “person” / “files” / “url” / “email” / “phone” / “rating” / “progress” / “auto_number” / “created_time” / “updated_time” / “created_by” / “updated_by” / “link” / “subtasks” / “note” / “lookup” / “rollup” / “formula” / “time_tracked” / “estimate” | yes |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { field: { id: string, fid: string, tableId: string, name: string, type: “title” / “text” / “long_text” / “number” / “currency” / “select” / “multi_select” / “status” / “checkbox” / “date” / “duration” / “person” / “files” / “url” / “email” / “phone” / “rating” / “progress” / “auto_number” / “created_time” / “updated_time” / “created_by” / “updated_by” / “link” / “subtasks” / “note” / “lookup” / “rollup” / “formula” / “time_tracked” / “estimate”, config: object, rank: string, required: boolean, description: string or null, system: boolean, systemRole: string or null, version: integer }, counts: { converted: integer, lost: integer, review: integer }, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
POST /tables/{tableId}/fields
Add a field to a table. Config is validated per type; formulas are type-checked.
Capability: structure.fields.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| Idempotency-Key | header | string | no |
| beforeFid | body | string or null | no |
| config | body | object | no |
| description | body | string or null | no |
| fid | body | string | no |
| id | body | string | no |
| name | body | string | yes |
| required | body | boolean | no |
| type | body | “title” / “text” / “long_text” / “number” / “currency” / “select” / “multi_select” / “status” / “checkbox” / “date” / “duration” / “person” / “files” / “url” / “email” / “phone” / “rating” / “progress” / “auto_number” / “created_time” / “updated_time” / “created_by” / “updated_by” / “link” / “subtasks” / “note” / “lookup” / “rollup” / “formula” / “time_tracked” / “estimate” | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { field: { id: string, fid: string, tableId: string, name: string, type: “title” / “text” / “long_text” / “number” / “currency” / “select” / “multi_select” / “status” / “checkbox” / “date” / “duration” / “person” / “files” / “url” / “email” / “phone” / “rating” / “progress” / “auto_number” / “created_time” / “updated_time” / “created_by” / “updated_by” / “link” / “subtasks” / “note” / “lookup” / “rollup” / “formula” / “time_tracked” / “estimate”, config: object, rank: string, required: boolean, description: string or null, system: boolean, systemRole: string or null, version: integer }, changeId: integer }.
POST /tables/{tableId}/fields/{fid}/trash
Move a field to the trash (its values stay in the records). Preview first, then commit.
Capability: structure.fields.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| fid | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { fid: string, trashedAt: string, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
GET /tables/{tableId}/fields
The fields of a table, in order (fields hidden from the caller are left out).
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
Output: { items: array
PATCH /tables/{tableId}/fields/{fid}
Rename a field, edit its description, required flag, order or same-type config.
Capability: structure.fields.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| fid | path | string | yes |
| beforeFid | body | string or null | no |
| config | body | object | no |
| description | body | string or null | no |
| name | body | string | no |
| required | body | boolean | no |
Output: { field: { id: string, fid: string, tableId: string, name: string, type: “title” / “text” / “long_text” / “number” / “currency” / “select” / “multi_select” / “status” / “checkbox” / “date” / “duration” / “person” / “files” / “url” / “email” / “phone” / “rating” / “progress” / “auto_number” / “created_time” / “updated_time” / “created_by” / “updated_by” / “link” / “subtasks” / “note” / “lookup” / “rollup” / “formula” / “time_tracked” / “estimate”, config: object, rank: string, required: boolean, description: string or null, system: boolean, systemRole: string or null, version: integer }, changeId: integer }.
POST /tables/{tableId}/forms
Create a form on a Boards table. Each question maps to one table field. Returns the form, unpublished. Send an idempotencyKey to make retries safe.
Capability: structure.views.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| Idempotency-Key | header | string | yes |
| definition | body | { title: string, description?: string, questions: array |
yes |
| id | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { form: { title: string, description: string, questions: array
GET /forms/{formId}
Get one form’s definition: title, questions and their board fields, and publish state. Forms that use a field hidden from you return NOT_FOUND.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| formId | path | string | yes |
Output: { form: { title: string, description: string, questions: array
GET /tables/{tableId}/forms
List the forms of one Boards table (tableId) that you can read, with their definitions. Not paginated.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| trash | query | boolean | no |
Output: { items: array
POST /forms/{formId}/publish
Publish a form so its public link accepts submissions, which are saved as records under your authority.
Capability: structure.views.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| formId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { form: { title: string, description: string, questions: array
POST /forms/{formId}/restore
Restore a form as an unpublished draft.
Capability: structure.views.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| formId | path | string | yes |
| Idempotency-Key | header | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { form: { title: string, description: string, questions: array
GET /forms/{formId}/submissions
List a form’s submissions as record ids and submit times, in a stable order. Only records you can read are returned, so a page may hold fewer than limit; read each with getRecord. Paginated: pass next as after until it is null.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| formId | path | string | yes |
| after | query | string | no |
| limit | query | integer | no |
Output: { items: array
POST /forms/{formId}/trash
Move a form to trash and disable its public link.
Capability: structure.views.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| formId | path | string | yes |
| Idempotency-Key | header | string | yes |
| Srvo-Confirmation | header | string | no |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { form: { title: string, description: string, questions: array
POST /forms/{formId}/unpublish
Unpublish a form so its public link stops accepting submissions.
Capability: structure.views.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| formId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { form: { title: string, description: string, questions: array
PATCH /forms/{formId}
Replace a form’s definition. Pass the form’s version as baseVersion. A published form is unpublished and must be published again.
Capability: structure.views.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| formId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
| definition | body | { title: string, description?: string, questions: array |
yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { form: { title: string, description: string, questions: array
POST /items
Create a folder, table, page, dashboard or form in a space. Tables get their primary Title field.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| audience | body | “private” / “workspace” | no |
| beforeId | body | string or null | no |
| icon | body | string or null | no |
| id | body | string | no |
| kind | body | “folder” / “table” / “page” / “dashboard” / “form” | yes |
| module | body | “boards” / “notes” / “files” / “srvo” | no |
| parentId | body | string or null | no |
| private | body | boolean | no |
| spaceId | body | string | no |
| title | body | string | yes |
| workspaceRole | body | “viewer” / “commenter” / “editor” / “owner” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { item: { id: string, spaceId?: string, parentId: string or null, kind: “folder” / “table” / “page” / “dashboard” / “form” / “file_folder”, title: string, icon: string or null, rank: string, module: string, visibility: “inherit” / “private”, createdBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, ownerId?: string or null, audience?: “private” / “shared” / “workspace”, myRole?: “viewer” / “commenter” / “editor” / “owner”, canShare?: boolean, parentVisible?: boolean, section?: “private” / “shared” / “workspace” }, primaryField: { id: string, fid: string, tableId: string, name: string, type: “title” / “text” / “long_text” / “number” / “currency” / “select” / “multi_select” / “status” / “checkbox” / “date” / “duration” / “person” / “files” / “url” / “email” / “phone” / “rating” / “progress” / “auto_number” / “created_time” / “updated_time” / “created_by” / “updated_by” / “link” / “subtasks” / “note” / “lookup” / “rollup” / “formula” / “time_tracked” / “estimate”, config: object, rank: string, required: boolean, description: string or null, system: boolean, systemRole: string or null, version: integer } or null, changeId: integer }.
POST /items/{itemId}/move
Move an item (with everything under it) to another parent or space.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
| beforeId | body | string or null | no |
| confirmToken | body | string | no |
| parentId | body | string or null | yes |
| spaceId | body | string | no |
Output: { item: { id: string, spaceId?: string, parentId: string or null, kind: “folder” / “table” / “page” / “dashboard” / “form” / “file_folder”, title: string, icon: string or null, rank: string, module: string, visibility: “inherit” / “private”, createdBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, ownerId?: string or null, audience?: “private” / “shared” / “workspace”, myRole?: “viewer” / “commenter” / “editor” / “owner”, canShare?: boolean, parentVisible?: boolean, section?: “private” / “shared” / “workspace” }, changeId: integer } or { preview: { gains: array
POST /items/{itemId}/reorder
Put an item before a sibling (beforeId) or last (null).
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
| beforeId | body | string or null | yes |
Output: { item: { id: string, spaceId?: string, parentId: string or null, kind: “folder” / “table” / “page” / “dashboard” / “form” / “file_folder”, title: string, icon: string or null, rank: string, module: string, visibility: “inherit” / “private”, createdBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, ownerId?: string or null, audience?: “private” / “shared” / “workspace”, myRole?: “viewer” / “commenter” / “editor” / “owner”, canShare?: boolean, parentVisible?: boolean, section?: “private” / “shared” / “workspace” }, changeId: integer }.
POST /items/{itemId}/restore
Restore a trashed item and its contents. Preview first, then confirm.
Capability: structure.items.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { item: { id: string, spaceId?: string, parentId: string or null, kind: “folder” / “table” / “page” / “dashboard” / “form” / “file_folder”, title: string, icon: string or null, rank: string, module: string, visibility: “inherit” / “private”, createdBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, ownerId?: string or null, audience?: “private” / “shared” / “workspace”, myRole?: “viewer” / “commenter” / “editor” / “owner”, canShare?: boolean, parentVisible?: boolean, section?: “private” / “shared” / “workspace” }, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
GET /items/{itemId}/share
Who can open an item and why: owner, people, teams, clients, workspace, inherited folders.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
Output: { itemId: string, version: integer, owner: { id: string, name: string, active: boolean } or null, audience: “private” / “shared” / “workspace”, workspaceRole: “viewer” / “commenter” / “editor” / “owner” or null, grants: array
POST /items/{itemId}/share
Share an item with people, teams, clients or the whole workspace, or change or remove access.
Capability: structure.items.share. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
| add | body | array<{ subject: object, role: “viewer” / “commenter” / “editor” / “owner” }> | no |
| baseVersion | body | integer | yes |
| confirmToken | body | string | no |
| notify | body | { message?: string } | no |
| remove | body | array |
no |
| update | body | array<{ grantId: string, role: “viewer” / “commenter” / “editor” / “owner” }> | no |
| workspace | body | “viewer” / “commenter” / “editor” / “owner” or null | no |
Output: { share: { itemId: string, version: integer, owner: object or null, audience: “private” / “shared” / “workspace”, workspaceRole: “viewer” / “commenter” / “editor” / “owner” or null, grants: array
POST /items/{itemId}/transfer-ownership
Make another workspace member the owner of an item; the previous owner keeps edit access.
Capability: structure.items.share. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
| baseVersion | body | integer | yes |
| confirmToken | body | string | no |
| toMemberId | body | string | yes |
Output: { share: { itemId: string, version: integer, owner: object or null, audience: “private” / “shared” / “workspace”, workspaceRole: “viewer” / “commenter” / “editor” / “owner” or null, grants: array
POST /items/{itemId}/trash
Move an item and everything under it to the trash (restorable for 30 days). Preview first, then commit.
Capability: structure.items.edit. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { itemId: string, trashedAt: string, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
GET /trash/items
Items in the trash the caller can see (newest first).
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| module | query | “boards” / “notes” / “files” / “srvo” | no |
Output: { items: array
PATCH /items/{itemId}
Rename an item or change its icon.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
| icon | body | string or null | no |
| title | body | string | no |
Output: { item: { id: string, spaceId?: string, parentId: string or null, kind: “folder” / “table” / “page” / “dashboard” / “form” / “file_folder”, title: string, icon: string or null, rank: string, module: string, visibility: “inherit” / “private”, createdBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, ownerId?: string or null, audience?: “private” / “shared” / “workspace”, myRole?: “viewer” / “commenter” / “editor” / “owner”, canShare?: boolean, parentVisible?: boolean, section?: “private” / “shared” / “workspace” }, changeId: integer }.
GET /recents
Visible personal recents, newest first. At most 100 entries retained for 90 days.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| limit | query | integer | no |
Output: { items: array
POST /recents/{itemId}
Remember a visible item for this member, pruning old and excess recents.
Capability: structure.tree.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| itemId | path | string | yes |
Output: { itemId: string, at: string, changeId: integer }.
POST /spaces
Create a space in a team (admins).
Capability: structure.spaces.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| color | body | string | no |
| icon | body | string or null | no |
| id | body | string | no |
| name | body | string | yes |
| teamId | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { space: { id: string, teamId: string, kind: “team” / “personal”, name: string, icon: string or null, color: string or null, visibility: “team” / “private”, rank: string, canEdit: boolean, version: integer }, changeId: integer }.
POST /spaces/{spaceId}/move
Move a space to another team. Preview lists members gaining or losing access.
Capability: structure.spaces.manage. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| spaceId | path | string | yes |
| Srvo-Confirmation | header | string | no |
| teamId | body | string | yes |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { space: { id: string, teamId: string, kind: “team” / “personal”, name: string, icon: string or null, color: string or null, visibility: “team” / “private”, rank: string, canEdit: boolean, version: integer }, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
POST /spaces/{spaceId}/restore
Restore a space within 30 days, keeping prior child trash states.
Capability: structure.spaces.manage. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| spaceId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { space: { id: string, teamId: string, kind: “team” / “personal”, name: string, icon: string or null, color: string or null, visibility: “team” / “private”, rank: string, canEdit: boolean, version: integer }, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
POST /spaces/{spaceId}/trash
Trash a space and its contents for 30 days. Preview first.
Capability: structure.spaces.manage. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| spaceId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { spaceId: string, trashedAt: string, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
GET /trash/spaces
List trashed spaces for space managers.
Capability: structure.spaces.manage. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| module | query | “boards” / “notes” / “files” / “srvo” | no |
Output: { spaces: array
PATCH /spaces/{spaceId}
Rename, re-icon, recolour or reorder a space (admins).
Capability: structure.spaces.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| spaceId | path | string | yes |
| beforeId | body | string or null | no |
| color | body | string or null | no |
| icon | body | string or null | no |
| name | body | string | no |
Output: { space: { id: string, teamId: string, kind: “team” / “personal”, name: string, icon: string or null, color: string or null, visibility: “team” / “private”, rank: string, canEdit: boolean, version: integer }, changeId: integer }.
POST /tables
Create a Boards table with its fields and views in one step (one undo). Start from a template (structure.templates.list) or pass fields and views. Private by default.
Capability: structure.items.edit. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| audience | body | “private” / “workspace” | no |
| fields | body | array<{ fid?: string, name: string, type: “text” / “long_text” / “number” / “currency” / “select” / “multi_select” / “status” / “checkbox” / “date” / “duration” / “person” / “files” / “url” / “email” / “phone” / “rating” / “progress” / “auto_number” / “created_time” / “updated_time” / “created_by” / “updated_by” / “link” / “subtasks” / “note” / “lookup” / “rollup” / “formula” / “time_tracked” / “estimate”, config?: object }> | no |
| icon | body | string or null | no |
| id | body | string | no |
| parentId | body | string or null | no |
| primaryName | body | string | no |
| spaceId | body | string | yes |
| templateId | body | “blank” / “projects” / “finances” / “todos” / “calendar” / “clients” | no |
| title | body | string | yes |
| views | body | array<{ type: “table” / “list” / “kanban” / “calendar” / “timeline” / “report” / “gallery” / “workload” / “mind_map” / “pivot” / “canvas”, name: string, config?: object }> | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { item: { id: string, spaceId?: string, parentId: string or null, kind: “folder” / “table” / “page” / “dashboard” / “form” / “file_folder”, title: string, icon: string or null, rank: string, module: string, visibility: “inherit” / “private”, createdBy: string or null, updatedAt: string, deletedAt: string or null, version: integer, ownerId?: string or null, audience?: “private” / “shared” / “workspace”, myRole?: “viewer” / “commenter” / “editor” / “owner”, canShare?: boolean, parentVisible?: boolean, section?: “private” / “shared” / “workspace” }, fields: array
GET /templates/boards
Board starting points (Blank, Projects, Finances, To-dos, Calendar / Events, Clients) with their fields and first view, for structure.tables.create.
Capability: structure.tree.read. Kind: read.
No input fields.
Output: { items: array
GET /tree
The sidebar tree: spaces, items and the caller’s favourites, as far as the caller can see.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| module | query | “boards” / “notes” / “files” / “srvo” | no |
Output: { structure?: “v2”, spaces: array
POST /tables/{tableId}/views
Save a new view of a table (shared, or personal with personal: true). Also how to copy a locked view.
Capability: structure.views.personal. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
| Idempotency-Key | header | string | no |
| beforeId | body | string or null | no |
| config | body | { filter?: { and: array |
no |
| id | body | string | no |
| locked | body | boolean | no |
| name | body | string | yes |
| personal | body | boolean | no |
| type | body | “table” / “list” / “kanban” / “calendar” / “timeline” / “report” / “gallery” / “workload” / “mind_map” / “pivot” / “canvas” | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { view: { id: string, tableId: string, type: “table” / “list” / “kanban” / “calendar” / “timeline” / “report” / “gallery” / “workload” / “mind_map” / “pivot” / “canvas”, name: string, ownerMemberId: string or null, createdBy: string or null, rank: string, locked: boolean, config: object, selectionStats: array<“count” / “sum” / “avg” / “min” / “max”>, canEdit: boolean, version: integer }, changeId: integer }.
DELETE /views/{viewId}
Delete a view (moves it to the trash; records are not touched).
Capability: structure.views.personal. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| viewId | path | string | yes |
| Srvo-Confirmation | header | string | no |
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { viewId: string, changeId: integer } or { preview: { summary: string, counts: object, warnings: array
GET /tables/{tableId}/views
The saved views of a table: shared ones plus the caller’s personal ones, in order.
Capability: structure.tree.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| tableId | path | string | yes |
Output: { items: array
POST /views/{viewId}/reorder
Put a view before another (beforeId) or last (null). Locked views follow the lock rules.
Capability: structure.views.personal. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| viewId | path | string | yes |
| beforeId | body | string or null | yes |
Output: { view: { id: string, tableId: string, type: “table” / “list” / “kanban” / “calendar” / “timeline” / “report” / “gallery” / “workload” / “mind_map” / “pivot” / “canvas”, name: string, ownerMemberId: string or null, createdBy: string or null, rank: string, locked: boolean, config: object, selectionStats: array<“count” / “sum” / “avg” / “min” / “max”>, canEdit: boolean, version: integer }, changeId: integer }.
PUT /views/{viewId}/selection-stats
Save which statistics the caller sees for a selection in this view (per person; locks don’t apply).
Capability: structure.views.personal. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| viewId | path | string | yes |
| stats | body | array<“count” / “sum” / “avg” / “min” / “max”> | yes |
Output: { view: { id: string, tableId: string, type: “table” / “list” / “kanban” / “calendar” / “timeline” / “report” / “gallery” / “workload” / “mind_map” / “pivot” / “canvas”, name: string, ownerMemberId: string or null, createdBy: string or null, rank: string, locked: boolean, config: object, selectionStats: array<“count” / “sum” / “avg” / “min” / “max”>, canEdit: boolean, version: integer }, changeId: integer }.
PATCH /views/{viewId}
Change a view’s name, config (merged key by key) or lock. Locked views: only admins or their creator with the lock right; others save a copy.
Capability: structure.views.personal. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| viewId | path | string | yes |
| config | body | { filter?: { and: array |
no |
| locked | body | boolean | no |
| name | body | string | no |
Output: { view: { id: string, tableId: string, type: “table” / “list” / “kanban” / “calendar” / “timeline” / “report” / “gallery” / “workload” / “mind_map” / “pivot” / “canvas”, name: string, ownerMemberId: string or null, createdBy: string or null, rank: string, locked: boolean, config: object, selectionStats: array<“count” / “sum” / “avg” / “min” / “max”>, canEdit: boolean, version: integer }, changeId: integer }.
support
POST /support/feedback
Send feedback to SRVO support
Capability: core.self.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| errorId | body | string | no |
| includeTechnicalDetails | body | boolean | no |
| kind | body | “bug” / “idea” / “praise” | yes |
| message | body | string | yes |
| technicalDetails | body | { route?: string, release?: string, device?: { browser?: “chrome” / “safari” / “firefox” / “edge” / “other”, os?: “ios” / “macos” / “windows” / “android” / “linux” / “other”, type?: “phone” / “tablet” / “desktop” / “other” }, errors?: array |
no |
Output: { id: string }.
track
POST /track/entries
Create a completed manual time entry. Overlaps are allowed.
Capability: track.entries.create. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| billable | body | boolean | no |
| clientRecordId | body | string or null | no |
| description | body | string | no |
| endAt | body | string | yes |
| id | body | string | no |
| memberId | body | string | no |
| mentionedMemberIds | body | array |
no |
| note | body | string | no |
| projectRecordId | body | string or null | no |
| recordId | body | string or null | no |
| startAt | body | string | yes |
| tagIds | body | array |
no |
| timeZone | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array
POST /track/entries/trash
Move time entries to trash. Preview and confirm the exact versions.
Capability: track.entries.delete. Kind: destructive.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| Srvo-Confirmation | header | string | no |
| entryIds | body | array |
yes |
| expectedVersions | body | object | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Srvo-Confirmation: Without it the call returns a preview and a token; send the token back to commit.
Output: { entryIds: array
POST /track/entries/export
Export own or permitted member/team time for the input date range with current rates and rounding. Returns filename, contentType and base64 body over MCP, up to 1 MiB; use REST for larger files. No paging.
Capability: track.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| billable | body | “yes” / “no” | no |
| clientId | body | string | no |
| entryIds | body | array |
no |
| format | body | “csv” / “xlsx” | no |
| from | body | string | yes |
| hours | body | “raw” / “rounded” / “both” | no |
| invoiced | body | “yes” / “no” | no |
| locale | body | “en” / “hu” | no |
| memberId | body | string | no |
| notes | body | “yes” / “no” | no |
| projectId | body | string | no |
| rounding | body | “rule” / “off” / “entry” / “report” | no |
| scope | body | “own” / “accessible” | no |
| tagId | body | string | no |
| teamId | body | string | no |
| timeZone | body | string | yes |
| to | body | string | yes |
Output: string.
GET /track/entries/{entryId}
Get a visible time entry.
Capability: track.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| entryId | path | string | yes |
| includeDeleted | query | boolean | no |
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array
GET /track/entries
List own time or explicitly permitted member/team time intersecting a UTC range.
Capability: track.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| scope | query | “own” / “accessible” | no |
| from | query | string | yes |
| to | query | string | yes |
| timeZone | query | string | yes |
| memberId | query | string | no |
| teamId | query | string | no |
| limit | query | integer | no |
| cursor | query | string | no |
Output: { items: array
POST /track/entries/{entryId}/mentions
Invite memberIds to copy your confirmed entryId. Returns invitations; recipients keep independently editable copies. People only.
Capability: track.entries.update. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| entryId | path | string | yes |
| Idempotency-Key | header | string | yes |
| memberIds | body | array |
yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { mentions: array
POST /track/entries/{entryId}/restore
Restore a trashed entry by entryId and baseVersion. Returns the restored entry and changeId. People only.
Capability: track.entries.restore. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| entryId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array
POST /track/entries/summary
Day/week and project/client totals in an explicit time zone. Drafts excluded; overlaps count independently.
Capability: track.entries.read. Kind: read.
| Field | In | Type | Required |
|---|---|---|---|
| from | body | string | yes |
| memberId | body | string | no |
| rounding | body | { mode?: “off” / “up” / “down” / “nearest”, stepS?: integer, apply?: “entry” / “report” } | no |
| scope | body | “own” / “accessible” | no |
| teamId | body | string | no |
| timeZone | body | string | yes |
| to | body | string | yes |
Output: { timeZone: string, asOf: string, totals: { rawS: integer, roundedS: integer, billableS: integer, nonBillableS: integer }, days: array
PATCH /track/entries/{entryId}
Update a time entry at baseVersion. Completed entries cannot become timers.
Capability: track.entries.update. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| entryId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
| mentionedMemberIds | body | array |
no |
| patch | body | { description?: string, recordId?: string or null, projectRecordId?: string or null, clientRecordId?: string or null, tagIds?: array |
yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array
POST /track/mentions/{mentionId}/accept
Accept your invitation once and create your independently editable time entry.
Capability: track.entries.create. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| mentionId | path | string | yes |
Output: { mentions: array
POST /track/mentions/{mentionId}/decline
Decline your Track invitation.
Capability: track.entries.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| mentionId | path | string | yes |
Output: { mentions: array
GET /track/mentions/people
Return all eligible active colleague id/name pairs in this workspace. No paging. People only.
Capability: track.entries.update. Kind: read.
No input fields.
Output: { items: array
GET /track/pickers
Read permitted Boards clients and projects for Track pickers.
Capability: track.entries.read. Kind: read.
No input fields.
Output: { clients: array
GET /track/preferences
Return your saved Track view and calendar range. No inputs or paging. People only.
Capability: track.entries.read. Kind: read.
No input fields.
Output: { view: “calendar” / “list” / “timesheet”, calendarRange: 1 or 5 or 7 or “month” }.
PATCH /track/preferences
Save your Track view and calendar range patch. Returns your saved preferences. People only.
Capability: track.entries.read. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| calendarRange | body | 1 or 5 or 7 or “month” | no |
| view | body | “calendar” / “list” / “timesheet” | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { view: “calendar” / “list” / “timesheet”, calendarRange: 1 or 5 or 7 or “month” }.
GET /track/settings
Read applicable Track settings. Other members’ rates and costs are excluded.
Capability: track.entries.read. Kind: read.
No input fields.
Output: { settings: { rates: array
PUT /track/settings
Save workspace Track settings at baseVersion. Returns settings and changeId. Human owner/admin only; stale versions fail.
Capability: track.settings.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
| settings | body | { rates: array |
yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { settings: { rates: array
POST /track/tags/{tagId}/archive
Set tagId archived state without changing historical entries. Returns tag and changeId. Human owner/admin only.
Capability: track.settings.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| tagId | path | string | yes |
| Idempotency-Key | header | string | yes |
| archived | body | boolean | no |
| baseVersion | body | integer | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { tag: { id: string, name: string, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink”, archived: boolean, version: integer }, changeId: integer }.
POST /track/tags
Create a Track tag from name and palette color. Returns tag and changeId. Human owner/admin only.
Capability: track.settings.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| color | body | “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” | no |
| id | body | string | no |
| name | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { tag: { id: string, name: string, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink”, archived: boolean, version: integer }, changeId: integer }.
GET /track/tags
List the Track tag catalogue, including archived tags for history.
Capability: track.entries.read. Kind: read.
No input fields.
Output: { items: array
PATCH /track/tags/{tagId}
Update tagId name and optional palette color. Returns tag and changeId. Human owner/admin only.
Capability: track.settings.manage. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| tagId | path | string | yes |
| Idempotency-Key | header | string | yes |
| baseVersion | body | integer | yes |
| color | body | “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink” | no |
| name | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { tag: { id: string, name: string, color: “gray” / “red” / “orange” / “amber” / “green” / “teal” / “cyan” / “sky” / “blue” / “indigo” / “purple” / “pink”, archived: boolean, version: integer }, changeId: integer }.
POST /track/timer/continue
Stop your running timer and continue entryId atomically. Returns the current entry and stoppedEntry. People only.
Capability: track.timer.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| entryId | body | string | yes |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array
GET /track/timer
Read your running timer, or null when none is running.
Capability: track.timer.use. Kind: read.
No input fields.
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array
POST /track/timer/start
Start a timer for yourself (agents start it for their person, as a draft).
Capability: track.timer.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | yes |
| billable | body | boolean | no |
| clientRecordId | body | string or null | no |
| description | body | string | no |
| id | body | string | no |
| mentionedMemberIds | body | array |
no |
| note | body | string | no |
| projectRecordId | body | string or null | no |
| recordId | body | string | no |
| startAt | body | string | no |
| tagIds | body | array |
no |
| timeZone | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array
POST /track/timer/stop
Stop your running timer.
Capability: track.timer.use. Kind: write.
| Field | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
| baseVersion | body | integer | no |
| endAt | body | string | no |
| entryId | body | string | no |
Idempotency-Key: Retry-safe key (8–128 chars). Replays return the stored result for 24 h.
Output: { entry: { id: string, memberId: string, sessionId?: string or null, mentions?: array