Saaslivery API

v1.0.0 · 1522 endpoints · 9 websockets
OPTIONS /* undocumented

/*

Handled by <lambda>
Responses
200Successful Response
OPTIONS /*
1curl -X OPTIONS "http://localhost:8000/*"
1fetch("http://localhost:8000/*", { method: "OPTIONS" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.options("http://localhost:8000/*")
4print(response.json())
200 Example Response
No Body
GET /.well-known/microsoft-identity-association.json undocumented

/.well-known/microsoft-identity-association.json

Handled by microsoft_identity
Responses
200Successful Response
GET /.well-known/microsoft-identity-association.json
1curl "http://localhost:8000/.well-known/microsoft-identity-association.json"
1fetch("http://localhost:8000/.well-known/microsoft-identity-association.json")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/.well-known/microsoft-identity-association.json")
4print(response.json())
200 Example Response
No Body
DELETE /totps

Disable 2FA

Handled by disable_totp
Body · DisableTotpapplication/json
password string · min length: 1
required
propertyName anything
Responses
200Successful Response
DELETE /totps
1curl -X DELETE "http://localhost:8000/totps" \
2 -H "Content-Type: application/json" \
3 -d '{"password":"string"}'
1fetch("http://localhost:8000/totps", {
2 method: "DELETE",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "password": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.delete(
4 "http://localhost:8000/totps",
5 json={"password":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /totps

Verify code and enable 2FA

Handled by enable_totp
Body · EnableTotpapplication/json
code string · min length: 6 · max length: 6
required
propertyName anything
Responses
200Successful Response
PUT /totps
1curl -X PUT "http://localhost:8000/totps" \
2 -H "Content-Type: application/json" \
3 -d '{"code":"string"}'
1fetch("http://localhost:8000/totps", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "code": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/totps",
5 json={"code":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /ai/commands

Ask about the current app

POST /ai/commands — answer a question about the app the member is in.

Handled by api_command
Body · AskWorkspaceapplication/json
app string · min length: 1 · max length: 64
required
q string · min length: 1 · max length: 2000
required
propertyName anything
Responses
200Successful Response
POST /ai/commands
1curl -X POST "http://localhost:8000/ai/commands" \
2 -H "Content-Type: application/json" \
3 -d '{"app":"string","q":"string"}'
1fetch("http://localhost:8000/ai/commands", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "app": "string",
6 "q": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/ai/commands",
5 json={"app":"string","q":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /api-keys

Create API key

POST /api-keys: mint a key; the secret appears in this response only. A scoped key may start with an empty grant list: like a fresh role, it holds nothing until permissions are ticked on its detail page.

Handled by api_create_api_key
Body · CreateApiKeyapplication/json
name string · min length: 1 · max length: 100
required
full_access
scopes array
expires_at string · max length: 40
propertyName anything
Responses
200Successful Response
POST /api-keys
1curl -X POST "http://localhost:8000/api-keys" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","full_access":null,"scopes":["string"],"expires_at":"string"}'
1fetch("http://localhost:8000/api-keys", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "full_access": null,
7 "scopes": [
8 "string"
9 ],
10 "expires_at": "string"
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/api-keys",
5 json={"name":"string","full_access":null,"scopes":["string"],"expires_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /api-keys/:key_id

Update or revoke API key

PUT /api-keys/:key_id: rename, re-scope, or revoke a key.

Handled by api_update_api_key
Parameters
key_id string · path
required
Body · UpdateApiKeyapplication/json
name string · min length: 1 · max length: 100
full_access
scopes array
status
propertyName anything
Responses
200Successful Response
PUT /api-keys/example
1curl -X PUT "http://localhost:8000/api-keys/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","full_access":null,"scopes":["string"],"status":null}'
1fetch("http://localhost:8000/api-keys/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "full_access": null,
7 "scopes": [
8 "string"
9 ],
10 "status": null
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/api-keys/example",
5 json={"name":"string","full_access":null,"scopes":["string"],"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /about undocumented

/about

Handled by about
Responses
200Successful Response
GET /about
1curl "http://localhost:8000/about"
1fetch("http://localhost:8000/about")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/about")
4print(response.json())
200 Example Response
No Body
PATCH /me/notification-preferences

Patch notification prefs

Handled by api_patch_notification_prefs
Body · UpdateNotificationPrefsapplication/json
channel
required
patch object
required
propertyName anything
Responses
200Successful Response
PATCH /me/notification-preferences
1curl -X PATCH "http://localhost:8000/me/notification-preferences" \
2 -H "Content-Type: application/json" \
3 -d '{"channel":null,"patch":{"enabled":null,"toast":null,"sound":"string"}}'
1fetch("http://localhost:8000/me/notification-preferences", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "channel": null,
6 "patch": {
7 "enabled": null,
8 "toast": null,
9 "sound": "string"
10 }
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/me/notification-preferences",
5 json={"channel":null,"patch":{"enabled":null,"toast":null,"sound":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/accounts

Create an account

Handled by api_create_account
Body · CreateAccountapplication/json
code string · min length: 1 · max length: 20
required
name string · min length: 1 · max length: 200
required
type
required
parent_id string
description string · max length: 1000
normal_balance
is_contra
is_bank
propertyName anything
Responses
200Successful Response
POST /finance/accounts
1curl -X POST "http://localhost:8000/finance/accounts" \
2 -H "Content-Type: application/json" \
3 -d '{"code":"string","name":"string","type":null,"parent_id":"string","description":"string","normal_balance":null,"is_contra":null,"is_bank":null}'
1fetch("http://localhost:8000/finance/accounts", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "code": "string",
6 "name": "string",
7 "type": null,
8 "parent_id": "string",
9 "description": "string",
10 "normal_balance": null,
11 "is_contra": null,
12 "is_bank": null
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/accounts",
5 json={"code":"string","name":"string","type":null,"parent_id":"string","description":"string","normal_balance":null,"is_contra":null,"is_bank":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/accounts/:account_id

Update an account

Handled by api_update_account
Parameters
account_id string · path
required
Body · UpdateAccountapplication/json
display_name string · max length: 200
show_in_unified
propertyName anything
Responses
200Successful Response
PUT /finance/accounts/example
1curl -X PUT "http://localhost:8000/finance/accounts/example" \
2 -H "Content-Type: application/json" \
3 -d '{"display_name":"string","show_in_unified":null}'
1fetch("http://localhost:8000/finance/accounts/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "display_name": "string",
6 "show_in_unified": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/accounts/example",
5 json={"display_name":"string","show_in_unified":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /activity undocumented

/activity

Handled by api_list_activity
Responses
200Successful Response
GET /activity
1curl "http://localhost:8000/activity"
1fetch("http://localhost:8000/activity")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/activity")
4print(response.json())
200 Example Response
No Body
GET /admin/file-members/:member_mrn/folders undocumented

/admin/file-members/:member_mrn/folders

Handled by api_admin_list_member_folders
Parameters
member_mrn string · path
required
Responses
200Successful Response
GET /admin/file-members/example/folders
1curl "http://localhost:8000/admin/file-members/example/folders"
1fetch("http://localhost:8000/admin/file-members/example/folders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/admin/file-members/example/folders")
4print(response.json())
200 Example Response
No Body
GET /admin/file-members/:member_mrn/files undocumented

/admin/file-members/:member_mrn/files

Handled by api_admin_list_member_files
Parameters
member_mrn string · path
required
Responses
200Successful Response
GET /admin/file-members/example/files
1curl "http://localhost:8000/admin/file-members/example/files"
1fetch("http://localhost:8000/admin/file-members/example/files")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/admin/file-members/example/files")
4print(response.json())
200 Example Response
No Body
GET /admin/file-stats undocumented

/admin/file-stats

GET /admin/file-stats — workspace storage overview for the admin view.

Handled by api_admin_file_stats
Responses
200Successful Response
GET /admin/file-stats
1curl "http://localhost:8000/admin/file-stats"
1fetch("http://localhost:8000/admin/file-stats")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/admin/file-stats")
4print(response.json())
200 Example Response
No Body
GET /admin/activity-exports undocumented

/admin/activity-exports

GET /admin/activity-exports — the audit trail as a CSV download. Optional ``after`` / ``before`` ISO instants bound the window.

Handled by api_admin_activity_export
Responses
200Successful Response
GET /admin/activity-exports
1curl "http://localhost:8000/admin/activity-exports"
1fetch("http://localhost:8000/admin/activity-exports")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/admin/activity-exports")
4print(response.json())
200 Example Response
No Body
POST /admin/file-transfers

Transfer file ownership

POST /admin/file-transfers — move every file and folder one member owns to another member (offboarding). Root-level name collisions in the recipient's space are suffixed, never merged or replaced.

Handled by api_admin_transfer_files
Body · TransferFilesapplication/json
from_mrn string · min length: 1
required
to_mrn string · min length: 1
required
propertyName anything
Responses
200Successful Response
POST /admin/file-transfers
1curl -X POST "http://localhost:8000/admin/file-transfers" \
2 -H "Content-Type: application/json" \
3 -d '{"from_mrn":"string","to_mrn":"string"}'
1fetch("http://localhost:8000/admin/file-transfers", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "from_mrn": "string",
6 "to_mrn": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/admin/file-transfers",
5 json={"from_mrn":"string","to_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /elevations

Break glass into admin mode

POST /elevations — break glass. Re-authentication is the point of the exercise: a stolen session should not be able to elevate itself just because the person it was stolen from happens to be an admin. TOTP when the account has it (a second factor beats a password an attacker may already have), password otherwise, and a recovery code as the way back in for someone who lost their phone. Deliberately never a mailed code: admin actions must not depend on reaching a mailbox, least of all one we host.

Handled by api_start_elevation
Body · StartElevationapplication/json
reason string · min length: 3 · max length: 500
required
code string · min length: 6 · max length: 6
totp string · min length: 6 · max length: 10
propertyName anything
Responses
200Successful Response
POST /elevations
1curl -X POST "http://localhost:8000/elevations" \
2 -H "Content-Type: application/json" \
3 -d '{"reason":"string","code":"string","totp":"string"}'
1fetch("http://localhost:8000/elevations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "reason": "string",
6 "code": "string",
7 "totp": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/elevations",
5 json={"reason":"string","code":"string","totp":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /admin-audit undocumented

/admin-audit

GET /admin-audit — what admins did while elevated. The workspace-facing trail. Reads are coalesced by core.elevation.record, so a row can represent many identical views; `hits` says how many.

Handled by api_list_admin_audit
Responses
200Successful Response
GET /admin-audit
1curl "http://localhost:8000/admin-audit"
1fetch("http://localhost:8000/admin-audit")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/admin-audit")
4print(response.json())
200 Example Response
No Body
DELETE /api-keys/:key_id undocumented

/api-keys/:key_id

DELETE /api-keys/:key_id: remove the key and its audit row.

Handled by api_delete_api_key
Parameters
key_id string · path
required
Responses
200Successful Response
DELETE /api-keys/example
1curl -X DELETE "http://localhost:8000/api-keys/example"
1fetch("http://localhost:8000/api-keys/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/api-keys/example")
4print(response.json())
200 Example Response
No Body
GET /api-keys undocumented

/api-keys

GET /api-keys: list the workspace's API keys (never the secrets).

Handled by api_list_api_keys
Responses
200Successful Response
GET /api-keys
1curl "http://localhost:8000/api-keys"
1fetch("http://localhost:8000/api-keys")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/api-keys")
4print(response.json())
200 Example Response
No Body
PUT /api-keys/:key_id/secret undocumented

/api-keys/:key_id/secret

PUT /api-keys/:key_id/secret: replace the secret; old one dies now.

Handled by api_rotate_api_key
Parameters
key_id string · path
required
Responses
200Successful Response
PUT /api-keys/example/secret
1curl -X PUT "http://localhost:8000/api-keys/example/secret"
1fetch("http://localhost:8000/api-keys/example/secret", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/api-keys/example/secret")
4print(response.json())
200 Example Response
No Body
GET /app/:slug undocumented

/app/:slug

Handled by app_detail
Parameters
slug string · path
required
Responses
200Successful Response
GET /app/example
1curl "http://localhost:8000/app/example"
1fetch("http://localhost:8000/app/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/example")
4print(response.json())
200 Example Response
No Body
GET /app/mail/ undocumented

/app/mail/

Main mail screen. Renders the not-configured landing until the workspace has a domain or a connected account; otherwise the three-pane client.

Handled by index
Responses
200Successful Response
GET /app/mail/
1curl "http://localhost:8000/app/mail/"
1fetch("http://localhost:8000/app/mail/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/mail/")
4print(response.json())
200 Example Response
No Body
GET /app/mail/settings undocumented

/app/mail/settings

Admin: email hosting — add a domain, view DNS to publish, provision mailboxes, manage group mailboxes + the wildcard catch-all. Renders the same SPA on its settings view (deep-link target).

Handled by settings
Responses
200Successful Response
GET /app/mail/settings
1curl "http://localhost:8000/app/mail/settings"
1fetch("http://localhost:8000/app/mail/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/mail/settings")
4print(response.json())
200 Example Response
No Body
GET /app/calls/ undocumented

/app/calls/

Handled by index
Responses
200Successful Response
GET /app/calls/
1curl "http://localhost:8000/app/calls/"
1fetch("http://localhost:8000/app/calls/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/calls/")
4print(response.json())
200 Example Response
No Body
GET /app/calls/recordings undocumented

/app/calls/recordings

Handled by recordings_page
Responses
200Successful Response
GET /app/calls/recordings
1curl "http://localhost:8000/app/calls/recordings"
1fetch("http://localhost:8000/app/calls/recordings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/calls/recordings")
4print(response.json())
200 Example Response
No Body
GET /app/calls/join/:slug undocumented

/app/calls/join/:slug

Handled by join_page
Parameters
slug string · path
required
Responses
200Successful Response
GET /app/calls/join/example
1curl "http://localhost:8000/app/calls/join/example"
1fetch("http://localhost:8000/app/calls/join/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/calls/join/example")
4print(response.json())
200 Example Response
No Body
GET /app/calls/partials/forms/schedule-call undocumented

/app/calls/partials/forms/schedule-call

Form partial — loaded by HTMX into #form-panel.

Handled by schedule_call_form
Responses
200Successful Response
GET /app/calls/partials/forms/schedule-call
1curl "http://localhost:8000/app/calls/partials/forms/schedule-call"
1fetch("http://localhost:8000/app/calls/partials/forms/schedule-call")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/calls/partials/forms/schedule-call")
4print(response.json())
200 Example Response
No Body
GET /app/calls/partials/call/:call_id undocumented

/app/calls/partials/call/:call_id

Call detail card (core/details) for the history sidepane.

Handled by call_detail_partial
Parameters
call_id string · path
required
Responses
200Successful Response
GET /app/calls/partials/call/example
1curl "http://localhost:8000/app/calls/partials/call/example"
1fetch("http://localhost:8000/app/calls/partials/call/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/calls/partials/call/example")
4print(response.json())
200 Example Response
No Body
GET /app/canvas/ undocumented

/app/canvas/

GET /app/canvas/ — dashboard: templates row + recent boards + New board.

Handled by index
Responses
200Successful Response
GET /app/canvas/
1curl "http://localhost:8000/app/canvas/"
1fetch("http://localhost:8000/app/canvas/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/canvas/")
4print(response.json())
200 Example Response
No Body
GET /app/canvas/board/:board_id undocumented

/app/canvas/board/:board_id

GET /app/canvas/board/:board_id — the canvas editor.

Handled by board
Parameters
board_id string · path
required
Responses
200Successful Response
GET /app/canvas/board/example
1curl "http://localhost:8000/app/canvas/board/example"
1fetch("http://localhost:8000/app/canvas/board/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/canvas/board/example")
4print(response.json())
200 Example Response
No Body
GET /app/canvas/partials/boards undocumented

/app/canvas/partials/boards

GET /app/canvas/partials/boards — board grid (HTMX refresh after create/delete).

Handled by board_grid_partial
Responses
200Successful Response
GET /app/canvas/partials/boards
1curl "http://localhost:8000/app/canvas/partials/boards"
1fetch("http://localhost:8000/app/canvas/partials/boards")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/canvas/partials/boards")
4print(response.json())
200 Example Response
No Body
GET /app/canvas/assets/:asset_id undocumented

/app/canvas/assets/:asset_id

GET /app/canvas/assets/:asset_id — redirect to a fresh presigned R2 URL. Same-origin (wildcard subdomain) so <img> loads carry the session cookie.

Handled by api_get_asset
Parameters
asset_id string · path
required
Responses
200Successful Response
GET /app/canvas/assets/example
1curl "http://localhost:8000/app/canvas/assets/example"
1fetch("http://localhost:8000/app/canvas/assets/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/canvas/assets/example")
4print(response.json())
200 Example Response
No Body
GET /app/chat/ undocumented

/app/chat/

Main chat view — chat list sidebar plus message area.

Handled by index
Responses
200Successful Response
GET /app/chat/
1curl "http://localhost:8000/app/chat/"
1fetch("http://localhost:8000/app/chat/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/chat/")
4print(response.json())
200 Example Response
No Body
GET /app/chat/chats/:chat_id undocumented

/app/chat/chats/:chat_id

Deep link to a specific conversation.

Handled by chat_page
Parameters
chat_id string · path
required
Responses
200Successful Response
GET /app/chat/chats/example
1curl "http://localhost:8000/app/chat/chats/example"
1fetch("http://localhost:8000/app/chat/chats/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/chat/chats/example")
4print(response.json())
200 Example Response
No Body
GET /app/chat/partials/chats undocumented

/app/chat/partials/chats

Refreshed chat sidebar.

Handled by chat_list_partial
Responses
200Successful Response
GET /app/chat/partials/chats
1curl "http://localhost:8000/app/chat/partials/chats"
1fetch("http://localhost:8000/app/chat/partials/chats")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/chat/partials/chats")
4print(response.json())
200 Example Response
No Body
GET /app/chat/partials/chats/:chat_id/messages undocumented

/app/chat/partials/chats/:chat_id/messages

Older messages for a conversation, for the load-more control.

Handled by message_list_partial
Parameters
chat_id string · path
required
Responses
200Successful Response
GET /app/chat/partials/chats/example/messages
1curl "http://localhost:8000/app/chat/partials/chats/example/messages"
1fetch("http://localhost:8000/app/chat/partials/chats/example/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/chat/partials/chats/example/messages")
4print(response.json())
200 Example Response
No Body
GET /app/chat/partials/chats/:chat_id/header undocumented

/app/chat/partials/chats/:chat_id/header

Chat title and participants bar.

Handled by chat_header_partial
Parameters
chat_id string · path
required
Responses
200Successful Response
GET /app/chat/partials/chats/example/header
1curl "http://localhost:8000/app/chat/partials/chats/example/header"
1fetch("http://localhost:8000/app/chat/partials/chats/example/header")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/chat/partials/chats/example/header")
4print(response.json())
200 Example Response
No Body
GET /app/chat/partials/chats/:chat_id/info undocumented

/app/chat/partials/chats/:chat_id/info

Details slide-out. Serves both group info and DM contact info. One template branches on chat.type. It used to render the group panel for both, so opening "Contact info" on a DM showed a group avatar, the literal word "None" as the title (DMs have no name), a member count, and a "Leave Group" button that the API rejects for DMs.

Handled by chat_info_partial
Parameters
chat_id string · path
required
Responses
200Successful Response
GET /app/chat/partials/chats/example/info
1curl "http://localhost:8000/app/chat/partials/chats/example/info"
1fetch("http://localhost:8000/app/chat/partials/chats/example/info")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/chat/partials/chats/example/info")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/ undocumented

/app/contacts/

Dashboard — a MicroDash board. The page is a shell; every figure comes from GET /contacts/dashboard so the board can refresh without a reload.

Handled by index
Responses
200Successful Response
GET /app/contacts/
1curl "http://localhost:8000/app/contacts/"
1fetch("http://localhost:8000/app/contacts/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/contacts undocumented

/app/contacts/contacts

Contact directory with filters.

Handled by contacts_page
Responses
200Successful Response
GET /app/contacts/contacts
1curl "http://localhost:8000/app/contacts/contacts"
1fetch("http://localhost:8000/app/contacts/contacts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/contacts")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/contacts/:contact_id undocumented

/app/contacts/contacts/:contact_id

Contact detail — company info, interactions timeline, segment membership.

Handled by contact_page
Parameters
contact_id string · path
required
Responses
200Successful Response
GET /app/contacts/contacts/example
1curl "http://localhost:8000/app/contacts/contacts/example"
1fetch("http://localhost:8000/app/contacts/contacts/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/contacts/example")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/companies undocumented

/app/contacts/companies

Company directory with filters.

Handled by companies_page
Responses
200Successful Response
GET /app/contacts/companies
1curl "http://localhost:8000/app/contacts/companies"
1fetch("http://localhost:8000/app/contacts/companies")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/companies")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/companies/:company_id undocumented

/app/contacts/companies/:company_id

Company detail — all contacts, all interactions.

Handled by company_page
Parameters
company_id string · path
required
Responses
200Successful Response
GET /app/contacts/companies/example
1curl "http://localhost:8000/app/contacts/companies/example"
1fetch("http://localhost:8000/app/contacts/companies/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/companies/example")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/segments undocumented

/app/contacts/segments

Segment list.

Handled by segments_page
Responses
200Successful Response
GET /app/contacts/segments
1curl "http://localhost:8000/app/contacts/segments"
1fetch("http://localhost:8000/app/contacts/segments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/segments")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/segments/:segment_id undocumented

/app/contacts/segments/:segment_id

Segment detail — resolved members.

Handled by segment_page
Parameters
segment_id string · path
required
Responses
200Successful Response
GET /app/contacts/segments/example
1curl "http://localhost:8000/app/contacts/segments/example"
1fetch("http://localhost:8000/app/contacts/segments/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/segments/example")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/inbox undocumented

/app/contacts/inbox

The outsider inbox — conversations by status, with the thread alongside.

Handled by inbox_page
Responses
200Successful Response
GET /app/contacts/inbox
1curl "http://localhost:8000/app/contacts/inbox"
1fetch("http://localhost:8000/app/contacts/inbox")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/inbox")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/settings undocumented

/app/contacts/settings

Widget settings — the embed snippet, key rotation, origins, appearance. A shell only: the page loads its values from GET /contacts/settings so the greeting and origins never have to survive a trip through an x-data attribute.

Handled by settings_page
Responses
200Successful Response
GET /app/contacts/settings
1curl "http://localhost:8000/app/contacts/settings"
1fetch("http://localhost:8000/app/contacts/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/settings")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/conversations undocumented

/app/contacts/partials/conversations

HTMX: the inbox list, filtered by status, assignee and priority.

Handled by conversation_list_partial
Responses
200Successful Response
GET /app/contacts/partials/conversations
1curl "http://localhost:8000/app/contacts/partials/conversations"
1fetch("http://localhost:8000/app/contacts/partials/conversations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/conversations")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/conversations/:conversation_id undocumented

/app/contacts/partials/conversations/:conversation_id

HTMX: one thread with its reply box. Staff see everything, internal notes included: this partial is behind contacts.conversations.view and never reaches a visitor.

Handled by conversation_thread_partial
Parameters
conversation_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/conversations/example
1curl "http://localhost:8000/app/contacts/partials/conversations/example"
1fetch("http://localhost:8000/app/contacts/partials/conversations/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/conversations/example")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/contacts/:contact_id/conversations undocumented

/app/contacts/partials/contacts/:contact_id/conversations

HTMX: the conversations section on a contact page.

Handled by contact_conversations_partial
Parameters
contact_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/contacts/example/conversations
1curl "http://localhost:8000/app/contacts/partials/contacts/example/conversations"
1fetch("http://localhost:8000/app/contacts/partials/contacts/example/conversations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/contacts/example/conversations")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/import undocumented

/app/contacts/partials/import

HTMX: the CSV import drawer. A generic drawer rather than the form system: the fields depend on the pasted file's header, so there is no static Form class to declare.

Handled by import_drawer_partial
Responses
200Successful Response
GET /app/contacts/partials/import
1curl "http://localhost:8000/app/contacts/partials/import"
1fetch("http://localhost:8000/app/contacts/partials/import")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/import")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/contacts/:contact_id/merge undocumented

/app/contacts/partials/contacts/:contact_id/merge

HTMX: pick a duplicate to fold into this contact.

Handled by merge_drawer_partial
Parameters
contact_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/contacts/example/merge
1curl "http://localhost:8000/app/contacts/partials/contacts/example/merge"
1fetch("http://localhost:8000/app/contacts/partials/contacts/example/merge")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/contacts/example/merge")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/contact-list undocumented

/app/contacts/partials/contact-list

HTMX: contact table with filters.

Handled by contact_list_partial
Responses
200Successful Response
GET /app/contacts/partials/contact-list
1curl "http://localhost:8000/app/contacts/partials/contact-list"
1fetch("http://localhost:8000/app/contacts/partials/contact-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/contact-list")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/contacts/:contact_id/detail undocumented

/app/contacts/partials/contacts/:contact_id/detail

HTMX: contact detail panel.

Handled by contact_detail_partial
Parameters
contact_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/contacts/example/detail
1curl "http://localhost:8000/app/contacts/partials/contacts/example/detail"
1fetch("http://localhost:8000/app/contacts/partials/contacts/example/detail")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/contacts/example/detail")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/company-list undocumented

/app/contacts/partials/company-list

HTMX: company table with filters.

Handled by company_list_partial
Responses
200Successful Response
GET /app/contacts/partials/company-list
1curl "http://localhost:8000/app/contacts/partials/company-list"
1fetch("http://localhost:8000/app/contacts/partials/company-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/company-list")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/companies/:company_id/detail undocumented

/app/contacts/partials/companies/:company_id/detail

HTMX: company detail panel with contacts.

Handled by company_detail_partial
Parameters
company_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/companies/example/detail
1curl "http://localhost:8000/app/contacts/partials/companies/example/detail"
1fetch("http://localhost:8000/app/contacts/partials/companies/example/detail")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/companies/example/detail")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/interactions undocumented

/app/contacts/partials/interactions

HTMX: interaction timeline for a contact or company.

Handled by interaction_list_partial
Responses
200Successful Response
GET /app/contacts/partials/interactions
1curl "http://localhost:8000/app/contacts/partials/interactions"
1fetch("http://localhost:8000/app/contacts/partials/interactions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/interactions")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/segment-list undocumented

/app/contacts/partials/segment-list

HTMX: segment cards.

Handled by segment_list_partial
Responses
200Successful Response
GET /app/contacts/partials/segment-list
1curl "http://localhost:8000/app/contacts/partials/segment-list"
1fetch("http://localhost:8000/app/contacts/partials/segment-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/segment-list")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/segments/:segment_id/members undocumented

/app/contacts/partials/segments/:segment_id/members

HTMX: resolved segment members.

Handled by segment_members_partial
Parameters
segment_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/segments/example/members
1curl "http://localhost:8000/app/contacts/partials/segments/example/members"
1fetch("http://localhost:8000/app/contacts/partials/segments/example/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/segments/example/members")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/forms/new-contact undocumented

/app/contacts/partials/forms/new-contact

HTMX: contact form with company auto-suggest.

Handled by new_contact_form
Responses
200Successful Response
GET /app/contacts/partials/forms/new-contact
1curl "http://localhost:8000/app/contacts/partials/forms/new-contact"
1fetch("http://localhost:8000/app/contacts/partials/forms/new-contact")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/forms/new-contact")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/forms/new-company undocumented

/app/contacts/partials/forms/new-company

HTMX: company form.

Handled by new_company_form
Responses
200Successful Response
GET /app/contacts/partials/forms/new-company
1curl "http://localhost:8000/app/contacts/partials/forms/new-company"
1fetch("http://localhost:8000/app/contacts/partials/forms/new-company")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/forms/new-company")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/forms/new-interaction undocumented

/app/contacts/partials/forms/new-interaction

HTMX: log interaction form.

Handled by new_interaction_form
Responses
200Successful Response
GET /app/contacts/partials/forms/new-interaction
1curl "http://localhost:8000/app/contacts/partials/forms/new-interaction"
1fetch("http://localhost:8000/app/contacts/partials/forms/new-interaction")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/forms/new-interaction")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/forms/new-segment undocumented

/app/contacts/partials/forms/new-segment

HTMX: segment form.

Handled by new_segment_form
Responses
200Successful Response
GET /app/contacts/partials/forms/new-segment
1curl "http://localhost:8000/app/contacts/partials/forms/new-segment"
1fetch("http://localhost:8000/app/contacts/partials/forms/new-segment")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/forms/new-segment")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/forms/contacts/:contact_id/edit undocumented

/app/contacts/partials/forms/contacts/:contact_id/edit

HTMX: edit-contact form, prefilled with the contact's current values.

Handled by edit_contact_form
Parameters
contact_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/forms/contacts/example/edit
1curl "http://localhost:8000/app/contacts/partials/forms/contacts/example/edit"
1fetch("http://localhost:8000/app/contacts/partials/forms/contacts/example/edit")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/forms/contacts/example/edit")
4print(response.json())
200 Example Response
No Body
GET /app/contacts/partials/forms/companies/:company_id/edit undocumented

/app/contacts/partials/forms/companies/:company_id/edit

HTMX: edit-company form, prefilled with the company's current values.

Handled by edit_company_form
Parameters
company_id string · path
required
Responses
200Successful Response
GET /app/contacts/partials/forms/companies/example/edit
1curl "http://localhost:8000/app/contacts/partials/forms/companies/example/edit"
1fetch("http://localhost:8000/app/contacts/partials/forms/companies/example/edit")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/contacts/partials/forms/companies/example/edit")
4print(response.json())
200 Example Response
No Body
GET /app/crm/ undocumented

/app/crm/

The CRM home: a MicroDash widget board, role-branched manager/rep. Layout, widget choice, and every number are client-side; the server only stamps what the board needs to know before it can fetch (role, the default pipeline for the funnel widget, and the currency rollups are shown in).

Handled by index
Responses
200Successful Response
GET /app/crm/
1curl "http://localhost:8000/app/crm/"
1fetch("http://localhost:8000/app/crm/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/")
4print(response.json())
200 Example Response
No Body
GET /app/crm/pipelines undocumented

/app/crm/pipelines

The pipelines card grid. Was the app landing page before the board.

Handled by pipelines_page
Responses
200Successful Response
GET /app/crm/pipelines
1curl "http://localhost:8000/app/crm/pipelines"
1fetch("http://localhost:8000/app/crm/pipelines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/pipelines")
4print(response.json())
200 Example Response
No Body
GET /app/crm/deals undocumented

/app/crm/deals

Global deal list: every deal in the workspace, no pipeline required. Pipelines and members are fetched client-side rather than stamped here: a name carrying an apostrophe would break the inline filter config.

Handled by deals_page
Responses
200Successful Response
GET /app/crm/deals
1curl "http://localhost:8000/app/crm/deals"
1fetch("http://localhost:8000/app/crm/deals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/deals")
4print(response.json())
200 Example Response
No Body
GET /app/crm/leads undocumented

/app/crm/leads

Leads: contacts in the lead lifecycle, ranked by score, from the projection.

Handled by leads_page
Responses
200Successful Response
GET /app/crm/leads
1curl "http://localhost:8000/app/crm/leads"
1fetch("http://localhost:8000/app/crm/leads")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/leads")
4print(response.json())
200 Example Response
No Body
GET /app/crm/targets undocumented

/app/crm/targets

Workspace-level targets and the rep leaderboard. The old targets view lived inside one pipeline, which hid every workspace-wide quota and left the leaderboard endpoint with no UI at all.

Handled by targets_page
Responses
200Successful Response
GET /app/crm/targets
1curl "http://localhost:8000/app/crm/targets"
1fetch("http://localhost:8000/app/crm/targets")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/targets")
4print(response.json())
200 Example Response
No Body
GET /app/crm/scoring undocumented

/app/crm/scoring

Lead and deal scoring rules. Wires the previously orphaned rule form.

Handled by scoring_page
Responses
200Successful Response
GET /app/crm/scoring
1curl "http://localhost:8000/app/crm/scoring"
1fetch("http://localhost:8000/app/crm/scoring")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/scoring")
4print(response.json())
200 Example Response
No Body
GET /app/crm/pipeline/:pipeline_id undocumented

/app/crm/pipeline/:pipeline_id

Handled by pipeline_detail
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /app/crm/pipeline/example
1curl "http://localhost:8000/app/crm/pipeline/example"
1fetch("http://localhost:8000/app/crm/pipeline/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/pipeline/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/kanban/:pipeline_id undocumented

/app/crm/partials/kanban/:pipeline_id

Handled by kanban_partial
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/kanban/example
1curl "http://localhost:8000/app/crm/partials/kanban/example"
1fetch("http://localhost:8000/app/crm/partials/kanban/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/kanban/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/deal/:deal_id undocumented

/app/crm/partials/deal/:deal_id

Handled by deal_detail_partial
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/deal/example
1curl "http://localhost:8000/app/crm/partials/deal/example"
1fetch("http://localhost:8000/app/crm/partials/deal/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/deal/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/targets/:pipeline_id undocumented

/app/crm/partials/targets/:pipeline_id

Handled by targets_partial
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/targets/example
1curl "http://localhost:8000/app/crm/partials/targets/example"
1fetch("http://localhost:8000/app/crm/partials/targets/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/targets/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/reports/:pipeline_id undocumented

/app/crm/partials/reports/:pipeline_id

Handled by reports_partial
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/reports/example
1curl "http://localhost:8000/app/crm/partials/reports/example"
1fetch("http://localhost:8000/app/crm/partials/reports/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/reports/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/stages/:pipeline_id undocumented

/app/crm/partials/stages/:pipeline_id

Stage editor: the pipeline's stages, ordered, with their templates.

Handled by stages_partial
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/stages/example
1curl "http://localhost:8000/app/crm/partials/stages/example"
1fetch("http://localhost:8000/app/crm/partials/stages/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/stages/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/new-pipeline undocumented

/app/crm/partials/forms/new-pipeline

Handled by new_pipeline_form
Responses
200Successful Response
GET /app/crm/partials/forms/new-pipeline
1curl "http://localhost:8000/app/crm/partials/forms/new-pipeline"
1fetch("http://localhost:8000/app/crm/partials/forms/new-pipeline")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/new-pipeline")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/edit-pipeline/:pipeline_id undocumented

/app/crm/partials/forms/edit-pipeline/:pipeline_id

Handled by edit_pipeline_form
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/forms/edit-pipeline/example
1curl "http://localhost:8000/app/crm/partials/forms/edit-pipeline/example"
1fetch("http://localhost:8000/app/crm/partials/forms/edit-pipeline/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/edit-pipeline/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/new-stage/:pipeline_id undocumented

/app/crm/partials/forms/new-stage/:pipeline_id

Handled by new_stage_form
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/forms/new-stage/example
1curl "http://localhost:8000/app/crm/partials/forms/new-stage/example"
1fetch("http://localhost:8000/app/crm/partials/forms/new-stage/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/new-stage/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/new-deal undocumented

/app/crm/partials/forms/new-deal

Handled by new_deal_form
Responses
200Successful Response
GET /app/crm/partials/forms/new-deal
1curl "http://localhost:8000/app/crm/partials/forms/new-deal"
1fetch("http://localhost:8000/app/crm/partials/forms/new-deal")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/new-deal")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/edit-deal/:deal_id undocumented

/app/crm/partials/forms/edit-deal/:deal_id

Handled by edit_deal_form
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/forms/edit-deal/example
1curl "http://localhost:8000/app/crm/partials/forms/edit-deal/example"
1fetch("http://localhost:8000/app/crm/partials/forms/edit-deal/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/edit-deal/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/deal-proposal/:deal_id undocumented

/app/crm/partials/forms/deal-proposal/:deal_id

Handled by deal_proposal_form
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/forms/deal-proposal/example
1curl "http://localhost:8000/app/crm/partials/forms/deal-proposal/example"
1fetch("http://localhost:8000/app/crm/partials/forms/deal-proposal/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/deal-proposal/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/new-target undocumented

/app/crm/partials/forms/new-target

Handled by new_target_form
Responses
200Successful Response
GET /app/crm/partials/forms/new-target
1curl "http://localhost:8000/app/crm/partials/forms/new-target"
1fetch("http://localhost:8000/app/crm/partials/forms/new-target")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/new-target")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/edit-target/:target_id undocumented

/app/crm/partials/forms/edit-target/:target_id

Handled by edit_target_form
Parameters
target_id string · path
required
Responses
200Successful Response
GET /app/crm/partials/forms/edit-target/example
1curl "http://localhost:8000/app/crm/partials/forms/edit-target/example"
1fetch("http://localhost:8000/app/crm/partials/forms/edit-target/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/edit-target/example")
4print(response.json())
200 Example Response
No Body
GET /app/crm/partials/forms/new-scoring-rule undocumented

/app/crm/partials/forms/new-scoring-rule

Handled by new_scoring_rule_form
Responses
200Successful Response
GET /app/crm/partials/forms/new-scoring-rule
1curl "http://localhost:8000/app/crm/partials/forms/new-scoring-rule"
1fetch("http://localhost:8000/app/crm/partials/forms/new-scoring-rule")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/crm/partials/forms/new-scoring-rule")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/ undocumented

/app/feeds/

Main feeds page — 3-column Twitter-like layout.

Handled by index
Responses
200Successful Response
GET /app/feeds/
1curl "http://localhost:8000/app/feeds/"
1fetch("http://localhost:8000/app/feeds/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/post/:post_id undocumented

/app/feeds/post/:post_id

Single post view with all replies — works for any depth of nesting.

Handled by post_page
Parameters
post_id string · path
required
Responses
200Successful Response
GET /app/feeds/post/example
1curl "http://localhost:8000/app/feeds/post/example"
1fetch("http://localhost:8000/app/feeds/post/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/post/example")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/explore undocumented

/app/feeds/explore

Explore page — trending posts and search.

Handled by explore_page
Responses
200Successful Response
GET /app/feeds/explore
1curl "http://localhost:8000/app/feeds/explore"
1fetch("http://localhost:8000/app/feeds/explore")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/explore")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/notifications undocumented

/app/feeds/notifications

Notifications page — reactions, replies, and follows on your content.

Handled by notifications_page
Responses
200Successful Response
GET /app/feeds/notifications
1curl "http://localhost:8000/app/feeds/notifications"
1fetch("http://localhost:8000/app/feeds/notifications")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/notifications")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/bookmarks undocumented

/app/feeds/bookmarks

Bookmarks page — saved posts.

Handled by bookmarks_page
Responses
200Successful Response
GET /app/feeds/bookmarks
1curl "http://localhost:8000/app/feeds/bookmarks"
1fetch("http://localhost:8000/app/feeds/bookmarks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/bookmarks")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/profile/:member_mrn undocumented

/app/feeds/profile/:member_mrn

Profile page — user's posts, follower/following counts.

Handled by profile_page
Parameters
member_mrn string · path
required
Responses
200Successful Response
GET /app/feeds/profile/example
1curl "http://localhost:8000/app/feeds/profile/example"
1fetch("http://localhost:8000/app/feeds/profile/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/profile/example")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/feed undocumented

/app/feeds/partials/feed

Load feed posts — used for infinite scroll / refresh.

Handled by feed_partial
Responses
200Successful Response
GET /app/feeds/partials/feed
1curl "http://localhost:8000/app/feeds/partials/feed"
1fetch("http://localhost:8000/app/feeds/partials/feed")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/feed")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/post/:post_id undocumented

/app/feeds/partials/post/:post_id

Single post card partial.

Handled by post_detail_partial
Parameters
post_id string · path
required
Responses
200Successful Response
GET /app/feeds/partials/post/example
1curl "http://localhost:8000/app/feeds/partials/post/example"
1fetch("http://localhost:8000/app/feeds/partials/post/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/post/example")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/compose undocumented

/app/feeds/partials/compose

Compose form partial.

Handled by compose_partial
Responses
200Successful Response
GET /app/feeds/partials/compose
1curl "http://localhost:8000/app/feeds/partials/compose"
1fetch("http://localhost:8000/app/feeds/partials/compose")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/compose")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/replies/:post_id undocumented

/app/feeds/partials/replies/:post_id

Load replies for a post.

Handled by replies_partial
Parameters
post_id string · path
required
Responses
200Successful Response
GET /app/feeds/partials/replies/example
1curl "http://localhost:8000/app/feeds/partials/replies/example"
1fetch("http://localhost:8000/app/feeds/partials/replies/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/replies/example")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/trending undocumented

/app/feeds/partials/trending

Trending posts sidebar partial.

Handled by trending_partial
Responses
200Successful Response
GET /app/feeds/partials/trending
1curl "http://localhost:8000/app/feeds/partials/trending"
1fetch("http://localhost:8000/app/feeds/partials/trending")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/trending")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/who-to-follow undocumented

/app/feeds/partials/who-to-follow

Who to follow sidebar partial.

Handled by who_to_follow_partial
Responses
200Successful Response
GET /app/feeds/partials/who-to-follow
1curl "http://localhost:8000/app/feeds/partials/who-to-follow"
1fetch("http://localhost:8000/app/feeds/partials/who-to-follow")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/who-to-follow")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/profile/:member_mrn undocumented

/app/feeds/partials/profile/:member_mrn

Profile sidebar card for a member.

Handled by profile_partial
Parameters
member_mrn string · path
required
Responses
200Successful Response
GET /app/feeds/partials/profile/example
1curl "http://localhost:8000/app/feeds/partials/profile/example"
1fetch("http://localhost:8000/app/feeds/partials/profile/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/profile/example")
4print(response.json())
200 Example Response
No Body
GET /app/feeds/partials/share/:post_id undocumented

/app/feeds/partials/share/:post_id

Share drawer partial — loaded via HTMX into #share-panel.

Handled by share_drawer_partial
Parameters
post_id string · path
required
Responses
200Successful Response
GET /app/feeds/partials/share/example
1curl "http://localhost:8000/app/feeds/partials/share/example"
1fetch("http://localhost:8000/app/feeds/partials/share/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/feeds/partials/share/example")
4print(response.json())
200 Example Response
No Body
GET /app/files/ undocumented

/app/files/

The Files landing page: a MicroDash board over /file-statistics. Nothing is queried here. The board fetches its own data so the widgets can show skeletons while it lands, and so a refresh after an upload is one API call rather than a page render.

Handled by dashboard_page
Responses
200Successful Response
GET /app/files/
1curl "http://localhost:8000/app/files/"
1fetch("http://localhost:8000/app/files/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/")
4print(response.json())
200 Example Response
No Body
GET /app/files/browse undocumented

/app/files/browse

File manager — personal root with sidebar.

Handled by browse_page
Responses
200Successful Response
GET /app/files/browse
1curl "http://localhost:8000/app/files/browse"
1fetch("http://localhost:8000/app/files/browse")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/browse")
4print(response.json())
200 Example Response
No Body
GET /app/files/folders/:folder_id undocumented

/app/files/folders/:folder_id

Deep link into a specific folder.

Handled by folder_page
Parameters
folder_id string · path
required
Responses
200Successful Response
GET /app/files/folders/example
1curl "http://localhost:8000/app/files/folders/example"
1fetch("http://localhost:8000/app/files/folders/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/folders/example")
4print(response.json())
200 Example Response
No Body
GET /app/files/recents undocumented

/app/files/recents

Recently uploaded/updated files + recently viewed files (two tabs).

Handled by recents_page
Responses
200Successful Response
GET /app/files/recents
1curl "http://localhost:8000/app/files/recents"
1fetch("http://localhost:8000/app/files/recents")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/recents")
4print(response.json())
200 Example Response
No Body
GET /app/files/shared undocumented

/app/files/shared

Sharing, in three tabs: with me, by me, and public links. Only the requested tab is queried. The other two are a click away and loading all three would triple the work for a view of one.

Handled by shared_page
Responses
200Successful Response
GET /app/files/shared
1curl "http://localhost:8000/app/files/shared"
1fetch("http://localhost:8000/app/files/shared")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/shared")
4print(response.json())
200 Example Response
No Body
GET /app/files/trash undocumented

/app/files/trash

Trash view.

Handled by trash_page
Responses
200Successful Response
GET /app/files/trash
1curl "http://localhost:8000/app/files/trash"
1fetch("http://localhost:8000/app/files/trash")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/trash")
4print(response.json())
200 Example Response
No Body
GET /app/files/activity undocumented

/app/files/activity

Activity log.

Handled by activity_page
Responses
200Successful Response
GET /app/files/activity
1curl "http://localhost:8000/app/files/activity"
1fetch("http://localhost:8000/app/files/activity")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/activity")
4print(response.json())
200 Example Response
No Body
GET /app/files/admin/members undocumented

/app/files/admin/members

Admin: browse all members' file trees.

Handled by admin_members_page
Responses
200Successful Response
GET /app/files/admin/members
1curl "http://localhost:8000/app/files/admin/members"
1fetch("http://localhost:8000/app/files/admin/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/admin/members")
4print(response.json())
200 Example Response
No Body
GET /app/files/s/:token undocumented

/app/files/s/:token

Old in-app share path — the link format before shares went public.

Handled by legacy_share_redirect
Parameters
token string · path
required
Responses
200Successful Response
GET /app/files/s/example
1curl "http://localhost:8000/app/files/s/example"
1fetch("http://localhost:8000/app/files/s/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/s/example")
4print(response.json())
200 Example Response
No Body
GET /app/files/partials/folders/:folder_id/contents undocumented

/app/files/partials/folders/:folder_id/contents

Handled by folder_contents_partial
Parameters
folder_id string · path
required
Responses
200Successful Response
GET /app/files/partials/folders/example/contents
1curl "http://localhost:8000/app/files/partials/folders/example/contents"
1fetch("http://localhost:8000/app/files/partials/folders/example/contents")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/partials/folders/example/contents")
4print(response.json())
200 Example Response
No Body
GET /app/files/partials/folders/:folder_id/breadcrumb undocumented

/app/files/partials/folders/:folder_id/breadcrumb

Handled by breadcrumb_partial
Parameters
folder_id string · path
required
Responses
200Successful Response
GET /app/files/partials/folders/example/breadcrumb
1curl "http://localhost:8000/app/files/partials/folders/example/breadcrumb"
1fetch("http://localhost:8000/app/files/partials/folders/example/breadcrumb")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/partials/folders/example/breadcrumb")
4print(response.json())
200 Example Response
No Body
GET /app/files/partials/sidebar undocumented

/app/files/partials/sidebar

Handled by sidebar_partial
Responses
200Successful Response
GET /app/files/partials/sidebar
1curl "http://localhost:8000/app/files/partials/sidebar"
1fetch("http://localhost:8000/app/files/partials/sidebar")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/partials/sidebar")
4print(response.json())
200 Example Response
No Body
GET /app/files/partials/items/:item_id/detail undocumented

/app/files/partials/items/:item_id/detail

Handled by file_detail_partial
Parameters
item_id string · path
required
Responses
200Successful Response
GET /app/files/partials/items/example/detail
1curl "http://localhost:8000/app/files/partials/items/example/detail"
1fetch("http://localhost:8000/app/files/partials/items/example/detail")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/partials/items/example/detail")
4print(response.json())
200 Example Response
No Body
GET /app/files/partials/shares/dialog undocumented

/app/files/partials/shares/dialog

Handled by share_dialog_partial
Responses
200Successful Response
GET /app/files/partials/shares/dialog
1curl "http://localhost:8000/app/files/partials/shares/dialog"
1fetch("http://localhost:8000/app/files/partials/shares/dialog")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/partials/shares/dialog")
4print(response.json())
200 Example Response
No Body
GET /app/files/partials/forms/new-folder undocumented

/app/files/partials/forms/new-folder

Handled by new_folder_form
Responses
200Successful Response
GET /app/files/partials/forms/new-folder
1curl "http://localhost:8000/app/files/partials/forms/new-folder"
1fetch("http://localhost:8000/app/files/partials/forms/new-folder")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/files/partials/forms/new-folder")
4print(response.json())
200 Example Response
No Body
GET /app/finance/ undocumented

/app/finance/

Handled by portal_page
Responses
200Successful Response
GET /app/finance/
1curl "http://localhost:8000/app/finance/"
1fetch("http://localhost:8000/app/finance/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/")
4print(response.json())
200 Example Response
No Body
GET /app/finance/console undocumented

/app/finance/console

Handled by index
Responses
200Successful Response
GET /app/finance/console
1curl "http://localhost:8000/app/finance/console"
1fetch("http://localhost:8000/app/finance/console")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/console")
4print(response.json())
200 Example Response
No Body
GET /app/finance/console/requests undocumented

/app/finance/console/requests

Employee Requests — the approvals queue inside the console. Gated in AUTHZ on finance.requests.manage.

Handled by console_requests_index
Responses
200Successful Response
GET /app/finance/console/requests
1curl "http://localhost:8000/app/finance/console/requests"
1fetch("http://localhost:8000/app/finance/console/requests")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/console/requests")
4print(response.json())
200 Example Response
No Body
GET /app/finance/requests undocumented

/app/finance/requests

My Requests — the portal-side page. Every portal member sees ONLY their own requests here (withdraw, message the reviewers) without ever entering the console. Reviewers handle the queue at /app/finance/console/requests.

Handled by requests_index
Responses
200Successful Response
GET /app/finance/requests
1curl "http://localhost:8000/app/finance/requests"
1fetch("http://localhost:8000/app/finance/requests")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/requests")
4print(response.json())
200 Example Response
No Body
GET /app/finance/quotes undocumented

/app/finance/quotes

Handled by quotes_index
Responses
200Successful Response
GET /app/finance/quotes
1curl "http://localhost:8000/app/finance/quotes"
1fetch("http://localhost:8000/app/finance/quotes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/quotes")
4print(response.json())
200 Example Response
No Body
GET /app/finance/quotes/:entry_id undocumented

/app/finance/quotes/:entry_id

Handled by quote_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/quotes/example
1curl "http://localhost:8000/app/finance/quotes/example"
1fetch("http://localhost:8000/app/finance/quotes/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/quotes/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/purchase-orders undocumented

/app/finance/purchase-orders

Handled by purchase_orders_index
Responses
200Successful Response
GET /app/finance/purchase-orders
1curl "http://localhost:8000/app/finance/purchase-orders"
1fetch("http://localhost:8000/app/finance/purchase-orders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/purchase-orders")
4print(response.json())
200 Example Response
No Body
GET /app/finance/purchase-orders/:entry_id undocumented

/app/finance/purchase-orders/:entry_id

Handled by purchase_order_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/purchase-orders/example
1curl "http://localhost:8000/app/finance/purchase-orders/example"
1fetch("http://localhost:8000/app/finance/purchase-orders/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/purchase-orders/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/orders undocumented

/app/finance/orders

Handled by orders_index
Responses
200Successful Response
GET /app/finance/orders
1curl "http://localhost:8000/app/finance/orders"
1fetch("http://localhost:8000/app/finance/orders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/orders")
4print(response.json())
200 Example Response
No Body
GET /app/finance/orders/:entry_id undocumented

/app/finance/orders/:entry_id

Handled by order_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/orders/example
1curl "http://localhost:8000/app/finance/orders/example"
1fetch("http://localhost:8000/app/finance/orders/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/orders/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/invoices undocumented

/app/finance/invoices

Handled by invoices_index
Responses
200Successful Response
GET /app/finance/invoices
1curl "http://localhost:8000/app/finance/invoices"
1fetch("http://localhost:8000/app/finance/invoices")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/invoices")
4print(response.json())
200 Example Response
No Body
GET /app/finance/invoices/:entry_id undocumented

/app/finance/invoices/:entry_id

Handled by invoice_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/invoices/example
1curl "http://localhost:8000/app/finance/invoices/example"
1fetch("http://localhost:8000/app/finance/invoices/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/invoices/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/bills undocumented

/app/finance/bills

Handled by bills_index
Responses
200Successful Response
GET /app/finance/bills
1curl "http://localhost:8000/app/finance/bills"
1fetch("http://localhost:8000/app/finance/bills")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/bills")
4print(response.json())
200 Example Response
No Body
GET /app/finance/bills/:entry_id undocumented

/app/finance/bills/:entry_id

Handled by bill_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/bills/example
1curl "http://localhost:8000/app/finance/bills/example"
1fetch("http://localhost:8000/app/finance/bills/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/bills/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/credit-notes undocumented

/app/finance/credit-notes

Handled by credit_notes_index
Responses
200Successful Response
GET /app/finance/credit-notes
1curl "http://localhost:8000/app/finance/credit-notes"
1fetch("http://localhost:8000/app/finance/credit-notes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/credit-notes")
4print(response.json())
200 Example Response
No Body
GET /app/finance/credit-notes/:entry_id undocumented

/app/finance/credit-notes/:entry_id

Handled by credit_note_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/credit-notes/example
1curl "http://localhost:8000/app/finance/credit-notes/example"
1fetch("http://localhost:8000/app/finance/credit-notes/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/credit-notes/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/purchase-credit-notes undocumented

/app/finance/purchase-credit-notes

Handled by purchase_credit_notes_index
Responses
200Successful Response
GET /app/finance/purchase-credit-notes
1curl "http://localhost:8000/app/finance/purchase-credit-notes"
1fetch("http://localhost:8000/app/finance/purchase-credit-notes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/purchase-credit-notes")
4print(response.json())
200 Example Response
No Body
GET /app/finance/purchase-credit-notes/:entry_id undocumented

/app/finance/purchase-credit-notes/:entry_id

Handled by purchase_credit_note_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/purchase-credit-notes/example
1curl "http://localhost:8000/app/finance/purchase-credit-notes/example"
1fetch("http://localhost:8000/app/finance/purchase-credit-notes/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/purchase-credit-notes/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/journal undocumented

/app/finance/journal

Handled by journal_index
Responses
200Successful Response
GET /app/finance/journal
1curl "http://localhost:8000/app/finance/journal"
1fetch("http://localhost:8000/app/finance/journal")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/journal")
4print(response.json())
200 Example Response
No Body
GET /app/finance/journal/:entry_id undocumented

/app/finance/journal/:entry_id

Handled by journal_detail
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/journal/example
1curl "http://localhost:8000/app/finance/journal/example"
1fetch("http://localhost:8000/app/finance/journal/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/journal/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/payments undocumented

/app/finance/payments

The payments list. Rows are not fetched here: like every other finance list, the grid loads them from GET /finance/payments, which owns the filtering, sorting, searching and paging.

Handled by payments_index
Responses
200Successful Response
GET /app/finance/payments
1curl "http://localhost:8000/app/finance/payments"
1fetch("http://localhost:8000/app/finance/payments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/payments")
4print(response.json())
200 Example Response
No Body
GET /app/finance/accounts undocumented

/app/finance/accounts

Handled by accounts_index
Responses
200Successful Response
GET /app/finance/accounts
1curl "http://localhost:8000/app/finance/accounts"
1fetch("http://localhost:8000/app/finance/accounts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/accounts")
4print(response.json())
200 Example Response
No Body
GET /app/finance/accounts/:account_id undocumented

/app/finance/accounts/:account_id

Handled by account_detail
Parameters
account_id string · path
required
Responses
200Successful Response
GET /app/finance/accounts/example
1curl "http://localhost:8000/app/finance/accounts/example"
1fetch("http://localhost:8000/app/finance/accounts/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/accounts/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/reports undocumented

/app/finance/reports

Handled by reports_index
Responses
200Successful Response
GET /app/finance/reports
1curl "http://localhost:8000/app/finance/reports"
1fetch("http://localhost:8000/app/finance/reports")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/reports")
4print(response.json())
200 Example Response
No Body
GET /app/finance/reconciliation undocumented

/app/finance/reconciliation

Handled by reconciliation_index
Responses
200Successful Response
GET /app/finance/reconciliation
1curl "http://localhost:8000/app/finance/reconciliation"
1fetch("http://localhost:8000/app/finance/reconciliation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/reconciliation")
4print(response.json())
200 Example Response
No Body
GET /app/finance/settings undocumented

/app/finance/settings

Handled by settings_index
Responses
200Successful Response
GET /app/finance/settings
1curl "http://localhost:8000/app/finance/settings"
1fetch("http://localhost:8000/app/finance/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/settings")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/branding-preview undocumented

/app/finance/partials/branding-preview

The Branding tab's preview: the real document, sample contents. Rendered server-side through the same build_document the PDF and the portal use, so the tab cannot show something the customer will never receive.

Handled by branding_preview_partial
Responses
200Successful Response
GET /app/finance/partials/branding-preview
1curl "http://localhost:8000/app/finance/partials/branding-preview"
1fetch("http://localhost:8000/app/finance/partials/branding-preview")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/branding-preview")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-quote undocumented

/app/finance/partials/forms/new-quote

Handled by new_quote_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-quote
1curl "http://localhost:8000/app/finance/partials/forms/new-quote"
1fetch("http://localhost:8000/app/finance/partials/forms/new-quote")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-quote")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/edit-quote/:entry_id undocumented

/app/finance/partials/forms/edit-quote/:entry_id

Handled by edit_quote_form
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/partials/forms/edit-quote/example
1curl "http://localhost:8000/app/finance/partials/forms/edit-quote/example"
1fetch("http://localhost:8000/app/finance/partials/forms/edit-quote/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/edit-quote/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/revise-quote/:entry_id undocumented

/app/finance/partials/forms/revise-quote/:entry_id

Handled by revise_quote_form
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/partials/forms/revise-quote/example
1curl "http://localhost:8000/app/finance/partials/forms/revise-quote/example"
1fetch("http://localhost:8000/app/finance/partials/forms/revise-quote/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/revise-quote/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-purchase-order undocumented

/app/finance/partials/forms/new-purchase-order

Handled by new_purchase_order_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-purchase-order
1curl "http://localhost:8000/app/finance/partials/forms/new-purchase-order"
1fetch("http://localhost:8000/app/finance/partials/forms/new-purchase-order")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-purchase-order")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-order undocumented

/app/finance/partials/forms/new-order

Handled by new_order_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-order
1curl "http://localhost:8000/app/finance/partials/forms/new-order"
1fetch("http://localhost:8000/app/finance/partials/forms/new-order")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-order")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-invoice undocumented

/app/finance/partials/forms/new-invoice

Handled by new_invoice_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-invoice
1curl "http://localhost:8000/app/finance/partials/forms/new-invoice"
1fetch("http://localhost:8000/app/finance/partials/forms/new-invoice")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-invoice")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-bill undocumented

/app/finance/partials/forms/new-bill

Handled by new_bill_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-bill
1curl "http://localhost:8000/app/finance/partials/forms/new-bill"
1fetch("http://localhost:8000/app/finance/partials/forms/new-bill")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-bill")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-credit-note undocumented

/app/finance/partials/forms/new-credit-note

The credit note drawer, from either entry point. With a source_entry_id on the query string the invoice is already decided (the button lives on that invoice's page), so it rides in hidden and the picker is not offered. Without one, the list page opened this, and the invoice has to be chosen.

Handled by new_credit_note_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-credit-note
1curl "http://localhost:8000/app/finance/partials/forms/new-credit-note"
1fetch("http://localhost:8000/app/finance/partials/forms/new-credit-note")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-credit-note")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-purchase-credit-note undocumented

/app/finance/partials/forms/new-purchase-credit-note

The purchase credit note drawer, from either entry point. The mirror of new_credit_note_form: with a source_entry_id on the query string the bill is already decided (the button lives on that bill's page), so it rides in hidden and the picker is not offered.

Handled by new_purchase_credit_note_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-purchase-credit-note
1curl "http://localhost:8000/app/finance/partials/forms/new-purchase-credit-note"
1fetch("http://localhost:8000/app/finance/partials/forms/new-purchase-credit-note")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-purchase-credit-note")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-journal undocumented

/app/finance/partials/forms/new-journal

Handled by new_journal_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-journal
1curl "http://localhost:8000/app/finance/partials/forms/new-journal"
1fetch("http://localhost:8000/app/finance/partials/forms/new-journal")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-journal")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-payment undocumented

/app/finance/partials/forms/new-payment

Handled by new_payment_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-payment
1curl "http://localhost:8000/app/finance/partials/forms/new-payment"
1fetch("http://localhost:8000/app/finance/partials/forms/new-payment")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-payment")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-account undocumented

/app/finance/partials/forms/new-account

Handled by new_account_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-account
1curl "http://localhost:8000/app/finance/partials/forms/new-account"
1fetch("http://localhost:8000/app/finance/partials/forms/new-account")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-account")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-period undocumented

/app/finance/partials/forms/new-period

Handled by new_period_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-period
1curl "http://localhost:8000/app/finance/partials/forms/new-period"
1fetch("http://localhost:8000/app/finance/partials/forms/new-period")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-period")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-dimension undocumented

/app/finance/partials/forms/new-dimension

Handled by new_dimension_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-dimension
1curl "http://localhost:8000/app/finance/partials/forms/new-dimension"
1fetch("http://localhost:8000/app/finance/partials/forms/new-dimension")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-dimension")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-tax-rate undocumented

/app/finance/partials/forms/new-tax-rate

Handled by new_tax_rate_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-tax-rate
1curl "http://localhost:8000/app/finance/partials/forms/new-tax-rate"
1fetch("http://localhost:8000/app/finance/partials/forms/new-tax-rate")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-tax-rate")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-payment-term undocumented

/app/finance/partials/forms/new-payment-term

Handled by new_payment_term_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-payment-term
1curl "http://localhost:8000/app/finance/partials/forms/new-payment-term"
1fetch("http://localhost:8000/app/finance/partials/forms/new-payment-term")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-payment-term")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-bank-rule undocumented

/app/finance/partials/forms/new-bank-rule

Handled by new_bank_rule_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-bank-rule
1curl "http://localhost:8000/app/finance/partials/forms/new-bank-rule"
1fetch("http://localhost:8000/app/finance/partials/forms/new-bank-rule")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-bank-rule")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-budget undocumented

/app/finance/partials/forms/new-budget

Handled by new_budget_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-budget
1curl "http://localhost:8000/app/finance/partials/forms/new-budget"
1fetch("http://localhost:8000/app/finance/partials/forms/new-budget")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-budget")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-recurring undocumented

/app/finance/partials/forms/new-recurring

Handled by new_recurring_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-recurring
1curl "http://localhost:8000/app/finance/partials/forms/new-recurring"
1fetch("http://localhost:8000/app/finance/partials/forms/new-recurring")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-recurring")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-expense-claim undocumented

/app/finance/partials/forms/new-expense-claim

Handled by new_expense_claim_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-expense-claim
1curl "http://localhost:8000/app/finance/partials/forms/new-expense-claim"
1fetch("http://localhost:8000/app/finance/partials/forms/new-expense-claim")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-expense-claim")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-advance undocumented

/app/finance/partials/forms/new-advance

Handled by new_advance_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-advance
1curl "http://localhost:8000/app/finance/partials/forms/new-advance"
1fetch("http://localhost:8000/app/finance/partials/forms/new-advance")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-advance")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/forms/new-purchase-request undocumented

/app/finance/partials/forms/new-purchase-request

Handled by new_purchase_request_form
Responses
200Successful Response
GET /app/finance/partials/forms/new-purchase-request
1curl "http://localhost:8000/app/finance/partials/forms/new-purchase-request"
1fetch("http://localhost:8000/app/finance/partials/forms/new-purchase-request")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/forms/new-purchase-request")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/entry-list undocumented

/app/finance/partials/entry-list

Handled by entry_list_partial
Responses
200Successful Response
GET /app/finance/partials/entry-list
1curl "http://localhost:8000/app/finance/partials/entry-list"
1fetch("http://localhost:8000/app/finance/partials/entry-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/entry-list")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/entry/:entry_id undocumented

/app/finance/partials/entry/:entry_id

Handled by entry_detail_partial
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /app/finance/partials/entry/example
1curl "http://localhost:8000/app/finance/partials/entry/example"
1fetch("http://localhost:8000/app/finance/partials/entry/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/entry/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/payment-list undocumented

/app/finance/partials/payment-list

Handled by payment_list_partial
Responses
200Successful Response
GET /app/finance/partials/payment-list
1curl "http://localhost:8000/app/finance/partials/payment-list"
1fetch("http://localhost:8000/app/finance/partials/payment-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/payment-list")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/settings-tree undocumented

/app/finance/partials/settings-tree

Handled by account_tree_partial
Responses
200Successful Response
GET /app/finance/partials/settings-tree
1curl "http://localhost:8000/app/finance/partials/settings-tree"
1fetch("http://localhost:8000/app/finance/partials/settings-tree")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/settings-tree")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/settings/:account_id/ledger undocumented

/app/finance/partials/settings/:account_id/ledger

Handled by account_ledger_partial
Parameters
account_id string · path
required
Responses
200Successful Response
GET /app/finance/partials/settings/example/ledger
1curl "http://localhost:8000/app/finance/partials/settings/example/ledger"
1fetch("http://localhost:8000/app/finance/partials/settings/example/ledger")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/settings/example/ledger")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/report/:report undocumented

/app/finance/partials/report/:report

Handled by report_partial
Parameters
report string · path
required
Responses
200Successful Response
GET /app/finance/partials/report/example
1curl "http://localhost:8000/app/finance/partials/report/example"
1fetch("http://localhost:8000/app/finance/partials/report/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/report/example")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/bank-imports undocumented

/app/finance/partials/bank-imports

Handled by bank_imports_partial
Responses
200Successful Response
GET /app/finance/partials/bank-imports
1curl "http://localhost:8000/app/finance/partials/bank-imports"
1fetch("http://localhost:8000/app/finance/partials/bank-imports")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/bank-imports")
4print(response.json())
200 Example Response
No Body
GET /app/finance/partials/matching/:import_id undocumented

/app/finance/partials/matching/:import_id

Handled by matching_partial
Parameters
import_id string · path
required
Responses
200Successful Response
GET /app/finance/partials/matching/example
1curl "http://localhost:8000/app/finance/partials/matching/example"
1fetch("http://localhost:8000/app/finance/partials/matching/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/finance/partials/matching/example")
4print(response.json())
200 Example Response
No Body
GET /app/growth/ undocumented

/app/growth/

Handled by index
Responses
200Successful Response
GET /app/growth/
1curl "http://localhost:8000/app/growth/"
1fetch("http://localhost:8000/app/growth/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/")
4print(response.json())
200 Example Response
No Body
GET /app/growth/console undocumented

/app/growth/console

Handled by home_page
Responses
200Successful Response
GET /app/growth/console
1curl "http://localhost:8000/app/growth/console"
1fetch("http://localhost:8000/app/growth/console")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/console")
4print(response.json())
200 Example Response
No Body
GET /app/growth/concerns undocumented

/app/growth/concerns

Staff triage for concerns: both the anonymous voice stream and named complaints. Route-gated to growth.results.view.

Handled by concerns_page
Responses
200Successful Response
GET /app/growth/concerns
1curl "http://localhost:8000/app/growth/concerns"
1fetch("http://localhost:8000/app/growth/concerns")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/concerns")
4print(response.json())
200 Example Response
No Body
GET /app/growth/dashboard/:campaign_id undocumented

/app/growth/dashboard/:campaign_id

Engagement deep-link to a specific campaign (from the Surveys list).

Handled by dashboard_page
Parameters
campaign_id string · path
required
Responses
200Successful Response
GET /app/growth/dashboard/example
1curl "http://localhost:8000/app/growth/dashboard/example"
1fetch("http://localhost:8000/app/growth/dashboard/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/dashboard/example")
4print(response.json())
200 Example Response
No Body
GET /app/growth/respond undocumented

/app/growth/respond

Handled by respond_page
Responses
200Successful Response
GET /app/growth/respond
1curl "http://localhost:8000/app/growth/respond"
1fetch("http://localhost:8000/app/growth/respond")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/respond")
4print(response.json())
200 Example Response
No Body
GET /app/growth/campaigns undocumented

/app/growth/campaigns

Handled by campaigns_page
Responses
200Successful Response
GET /app/growth/campaigns
1curl "http://localhost:8000/app/growth/campaigns"
1fetch("http://localhost:8000/app/growth/campaigns")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/campaigns")
4print(response.json())
200 Example Response
No Body
GET /app/growth/goals undocumented

/app/growth/goals

Handled by goals_page
Responses
200Successful Response
GET /app/growth/goals
1curl "http://localhost:8000/app/growth/goals"
1fetch("http://localhost:8000/app/growth/goals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/goals")
4print(response.json())
200 Example Response
No Body
GET /app/growth/feedback undocumented

/app/growth/feedback

Handled by feedback_page
Responses
200Successful Response
GET /app/growth/feedback
1curl "http://localhost:8000/app/growth/feedback"
1fetch("http://localhost:8000/app/growth/feedback")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/feedback")
4print(response.json())
200 Example Response
No Body
GET /app/growth/one-on-ones undocumented

/app/growth/one-on-ones

Handled by oneonones_page
Responses
200Successful Response
GET /app/growth/one-on-ones
1curl "http://localhost:8000/app/growth/one-on-ones"
1fetch("http://localhost:8000/app/growth/one-on-ones")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/one-on-ones")
4print(response.json())
200 Example Response
No Body
GET /app/growth/one-on-ones/log undocumented

/app/growth/one-on-ones/log

The full-page 1:1 composer. Accepts series_id and subject_mrn so logging from a recurring series lands inside that series (carrying its agenda forward) instead of starting an unattached 1:1.

Handled by log_interaction_page
Responses
200Successful Response
GET /app/growth/one-on-ones/log
1curl "http://localhost:8000/app/growth/one-on-ones/log"
1fetch("http://localhost:8000/app/growth/one-on-ones/log")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/one-on-ones/log")
4print(response.json())
200 Example Response
No Body
GET /app/growth/one-on-ones/interaction/:signal_id undocumented

/app/growth/one-on-ones/interaction/:signal_id

One logged 1:1, reopened. Same surface as the composer: past interactions stay editable so private notes and follow-ups can be added after the conversation.

Handled by interaction_page
Parameters
signal_id string · path
required
Responses
200Successful Response
GET /app/growth/one-on-ones/interaction/example
1curl "http://localhost:8000/app/growth/one-on-ones/interaction/example"
1fetch("http://localhost:8000/app/growth/one-on-ones/interaction/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/one-on-ones/interaction/example")
4print(response.json())
200 Example Response
No Body
GET /app/growth/reviews undocumented

/app/growth/reviews

Handled by reviews_page
Responses
200Successful Response
GET /app/growth/reviews
1curl "http://localhost:8000/app/growth/reviews"
1fetch("http://localhost:8000/app/growth/reviews")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/reviews")
4print(response.json())
200 Example Response
No Body
GET /app/growth/plans undocumented

/app/growth/plans

Handled by plans_page
Responses
200Successful Response
GET /app/growth/plans
1curl "http://localhost:8000/app/growth/plans"
1fetch("http://localhost:8000/app/growth/plans")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/plans")
4print(response.json())
200 Example Response
No Body
GET /app/growth/team undocumented

/app/growth/team

Handled by team_page
Responses
200Successful Response
GET /app/growth/team
1curl "http://localhost:8000/app/growth/team"
1fetch("http://localhost:8000/app/growth/team")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/team")
4print(response.json())
200 Example Response
No Body
GET /app/growth/frameworks undocumented

/app/growth/frameworks

Competencies, values, question bank and role profiles (Grow pillar).

Handled by frameworks_page
Responses
200Successful Response
GET /app/growth/frameworks
1curl "http://localhost:8000/app/growth/frameworks"
1fetch("http://localhost:8000/app/growth/frameworks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/frameworks")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/board/:tab undocumented

/app/growth/partials/board/:tab

One dashboard tab's board, swapped into #growth-tabpanel by HTMX.

Handled by board_partial
Parameters
tab string · path
required
Responses
200Successful Response
GET /app/growth/partials/board/example
1curl "http://localhost:8000/app/growth/partials/board/example"
1fetch("http://localhost:8000/app/growth/partials/board/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/board/example")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-campaign undocumented

/app/growth/partials/forms/new-campaign

The survey builder: pick drivers, add custom questions, eNPS + comment.

Handled by new_campaign_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-campaign
1curl "http://localhost:8000/app/growth/partials/forms/new-campaign"
1fetch("http://localhost:8000/app/growth/partials/forms/new-campaign")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-campaign")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-goal undocumented

/app/growth/partials/forms/new-goal

Create-goal modal form (Align pillar).

Handled by new_goal_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-goal
1curl "http://localhost:8000/app/growth/partials/forms/new-goal"
1fetch("http://localhost:8000/app/growth/partials/forms/new-goal")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-goal")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/log-progress undocumented

/app/growth/partials/forms/log-progress

Log-progress modal form for a specific goal.

Handled by log_progress_form
Responses
200Successful Response
GET /app/growth/partials/forms/log-progress
1curl "http://localhost:8000/app/growth/partials/forms/log-progress"
1fetch("http://localhost:8000/app/growth/partials/forms/log-progress")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/log-progress")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/give-praise undocumented

/app/growth/partials/forms/give-praise

Give-praise modal form (Connect pillar). Values chips come from the workspace framework (falling back to the built-in defaults).

Handled by give_praise_form
Responses
200Successful Response
GET /app/growth/partials/forms/give-praise
1curl "http://localhost:8000/app/growth/partials/forms/give-praise"
1fetch("http://localhost:8000/app/growth/partials/forms/give-praise")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/give-praise")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/give-feedback undocumented

/app/growth/partials/forms/give-feedback

Give-feedback modal form (Connect pillar). Accepts parent_id (the feedback_request being answered) and subject_mrn as query params so a request and its answer are threaded.

Handled by give_feedback_form
Responses
200Successful Response
GET /app/growth/partials/forms/give-feedback
1curl "http://localhost:8000/app/growth/partials/forms/give-feedback"
1fetch("http://localhost:8000/app/growth/partials/forms/give-feedback")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/give-feedback")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-checkin undocumented

/app/growth/partials/forms/new-checkin

New check-in modal form (Connect pillar).

Handled by new_checkin_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-checkin
1curl "http://localhost:8000/app/growth/partials/forms/new-checkin"
1fetch("http://localhost:8000/app/growth/partials/forms/new-checkin")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-checkin")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-cycle undocumented

/app/growth/partials/forms/new-cycle

New review-cycle modal form (Grow pillar).

Handled by new_cycle_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-cycle
1curl "http://localhost:8000/app/growth/partials/forms/new-cycle"
1fetch("http://localhost:8000/app/growth/partials/forms/new-cycle")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-cycle")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/write-review undocumented

/app/growth/partials/forms/write-review

Write-a-review modal form (Grow pillar). The cycle picker is populated per-request from the workspace's open review cycles; one per-competency star rating is appended for each workspace competency (empty = not rated). Accepts campaign_id and subject_mrn query params so a review task opens pre-addressed.

Handled by write_review_form
Responses
200Successful Response
GET /app/growth/partials/forms/write-review
1curl "http://localhost:8000/app/growth/partials/forms/write-review"
1fetch("http://localhost:8000/app/growth/partials/forms/write-review")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/write-review")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-plan undocumented

/app/growth/partials/forms/new-plan

New plan / PIP modal form (Grow pillar).

Handled by new_plan_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-plan
1curl "http://localhost:8000/app/growth/partials/forms/new-plan"
1fetch("http://localhost:8000/app/growth/partials/forms/new-plan")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-plan")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-attribute undocumented

/app/growth/partials/forms/new-attribute

New competency / value / bank question modal form (Grow pillar).

Handled by new_attribute_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-attribute
1curl "http://localhost:8000/app/growth/partials/forms/new-attribute"
1fetch("http://localhost:8000/app/growth/partials/forms/new-attribute")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-attribute")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-role-profile undocumented

/app/growth/partials/forms/new-role-profile

New role profile modal form (Grow pillar).

Handled by new_role_profile_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-role-profile
1curl "http://localhost:8000/app/growth/partials/forms/new-role-profile"
1fetch("http://localhost:8000/app/growth/partials/forms/new-role-profile")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-role-profile")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-series undocumented

/app/growth/partials/forms/new-series

Start-a-recurring-1:1 modal form (Connect pillar).

Handled by new_series_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-series
1curl "http://localhost:8000/app/growth/partials/forms/new-series"
1fetch("http://localhost:8000/app/growth/partials/forms/new-series")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-series")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/edit-series undocumented

/app/growth/partials/forms/edit-series

Edit a recurring 1:1: rhythm, title and next session. Participants are fixed once a series exists (changing who it is with would orphan its history), and the standing agenda is owned by the carry-over, not by hand.

Handled by edit_series_form
Responses
200Successful Response
GET /app/growth/partials/forms/edit-series
1curl "http://localhost:8000/app/growth/partials/forms/edit-series"
1fetch("http://localhost:8000/app/growth/partials/forms/edit-series")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/edit-series")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/nominate-reviewer undocumented

/app/growth/partials/forms/nominate-reviewer

Nominate-a-reviewer modal form (Grow pillar). The cycle picker holds the open review cycles; subject defaults to the nominator server-side.

Handled by nominate_reviewer_form
Responses
200Successful Response
GET /app/growth/partials/forms/nominate-reviewer
1curl "http://localhost:8000/app/growth/partials/forms/nominate-reviewer"
1fetch("http://localhost:8000/app/growth/partials/forms/nominate-reviewer")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/nominate-reviewer")
4print(response.json())
200 Example Response
No Body
GET /app/growth/partials/forms/new-concern undocumented

/app/growth/partials/forms/new-concern

Raise-a-concern modal form (portal). Anonymous by default.

Handled by new_concern_form
Responses
200Successful Response
GET /app/growth/partials/forms/new-concern
1curl "http://localhost:8000/app/growth/partials/forms/new-concern"
1fetch("http://localhost:8000/app/growth/partials/forms/new-concern")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/growth/partials/forms/new-concern")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/ undocumented

/app/leaves/

Dashboard — balances, upcoming PTOs, pending approvals.

Handled by index
Responses
200Successful Response
GET /app/leaves/
1curl "http://localhost:8000/app/leaves/"
1fetch("http://localhost:8000/app/leaves/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/ptos undocumented

/app/leaves/ptos

My PTOs — list with status filter.

Handled by ptos_page
Responses
200Successful Response
GET /app/leaves/ptos
1curl "http://localhost:8000/app/leaves/ptos"
1fetch("http://localhost:8000/app/leaves/ptos")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/ptos")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/approvals undocumented

/app/leaves/approvals

Approvals — requests the current user can act on, split into Current/History. Both tabs list exactly what the viewer is authorized for (manager → direct reports, default approver → their no-manager workers, owner → everyone), using the shared ``can_decide_pto_rule``. Current = pending requests (clicking opens the detail drawer with Approve / Deny); History = settled decisions.

Handled by approvals_page
Responses
200Successful Response
GET /app/leaves/approvals
1curl "http://localhost:8000/app/leaves/approvals"
1fetch("http://localhost:8000/app/leaves/approvals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/approvals")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/policies undocumented

/app/leaves/policies

Leave policies list — scoped by authz (managers all, members their own).

Handled by policies_page
Responses
200Successful Response
GET /app/leaves/policies
1curl "http://localhost:8000/app/leaves/policies"
1fetch("http://localhost:8000/app/leaves/policies")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/policies")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/policies/:id undocumented

/app/leaves/policies/:id

Leave policy detail page — read-only info + members; Edit opens the editor drawer. Renders inside the Policies section (nav stays on Policies) but shows the detail view instead of the list, mirroring the workers app's detail page.

Handled by policy_page
Parameters
id string · path
required
Responses
200Successful Response
GET /app/leaves/policies/example
1curl "http://localhost:8000/app/leaves/policies/example"
1fetch("http://localhost:8000/app/leaves/policies/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/policies/example")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/holidays undocumented

/app/leaves/holidays

Holidays list.

Handled by holidays_page
Responses
200Successful Response
GET /app/leaves/holidays
1curl "http://localhost:8000/app/leaves/holidays"
1fetch("http://localhost:8000/app/leaves/holidays")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/holidays")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/policies/:id undocumented

/app/leaves/partials/policies/:id

Policy detail drawer — loaded into #form-panel.

Handled by policy_detail_partial
Parameters
id string · path
required
Responses
200Successful Response
GET /app/leaves/partials/policies/example
1curl "http://localhost:8000/app/leaves/partials/policies/example"
1fetch("http://localhost:8000/app/leaves/partials/policies/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/policies/example")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/balances undocumented

/app/leaves/partials/balances

Handled by balance_summary_partial
Responses
200Successful Response
GET /app/leaves/partials/balances
1curl "http://localhost:8000/app/leaves/partials/balances"
1fetch("http://localhost:8000/app/leaves/partials/balances")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/balances")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/ptos undocumented

/app/leaves/partials/ptos

Handled by pto_list_partial
Responses
200Successful Response
GET /app/leaves/partials/ptos
1curl "http://localhost:8000/app/leaves/partials/ptos"
1fetch("http://localhost:8000/app/leaves/partials/ptos")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/ptos")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/availability undocumented

/app/leaves/partials/availability

Handled by team_availability_partial
Responses
200Successful Response
GET /app/leaves/partials/availability
1curl "http://localhost:8000/app/leaves/partials/availability"
1fetch("http://localhost:8000/app/leaves/partials/availability")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/availability")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/forms/new-pto undocumented

/app/leaves/partials/forms/new-pto

New PTO request form — rendered as platform form drawer.

Handled by new_pto_form
Responses
200Successful Response
GET /app/leaves/partials/forms/new-pto
1curl "http://localhost:8000/app/leaves/partials/forms/new-pto"
1fetch("http://localhost:8000/app/leaves/partials/forms/new-pto")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/forms/new-pto")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/forms/new-policy undocumented

/app/leaves/partials/forms/new-policy

New leave policy form — rendered as platform form drawer.

Handled by new_policy_form
Responses
200Successful Response
GET /app/leaves/partials/forms/new-policy
1curl "http://localhost:8000/app/leaves/partials/forms/new-policy"
1fetch("http://localhost:8000/app/leaves/partials/forms/new-policy")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/forms/new-policy")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/forms/new-holiday undocumented

/app/leaves/partials/forms/new-holiday

New holiday form — rendered as platform form drawer.

Handled by new_holiday_form
Responses
200Successful Response
GET /app/leaves/partials/forms/new-holiday
1curl "http://localhost:8000/app/leaves/partials/forms/new-holiday"
1fetch("http://localhost:8000/app/leaves/partials/forms/new-holiday")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/forms/new-holiday")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/forms/reconciliation undocumented

/app/leaves/partials/forms/reconciliation

Working-pattern reconciliation drawer — future bookings to recount. Data is fetched client-side from GET /leave-reconciliation (which enforces the balance-adjust capability), so this handler only renders the shell.

Handled by reconciliation_drawer
Responses
200Successful Response
GET /app/leaves/partials/forms/reconciliation
1curl "http://localhost:8000/app/leaves/partials/forms/reconciliation"
1fetch("http://localhost:8000/app/leaves/partials/forms/reconciliation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/forms/reconciliation")
4print(response.json())
200 Example Response
No Body
GET /app/leaves/partials/ptos/:id undocumented

/app/leaves/partials/ptos/:id

Handled by pto_detail_partial
Parameters
id string · path
required
Responses
200Successful Response
GET /app/leaves/partials/ptos/example
1curl "http://localhost:8000/app/leaves/partials/ptos/example"
1fetch("http://localhost:8000/app/leaves/partials/ptos/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/leaves/partials/ptos/example")
4print(response.json())
200 Example Response
No Body
GET /app/papers/ undocumented

/app/papers/

GET /app/papers/ — templates row + recent documents.

Handled by index
Responses
200Successful Response
GET /app/papers/
1curl "http://localhost:8000/app/papers/"
1fetch("http://localhost:8000/app/papers/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/papers/")
4print(response.json())
200 Example Response
No Body
GET /app/papers/doc/:document_id undocumented

/app/papers/doc/:document_id

GET /app/papers/doc/:document_id — document editor page.

Handled by editor
Parameters
document_id string · path
required
Responses
200Successful Response
GET /app/papers/doc/example
1curl "http://localhost:8000/app/papers/doc/example"
1fetch("http://localhost:8000/app/papers/doc/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/papers/doc/example")
4print(response.json())
200 Example Response
No Body
GET /app/papers/partials/documents undocumented

/app/papers/partials/documents

GET /app/papers/partials/documents — recent documents list (HTMX refresh).

Handled by doc_list_partial
Responses
200Successful Response
GET /app/papers/partials/documents
1curl "http://localhost:8000/app/papers/partials/documents"
1fetch("http://localhost:8000/app/papers/partials/documents")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/papers/partials/documents")
4print(response.json())
200 Example Response
No Body
GET /app/papers/partials/trash undocumented

/app/papers/partials/trash

GET /app/papers/partials/trash — the trash list (HTMX swap on the index). Scoped exactly like GET /papers/trash: only documents the caller could actually restore or destroy, which means owner/manage access, not merely being shared into them.

Handled by trash_partial
Responses
200Successful Response
GET /app/papers/partials/trash
1curl "http://localhost:8000/app/papers/partials/trash"
1fetch("http://localhost:8000/app/papers/partials/trash")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/papers/partials/trash")
4print(response.json())
200 Example Response
No Body
GET /app/papers/partials/doc/:document_id/comments undocumented

/app/papers/partials/doc/:document_id/comments

GET /app/papers/partials/doc/:document_id/comments — comments panel.

Handled by comments_partial
Parameters
document_id string · path
required
Responses
200Successful Response
GET /app/papers/partials/doc/example/comments
1curl "http://localhost:8000/app/papers/partials/doc/example/comments"
1fetch("http://localhost:8000/app/papers/partials/doc/example/comments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/papers/partials/doc/example/comments")
4print(response.json())
200 Example Response
No Body
GET /app/papers/partials/doc/:document_id/versions undocumented

/app/papers/partials/doc/:document_id/versions

GET /app/papers/partials/doc/:document_id/versions — version history panel.

Handled by versions_partial
Parameters
document_id string · path
required
Responses
200Successful Response
GET /app/papers/partials/doc/example/versions
1curl "http://localhost:8000/app/papers/partials/doc/example/versions"
1fetch("http://localhost:8000/app/papers/partials/doc/example/versions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/papers/partials/doc/example/versions")
4print(response.json())
200 Example Response
No Body
GET /app/settings/ undocumented

/app/settings/

Account tab default view. The Lobby is the workspace home now; Account is a normal tab opened from a Lobby button, so its entry point lands on the member's own profile settings.

Handled by index
Responses
200Successful Response
GET /app/settings/
1curl "http://localhost:8000/app/settings/"
1fetch("http://localhost:8000/app/settings/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/")
4print(response.json())
200 Example Response
No Body
GET /app/settings/account undocumented

/app/settings/account

Handled by settings_page
Responses
200Successful Response
GET /app/settings/account
1curl "http://localhost:8000/app/settings/account"
1fetch("http://localhost:8000/app/settings/account")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/account")
4print(response.json())
200 Example Response
No Body
GET /app/settings/account/:section undocumented

/app/settings/account/:section

Handled by settings_page
Parameters
section string · path
required
Responses
200Successful Response
GET /app/settings/account/example
1curl "http://localhost:8000/app/settings/account/example"
1fetch("http://localhost:8000/app/settings/account/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/account/example")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation undocumented

/app/settings/organisation

Handled by organisation_details
Responses
200Successful Response
GET /app/settings/organisation
1curl "http://localhost:8000/app/settings/organisation"
1fetch("http://localhost:8000/app/settings/organisation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/members undocumented

/app/settings/organisation/members

Handled by organisation_members
Responses
200Successful Response
GET /app/settings/organisation/members
1curl "http://localhost:8000/app/settings/organisation/members"
1fetch("http://localhost:8000/app/settings/organisation/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/members")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/members/:member_id undocumented

/app/settings/organisation/members/:member_id

Handled by organisation_member_detail
Parameters
member_id string · path
required
Responses
200Successful Response
GET /app/settings/organisation/members/example
1curl "http://localhost:8000/app/settings/organisation/members/example"
1fetch("http://localhost:8000/app/settings/organisation/members/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/members/example")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/roles undocumented

/app/settings/organisation/roles

Handled by organisation_roles
Responses
200Successful Response
GET /app/settings/organisation/roles
1curl "http://localhost:8000/app/settings/organisation/roles"
1fetch("http://localhost:8000/app/settings/organisation/roles")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/roles")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/roles/:role_id undocumented

/app/settings/organisation/roles/:role_id

Handled by organisation_role_detail
Parameters
role_id string · path
required
Responses
200Successful Response
GET /app/settings/organisation/roles/example
1curl "http://localhost:8000/app/settings/organisation/roles/example"
1fetch("http://localhost:8000/app/settings/organisation/roles/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/roles/example")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/apps undocumented

/app/settings/organisation/apps

Admin page — configure per-app access policy and allowed roles. The partial fetches installed apps + roles from /installations?policy=1 and /roles at mount time, so we only need the shell render here.

Handled by organisation_apps
Responses
200Successful Response
GET /app/settings/organisation/apps
1curl "http://localhost:8000/app/settings/organisation/apps"
1fetch("http://localhost:8000/app/settings/organisation/apps")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/apps")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/apps/:slug undocumented

/app/settings/organisation/apps/:slug

Per-app access page (specs/app-access-and-portals.md): admins, tile access, permission matrix, config document, exception grants. Reachable by workspace admins and the app's own admins; the partial fetches everything from GET /apps/:slug/access.

Handled by organisation_app_detail
Parameters
slug string · path
required
Responses
200Successful Response
GET /app/settings/organisation/apps/example
1curl "http://localhost:8000/app/settings/organisation/apps/example"
1fetch("http://localhost:8000/app/settings/organisation/apps/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/apps/example")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/billing undocumented

/app/settings/organisation/billing

Handled by organisation_billing
Responses
200Successful Response
GET /app/settings/organisation/billing
1curl "http://localhost:8000/app/settings/organisation/billing"
1fetch("http://localhost:8000/app/settings/organisation/billing")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/billing")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/billing/invoices undocumented

/app/settings/organisation/billing/invoices

Handled by organisation_invoices
Responses
200Successful Response
GET /app/settings/organisation/billing/invoices
1curl "http://localhost:8000/app/settings/organisation/billing/invoices"
1fetch("http://localhost:8000/app/settings/organisation/billing/invoices")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/billing/invoices")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/billing/methods undocumented

/app/settings/organisation/billing/methods

Handled by organisation_payment_methods
Responses
200Successful Response
GET /app/settings/organisation/billing/methods
1curl "http://localhost:8000/app/settings/organisation/billing/methods"
1fetch("http://localhost:8000/app/settings/organisation/billing/methods")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/billing/methods")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/settings undocumented

/app/settings/organisation/settings

Handled by organisation_settings
Responses
200Successful Response
GET /app/settings/organisation/settings
1curl "http://localhost:8000/app/settings/organisation/settings"
1fetch("http://localhost:8000/app/settings/organisation/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/settings")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/tokens undocumented

/app/settings/organisation/tokens

Admin page listing workspace API keys, with a create modal. Mirrors the roles list: rows render server-side, and each key's settings icon opens its in-card detail page where permissions live.

Handled by organisation_api_keys
Responses
200Successful Response
GET /app/settings/organisation/tokens
1curl "http://localhost:8000/app/settings/organisation/tokens"
1fetch("http://localhost:8000/app/settings/organisation/tokens")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/tokens")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/tokens/:key_id undocumented

/app/settings/organisation/tokens/:key_id

Admin page for one API key: permission scoping, rotate, revoke, delete. Mirrors the role detail page; the permission tree renders from the same manifest catalogue with the key's granted scopes pre-checked.

Handled by organisation_api_key_detail
Parameters
key_id string · path
required
Responses
200Successful Response
GET /app/settings/organisation/tokens/example
1curl "http://localhost:8000/app/settings/organisation/tokens/example"
1fetch("http://localhost:8000/app/settings/organisation/tokens/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/tokens/example")
4print(response.json())
200 Example Response
No Body
GET /app/settings/organisation/email undocumented

/app/settings/organisation/email

Admin page — MX email hosting (domains, mailboxes, group mailboxes, catch-all). Reuses the shared mail/partials/hosting_admin.html component (talks to the /mail/* API).

Handled by email_hosting
Responses
200Successful Response
GET /app/settings/organisation/email
1curl "http://localhost:8000/app/settings/organisation/email"
1fetch("http://localhost:8000/app/settings/organisation/email")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/settings/organisation/email")
4print(response.json())
200 Example Response
No Body
GET /app/sign/ undocumented

/app/sign/

Sign home: the insights dashboard. Backward compatibility: pre-sidenav deep links used /app/sign/?open={id}; those now land on the owning section (templates or contracts), which opens the builder.

Handled by index
Responses
200Successful Response
GET /app/sign/
1curl "http://localhost:8000/app/sign/"
1fetch("http://localhost:8000/app/sign/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/")
4print(response.json())
200 Example Response
No Body
GET /app/sign/contracts undocumented

/app/sign/contracts

Contracts: one-off and template-born documents with Draft/Sent/Completed tabs.

Handled by contracts_page
Responses
200Successful Response
GET /app/sign/contracts
1curl "http://localhost:8000/app/sign/contracts"
1fetch("http://localhost:8000/app/sign/contracts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/contracts")
4print(response.json())
200 Example Response
No Body
GET /app/sign/templates undocumented

/app/sign/templates

Templates: reusable templates with usage history.

Handled by templates_page
Responses
200Successful Response
GET /app/sign/templates
1curl "http://localhost:8000/app/sign/templates"
1fetch("http://localhost:8000/app/sign/templates")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/templates")
4print(response.json())
200 Example Response
No Body
GET /app/sign/signatories undocumented

/app/sign/signatories

Signatories: everyone ever added to a visible document.

Handled by signatories_page
Responses
200Successful Response
GET /app/sign/signatories
1curl "http://localhost:8000/app/sign/signatories"
1fetch("http://localhost:8000/app/sign/signatories")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/signatories")
4print(response.json())
200 Example Response
No Body
GET /app/sign/partials/forms/envelope-settings/:envelope_id undocumented

/app/sign/partials/forms/envelope-settings/:envelope_id

GET /app/sign/partials/forms/envelope-settings/:envelope_id — settings drawer (subject, message, signing order, expiry), prefilled from the envelope.

Handled by envelope_settings_form
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /app/sign/partials/forms/envelope-settings/example
1curl "http://localhost:8000/app/sign/partials/forms/envelope-settings/example"
1fetch("http://localhost:8000/app/sign/partials/forms/envelope-settings/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/partials/forms/envelope-settings/example")
4print(response.json())
200 Example Response
No Body
GET /app/sign/partials/forms/new-signer/:envelope_id undocumented

/app/sign/partials/forms/new-signer/:envelope_id

GET /app/sign/partials/forms/new-signer/:envelope_id — add-signer drawer with a workspace-member lookup (signer_mrn) or plain name/email for external guests.

Handled by new_signer_form
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /app/sign/partials/forms/new-signer/example
1curl "http://localhost:8000/app/sign/partials/forms/new-signer/example"
1fetch("http://localhost:8000/app/sign/partials/forms/new-signer/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/partials/forms/new-signer/example")
4print(response.json())
200 Example Response
No Body
GET /app/sign/partials/forms/edit-signer/:envelope_id/:recipient_id undocumented

/app/sign/partials/forms/edit-signer/:envelope_id/:recipient_id

GET /app/sign/partials/forms/edit-signer/:envelope_id/:recipient_id — edit a signer's name, email, role and order in a drawer, prefilled from the record.

Handled by edit_signer_form
Parameters
envelope_id string · path
required
recipient_id string · path
required
Responses
200Successful Response
GET /app/sign/partials/forms/edit-signer/example/example
1curl "http://localhost:8000/app/sign/partials/forms/edit-signer/example/example"
1fetch("http://localhost:8000/app/sign/partials/forms/edit-signer/example/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/partials/forms/edit-signer/example/example")
4print(response.json())
200 Example Response
No Body
GET /app/sign/partials/forms/access-code/:envelope_id/:recipient_id undocumented

/app/sign/partials/forms/access-code/:envelope_id/:recipient_id

GET /app/sign/partials/forms/access-code/:envelope_id/:recipient_id — set or replace one signer's access code (the current code is never shown back).

Handled by access_code_form
Parameters
envelope_id string · path
required
recipient_id string · path
required
Responses
200Successful Response
GET /app/sign/partials/forms/access-code/example/example
1curl "http://localhost:8000/app/sign/partials/forms/access-code/example/example"
1fetch("http://localhost:8000/app/sign/partials/forms/access-code/example/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/partials/forms/access-code/example/example")
4print(response.json())
200 Example Response
No Body
GET /app/sign/partials/forms/new-public-link/:envelope_id undocumented

/app/sign/partials/forms/new-public-link/:envelope_id

GET /app/sign/partials/forms/new-public-link/:envelope_id — mint a self-serve link on a template (optional expiry + submission cap).

Handled by new_public_link_form
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /app/sign/partials/forms/new-public-link/example
1curl "http://localhost:8000/app/sign/partials/forms/new-public-link/example"
1fetch("http://localhost:8000/app/sign/partials/forms/new-public-link/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/partials/forms/new-public-link/example")
4print(response.json())
200 Example Response
No Body
GET /app/sign/partials/signatory/:email undocumented

/app/sign/partials/signatory/:email

GET /app/sign/partials/signatory/:email — one signatory's floating detail card: their documents (with per-document state) and audit activity, scoped to what the caller can see. Deep-linkable via /app/sign/signatories?signatory=.

Handled by signatory_detail_partial
Parameters
email string · path
required
Responses
200Successful Response
GET /app/sign/partials/signatory/example
1curl "http://localhost:8000/app/sign/partials/signatory/example"
1fetch("http://localhost:8000/app/sign/partials/signatory/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/partials/signatory/example")
4print(response.json())
200 Example Response
No Body
GET /app/sign/partials/template-usage/:envelope_id undocumented

/app/sign/partials/template-usage/:envelope_id

GET /app/sign/partials/template-usage/:envelope_id — the template's usage history as a floating detail card: every document created from it, newest first. Deep-linkable via /app/sign/templates?usage=.

Handled by template_usage_partial
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /app/sign/partials/template-usage/example
1curl "http://localhost:8000/app/sign/partials/template-usage/example"
1fetch("http://localhost:8000/app/sign/partials/template-usage/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/sign/partials/template-usage/example")
4print(response.json())
200 Example Response
No Body
GET /app/slides/ undocumented

/app/slides/

GET /app/slides/. Templates + recent decks (Papers listing).

Handled by index
Responses
200Successful Response
GET /app/slides/
1curl "http://localhost:8000/app/slides/"
1fetch("http://localhost:8000/app/slides/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/slides/")
4print(response.json())
200 Example Response
No Body
GET /app/slides/deck/:id undocumented

/app/slides/deck/:id

GET /app/slides/deck/:id. Design studio (Phase 1: chrome only).

Handled by editor
Parameters
id string · path
required
Responses
200Successful Response
GET /app/slides/deck/example
1curl "http://localhost:8000/app/slides/deck/example"
1fetch("http://localhost:8000/app/slides/deck/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/slides/deck/example")
4print(response.json())
200 Example Response
No Body
GET /app/slides/present/:id undocumented

/app/slides/present/:id

GET /app/slides/present/:id. Full-screen present (Phase 1: placeholder).

Handled by presenter
Parameters
id string · path
required
Responses
200Successful Response
GET /app/slides/present/example
1curl "http://localhost:8000/app/slides/present/example"
1fetch("http://localhost:8000/app/slides/present/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/slides/present/example")
4print(response.json())
200 Example Response
No Body
GET /app/slides/partials/decks undocumented

/app/slides/partials/decks

GET /app/slides/partials/decks. Recent list (HTMX refresh).

Handled by deck_grid_partial
Responses
200Successful Response
GET /app/slides/partials/decks
1curl "http://localhost:8000/app/slides/partials/decks"
1fetch("http://localhost:8000/app/slides/partials/decks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/slides/partials/decks")
4print(response.json())
200 Example Response
No Body
GET /app/slides/partials/trash undocumented

/app/slides/partials/trash

GET /app/slides/partials/trash. Trash list (HTMX swap on the index).

Handled by trash_partial
Responses
200Successful Response
GET /app/slides/partials/trash
1curl "http://localhost:8000/app/slides/partials/trash"
1fetch("http://localhost:8000/app/slides/partials/trash")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/slides/partials/trash")
4print(response.json())
200 Example Response
No Body
GET /app/slides/assets/:asset_id undocumented

/app/slides/assets/:asset_id

GET /app/slides/assets/:asset_id. Redirect to a fresh presigned R2 URL. Same-origin (wildcard subdomain) so an <img> load carries the session cookie. The gate in authz.py has already resolved read access on the owning deck.

Handled by api_get_asset
Parameters
asset_id string · path
required
Responses
200Successful Response
GET /app/slides/assets/example
1curl "http://localhost:8000/app/slides/assets/example"
1fetch("http://localhost:8000/app/slides/assets/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/slides/assets/example")
4print(response.json())
200 Example Response
No Body
GET /app/tables/ undocumented

/app/tables/

GET /app/tables/ — templates row + recent tables.

Handled by index
Responses
200Successful Response
GET /app/tables/
1curl "http://localhost:8000/app/tables/"
1fetch("http://localhost:8000/app/tables/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tables/")
4print(response.json())
200 Example Response
No Body
GET /app/tables/:table_id undocumented

/app/tables/:table_id

GET /app/tables/:table_id — editor view for a specific table.

Handled by table_view
Parameters
table_id string · path
required
Responses
200Successful Response
GET /app/tables/example
1curl "http://localhost:8000/app/tables/example"
1fetch("http://localhost:8000/app/tables/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tables/example")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/ undocumented

/app/tasks/

Handled by index
Responses
200Successful Response
GET /app/tasks/
1curl "http://localhost:8000/app/tasks/"
1fetch("http://localhost:8000/app/tasks/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/board/:board_id undocumented

/app/tasks/board/:board_id

Handled by board
Parameters
board_id string · path
required
Responses
200Successful Response
GET /app/tasks/board/example
1curl "http://localhost:8000/app/tasks/board/example"
1fetch("http://localhost:8000/app/tasks/board/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/board/example")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/task-list undocumented

/app/tasks/partials/task-list

Handled by task_list_partial
Responses
200Successful Response
GET /app/tasks/partials/task-list
1curl "http://localhost:8000/app/tasks/partials/task-list"
1fetch("http://localhost:8000/app/tasks/partials/task-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/task-list")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/card/:task_id undocumented

/app/tasks/partials/card/:task_id

A single kanban card, for realtime patch-in-place on the board tab.

Handled by task_card_partial
Parameters
task_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/card/example
1curl "http://localhost:8000/app/tasks/partials/card/example"
1fetch("http://localhost:8000/app/tasks/partials/card/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/card/example")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/task/:task_id undocumented

/app/tasks/partials/task/:task_id

Handled by task_detail_partial
Parameters
task_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/task/example
1curl "http://localhost:8000/app/tasks/partials/task/example"
1fetch("http://localhost:8000/app/tasks/partials/task/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/task/example")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/task/:task_id/expanded undocumented

/app/tasks/partials/task/:task_id/expanded

Handled by task_expanded_partial
Parameters
task_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/task/example/expanded
1curl "http://localhost:8000/app/tasks/partials/task/example/expanded"
1fetch("http://localhost:8000/app/tasks/partials/task/example/expanded")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/task/example/expanded")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/forms/new-board undocumented

/app/tasks/partials/forms/new-board

Handled by new_board_form
Responses
200Successful Response
GET /app/tasks/partials/forms/new-board
1curl "http://localhost:8000/app/tasks/partials/forms/new-board"
1fetch("http://localhost:8000/app/tasks/partials/forms/new-board")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/forms/new-board")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/forms/new-task undocumented

/app/tasks/partials/forms/new-task

Handled by new_task_form
Responses
200Successful Response
GET /app/tasks/partials/forms/new-task
1curl "http://localhost:8000/app/tasks/partials/forms/new-task"
1fetch("http://localhost:8000/app/tasks/partials/forms/new-task")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/forms/new-task")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/board/:board_id/tab undocumented

/app/tasks/partials/board/:board_id/tab

Handled by board_tab_partial
Parameters
board_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/board/example/tab
1curl "http://localhost:8000/app/tasks/partials/board/example/tab"
1fetch("http://localhost:8000/app/tasks/partials/board/example/tab")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/board/example/tab")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/board/:board_id/lane-settings undocumented

/app/tasks/partials/board/:board_id/lane-settings

Handled by lane_settings_partial
Parameters
board_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/board/example/lane-settings
1curl "http://localhost:8000/app/tasks/partials/board/example/lane-settings"
1fetch("http://localhost:8000/app/tasks/partials/board/example/lane-settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/board/example/lane-settings")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/board/:board_id/settings undocumented

/app/tasks/partials/board/:board_id/settings

Handled by board_settings_partial
Parameters
board_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/board/example/settings
1curl "http://localhost:8000/app/tasks/partials/board/example/settings"
1fetch("http://localhost:8000/app/tasks/partials/board/example/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/board/example/settings")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/forms/new-incubator-task undocumented

/app/tasks/partials/forms/new-incubator-task

Handled by new_incubator_task_form
Responses
200Successful Response
GET /app/tasks/partials/forms/new-incubator-task
1curl "http://localhost:8000/app/tasks/partials/forms/new-incubator-task"
1fetch("http://localhost:8000/app/tasks/partials/forms/new-incubator-task")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/forms/new-incubator-task")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/forms/new-schedule undocumented

/app/tasks/partials/forms/new-schedule

Handled by new_schedule_form
Responses
200Successful Response
GET /app/tasks/partials/forms/new-schedule
1curl "http://localhost:8000/app/tasks/partials/forms/new-schedule"
1fetch("http://localhost:8000/app/tasks/partials/forms/new-schedule")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/forms/new-schedule")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/schedule/:schedule_id undocumented

/app/tasks/partials/schedule/:schedule_id

Schedule detail card (core/details) + linked tasks.

Handled by schedule_detail_partial
Parameters
schedule_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/schedule/example
1curl "http://localhost:8000/app/tasks/partials/schedule/example"
1fetch("http://localhost:8000/app/tasks/partials/schedule/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/schedule/example")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/wiki/:task_id undocumented

/app/tasks/partials/wiki/:task_id

Detail card (core/details) for previewing and editing a task's wiki.

Handled by wiki_detail_partial
Parameters
task_id string · path
required
Responses
200Successful Response
GET /app/tasks/partials/wiki/example
1curl "http://localhost:8000/app/tasks/partials/wiki/example"
1fetch("http://localhost:8000/app/tasks/partials/wiki/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/wiki/example")
4print(response.json())
200 Example Response
No Body
GET /app/tasks/partials/member-tasks undocumented

/app/tasks/partials/member-tasks

Side panel showing all tasks for a given assignee, with actions.

Handled by member_tasks_partial
Responses
200Successful Response
GET /app/tasks/partials/member-tasks
1curl "http://localhost:8000/app/tasks/partials/member-tasks"
1fetch("http://localhost:8000/app/tasks/partials/member-tasks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/tasks/partials/member-tasks")
4print(response.json())
200 Example Response
No Body
GET /app/wands/ undocumented

/app/wands/

Overview dashboard — the app's landing page. All numbers arrive via the /wands/stats API (fetched by the page), so the handler stays thin.

Handled by index
Responses
200Successful Response
GET /app/wands/
1curl "http://localhost:8000/app/wands/"
1fetch("http://localhost:8000/app/wands/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/")
4print(response.json())
200 Example Response
No Body
GET /app/wands/spells undocumented

/app/wands/spells

Handled by spells_page
Responses
200Successful Response
GET /app/wands/spells
1curl "http://localhost:8000/app/wands/spells"
1fetch("http://localhost:8000/app/wands/spells")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/spells")
4print(response.json())
200 Example Response
No Body
GET /app/wands/spells/:spell_id undocumented

/app/wands/spells/:spell_id

Handled by spell_page
Parameters
spell_id string · path
required
Responses
200Successful Response
GET /app/wands/spells/example
1curl "http://localhost:8000/app/wands/spells/example"
1fetch("http://localhost:8000/app/wands/spells/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/spells/example")
4print(response.json())
200 Example Response
No Body
GET /app/wands/macros undocumented

/app/wands/macros

Handled by macros_page
Responses
200Successful Response
GET /app/wands/macros
1curl "http://localhost:8000/app/wands/macros"
1fetch("http://localhost:8000/app/wands/macros")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/macros")
4print(response.json())
200 Example Response
No Body
GET /app/wands/runs undocumented

/app/wands/runs

Handled by runs_page
Responses
200Successful Response
GET /app/wands/runs
1curl "http://localhost:8000/app/wands/runs"
1fetch("http://localhost:8000/app/wands/runs")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/runs")
4print(response.json())
200 Example Response
No Body
GET /app/wands/partials/spells undocumented

/app/wands/partials/spells

Handled by spell_list_partial
Responses
200Successful Response
GET /app/wands/partials/spells
1curl "http://localhost:8000/app/wands/partials/spells"
1fetch("http://localhost:8000/app/wands/partials/spells")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/partials/spells")
4print(response.json())
200 Example Response
No Body
GET /app/wands/partials/spells/:spell_id undocumented

/app/wands/partials/spells/:spell_id

Handled by spell_detail_partial
Parameters
spell_id string · path
required
Responses
200Successful Response
GET /app/wands/partials/spells/example
1curl "http://localhost:8000/app/wands/partials/spells/example"
1fetch("http://localhost:8000/app/wands/partials/spells/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/partials/spells/example")
4print(response.json())
200 Example Response
No Body
GET /app/wands/partials/spells/:spell_id/builder undocumented

/app/wands/partials/spells/:spell_id/builder

Handled by spell_builder_partial
Parameters
spell_id string · path
required
Responses
200Successful Response
GET /app/wands/partials/spells/example/builder
1curl "http://localhost:8000/app/wands/partials/spells/example/builder"
1fetch("http://localhost:8000/app/wands/partials/spells/example/builder")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/partials/spells/example/builder")
4print(response.json())
200 Example Response
No Body
GET /app/wands/partials/spells/:spell_id/runs undocumented

/app/wands/partials/spells/:spell_id/runs

Handled by run_list_partial
Parameters
spell_id string · path
required
Responses
200Successful Response
GET /app/wands/partials/spells/example/runs
1curl "http://localhost:8000/app/wands/partials/spells/example/runs"
1fetch("http://localhost:8000/app/wands/partials/spells/example/runs")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/partials/spells/example/runs")
4print(response.json())
200 Example Response
No Body
GET /app/wands/partials/run/:run_id undocumented

/app/wands/partials/run/:run_id

Handled by run_detail_partial
Parameters
run_id string · path
required
Responses
200Successful Response
GET /app/wands/partials/run/example
1curl "http://localhost:8000/app/wands/partials/run/example"
1fetch("http://localhost:8000/app/wands/partials/run/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/partials/run/example")
4print(response.json())
200 Example Response
No Body
GET /app/wands/partials/macros undocumented

/app/wands/partials/macros

Handled by macro_list_partial
Responses
200Successful Response
GET /app/wands/partials/macros
1curl "http://localhost:8000/app/wands/partials/macros"
1fetch("http://localhost:8000/app/wands/partials/macros")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/partials/macros")
4print(response.json())
200 Example Response
No Body
GET /app/wands/partials/forms/new-spell undocumented

/app/wands/partials/forms/new-spell

Handled by new_spell_form
Responses
200Successful Response
GET /app/wands/partials/forms/new-spell
1curl "http://localhost:8000/app/wands/partials/forms/new-spell"
1fetch("http://localhost:8000/app/wands/partials/forms/new-spell")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wands/partials/forms/new-spell")
4print(response.json())
200 Example Response
No Body
GET /app/wiki/ undocumented

/app/wiki/

GET /app/wiki/ — main wiki page with sidebar tree + editor area.

Handled by index
Responses
200Successful Response
GET /app/wiki/
1curl "http://localhost:8000/app/wiki/"
1fetch("http://localhost:8000/app/wiki/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wiki/")
4print(response.json())
200 Example Response
No Body
GET /app/wiki/page/:page_id undocumented

/app/wiki/page/:page_id

GET /app/wiki/page/:page_id — view a specific page.

Handled by page_view
Parameters
page_id string · path
required
Responses
200Successful Response
GET /app/wiki/page/example
1curl "http://localhost:8000/app/wiki/page/example"
1fetch("http://localhost:8000/app/wiki/page/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wiki/page/example")
4print(response.json())
200 Example Response
No Body
GET /app/wiki/partials/tree undocumented

/app/wiki/partials/tree

GET /app/wiki/partials/tree — page tree sidebar.

Handled by tree_partial
Responses
200Successful Response
GET /app/wiki/partials/tree
1curl "http://localhost:8000/app/wiki/partials/tree"
1fetch("http://localhost:8000/app/wiki/partials/tree")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wiki/partials/tree")
4print(response.json())
200 Example Response
No Body
GET /app/wiki/partials/page/:page_id undocumented

/app/wiki/partials/page/:page_id

GET /app/wiki/partials/page/:page_id — page content area.

Handled by page_content_partial
Parameters
page_id string · path
required
Responses
200Successful Response
GET /app/wiki/partials/page/example
1curl "http://localhost:8000/app/wiki/partials/page/example"
1fetch("http://localhost:8000/app/wiki/partials/page/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wiki/partials/page/example")
4print(response.json())
200 Example Response
No Body
GET /app/wiki/partials/page/:page_id/comments undocumented

/app/wiki/partials/page/:page_id/comments

GET /app/wiki/partials/page/:page_id/comments — comments panel.

Handled by comments_partial
Parameters
page_id string · path
required
Responses
200Successful Response
GET /app/wiki/partials/page/example/comments
1curl "http://localhost:8000/app/wiki/partials/page/example/comments"
1fetch("http://localhost:8000/app/wiki/partials/page/example/comments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wiki/partials/page/example/comments")
4print(response.json())
200 Example Response
No Body
GET /app/wiki/partials/page/:page_id/versions undocumented

/app/wiki/partials/page/:page_id/versions

GET /app/wiki/partials/page/:page_id/versions — version history panel.

Handled by versions_partial
Parameters
page_id string · path
required
Responses
200Successful Response
GET /app/wiki/partials/page/example/versions
1curl "http://localhost:8000/app/wiki/partials/page/example/versions"
1fetch("http://localhost:8000/app/wiki/partials/page/example/versions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wiki/partials/page/example/versions")
4print(response.json())
200 Example Response
No Body
GET /app/wiki/partials/page/:page_id/breadcrumbs undocumented

/app/wiki/partials/page/:page_id/breadcrumbs

GET /app/wiki/partials/page/:page_id/breadcrumbs — breadcrumb trail.

Handled by breadcrumbs_partial
Parameters
page_id string · path
required
Responses
200Successful Response
GET /app/wiki/partials/page/example/breadcrumbs
1curl "http://localhost:8000/app/wiki/partials/page/example/breadcrumbs"
1fetch("http://localhost:8000/app/wiki/partials/page/example/breadcrumbs")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/wiki/partials/page/example/breadcrumbs")
4print(response.json())
200 Example Response
No Body
GET /app/workers/ undocumented

/app/workers/

The Workers landing — the self-service portal (specs/app-access-and-portals.md). Everyone with app access lands here. Holders of workers.portal.view get the portal (their own profile card plus squares per their capabilities, and an "Enter HRIS console" button for HR staff). Members without the key get the request-access wall instead of a dead end. Deliberately has no AUTHZ entry: the branching IS the gate; app access still applies upstream.

Handled by portal_page
Responses
200Successful Response
GET /app/workers/
1curl "http://localhost:8000/app/workers/"
1fetch("http://localhost:8000/app/workers/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/")
4print(response.json())
200 Example Response
No Body
GET /app/workers/directory undocumented

/app/workers/directory

Workers directory — MicroTable fetches data via API.

Handled by index
Responses
200Successful Response
GET /app/workers/directory
1curl "http://localhost:8000/app/workers/directory"
1fetch("http://localhost:8000/app/workers/directory")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/directory")
4print(response.json())
200 Example Response
No Body
GET /app/workers/colleagues undocumented

/app/workers/colleagues

Portal-side colleague directory: read-only cards with directory-grade fields only (name, title, department, work contact). Deliberately NOT the console workers table — that is an HR management surface. Inline cards, no click-through (specs/app-access-and-portals.md).

Handled by colleagues_page
Responses
200Successful Response
GET /app/workers/colleagues
1curl "http://localhost:8000/app/workers/colleagues"
1fetch("http://localhost:8000/app/workers/colleagues")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/colleagues")
4print(response.json())
200 Example Response
No Body
GET /app/workers/workers/:worker_id undocumented

/app/workers/workers/:worker_id

Single worker profile page.

Handled by worker_page
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /app/workers/workers/example
1curl "http://localhost:8000/app/workers/workers/example"
1fetch("http://localhost:8000/app/workers/workers/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/workers/example")
4print(response.json())
200 Example Response
No Body
GET /app/workers/departments undocumented

/app/workers/departments

Departments list with hierarchy.

Handled by departments_page
Responses
200Successful Response
GET /app/workers/departments
1curl "http://localhost:8000/app/workers/departments"
1fetch("http://localhost:8000/app/workers/departments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/departments")
4print(response.json())
200 Example Response
No Body
GET /app/workers/departments/:department_id undocumented

/app/workers/departments/:department_id

Single department — workers, head, description.

Handled by department_page
Parameters
department_id string · path
required
Responses
200Successful Response
GET /app/workers/departments/example
1curl "http://localhost:8000/app/workers/departments/example"
1fetch("http://localhost:8000/app/workers/departments/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/departments/example")
4print(response.json())
200 Example Response
No Body
GET /app/workers/org-chart undocumented

/app/workers/org-chart

Organisational chart — tree view built from workers.manager_id.

Handled by org_chart_page
Responses
200Successful Response
GET /app/workers/org-chart
1curl "http://localhost:8000/app/workers/org-chart"
1fetch("http://localhost:8000/app/workers/org-chart")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/org-chart")
4print(response.json())
200 Example Response
No Body
GET /app/workers/checklists undocumented

/app/workers/checklists

All checklist templates — filterable by type, with workflow analytics.

Handled by checklists_page
Responses
200Successful Response
GET /app/workers/checklists
1curl "http://localhost:8000/app/workers/checklists"
1fetch("http://localhost:8000/app/workers/checklists")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/checklists")
4print(response.json())
200 Example Response
No Body
GET /app/workers/checklists/:checklist_id undocumented

/app/workers/checklists/:checklist_id

Single checklist template — items, auto-assign settings, and assignments.

Handled by checklist_page
Parameters
checklist_id string · path
required
Responses
200Successful Response
GET /app/workers/checklists/example
1curl "http://localhost:8000/app/workers/checklists/example"
1fetch("http://localhost:8000/app/workers/checklists/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/checklists/example")
4print(response.json())
200 Example Response
No Body
GET /app/workers/compensation undocumented

/app/workers/compensation

Aggregate compensation view across all workers.

Handled by compensation_page
Responses
200Successful Response
GET /app/workers/compensation
1curl "http://localhost:8000/app/workers/compensation"
1fetch("http://localhost:8000/app/workers/compensation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/compensation")
4print(response.json())
200 Example Response
No Body
GET /app/workers/fields undocumented

/app/workers/fields

Custom profile fields admin — definitions grouped into profile sections.

Handled by fields_page
Responses
200Successful Response
GET /app/workers/fields
1curl "http://localhost:8000/app/workers/fields"
1fetch("http://localhost:8000/app/workers/fields")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/fields")
4print(response.json())
200 Example Response
No Body
GET /app/workers/reports undocumented

/app/workers/reports

People analytics — headcount trend, joiners vs leavers, attrition, tenure, upcoming people dates, composition breakdowns, payroll by team.

Handled by reports_page
Responses
200Successful Response
GET /app/workers/reports
1curl "http://localhost:8000/app/workers/reports"
1fetch("http://localhost:8000/app/workers/reports")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/reports")
4print(response.json())
200 Example Response
No Body
GET /app/workers/attendance undocumented

/app/workers/attendance

Attendance reconciliation — present / absent / on-leave per worker for a week. The visible week follows ?date=YYYY-MM-DD (defaults to today). Reads the worker_attendance_index projection (populated by events.py from system.attendance.* + core.leaves.pto.*). Absence is *derived* at read time for elapsed working days with no row, using each worker's location timezone and working days (attendance_location_index). No writes here: rule 5.

Handled by attendance_page
Responses
200Successful Response
GET /app/workers/attendance
1curl "http://localhost:8000/app/workers/attendance"
1fetch("http://localhost:8000/app/workers/attendance")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/attendance")
4print(response.json())
200 Example Response
No Body
GET /app/workers/hours undocumented

/app/workers/hours

Payable-hours report — worked time split into payable / off-hours / off-day. For the selected month, each worker's closed punches (worker_punch_projection) are overlapped with their location's schedule (attendance_location_index: timezone, working days, work window) to separate payable time (inside the window on a working day) from off-schedule time. Derived at read time against the location's CURRENT schedule, so it self-heals if the schedule changes. No writes (rule 5). Historical punches from before this report existed populate as workers clock out; a one-off re-emit can backfill older sessions.

Handled by hours_page
Responses
200Successful Response
GET /app/workers/hours
1curl "http://localhost:8000/app/workers/hours"
1fetch("http://localhost:8000/app/workers/hours")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/hours")
4print(response.json())
200 Example Response
No Body
GET /app/workers/locations undocumented

/app/workers/locations

Work locations management — timezone + working days per site. Chrome only: the table runs client-side against the core /attendance/locations API (admin-gated writes); create/edit use the standard platform form drawer (new_location_form / edit_location_form). The Workers projection (attendance_location_index) is updated via events, not from here. See specs/attendance-locations.md.

Handled by locations_page
Responses
200Successful Response
GET /app/workers/locations
1curl "http://localhost:8000/app/workers/locations"
1fetch("http://localhost:8000/app/workers/locations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/locations")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/attendance-calendar undocumented

/app/workers/partials/attendance-calendar

Mini-month calendar popover for the Attendance week picker. ?date= keeps the selected week highlighted; ?cal=YYYY-MM browses months without leaving the popover (month arrows swap only this fragment).

Handled by attendance_calendar_partial
Responses
200Successful Response
GET /app/workers/partials/attendance-calendar
1curl "http://localhost:8000/app/workers/partials/attendance-calendar"
1fetch("http://localhost:8000/app/workers/partials/attendance-calendar")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/attendance-calendar")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/worker-list undocumented

/app/workers/partials/worker-list

Filtered worker list partial.

Handled by worker_list_partial
Responses
200Successful Response
GET /app/workers/partials/worker-list
1curl "http://localhost:8000/app/workers/partials/worker-list"
1fetch("http://localhost:8000/app/workers/partials/worker-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/worker-list")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/workers/:worker_id undocumented

/app/workers/partials/workers/:worker_id

Single worker card partial.

Handled by worker_detail_partial
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /app/workers/partials/workers/example
1curl "http://localhost:8000/app/workers/partials/workers/example"
1fetch("http://localhost:8000/app/workers/partials/workers/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/workers/example")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/department-list undocumented

/app/workers/partials/department-list

Department list partial.

Handled by department_list_partial
Responses
200Successful Response
GET /app/workers/partials/department-list
1curl "http://localhost:8000/app/workers/partials/department-list"
1fetch("http://localhost:8000/app/workers/partials/department-list")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/department-list")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/department/:department_id undocumented

/app/workers/partials/department/:department_id

Single department detail partial.

Handled by department_detail_partial
Parameters
department_id string · path
required
Responses
200Successful Response
GET /app/workers/partials/department/example
1curl "http://localhost:8000/app/workers/partials/department/example"
1fetch("http://localhost:8000/app/workers/partials/department/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/department/example")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/org-chart undocumented

/app/workers/partials/org-chart

Org chart tree partial — for HTMX refresh.

Handled by org_chart_partial
Responses
200Successful Response
GET /app/workers/partials/org-chart
1curl "http://localhost:8000/app/workers/partials/org-chart"
1fetch("http://localhost:8000/app/workers/partials/org-chart")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/org-chart")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/new-worker undocumented

/app/workers/partials/forms/new-worker

New worker form — rendered as platform form drawer.

Handled by new_worker_form
Responses
200Successful Response
GET /app/workers/partials/forms/new-worker
1curl "http://localhost:8000/app/workers/partials/forms/new-worker"
1fetch("http://localhost:8000/app/workers/partials/forms/new-worker")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/new-worker")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/new-department undocumented

/app/workers/partials/forms/new-department

New department form — rendered as platform form drawer.

Handled by new_department_form
Responses
200Successful Response
GET /app/workers/partials/forms/new-department
1curl "http://localhost:8000/app/workers/partials/forms/new-department"
1fetch("http://localhost:8000/app/workers/partials/forms/new-department")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/new-department")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/new-checklist undocumented

/app/workers/partials/forms/new-checklist

New checklist template form — rendered as platform form drawer.

Handled by new_checklist_form
Responses
200Successful Response
GET /app/workers/partials/forms/new-checklist
1curl "http://localhost:8000/app/workers/partials/forms/new-checklist"
1fetch("http://localhost:8000/app/workers/partials/forms/new-checklist")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/new-checklist")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/assign-checklist undocumented

/app/workers/partials/forms/assign-checklist

Assign a checklist to a worker — rendered as platform form drawer.

Handled by assign_checklist_form
Responses
200Successful Response
GET /app/workers/partials/forms/assign-checklist
1curl "http://localhost:8000/app/workers/partials/forms/assign-checklist"
1fetch("http://localhost:8000/app/workers/partials/forms/assign-checklist")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/assign-checklist")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/checklist-responsible undocumented

/app/workers/partials/forms/checklist-responsible

Assign-responsible modal for a checklist assignment, PUT to the worker-specific assignment, pre-selecting the current responsible worker.

Handled by checklist_responsible_form
Responses
200Successful Response
GET /app/workers/partials/forms/checklist-responsible
1curl "http://localhost:8000/app/workers/partials/forms/checklist-responsible"
1fetch("http://localhost:8000/app/workers/partials/forms/checklist-responsible")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/checklist-responsible")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/compensation/:worker_id undocumented

/app/workers/partials/compensation/:worker_id

Compensation detail card (core/details) for one worker.

Handled by compensation_detail_partial
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /app/workers/partials/compensation/example
1curl "http://localhost:8000/app/workers/partials/compensation/example"
1fetch("http://localhost:8000/app/workers/partials/compensation/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/compensation/example")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/new-compensation undocumented

/app/workers/partials/forms/new-compensation

New compensation form — rendered as platform form drawer.

Handled by new_compensation_form
Responses
200Successful Response
GET /app/workers/partials/forms/new-compensation
1curl "http://localhost:8000/app/workers/partials/forms/new-compensation"
1fetch("http://localhost:8000/app/workers/partials/forms/new-compensation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/new-compensation")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/nested-compensation undocumented

/app/workers/partials/forms/nested-compensation

Add the first compensation package for a worker (nested form, level 2).

Handled by nested_compensation_form
Responses
200Successful Response
GET /app/workers/partials/forms/nested-compensation
1curl "http://localhost:8000/app/workers/partials/forms/nested-compensation"
1fetch("http://localhost:8000/app/workers/partials/forms/nested-compensation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/nested-compensation")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/edit-compensation undocumented

/app/workers/partials/forms/edit-compensation

Edit the current package — saves a NEW effective-dated version, pre-filled from the current one. Never overwrites: the prior record stays as history.

Handled by edit_compensation_form
Responses
200Successful Response
GET /app/workers/partials/forms/edit-compensation
1curl "http://localhost:8000/app/workers/partials/forms/edit-compensation"
1fetch("http://localhost:8000/app/workers/partials/forms/edit-compensation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/edit-compensation")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/new-employment undocumented

/app/workers/partials/forms/new-employment

Add an employment record (contract/role period) for a worker.

Handled by new_employment_form
Responses
200Successful Response
GET /app/workers/partials/forms/new-employment
1curl "http://localhost:8000/app/workers/partials/forms/new-employment"
1fetch("http://localhost:8000/app/workers/partials/forms/new-employment")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/new-employment")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/edit-employment undocumented

/app/workers/partials/forms/edit-employment

Edit an existing employment record, pre-filled from the stored record.

Handled by edit_employment_form
Responses
200Successful Response
GET /app/workers/partials/forms/edit-employment
1curl "http://localhost:8000/app/workers/partials/forms/edit-employment"
1fetch("http://localhost:8000/app/workers/partials/forms/edit-employment")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/edit-employment")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/terminate-worker undocumented

/app/workers/partials/forms/terminate-worker

Terminate a worker's employment — closes all open/upcoming contracts.

Handled by terminate_worker_form
Responses
200Successful Response
GET /app/workers/partials/forms/terminate-worker
1curl "http://localhost:8000/app/workers/partials/forms/terminate-worker"
1fetch("http://localhost:8000/app/workers/partials/forms/terminate-worker")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/terminate-worker")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/new-location undocumented

/app/workers/partials/forms/new-location

Add-location drawer — standard platform form posting to the attendance API.

Handled by new_location_form
Responses
200Successful Response
GET /app/workers/partials/forms/new-location
1curl "http://localhost:8000/app/workers/partials/forms/new-location"
1fetch("http://localhost:8000/app/workers/partials/forms/new-location")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/new-location")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/edit-location undocumented

/app/workers/partials/forms/edit-location

Edit-location drawer. Prefill values are echoed from the row the page already loaded client-side (this page is chrome over the attendance API), so there is no DB read here — which also keeps the Workers app off the attendance-owned table.

Handled by edit_location_form
Responses
200Successful Response
GET /app/workers/partials/forms/edit-location
1curl "http://localhost:8000/app/workers/partials/forms/edit-location"
1fetch("http://localhost:8000/app/workers/partials/forms/edit-location")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/edit-location")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/edit-personal undocumented

/app/workers/partials/forms/edit-personal

Edit personal details drawer — pre-filled from workers.personal.

Handled by edit_personal_form
Responses
200Successful Response
GET /app/workers/partials/forms/edit-personal
1curl "http://localhost:8000/app/workers/partials/forms/edit-personal"
1fetch("http://localhost:8000/app/workers/partials/forms/edit-personal")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/edit-personal")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/edit-bank undocumented

/app/workers/partials/forms/edit-bank

Edit bank details drawer — flat fields only (identifiers have their own editor in the profile section).

Handled by edit_bank_form
Responses
200Successful Response
GET /app/workers/partials/forms/edit-bank
1curl "http://localhost:8000/app/workers/partials/forms/edit-bank"
1fetch("http://localhost:8000/app/workers/partials/forms/edit-bank")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/edit-bank")
4print(response.json())
200 Example Response
No Body
GET /app/workers/partials/forms/field-definition undocumented

/app/workers/partials/forms/field-definition

Create/edit a custom profile field — custom drawer (needs the per-line options editor and an immutable type on edit, which the form system can't express; mirrors the nested_compensation_form precedent).

Handled by field_definition_form
Responses
200Successful Response
GET /app/workers/partials/forms/field-definition
1curl "http://localhost:8000/app/workers/partials/forms/field-definition"
1fetch("http://localhost:8000/app/workers/partials/forms/field-definition")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/workers/partials/forms/field-definition")
4print(response.json())
200 Example Response
No Body
GET /app/lobby/ undocumented

/app/lobby/

GET/POST /app/lobby/, the workspace home dashboard.

Handled by index
Responses
200Successful Response
GET /app/lobby/
1curl "http://localhost:8000/app/lobby/"
1fetch("http://localhost:8000/app/lobby/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/app/lobby/")
4print(response.json())
200 Example Response
No Body
POST /app/mail/ undocumented

/app/mail/

Main mail screen. Renders the not-configured landing until the workspace has a domain or a connected account; otherwise the three-pane client.

Handled by index
Responses
200Successful Response
POST /app/mail/
1curl -X POST "http://localhost:8000/app/mail/"
1fetch("http://localhost:8000/app/mail/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/mail/")
4print(response.json())
200 Example Response
No Body
POST /app/mail/settings undocumented

/app/mail/settings

Admin: email hosting — add a domain, view DNS to publish, provision mailboxes, manage group mailboxes + the wildcard catch-all. Renders the same SPA on its settings view (deep-link target).

Handled by settings
Responses
200Successful Response
POST /app/mail/settings
1curl -X POST "http://localhost:8000/app/mail/settings"
1fetch("http://localhost:8000/app/mail/settings", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/mail/settings")
4print(response.json())
200 Example Response
No Body
POST /app/calls/ undocumented

/app/calls/

Handled by index
Responses
200Successful Response
POST /app/calls/
1curl -X POST "http://localhost:8000/app/calls/"
1fetch("http://localhost:8000/app/calls/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/calls/")
4print(response.json())
200 Example Response
No Body
POST /app/chat/ undocumented

/app/chat/

Main chat view — chat list sidebar plus message area.

Handled by index
Responses
200Successful Response
POST /app/chat/
1curl -X POST "http://localhost:8000/app/chat/"
1fetch("http://localhost:8000/app/chat/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/chat/")
4print(response.json())
200 Example Response
No Body
POST /app/contacts/ undocumented

/app/contacts/

Dashboard — a MicroDash board. The page is a shell; every figure comes from GET /contacts/dashboard so the board can refresh without a reload.

Handled by index
Responses
200Successful Response
POST /app/contacts/
1curl -X POST "http://localhost:8000/app/contacts/"
1fetch("http://localhost:8000/app/contacts/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/contacts/")
4print(response.json())
200 Example Response
No Body
POST /app/crm/ undocumented

/app/crm/

The CRM home: a MicroDash widget board, role-branched manager/rep. Layout, widget choice, and every number are client-side; the server only stamps what the board needs to know before it can fetch (role, the default pipeline for the funnel widget, and the currency rollups are shown in).

Handled by index
Responses
200Successful Response
POST /app/crm/
1curl -X POST "http://localhost:8000/app/crm/"
1fetch("http://localhost:8000/app/crm/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/crm/")
4print(response.json())
200 Example Response
No Body
POST /app/crm/pipelines undocumented

/app/crm/pipelines

The pipelines card grid. Was the app landing page before the board.

Handled by pipelines_page
Responses
200Successful Response
POST /app/crm/pipelines
1curl -X POST "http://localhost:8000/app/crm/pipelines"
1fetch("http://localhost:8000/app/crm/pipelines", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/crm/pipelines")
4print(response.json())
200 Example Response
No Body
POST /app/crm/deals undocumented

/app/crm/deals

Global deal list: every deal in the workspace, no pipeline required. Pipelines and members are fetched client-side rather than stamped here: a name carrying an apostrophe would break the inline filter config.

Handled by deals_page
Responses
200Successful Response
POST /app/crm/deals
1curl -X POST "http://localhost:8000/app/crm/deals"
1fetch("http://localhost:8000/app/crm/deals", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/crm/deals")
4print(response.json())
200 Example Response
No Body
POST /app/crm/leads undocumented

/app/crm/leads

Leads: contacts in the lead lifecycle, ranked by score, from the projection.

Handled by leads_page
Responses
200Successful Response
POST /app/crm/leads
1curl -X POST "http://localhost:8000/app/crm/leads"
1fetch("http://localhost:8000/app/crm/leads", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/crm/leads")
4print(response.json())
200 Example Response
No Body
POST /app/crm/targets undocumented

/app/crm/targets

Workspace-level targets and the rep leaderboard. The old targets view lived inside one pipeline, which hid every workspace-wide quota and left the leaderboard endpoint with no UI at all.

Handled by targets_page
Responses
200Successful Response
POST /app/crm/targets
1curl -X POST "http://localhost:8000/app/crm/targets"
1fetch("http://localhost:8000/app/crm/targets", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/crm/targets")
4print(response.json())
200 Example Response
No Body
POST /app/crm/scoring undocumented

/app/crm/scoring

Lead and deal scoring rules. Wires the previously orphaned rule form.

Handled by scoring_page
Responses
200Successful Response
POST /app/crm/scoring
1curl -X POST "http://localhost:8000/app/crm/scoring"
1fetch("http://localhost:8000/app/crm/scoring", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/crm/scoring")
4print(response.json())
200 Example Response
No Body
POST /app/feeds/ undocumented

/app/feeds/

Main feeds page — 3-column Twitter-like layout.

Handled by index
Responses
200Successful Response
POST /app/feeds/
1curl -X POST "http://localhost:8000/app/feeds/"
1fetch("http://localhost:8000/app/feeds/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/feeds/")
4print(response.json())
200 Example Response
No Body
POST /app/files/ undocumented

/app/files/

The Files landing page: a MicroDash board over /file-statistics. Nothing is queried here. The board fetches its own data so the widgets can show skeletons while it lands, and so a refresh after an upload is one API call rather than a page render.

Handled by dashboard_page
Responses
200Successful Response
POST /app/files/
1curl -X POST "http://localhost:8000/app/files/"
1fetch("http://localhost:8000/app/files/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/files/")
4print(response.json())
200 Example Response
No Body
POST /app/finance/ undocumented

/app/finance/

Handled by portal_page
Responses
200Successful Response
POST /app/finance/
1curl -X POST "http://localhost:8000/app/finance/"
1fetch("http://localhost:8000/app/finance/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/finance/")
4print(response.json())
200 Example Response
No Body
POST /app/growth/ undocumented

/app/growth/

Handled by index
Responses
200Successful Response
POST /app/growth/
1curl -X POST "http://localhost:8000/app/growth/"
1fetch("http://localhost:8000/app/growth/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/growth/")
4print(response.json())
200 Example Response
No Body
POST /app/leaves/ undocumented

/app/leaves/

Dashboard — balances, upcoming PTOs, pending approvals.

Handled by index
Responses
200Successful Response
POST /app/leaves/
1curl -X POST "http://localhost:8000/app/leaves/"
1fetch("http://localhost:8000/app/leaves/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/leaves/")
4print(response.json())
200 Example Response
No Body
POST /app/settings/ undocumented

/app/settings/

Account tab default view. The Lobby is the workspace home now; Account is a normal tab opened from a Lobby button, so its entry point lands on the member's own profile settings.

Handled by index
Responses
200Successful Response
POST /app/settings/
1curl -X POST "http://localhost:8000/app/settings/"
1fetch("http://localhost:8000/app/settings/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/settings/")
4print(response.json())
200 Example Response
No Body
POST /app/sign/ undocumented

/app/sign/

Sign home: the insights dashboard. Backward compatibility: pre-sidenav deep links used /app/sign/?open={id}; those now land on the owning section (templates or contracts), which opens the builder.

Handled by index
Responses
200Successful Response
POST /app/sign/
1curl -X POST "http://localhost:8000/app/sign/"
1fetch("http://localhost:8000/app/sign/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/sign/")
4print(response.json())
200 Example Response
No Body
POST /app/tasks/ undocumented

/app/tasks/

Handled by index
Responses
200Successful Response
POST /app/tasks/
1curl -X POST "http://localhost:8000/app/tasks/"
1fetch("http://localhost:8000/app/tasks/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/tasks/")
4print(response.json())
200 Example Response
No Body
POST /app/wands/ undocumented

/app/wands/

Overview dashboard — the app's landing page. All numbers arrive via the /wands/stats API (fetched by the page), so the handler stays thin.

Handled by index
Responses
200Successful Response
POST /app/wands/
1curl -X POST "http://localhost:8000/app/wands/"
1fetch("http://localhost:8000/app/wands/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/wands/")
4print(response.json())
200 Example Response
No Body
POST /app/workers/ undocumented

/app/workers/

The Workers landing — the self-service portal (specs/app-access-and-portals.md). Everyone with app access lands here. Holders of workers.portal.view get the portal (their own profile card plus squares per their capabilities, and an "Enter HRIS console" button for HR staff). Members without the key get the request-access wall instead of a dead end. Deliberately has no AUTHZ entry: the branching IS the gate; app access still applies upstream.

Handled by portal_page
Responses
200Successful Response
POST /app/workers/
1curl -X POST "http://localhost:8000/app/workers/"
1fetch("http://localhost:8000/app/workers/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/workers/")
4print(response.json())
200 Example Response
No Body
POST /app/lobby/ undocumented

/app/lobby/

GET/POST /app/lobby/, the workspace home dashboard.

Handled by index
Responses
200Successful Response
POST /app/lobby/
1curl -X POST "http://localhost:8000/app/lobby/"
1fetch("http://localhost:8000/app/lobby/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/app/lobby/")
4print(response.json())
200 Example Response
No Body
GET /applications/:slug/status undocumented

/applications/:slug/status

GET /accounts/apps/status/:slug — Check install status for a specific app.

Handled by api_app_status
Parameters
slug string · path
required
Responses
200Successful Response
GET /applications/example/status
1curl "http://localhost:8000/applications/example/status"
1fetch("http://localhost:8000/applications/example/status")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/applications/example/status")
4print(response.json())
200 Example Response
No Body
POST /applications/:slug/requests undocumented

/applications/:slug/requests

POST /applications/:slug/requests — Request app install (any authenticated member).

Handled by api_request_install
Parameters
slug string · path
required
Responses
200Successful Response
POST /applications/example/requests
1curl -X POST "http://localhost:8000/applications/example/requests"
1fetch("http://localhost:8000/applications/example/requests", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/applications/example/requests")
4print(response.json())
200 Example Response
No Body
GET /apps/:slug/access undocumented

/apps/:slug/access

GET /apps/:slug/access — everything configured for one app, in one envelope: tile access, permission matrix, config document, and exception grants. The audit surface for "who can see what in this app".

Handled by api_app_access
Parameters
slug string · path
required
Responses
200Successful Response
GET /apps/example/access
1curl "http://localhost:8000/apps/example/access"
1fetch("http://localhost:8000/apps/example/access")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/apps/example/access")
4print(response.json())
200 Example Response
No Body
GET /apps/:slug/settings undocumented

/apps/:slug/settings

GET /apps/:slug/settings — the app's effective config document.

Handled by api_get_app_settings
Parameters
slug string · path
required
Responses
200Successful Response
GET /apps/example/settings
1curl "http://localhost:8000/apps/example/settings"
1fetch("http://localhost:8000/apps/example/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/apps/example/settings")
4print(response.json())
200 Example Response
No Body
POST /applications/:slug/installations

Install app

POST /accounts/apps/install — Install an app (admin/owner only).

Handled by api_install_app
Parameters
slug string · path
required
Body · InstallAppapplication/json
access_policy
allowed_roles array
propertyName anything
Responses
200Successful Response
POST /applications/example/installations
1curl -X POST "http://localhost:8000/applications/example/installations" \
2 -H "Content-Type: application/json" \
3 -d '{"access_policy":null,"allowed_roles":["string"]}'
1fetch("http://localhost:8000/applications/example/installations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "access_policy": null,
6 "allowed_roles": [
7 "string"
8 ]
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/applications/example/installations",
5 json={"access_policy":null,"allowed_roles":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /applications/:slug/access-requests

Request access to restricted app

POST /apps/:slug/access-requests — Request access to a restricted app. Notifies all workspace admins (owner + admin roles). Mirrors the install- request flow (api_request_install) but for apps that ARE installed yet gated by access_policy='roles' the requester doesn't hold.

Handled by api_request_access
Parameters
slug string · path
required
Body · RequestAppAccessapplication/json
message string · max length: 280
propertyName anything
Responses
200Successful Response
POST /applications/example/access-requests
1curl -X POST "http://localhost:8000/applications/example/access-requests" \
2 -H "Content-Type: application/json" \
3 -d '{"message":"string"}'
1fetch("http://localhost:8000/applications/example/access-requests", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "message": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/applications/example/access-requests",
5 json={"message":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /applications/:slug/access

Set app access policy

Update which roles can reach an installed app. Body: {access_policy: "everyone"|"roles"|"approval", allowed_roles?: [role_id]} When access_policy is 'everyone' the allowed_roles list is cleared.

Handled by api_update_app_access
Parameters
slug string · path
required
Body · UpdateAppAccessapplication/json
access_policy
required
allowed_roles array
redlist array
propertyName anything
Responses
200Successful Response
PUT /applications/example/access
1curl -X PUT "http://localhost:8000/applications/example/access" \
2 -H "Content-Type: application/json" \
3 -d '{"access_policy":null,"allowed_roles":["string"],"redlist":["string"]}'
1fetch("http://localhost:8000/applications/example/access", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "access_policy": null,
6 "allowed_roles": [
7 "string"
8 ],
9 "redlist": [
10 "string"
11 ]
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/applications/example/access",
5 json={"access_policy":null,"allowed_roles":["string"],"redlist":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /apps/:slug/roles/:role_id/permissions

Set one app's permission slice on a role

PUT /apps/:slug/roles/:role_id/permissions — replace ONE app's slice of a role's permissions. The only role-editing power an app admin has: other apps' slices, platform roles, and role membership are out of reach.

Handled by api_update_app_role_slice
Parameters
slug string · path
required
role_id string · path
required
Body · UpdateAppRoleSliceapplication/json
permissions array
required
propertyName anything
Responses
200Successful Response
PUT /apps/example/roles/example/permissions
1curl -X PUT "http://localhost:8000/apps/example/roles/example/permissions" \
2 -H "Content-Type: application/json" \
3 -d '{"permissions":["string"]}'
1fetch("http://localhost:8000/apps/example/roles/example/permissions", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "permissions": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/apps/example/roles/example/permissions",
5 json={"permissions":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /apps/:slug/settings undocumented

/apps/:slug/settings

PUT /apps/:slug/settings — replace the app's config document. The body is the full document. It is validated against the pytastic schema the app registered via core.appconfig (rule 12's schema-first requirement is satisfied per-app; a static route schema is impossible for a surface whose shape each app defines).

Handled by api_put_app_settings
Parameters
slug string · path
required
Responses
200Successful Response
PUT /apps/example/settings
1curl -X PUT "http://localhost:8000/apps/example/settings"
1fetch("http://localhost:8000/apps/example/settings", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/apps/example/settings")
4print(response.json())
200 Example Response
No Body
GET /assets/* undocumented

/assets/*

Handled by serve_assets
Responses
200Successful Response
GET /assets/*
1curl "http://localhost:8000/assets/*"
1fetch("http://localhost:8000/assets/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/assets/*")
4print(response.json())
200 Example Response
No Body
DELETE /attendance/locations/:id undocumented

/attendance/locations/:id

Permanently delete a location. Workers assigned to it must be reassigned first (the Workers app handles that via its own reassignment endpoint, driven by the delete dialog). Here we just remove the row and emit .deleted so projections drop their copy.

Handled by api_delete_location
Parameters
id string · path
required
Responses
200Successful Response
DELETE /attendance/locations/example
1curl -X DELETE "http://localhost:8000/attendance/locations/example"
1fetch("http://localhost:8000/attendance/locations/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/attendance/locations/example")
4print(response.json())
200 Example Response
No Body
GET /attendance/status undocumented

/attendance/status

Handled by api_get_status
Responses
200Successful Response
GET /attendance/status
1curl "http://localhost:8000/attendance/status"
1fetch("http://localhost:8000/attendance/status")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/attendance/status")
4print(response.json())
200 Example Response
No Body
GET /attendance/entries undocumented

/attendance/entries

Handled by api_list_entries
Responses
200Successful Response
GET /attendance/entries
1curl "http://localhost:8000/attendance/entries"
1fetch("http://localhost:8000/attendance/entries")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/attendance/entries")
4print(response.json())
200 Example Response
No Body
GET /attendance/timesheets undocumented

/attendance/timesheets

Handled by api_list_timesheets
Responses
200Successful Response
GET /attendance/timesheets
1curl "http://localhost:8000/attendance/timesheets"
1fetch("http://localhost:8000/attendance/timesheets")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/attendance/timesheets")
4print(response.json())
200 Example Response
No Body
GET /attendance/timesheets/:id undocumented

/attendance/timesheets/:id

Handled by api_get_timesheet
Parameters
id string · path
required
Responses
200Successful Response
GET /attendance/timesheets/example
1curl "http://localhost:8000/attendance/timesheets/example"
1fetch("http://localhost:8000/attendance/timesheets/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/attendance/timesheets/example")
4print(response.json())
200 Example Response
No Body
GET /attendance/timezones undocumented

/attendance/timezones

Friendly timezone search for the location form's picker. Searchable by city, US state, country, or zone (e.g. "houston", "texas", "port louis"). Returns {timezone, label}; the picker stores the IANA value and shows the label. Reference data only — no workspace scoping needed, but still requires an authenticated session. See core/timezones.py.

Handled by api_search_timezones
Responses
200Successful Response
GET /attendance/timezones
1curl "http://localhost:8000/attendance/timezones"
1fetch("http://localhost:8000/attendance/timezones")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/attendance/timezones")
4print(response.json())
200 Example Response
No Body
GET /attendance/locations undocumented

/attendance/locations

Handled by api_list_locations
Responses
200Successful Response
GET /attendance/locations
1curl "http://localhost:8000/attendance/locations"
1fetch("http://localhost:8000/attendance/locations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/attendance/locations")
4print(response.json())
200 Example Response
No Body
PATCH /attendance/timesheets/:id

Update a timesheet

Handled by api_update_timesheet
Parameters
id string · path
required
Body · UpdateTimesheetapplication/json
status string · min length: 1 · max length: 20
required
propertyName anything
Responses
200Successful Response
PATCH /attendance/timesheets/example
1curl -X PATCH "http://localhost:8000/attendance/timesheets/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":"string"}'
1fetch("http://localhost:8000/attendance/timesheets/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/attendance/timesheets/example",
5 json={"status":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /attendance/locations/:id

Update a location

Handled by api_update_location
Parameters
id string · path
required
Body · UpdateLocationapplication/json
name string · min length: 1 · max length: 120
timezone string · min length: 1 · max length: 64
workdays
work_start string · max length: 5
work_end string · max length: 5
is_default
propertyName anything
Responses
200Successful Response
PATCH /attendance/locations/example
1curl -X PATCH "http://localhost:8000/attendance/locations/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","timezone":"string","workdays":null,"work_start":"string","work_end":"string","is_default":null}'
1fetch("http://localhost:8000/attendance/locations/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "timezone": "string",
7 "workdays": null,
8 "work_start": "string",
9 "work_end": "string",
10 "is_default": null
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/attendance/locations/example",
5 json={"name":"string","timezone":"string","workdays":null,"work_start":"string","work_end":"string","is_default":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /attendance/clock-ins

Clock in

Handled by api_clock_in
Body · ClockInapplication/json
note string · max length: 500
source string · max length: 50
propertyName anything
Responses
200Successful Response
POST /attendance/clock-ins
1curl -X POST "http://localhost:8000/attendance/clock-ins" \
2 -H "Content-Type: application/json" \
3 -d '{"note":"string","source":"string"}'
1fetch("http://localhost:8000/attendance/clock-ins", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "note": "string",
6 "source": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/attendance/clock-ins",
5 json={"note":"string","source":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /attendance/clock-outs

Clock out

Handled by api_clock_out
Body · ClockOutapplication/json
note string · max length: 500
propertyName anything
Responses
200Successful Response
POST /attendance/clock-outs
1curl -X POST "http://localhost:8000/attendance/clock-outs" \
2 -H "Content-Type: application/json" \
3 -d '{"note":"string"}'
1fetch("http://localhost:8000/attendance/clock-outs", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "note": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/attendance/clock-outs",
5 json={"note":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /attendance/locations

Create a location

Handled by api_create_location
Body · CreateLocationapplication/json
name string · min length: 1 · max length: 120
required
timezone string · min length: 1 · max length: 64
required
workdays
work_start string · max length: 5
work_end string · max length: 5
is_default
propertyName anything
Responses
200Successful Response
POST /attendance/locations
1curl -X POST "http://localhost:8000/attendance/locations" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","timezone":"string","workdays":null,"work_start":"string","work_end":"string","is_default":null}'
1fetch("http://localhost:8000/attendance/locations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "timezone": "string",
7 "workdays": null,
8 "work_start": "string",
9 "work_end": "string",
10 "is_default": null
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/attendance/locations",
5 json={"name":"string","timezone":"string","workdays":null,"work_start":"string","work_end":"string","is_default":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /audit undocumented

/audit

GET /audit — audit log feed page.

Handled by audit_page
Responses
200Successful Response
GET /audit
1curl "http://localhost:8000/audit"
1fetch("http://localhost:8000/audit")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/audit")
4print(response.json())
200 Example Response
No Body
POST /sessions/links

Email a sign-in link

POST /sessions/links — mail proof of mailbox for one workspace. Always answers the same way. Whether the address exists, belongs to this workspace, or is a stranger's is not something an unauthenticated caller gets to learn: this endpoint would otherwise be a membership oracle for any workspace whose slug you can guess.

Handled by request_sign_in_link
Body · SignInRequestapplication/json
email string · min length: 1 · email
required
workspace string · min length: 1 · max length: 100
required
propertyName anything
Responses
200Successful Response
POST /sessions/links
1curl -X POST "http://localhost:8000/sessions/links" \
2 -H "Content-Type: application/json" \
3 -d '{"email":"user@example.com","workspace":"string"}'
1fetch("http://localhost:8000/sessions/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "email": "user@example.com",
6 "workspace": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sessions/links",
5 json={"email":"user@example.com","workspace":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sessions

Sign in

POST /sessions — sign in. Three ways in, all landing on the same seat lookup and 2FA gate: * a password (`email` + `password` + `workspace`), * a confirmed link (`token`), * the fast path (`email` + `workspace`) for a caller already holding a live session for that identity, which mints and mails nothing. Whichever route, 2FA is asked for exactly once at the end, and only if the account has it. There is no mailed code: see core/magiclink.py for why.

Handled by login
Body · Loginapplication/json
email string · min length: 1 · email
workspace string · min length: 1 · max length: 100
password string · min length: 1
token string · min length: 1 · max length: 200
totp string · min length: 6 · max length: 8
is_recovery_code
propertyName anything
Responses
200Successful Response
POST /sessions
1curl -X POST "http://localhost:8000/sessions" \
2 -H "Content-Type: application/json" \
3 -d '{"email":"user@example.com","workspace":"string","password":"string","token":"string","totp":"string","is_recovery_code":null}'
1fetch("http://localhost:8000/sessions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "email": "user@example.com",
6 "workspace": "string",
7 "password": "string",
8 "token": "string",
9 "totp": "string",
10 "is_recovery_code": null
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sessions",
5 json={"email":"user@example.com","workspace":"string","password":"string","token":"string","totp":"string","is_recovery_code":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workspaces/lookup

Find a workspace by name

POST /workspaces/lookup — resolve a typed workspace name to its address. Unlike the sign-in endpoints this one DOES confirm existence, because a finder that refuses to say whether it found anything is not a finder. The exposure is small: a workspace slug is already its public subdomain, so this tells an enumerator nothing the DNS name does not. Rate limited by IP to keep that from being cheap at scale.

Handled by lookup_workspace
Body · WorkspaceLookupapplication/json
slug string · min length: 1 · max length: 100
required
propertyName anything
Responses
200Successful Response
POST /workspaces/lookup
1curl -X POST "http://localhost:8000/workspaces/lookup" \
2 -H "Content-Type: application/json" \
3 -d '{"slug":"string"}'
1fetch("http://localhost:8000/workspaces/lookup", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "slug": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workspaces/lookup",
5 json={"slug":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workspaces

Sign up

Handled by signup
Body · Signupapplication/json
company_name string · min length: 1 · max length: 200
required
full_name string · min length: 1 · max length: 200
required
email string · min length: 1 · email
required
terms_agreed
required
company_location string
industry string
company_size string
job_title string
propertyName anything
Responses
200Successful Response
POST /workspaces
1curl -X POST "http://localhost:8000/workspaces" \
2 -H "Content-Type: application/json" \
3 -d '{"company_name":"string","full_name":"string","email":"user@example.com","terms_agreed":null,"company_location":"string","industry":"string","company_size":"string","job_title":"string"}'
1fetch("http://localhost:8000/workspaces", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "company_name": "string",
6 "full_name": "string",
7 "email": "user@example.com",
8 "terms_agreed": null,
9 "company_location": "string",
10 "industry": "string",
11 "company_size": "string",
12 "job_title": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workspaces",
5 json={"company_name":"string","full_name":"string","email":"user@example.com","terms_agreed":null,"company_location":"string","industry":"string","company_size":"string","job_title":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /verifications

Verify OTP

Handled by verify
Body · Verifyapplication/json
code string · min length: 1
required
password string · min length: 8
required
propertyName anything
Responses
200Successful Response
POST /verifications
1curl -X POST "http://localhost:8000/verifications" \
2 -H "Content-Type: application/json" \
3 -d '{"code":"string","password":"string"}'
1fetch("http://localhost:8000/verifications", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "code": "string",
6 "password": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/verifications",
5 json={"code":"string","password":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /invitations/:token

Accept invitation

PUT /invitations/:token — Accept a workspace invitation and set a password. Acceptance flips the membership from "invited" to "joined", which is the gate `_seat` enforces on every sign-in afterwards. Holding the invitation mail already proves the mailbox, so the password chosen here is not a second proof: it is the credential for every sign-in after this one, so that getting in never depends on reaching a mailbox again.

Handled by accept_invitation
Parameters
token string · path
required
Body · AcceptInvitationapplication/json
password string · min length: 8
required
totp string · min length: 6 · max length: 8
propertyName anything
Responses
200Successful Response
PUT /invitations/example
1curl -X PUT "http://localhost:8000/invitations/example" \
2 -H "Content-Type: application/json" \
3 -d '{"password":"string","totp":"string"}'
1fetch("http://localhost:8000/invitations/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "password": "string",
6 "totp": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/invitations/example",
5 json={"password":"string","totp":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /avatars/:member_id undocumented

/avatars/:member_id

DELETE /avatars/:member_id — clear avatar, revert to initials.

Handled by remove_avatar
Parameters
member_id string · path
required
Responses
200Successful Response
DELETE /avatars/example
1curl -X DELETE "http://localhost:8000/avatars/example"
1fetch("http://localhost:8000/avatars/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/avatars/example")
4print(response.json())
200 Example Response
No Body
POST /avatars/:member_id undocumented

/avatars/:member_id

POST /avatars/:member_id — upload profile avatar to R2.

Handled by upload_avatar
Parameters
member_id string · path
required
Responses
200Successful Response
POST /avatars/example
1curl -X POST "http://localhost:8000/avatars/example"
1fetch("http://localhost:8000/avatars/example", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/avatars/example")
4print(response.json())
200 Example Response
No Body
POST /payment-methods

Add payment method

POST /accounts/billing/payment-methods — Add a payment method via Flutterwave v4.

Handled by api_add_payment_method
Body · AddPaymentMethodapplication/json
card_number string · min length: 13 · max length: 19
required
expiry_month string · min length: 1 · max length: 2
required
expiry_year string · min length: 2 · max length: 4
required
cvv string · min length: 3 · max length: 4
required
propertyName anything
Responses
200Successful Response
POST /payment-methods
1curl -X POST "http://localhost:8000/payment-methods" \
2 -H "Content-Type: application/json" \
3 -d '{"card_number":"string","expiry_month":"string","expiry_year":"string","cvv":"string"}'
1fetch("http://localhost:8000/payment-methods", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "card_number": "string",
6 "expiry_month": "string",
7 "expiry_year": "string",
8 "cvv": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/payment-methods",
5 json={"card_number":"string","expiry_month":"string","expiry_year":"string","cvv":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /plan

Switch plan

PUT /plan — Switch plan (tier or Per-App) immediately, with upgrade proration.

Handled by api_switch_plan
Body · SwitchPlanapplication/json
plan
required
propertyName anything
Responses
200Successful Response
PUT /plan
1curl -X PUT "http://localhost:8000/plan" \
2 -H "Content-Type: application/json" \
3 -d '{"plan":null}'
1fetch("http://localhost:8000/plan", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "plan": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/plan",
5 json={"plan":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /plan/interval

Update billing interval

PUT /plan/interval — Switch billing interval (monthly/annual). The live invoice loop reads the interval fresh on its next firing, so no loop surgery is needed for annual→monthly. Switching an ACTIVE workspace TO annual bills the year upfront now: an immediate 'seats' invoice.due is emitted, and the existing monthly loop converts itself to the usage loop when it next fires.

Handled by api_update_billing_interval
Body · UpdateBillingIntervalapplication/json
billing_interval
required
propertyName anything
Responses
200Successful Response
PUT /plan/interval
1curl -X PUT "http://localhost:8000/plan/interval" \
2 -H "Content-Type: application/json" \
3 -d '{"billing_interval":null}'
1fetch("http://localhost:8000/plan/interval", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "billing_interval": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/plan/interval",
5 json={"billing_interval":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/bills/:entry_id

Receive/approve/void a bill

Handled by api_patch_bill
Parameters
entry_id string · path
required
Body · UpdateBillStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/bills/example
1curl -X PATCH "http://localhost:8000/finance/bills/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/bills/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/bills/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/bills

Create a bill

Handled by api_create_bill
Body · CreateBillapplication/json
date string · min length: 10
required
items array
company_mrn string
contact_mrn string
currency string · min length: 3 · max length: 3
required
exchange_rate number
due_date string · min length: 10
memo string · max length: 5000
tags array
sources array
adjustments array
dimensions
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/bills
1curl -X POST "http://localhost:8000/finance/bills" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"sources":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/bills", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "company_mrn": "string",
26 "contact_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "due_date": "string",
30 "memo": "string",
31 "tags": [
32 "string"
33 ],
34 "sources": [
35 "string"
36 ],
37 "adjustments": [
38 {
39 "label": "string",
40 "type": null,
41 "value": 1.5,
42 "amount": 1.5,
43 "account_code": "string"
44 }
45 ],
46 "dimensions": null,
47 "idempotency_key": "string"
48}),
49})
50 .then((res) => res.json())
51 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/bills",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"sources":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/bills/:entry_id

Update a draft bill

Handled by api_update_bill
Parameters
entry_id string · path
required
Body · UpdateBillapplication/json
date string · min length: 10
items array
company_mrn string
contact_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
due_date string · min length: 10
memo string · max length: 5000
tags array
adjustments array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/bills/example
1curl -X PUT "http://localhost:8000/finance/bills/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null}'
1fetch("http://localhost:8000/finance/bills/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "company_mrn": "string",
26 "contact_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "due_date": "string",
30 "memo": "string",
31 "tags": [
32 "string"
33 ],
34 "adjustments": [
35 {
36 "label": "string",
37 "type": null,
38 "value": 1.5,
39 "amount": 1.5,
40 "account_code": "string"
41 }
42 ],
43 "dimensions": null
44}),
45})
46 .then((res) => res.json())
47 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/bills/example",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /boards/:board_id/tasks/:task_id undocumented

/boards/:board_id/tasks/:task_id

Return a single task from the board to the incubator.

Handled by api_return_to_incubator
Parameters
board_id string · path
required
task_id string · path
required
Responses
200Successful Response
DELETE /boards/example/tasks/example
1curl -X DELETE "http://localhost:8000/boards/example/tasks/example"
1fetch("http://localhost:8000/boards/example/tasks/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/boards/example/tasks/example")
4print(response.json())
200 Example Response
No Body
DELETE /boards/:board_id/tasks undocumented

/boards/:board_id/tasks

DELETE /boards/:board_id/tasks?scheduled=false — clear unplanned tasks from board.

Handled by api_clear_unplanned
Parameters
board_id string · path
required
Responses
200Successful Response
DELETE /boards/example/tasks
1curl -X DELETE "http://localhost:8000/boards/example/tasks"
1fetch("http://localhost:8000/boards/example/tasks", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/boards/example/tasks")
4print(response.json())
200 Example Response
No Body
DELETE /boards/:board_id

Delete a board

Handled by api_delete_board
Parameters
board_id string · path
required
Body · DeleteBoardapplication/json
confirm_key string · min length: 1
required
propertyName anything
Responses
200Successful Response
DELETE /boards/example
1curl -X DELETE "http://localhost:8000/boards/example" \
2 -H "Content-Type: application/json" \
3 -d '{"confirm_key":"string"}'
1fetch("http://localhost:8000/boards/example", {
2 method: "DELETE",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "confirm_key": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.delete(
4 "http://localhost:8000/boards/example",
5 json={"confirm_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /boards/:board_id/members/:member_id undocumented

/boards/:board_id/members/:member_id

Handled by api_remove_board_member
Parameters
board_id string · path
required
member_id string · path
required
Responses
200Successful Response
DELETE /boards/example/members/example
1curl -X DELETE "http://localhost:8000/boards/example/members/example"
1fetch("http://localhost:8000/boards/example/members/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/boards/example/members/example")
4print(response.json())
200 Example Response
No Body
GET /boards undocumented

/boards

Handled by api_list_boards
Responses
200Successful Response
GET /boards
1curl "http://localhost:8000/boards"
1fetch("http://localhost:8000/boards")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/boards")
4print(response.json())
200 Example Response
No Body
GET /boards/:board_id/members undocumented

/boards/:board_id/members

Handled by api_list_board_members
Parameters
board_id string · path
required
Responses
200Successful Response
GET /boards/example/members
1curl "http://localhost:8000/boards/example/members"
1fetch("http://localhost:8000/boards/example/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/boards/example/members")
4print(response.json())
200 Example Response
No Body
PATCH /boards/:board_id

Rename a topic

Rename a topic across all tasks in a board.

Handled by api_rename_topic
Parameters
board_id string · path
required
Body · RenameTopicapplication/json
old_name string · min length: 1
required
new_name string · min length: 1
required
propertyName anything
Responses
200Successful Response
PATCH /boards/example
1curl -X PATCH "http://localhost:8000/boards/example" \
2 -H "Content-Type: application/json" \
3 -d '{"old_name":"string","new_name":"string"}'
1fetch("http://localhost:8000/boards/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "old_name": "string",
6 "new_name": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/boards/example",
5 json={"old_name":"string","new_name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /boards/:board_id/columns

Rename a board column

Rename a board column (lane) and update all tasks referencing it.

Handled by api_rename_lane
Parameters
board_id string · path
required
Body · RenameTopicapplication/json
old_name string · min length: 1
required
new_name string · min length: 1
required
propertyName anything
Responses
200Successful Response
PATCH /boards/example/columns
1curl -X PATCH "http://localhost:8000/boards/example/columns" \
2 -H "Content-Type: application/json" \
3 -d '{"old_name":"string","new_name":"string"}'
1fetch("http://localhost:8000/boards/example/columns", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "old_name": "string",
6 "new_name": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/boards/example/columns",
5 json={"old_name":"string","new_name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /boards/:board_id/members/:member_id

Change a project member's role

Handled by api_update_board_member
Parameters
board_id string · path
required
member_id string · path
required
Body · UpdateBoardMemberapplication/json
role
required
propertyName anything
Responses
200Successful Response
PATCH /boards/example/members/example
1curl -X PATCH "http://localhost:8000/boards/example/members/example" \
2 -H "Content-Type: application/json" \
3 -d '{"role":null}'
1fetch("http://localhost:8000/boards/example/members/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "role": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/boards/example/members/example",
5 json={"role":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /boards

Create a board

Handled by api_create_board
Body · CreateBoardapplication/json
title string · min length: 1 · max length: 200
required
description string · max length: 2000
template_id string
is_template
grid object
propertyName anything
Responses
200Successful Response
POST /boards
1curl -X POST "http://localhost:8000/boards" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","description":"string","template_id":"string","is_template":null,"grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}}'
1fetch("http://localhost:8000/boards", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "description": "string",
7 "template_id": "string",
8 "is_template": null,
9 "grid": {
10 "mode": null,
11 "spacing": 1,
12 "snap": null,
13 "background": "string",
14 "default_sticky_color": "string"
15 }
16}),
17})
18 .then((res) => res.json())
19 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/boards",
5 json={"title":"string","description":"string","template_id":"string","is_template":null,"grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /boards/:board_id/tasks

Pull tasks onto a board

POST /boards/:board_id/tasks — pull tasks from incubator onto a board. Accepts either explicit task_ids or a schedule_id, exactly one. With schedule_id, every incubator task in that schedule is pulled at once.

Handled by api_pull_tasks
Parameters
board_id string · path
required
Body · PullTasksapplication/json
task_ids array
schedule_id string
propertyName anything
Responses
200Successful Response
POST /boards/example/tasks
1curl -X POST "http://localhost:8000/boards/example/tasks" \
2 -H "Content-Type: application/json" \
3 -d '{"task_ids":["string"],"schedule_id":"string"}'
1fetch("http://localhost:8000/boards/example/tasks", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "task_ids": [
6 "string"
7 ],
8 "schedule_id": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/boards/example/tasks",
5 json={"task_ids":["string"],"schedule_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /boards/:board_id/members

Add a project member

Handled by api_add_board_member
Parameters
board_id string · path
required
Body · AddBoardMemberapplication/json
member_id string · min length: 1
required
role
required
propertyName anything
Responses
200Successful Response
POST /boards/example/members
1curl -X POST "http://localhost:8000/boards/example/members" \
2 -H "Content-Type: application/json" \
3 -d '{"member_id":"string","role":null}'
1fetch("http://localhost:8000/boards/example/members", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "member_id": "string",
6 "role": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/boards/example/members",
5 json={"member_id":"string","role":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /views

Save a board view

Handled by api_create_saved_view
Body · CreateSavedViewapplication/json
board_id string
required
name string · min length: 1 · max length: 80
required
tab string · min length: 1 · max length: 40
required
schedule_id string
propertyName anything
Responses
200Successful Response
POST /views
1curl -X POST "http://localhost:8000/views" \
2 -H "Content-Type: application/json" \
3 -d '{"board_id":"string","name":"string","tab":"string","schedule_id":"string"}'
1fetch("http://localhost:8000/views", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "board_id": "string",
6 "name": "string",
7 "tab": "string",
8 "schedule_id": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/views",
5 json={"board_id":"string","name":"string","tab":"string","schedule_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /boards/:board_id

Update board settings

Update board settings (name, description, columns).

Handled by api_update_board
Parameters
board_id string · path
required
Body · UpdateBoardapplication/json
title string · min length: 1 · max length: 200
description string · max length: 2000
grid object
propertyName anything
Responses
200Successful Response
PUT /boards/example
1curl -X PUT "http://localhost:8000/boards/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","description":"string","grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}}'
1fetch("http://localhost:8000/boards/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "description": "string",
7 "grid": {
8 "mode": null,
9 "spacing": 1,
10 "snap": null,
11 "background": "string",
12 "default_sticky_color": "string"
13 }
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/boards/example",
5 json={"title":"string","description":"string","grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/budgets/:budget_id

Update a budget

Handled by handler
Parameters
budget_id string · path
required
Body · BudgetEntryapplication/json
account_id string · min length: 1
required
period_start string · min length: 10
required
period_end string · min length: 10
required
amount number
required
dimensions object
notes string · max length: 2000
propertyName anything
Responses
200Successful Response
PATCH /finance/budgets/example
1curl -X PATCH "http://localhost:8000/finance/budgets/example" \
2 -H "Content-Type: application/json" \
3 -d '{"account_id":"string","period_start":"string","period_end":"string","amount":1.5,"dimensions":{"department":"string","location":"string","project":"string"},"notes":"string"}'
1fetch("http://localhost:8000/finance/budgets/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "account_id": "string",
6 "period_start": "string",
7 "period_end": "string",
8 "amount": 1.5,
9 "dimensions": {
10 "department": "string",
11 "location": "string",
12 "project": "string"
13 },
14 "notes": "string"
15}),
16})
17 .then((res) => res.json())
18 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/budgets/example",
5 json={"account_id":"string","period_start":"string","period_end":"string","amount":1.5,"dimensions":{"department":"string","location":"string","project":"string"},"notes":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/budgets

Create a budget

Handled by handler
Body · BudgetEntryapplication/json
account_id string · min length: 1
required
period_start string · min length: 10
required
period_end string · min length: 10
required
amount number
required
dimensions object
notes string · max length: 2000
propertyName anything
Responses
200Successful Response
POST /finance/budgets
1curl -X POST "http://localhost:8000/finance/budgets" \
2 -H "Content-Type: application/json" \
3 -d '{"account_id":"string","period_start":"string","period_end":"string","amount":1.5,"dimensions":{"department":"string","location":"string","project":"string"},"notes":"string"}'
1fetch("http://localhost:8000/finance/budgets", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "account_id": "string",
6 "period_start": "string",
7 "period_end": "string",
8 "amount": 1.5,
9 "dimensions": {
10 "department": "string",
11 "location": "string",
12 "project": "string"
13 },
14 "notes": "string"
15}),
16})
17 .then((res) => res.json())
18 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/budgets",
5 json={"account_id":"string","period_start":"string","period_end":"string","amount":1.5,"dimensions":{"department":"string","location":"string","project":"string"},"notes":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /calls/:id undocumented

/calls/:id

Handled by api_delete_call
Parameters
id string · path
required
Responses
200Successful Response
DELETE /calls/example
1curl -X DELETE "http://localhost:8000/calls/example"
1fetch("http://localhost:8000/calls/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/calls/example")
4print(response.json())
200 Example Response
No Body
DELETE /calls/:id/participants/:member_mrn undocumented

/calls/:id/participants/:member_mrn

Handled by api_remove_participant
Parameters
id string · path
required
member_mrn string · path
required
Responses
200Successful Response
DELETE /calls/example/participants/example
1curl -X DELETE "http://localhost:8000/calls/example/participants/example"
1fetch("http://localhost:8000/calls/example/participants/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/calls/example/participants/example")
4print(response.json())
200 Example Response
No Body
DELETE /calls/:id/sessions undocumented

/calls/:id/sessions

Handled by api_leave_call
Parameters
id string · path
required
Responses
200Successful Response
DELETE /calls/example/sessions
1curl -X DELETE "http://localhost:8000/calls/example/sessions"
1fetch("http://localhost:8000/calls/example/sessions", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/calls/example/sessions")
4print(response.json())
200 Example Response
No Body
DELETE /calls/:id/recordings/:recording_id undocumented

/calls/:id/recordings/:recording_id

Handled by api_delete_recording
Parameters
id string · path
required
recording_id string · path
required
Responses
200Successful Response
DELETE /calls/example/recordings/example
1curl -X DELETE "http://localhost:8000/calls/example/recordings/example"
1fetch("http://localhost:8000/calls/example/recordings/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/calls/example/recordings/example")
4print(response.json())
200 Example Response
No Body
GET /calls undocumented

/calls

Handled by api_list_calls
Responses
200Successful Response
GET /calls
1curl "http://localhost:8000/calls"
1fetch("http://localhost:8000/calls")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls")
4print(response.json())
200 Example Response
No Body
GET /calls/:id undocumented

/calls/:id

Handled by api_get_call
Parameters
id string · path
required
Responses
200Successful Response
GET /calls/example
1curl "http://localhost:8000/calls/example"
1fetch("http://localhost:8000/calls/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls/example")
4print(response.json())
200 Example Response
No Body
GET /calls/:id/participants undocumented

/calls/:id/participants

Handled by api_list_participants
Parameters
id string · path
required
Responses
200Successful Response
GET /calls/example/participants
1curl "http://localhost:8000/calls/example/participants"
1fetch("http://localhost:8000/calls/example/participants")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls/example/participants")
4print(response.json())
200 Example Response
No Body
GET /calls/:id/admission undocumented

/calls/:id/admission

Poll endpoint for a member who knocked under the lobby policy. Mirrors the guest admission poll. Returns one of: - {state: 'waiting'} — host hasn't decided yet - {state: 'denied'} — host declined - {state: 'admitted'} — host let them in; the member then navigates to the room, where api_join_call mints their LK token - {state: 'idle'} — no pending knock for this member

Handled by api_member_admission_status
Parameters
id string · path
required
Responses
200Successful Response
GET /calls/example/admission
1curl "http://localhost:8000/calls/example/admission"
1fetch("http://localhost:8000/calls/example/admission")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls/example/admission")
4print(response.json())
200 Example Response
No Body
GET /calls/:id/links undocumented

/calls/:id/links

Handled by api_list_links
Parameters
id string · path
required
Responses
200Successful Response
GET /calls/example/links
1curl "http://localhost:8000/calls/example/links"
1fetch("http://localhost:8000/calls/example/links")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls/example/links")
4print(response.json())
200 Example Response
No Body
GET /calls/:id/messages undocumented

/calls/:id/messages

Handled by api_list_messages
Parameters
id string · path
required
Responses
200Successful Response
GET /calls/example/messages
1curl "http://localhost:8000/calls/example/messages"
1fetch("http://localhost:8000/calls/example/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls/example/messages")
4print(response.json())
200 Example Response
No Body
GET /calls/:id/recordings undocumented

/calls/:id/recordings

Handled by api_list_recordings
Parameters
id string · path
required
Responses
200Successful Response
GET /calls/example/recordings
1curl "http://localhost:8000/calls/example/recordings"
1fetch("http://localhost:8000/calls/example/recordings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls/example/recordings")
4print(response.json())
200 Example Response
No Body
PATCH /calls/:id

Update a call

Handled by api_update_call
Parameters
id string · path
required
Body · UpdateCallapplication/json
title string · max length: 200
scheduled_at string
status
format
access_policy
settings object
attendees_can_mic
attendees_can_camera
attendees_can_screenshare
attendees_can_chat
hide_attendee_tiles
propertyName anything
Responses
200Successful Response
PATCH /calls/example
1curl -X PATCH "http://localhost:8000/calls/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","scheduled_at":"string","status":null,"format":null,"access_policy":null,"settings":{"waiting_room":null,"allow_screen_share":null,"mute_on_join":null,"record":null},"attendees_can_mic":null,"attendees_can_camera":null,"attendees_can_screenshare":null,"attendees_can_chat":null,"hide_attendee_tiles":null}'
1fetch("http://localhost:8000/calls/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "scheduled_at": "string",
7 "status": null,
8 "format": null,
9 "access_policy": null,
10 "settings": {
11 "waiting_room": null,
12 "allow_screen_share": null,
13 "mute_on_join": null,
14 "record": null
15 },
16 "attendees_can_mic": null,
17 "attendees_can_camera": null,
18 "attendees_can_screenshare": null,
19 "attendees_can_chat": null,
20 "hide_attendee_tiles": null
21}),
22})
23 .then((res) => res.json())
24 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/calls/example",
5 json={"title":"string","scheduled_at":"string","status":null,"format":null,"access_policy":null,"settings":{"waiting_room":null,"allow_screen_share":null,"mute_on_join":null,"record":null},"attendees_can_mic":null,"attendees_can_camera":null,"attendees_can_screenshare":null,"attendees_can_chat":null,"hide_attendee_tiles":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /calls

Create a call

Handled by api_create_call
Body · CreateCallapplication/json
type
required
mode
format
title string · max length: 200
participants array
source_mrn string
scheduled_at string
max_participants integer · min: 2 · max: 200
access_policy
settings object
external_invitees_text string · max length: 4000
propertyName anything
Responses
200Successful Response
POST /calls
1curl -X POST "http://localhost:8000/calls" \
2 -H "Content-Type: application/json" \
3 -d '{"type":null,"mode":null,"format":null,"title":"string","participants":["string"],"source_mrn":"string","scheduled_at":"string","max_participants":1,"access_policy":null,"settings":{"waiting_room":null,"allow_screen_share":null,"mute_on_join":null,"record":null},"external_invitees_text":"string"}'
1fetch("http://localhost:8000/calls", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "type": null,
6 "mode": null,
7 "format": null,
8 "title": "string",
9 "participants": [
10 "string"
11 ],
12 "source_mrn": "string",
13 "scheduled_at": "string",
14 "max_participants": 1,
15 "access_policy": null,
16 "settings": {
17 "waiting_room": null,
18 "allow_screen_share": null,
19 "mute_on_join": null,
20 "record": null
21 },
22 "external_invitees_text": "string"
23}),
24})
25 .then((res) => res.json())
26 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/calls",
5 json={"type":null,"mode":null,"format":null,"title":"string","participants":["string"],"source_mrn":"string","scheduled_at":"string","max_participants":1,"access_policy":null,"settings":{"waiting_room":null,"allow_screen_share":null,"mute_on_join":null,"record":null},"external_invitees_text":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /calls/:id/sessions undocumented

/calls/:id/sessions

Handled by api_join_call
Parameters
id string · path
required
Responses
200Successful Response
POST /calls/example/sessions
1curl -X POST "http://localhost:8000/calls/example/sessions"
1fetch("http://localhost:8000/calls/example/sessions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/calls/example/sessions")
4print(response.json())
200 Example Response
No Body
POST /calls/:id/sessions/leave undocumented

/calls/:id/sessions/leave

Handled by api_leave_call
Parameters
id string · path
required
Responses
200Successful Response
POST /calls/example/sessions/leave
1curl -X POST "http://localhost:8000/calls/example/sessions/leave"
1fetch("http://localhost:8000/calls/example/sessions/leave", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/calls/example/sessions/leave")
4print(response.json())
200 Example Response
No Body
POST /calls/:id/token undocumented

/calls/:id/token

Mint a fresh LiveKit token for a call the member is already in. Used by the client's proactive refresh timer before the current token's `exp` kicks in. No side effects — does not update participant status or emit events.

Handled by api_refresh_call_token
Parameters
id string · path
required
Responses
200Successful Response
POST /calls/example/token
1curl -X POST "http://localhost:8000/calls/example/token"
1fetch("http://localhost:8000/calls/example/token", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/calls/example/token")
4print(response.json())
200 Example Response
No Body
POST /calls/:id/recordings/:recording_id/parts undocumented

/calls/:id/recordings/:recording_id/parts

Receive one chunk of an in-progress recording and stream it into R2 as a multipart part. Binary multipart body (not JSON). Host-only. The server holds at most one part (~8 MiB) in memory, so even long recordings never balloon it.

Handled by api_upload_recording_part
Parameters
id string · path
required
recording_id string · path
required
Responses
200Successful Response
POST /calls/example/recordings/example/parts
1curl -X POST "http://localhost:8000/calls/example/recordings/example/parts"
1fetch("http://localhost:8000/calls/example/recordings/example/parts", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/calls/example/recordings/example/parts")
4print(response.json())
200 Example Response
No Body
POST /chats/:id/call-requests

Request a call from chat

POST /chats/:id/call-requests — ask the Calls app to start a call.

Handled by api_request_call
Parameters
id string · path
required
Body · RequestCallapplication/json
mode
propertyName anything
Responses
200Successful Response
POST /chats/example/call-requests
1curl -X POST "http://localhost:8000/chats/example/call-requests" \
2 -H "Content-Type: application/json" \
3 -d '{"mode":null}'
1fetch("http://localhost:8000/chats/example/call-requests", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "mode": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/chats/example/call-requests",
5 json={"mode":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /calls/:call_id undocumented

/calls/:call_id

Handled by call_page
Parameters
call_id string · path
required
Responses
200Successful Response
GET /calls/example
1curl "http://localhost:8000/calls/example"
1fetch("http://localhost:8000/calls/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/calls/example")
4print(response.json())
200 Example Response
No Body
DELETE /canvas/boards/:board_id undocumented

/canvas/boards/:board_id

DELETE /canvas/boards/:board_id — soft-delete + drop grants (owner only).

Handled by api_delete_board
Parameters
board_id string · path
required
Responses
200Successful Response
DELETE /canvas/boards/example
1curl -X DELETE "http://localhost:8000/canvas/boards/example"
1fetch("http://localhost:8000/canvas/boards/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/canvas/boards/example")
4print(response.json())
200 Example Response
No Body
DELETE /canvas/boards/:board_id/comments/:comment_id undocumented

/canvas/boards/:board_id/comments/:comment_id

DELETE /canvas/boards/:board_id/comments/:comment_id — author or board manager.

Handled by api_delete_comment
Parameters
board_id string · path
required
comment_id string · path
required
Responses
200Successful Response
DELETE /canvas/boards/example/comments/example
1curl -X DELETE "http://localhost:8000/canvas/boards/example/comments/example"
1fetch("http://localhost:8000/canvas/boards/example/comments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/canvas/boards/example/comments/example")
4print(response.json())
200 Example Response
No Body
DELETE /canvas/boards/:board_id/vote-sessions/:session_id/votes/:object_id undocumented

/canvas/boards/:board_id/vote-sessions/:session_id/votes/:object_id

DELETE /canvas/boards/:board_id/vote-sessions/:session_id/votes/:object_id. Takes back ONE of the caller's votes on that object (a session that allows repeats can hold several), and only ever their own.

Handled by api_remove_vote
Parameters
board_id string · path
required
session_id string · path
required
object_id string · path
required
Responses
200Successful Response
DELETE /canvas/boards/example/vote-sessions/example/votes/example
1curl -X DELETE "http://localhost:8000/canvas/boards/example/vote-sessions/example/votes/example"
1fetch("http://localhost:8000/canvas/boards/example/vote-sessions/example/votes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/canvas/boards/example/vote-sessions/example/votes/example")
4print(response.json())
200 Example Response
No Body
DELETE /canvas/boards/:board_id/exports/:target undocumented

/canvas/boards/:board_id/exports/:target

DELETE /canvas/boards/:board_id/exports/:target — take this board's saved exports back out of Files. Files refuses to delete anything Canvas owns, so removing an export has to happen here, in the app that put it there.

Handled by api_delete_export
Parameters
board_id string · path
required
target string · path
required
Responses
200Successful Response
DELETE /canvas/boards/example/exports/example
1curl -X DELETE "http://localhost:8000/canvas/boards/example/exports/example"
1fetch("http://localhost:8000/canvas/boards/example/exports/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/canvas/boards/example/exports/example")
4print(response.json())
200 Example Response
No Body
GET /canvas/boards undocumented

/canvas/boards

GET /canvas/boards — boards the caller can access. ?is_template=true filters templates.

Handled by api_list_boards
Responses
200Successful Response
GET /canvas/boards
1curl "http://localhost:8000/canvas/boards"
1fetch("http://localhost:8000/canvas/boards")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/canvas/boards")
4print(response.json())
200 Example Response
No Body
GET /canvas/templates undocumented

/canvas/templates

GET /canvas/templates — sugar for ?is_template=true.

Handled by api_list_templates
Responses
200Successful Response
GET /canvas/templates
1curl "http://localhost:8000/canvas/templates"
1fetch("http://localhost:8000/canvas/templates")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/canvas/templates")
4print(response.json())
200 Example Response
No Body
GET /canvas/boards/:board_id undocumented

/canvas/boards/:board_id

GET /canvas/boards/:board_id — board metadata (no content).

Handled by api_get_board
Parameters
board_id string · path
required
Responses
200Successful Response
GET /canvas/boards/example
1curl "http://localhost:8000/canvas/boards/example"
1fetch("http://localhost:8000/canvas/boards/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/canvas/boards/example")
4print(response.json())
200 Example Response
No Body
GET /canvas/boards/:board_id/content undocumented

/canvas/boards/:board_id/content

GET /canvas/boards/:board_id/content — opaque board content to bootstrap the client.

Handled by api_get_content
Parameters
board_id string · path
required
Responses
200Successful Response
GET /canvas/boards/example/content
1curl "http://localhost:8000/canvas/boards/example/content"
1fetch("http://localhost:8000/canvas/boards/example/content")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/canvas/boards/example/content")
4print(response.json())
200 Example Response
No Body
GET /canvas/boards/:board_id/comments undocumented

/canvas/boards/:board_id/comments

GET /canvas/boards/:board_id/comments — threaded comments for a board.

Handled by api_list_comments
Parameters
board_id string · path
required
Responses
200Successful Response
GET /canvas/boards/example/comments
1curl "http://localhost:8000/canvas/boards/example/comments"
1fetch("http://localhost:8000/canvas/boards/example/comments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/canvas/boards/example/comments")
4print(response.json())
200 Example Response
No Body
GET /canvas/boards/:board_id/vote-sessions undocumented

/canvas/boards/:board_id/vote-sessions

GET /canvas/boards/:board_id/vote-sessions — history, newest first.

Handled by api_list_vote_sessions
Parameters
board_id string · path
required
Responses
200Successful Response
GET /canvas/boards/example/vote-sessions
1curl "http://localhost:8000/canvas/boards/example/vote-sessions"
1fetch("http://localhost:8000/canvas/boards/example/vote-sessions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/canvas/boards/example/vote-sessions")
4print(response.json())
200 Example Response
No Body
GET /canvas/boards/:board_id/vote-sessions/:session_id undocumented

/canvas/boards/:board_id/vote-sessions/:session_id

GET /canvas/boards/:board_id/vote-sessions/:session_id — one session + counts.

Handled by api_get_vote_session
Parameters
board_id string · path
required
session_id string · path
required
Responses
200Successful Response
GET /canvas/boards/example/vote-sessions/example
1curl "http://localhost:8000/canvas/boards/example/vote-sessions/example"
1fetch("http://localhost:8000/canvas/boards/example/vote-sessions/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/canvas/boards/example/vote-sessions/example")
4print(response.json())
200 Example Response
No Body
PATCH /canvas/boards/:board_id

Update a board

PATCH /canvas/boards/:board_id — title, description, grid settings.

Handled by api_update_board
Parameters
board_id string · path
required
Body · UpdateBoardapplication/json
title string · min length: 1 · max length: 200
description string · max length: 2000
grid object
propertyName anything
Responses
200Successful Response
PATCH /canvas/boards/example
1curl -X PATCH "http://localhost:8000/canvas/boards/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","description":"string","grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}}'
1fetch("http://localhost:8000/canvas/boards/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "description": "string",
7 "grid": {
8 "mode": null,
9 "spacing": 1,
10 "snap": null,
11 "background": "string",
12 "default_sticky_color": "string"
13 }
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/canvas/boards/example",
5 json={"title":"string","description":"string","grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /canvas/boards/:board_id/content

Save board content

PATCH /canvas/boards/:board_id/content — persist the (debounced) content snapshot.

Handled by api_save_content
Parameters
board_id string · path
required
Body · SaveContentapplication/json
ydoc_state string · min length: 1
required
thumbnail_key string · max length: 512
restore_snapshot_id string
asset_ids array
propertyName anything
Responses
200Successful Response
PATCH /canvas/boards/example/content
1curl -X PATCH "http://localhost:8000/canvas/boards/example/content" \
2 -H "Content-Type: application/json" \
3 -d '{"ydoc_state":"string","thumbnail_key":"string","restore_snapshot_id":"string","asset_ids":["string"]}'
1fetch("http://localhost:8000/canvas/boards/example/content", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "ydoc_state": "string",
6 "thumbnail_key": "string",
7 "restore_snapshot_id": "string",
8 "asset_ids": [
9 "string"
10 ]
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/canvas/boards/example/content",
5 json={"ydoc_state":"string","thumbnail_key":"string","restore_snapshot_id":"string","asset_ids":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /canvas/boards/:board_id/comments/:comment_id

Edit/resolve a comment

PATCH /canvas/boards/:board_id/comments/:comment_id — edit body (author) or resolve.

Handled by api_update_comment
Parameters
board_id string · path
required
comment_id string · path
required
Body · UpdateCommentapplication/json
body string · min length: 1 · max length: 4000
resolved
propertyName anything
Responses
200Successful Response
PATCH /canvas/boards/example/comments/example
1curl -X PATCH "http://localhost:8000/canvas/boards/example/comments/example" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string","resolved":null}'
1fetch("http://localhost:8000/canvas/boards/example/comments/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string",
6 "resolved": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/canvas/boards/example/comments/example",
5 json={"body":"string","resolved":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /canvas/boards/:board_id/vote-sessions/:session_id

Close a vote session

PATCH /canvas/boards/:board_id/vote-sessions/:session_id — close the round. Closing freezes the tally into `results` so history survives the board being edited afterwards, and stops badges reading from a session nobody is in.

Handled by api_update_vote_session
Parameters
board_id string · path
required
session_id string · path
required
Body · UpdateVoteSessionapplication/json
status
required
object_labels array
propertyName anything
Responses
200Successful Response
PATCH /canvas/boards/example/vote-sessions/example
1curl -X PATCH "http://localhost:8000/canvas/boards/example/vote-sessions/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null,"object_labels":[{"object_id":"string","label":"string"}]}'
1fetch("http://localhost:8000/canvas/boards/example/vote-sessions/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null,
6 "object_labels": [
7 {
8 "object_id": "string",
9 "label": "string"
10 }
11 ]
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/canvas/boards/example/vote-sessions/example",
5 json={"status":null,"object_labels":[{"object_id":"string","label":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /canvas/boards

Create a board

POST /canvas/boards — create a board (optionally cloned from a template).

Handled by api_create_board
Body · CreateBoardapplication/json
title string · min length: 1 · max length: 200
required
description string · max length: 2000
template_id string
is_template
grid object
propertyName anything
Responses
200Successful Response
POST /canvas/boards
1curl -X POST "http://localhost:8000/canvas/boards" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","description":"string","template_id":"string","is_template":null,"grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}}'
1fetch("http://localhost:8000/canvas/boards", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "description": "string",
7 "template_id": "string",
8 "is_template": null,
9 "grid": {
10 "mode": null,
11 "spacing": 1,
12 "snap": null,
13 "background": "string",
14 "default_sticky_color": "string"
15 }
16}),
17})
18 .then((res) => res.json())
19 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/canvas/boards",
5 json={"title":"string","description":"string","template_id":"string","is_template":null,"grid":{"mode":null,"spacing":1,"snap":null,"background":"string","default_sticky_color":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /canvas/boards/:board_id/duplications undocumented

/canvas/boards/:board_id/duplications

POST /canvas/boards/:board_id/duplications — copy a board (or instantiate a template).

Handled by api_duplicate_board
Parameters
board_id string · path
required
Responses
200Successful Response
POST /canvas/boards/example/duplications
1curl -X POST "http://localhost:8000/canvas/boards/example/duplications"
1fetch("http://localhost:8000/canvas/boards/example/duplications", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/canvas/boards/example/duplications")
4print(response.json())
200 Example Response
No Body
POST /canvas/boards/:board_id/assets

Register a board image

POST /canvas/boards/:board_id/assets — register an uploaded board image. Called by the editor right after the platform upload confirm so the asset is servable immediately, instead of waiting on the upload-confirmed event round trip. The event handler in events.py remains the idempotent backup.

Handled by api_create_asset
Parameters
board_id string · path
required
Body · CreateAssetapplication/json
asset_id string · min length: 6 · max length: 64
required
storage_key string · min length: 1 · max length: 512
required
filename string · min length: 1 · max length: 255
required
content_type string · min length: 1 · max length: 100
required
size_bytes integer · min: 0
required
width integer · min: 0
height integer · min: 0
propertyName anything
Responses
200Successful Response
POST /canvas/boards/example/assets
1curl -X POST "http://localhost:8000/canvas/boards/example/assets" \
2 -H "Content-Type: application/json" \
3 -d '{"asset_id":"string","storage_key":"string","filename":"string","content_type":"string","size_bytes":1,"width":1,"height":1}'
1fetch("http://localhost:8000/canvas/boards/example/assets", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "asset_id": "string",
6 "storage_key": "string",
7 "filename": "string",
8 "content_type": "string",
9 "size_bytes": 1,
10 "width": 1,
11 "height": 1
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/canvas/boards/example/assets",
5 json={"asset_id":"string","storage_key":"string","filename":"string","content_type":"string","size_bytes":1,"width":1,"height":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /canvas/boards/:board_id/comments

Add a comment

POST /canvas/boards/:board_id/comments — add a comment.

Handled by api_create_comment
Parameters
board_id string · path
required
Body · CreateCommentapplication/json
body string · min length: 1 · max length: 4000
required
object_id string · max length: 64
parent_id string · max length: 64
nx number
ny number
propertyName anything
Responses
200Successful Response
POST /canvas/boards/example/comments
1curl -X POST "http://localhost:8000/canvas/boards/example/comments" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string","object_id":"string","parent_id":"string","nx":1.5,"ny":1.5}'
1fetch("http://localhost:8000/canvas/boards/example/comments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string",
6 "object_id": "string",
7 "parent_id": "string",
8 "nx": 1.5,
9 "ny": 1.5
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/canvas/boards/example/comments",
5 json={"body":"string","object_id":"string","parent_id":"string","nx":1.5,"ny":1.5},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /canvas/boards/:board_id/vote-sessions

Start a vote session

POST /canvas/boards/:board_id/vote-sessions — open a round of dot voting.

Handled by api_start_vote_session
Parameters
board_id string · path
required
Body · StartVoteSessionapplication/json
label string · max length: 120
max_votes_per_member integer · min: 1 · max: 99
allow_repeat_votes
scope_frame_id string · max length: 64
scope_ids array
propertyName anything
Responses
200Successful Response
POST /canvas/boards/example/vote-sessions
1curl -X POST "http://localhost:8000/canvas/boards/example/vote-sessions" \
2 -H "Content-Type: application/json" \
3 -d '{"label":"string","max_votes_per_member":1,"allow_repeat_votes":null,"scope_frame_id":"string","scope_ids":["string"]}'
1fetch("http://localhost:8000/canvas/boards/example/vote-sessions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "label": "string",
6 "max_votes_per_member": 1,
7 "allow_repeat_votes": null,
8 "scope_frame_id": "string",
9 "scope_ids": [
10 "string"
11 ]
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/canvas/boards/example/vote-sessions",
5 json={"label":"string","max_votes_per_member":1,"allow_repeat_votes":null,"scope_frame_id":"string","scope_ids":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /canvas/boards/:board_id/vote-sessions/:session_id/votes

Cast a vote

POST /canvas/boards/:board_id/vote-sessions/:session_id/votes — spend one vote.

Handled by api_cast_vote
Parameters
board_id string · path
required
session_id string · path
required
Body · CastVoteapplication/json
object_id string · min length: 1 · max length: 64
required
propertyName anything
Responses
200Successful Response
POST /canvas/boards/example/vote-sessions/example/votes
1curl -X POST "http://localhost:8000/canvas/boards/example/vote-sessions/example/votes" \
2 -H "Content-Type: application/json" \
3 -d '{"object_id":"string"}'
1fetch("http://localhost:8000/canvas/boards/example/vote-sessions/example/votes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "object_id": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/canvas/boards/example/vote-sessions/example/votes",
5 json={"object_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /canvas/boards/:board_id/exports

Export a board

POST /canvas/boards/:board_id/exports — download is client-side; target=files persists the client-rendered image to R2 and emits an event Files ingests.

Handled by api_export_board
Parameters
board_id string · path
required
Body · ExportBoardapplication/json
format
required
target
data_url string · min length: 1
filename string · max length: 200
propertyName anything
Responses
200Successful Response
POST /canvas/boards/example/exports
1curl -X POST "http://localhost:8000/canvas/boards/example/exports" \
2 -H "Content-Type: application/json" \
3 -d '{"format":null,"target":null,"data_url":"string","filename":"string"}'
1fetch("http://localhost:8000/canvas/boards/example/exports", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "format": null,
6 "target": null,
7 "data_url": "string",
8 "filename": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/canvas/boards/example/exports",
5 json={"format":null,"target":null,"data_url":"string","filename":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /chats/:id

Update a chat

PATCH /chats/:id — update group name, description, or avatar.

Handled by api_update_chat
Parameters
id string · path
required
Body · UpdateChatapplication/json
name string · max length: 100
description string · max length: 500
avatar_key string
propertyName anything
Responses
200Successful Response
PATCH /chats/example
1curl -X PATCH "http://localhost:8000/chats/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","avatar_key":"string"}'
1fetch("http://localhost:8000/chats/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "avatar_key": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/chats/example",
5 json={"name":"string","description":"string","avatar_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /chats

Create a chat

POST /chats — create a conversation.

Handled by api_create_chat
Body · CreateChatapplication/json
type
required
name string · min length: 1 · max length: 100
description string · max length: 500
participants array
required
propertyName anything
Responses
200Successful Response
POST /chats
1curl -X POST "http://localhost:8000/chats" \
2 -H "Content-Type: application/json" \
3 -d '{"type":null,"name":"string","description":"string","participants":["string"]}'
1fetch("http://localhost:8000/chats", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "type": null,
6 "name": "string",
7 "description": "string",
8 "participants": [
9 "string"
10 ]
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/chats",
5 json={"type":null,"name":"string","description":"string","participants":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /chats/:id undocumented

/chats/:id

DELETE /chats/:id — delete a conversation. For a DM this is per-member: it clears the chat from the caller's own view only, leaving the other participant's copy and history intact. The chat reappears for them if a new message arrives, showing only the post-delete history. For a group it removes the conversation for everyone, so it needs the in-chat admin role or the workspace-wide manage override.

Handled by api_delete_chat
Parameters
id string · path
required
Responses
200Successful Response
DELETE /chats/example
1curl -X DELETE "http://localhost:8000/chats/example"
1fetch("http://localhost:8000/chats/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/example")
4print(response.json())
200 Example Response
No Body
DELETE /chats/:id/messages undocumented

/chats/:id/messages

DELETE /chats/:id/messages — clear the conversation for the caller only.

Handled by api_clear_chat
Parameters
id string · path
required
Responses
200Successful Response
DELETE /chats/example/messages
1curl -X DELETE "http://localhost:8000/chats/example/messages"
1fetch("http://localhost:8000/chats/example/messages", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/example/messages")
4print(response.json())
200 Example Response
No Body
DELETE /chats/:id/messages/:msg_id undocumented

/chats/:id/messages/:msg_id

DELETE /chats/:id/messages/:msg_id — soft-delete a message.

Handled by api_delete_message
Parameters
id string · path
required
msg_id string · path
required
Responses
200Successful Response
DELETE /chats/example/messages/example
1curl -X DELETE "http://localhost:8000/chats/example/messages/example"
1fetch("http://localhost:8000/chats/example/messages/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/example/messages/example")
4print(response.json())
200 Example Response
No Body
DELETE /chats/:id/messages/:msg_id/reactions/:emoji undocumented

/chats/:id/messages/:msg_id/reactions/:emoji

DELETE /chats/:id/messages/:msg_id/reactions/:emoji — remove a reaction.

Handled by api_remove_reaction
Parameters
id string · path
required
msg_id string · path
required
emoji string · path
required
Responses
200Successful Response
DELETE /chats/example/messages/example/reactions/example
1curl -X DELETE "http://localhost:8000/chats/example/messages/example/reactions/example"
1fetch("http://localhost:8000/chats/example/messages/example/reactions/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/example/messages/example/reactions/example")
4print(response.json())
200 Example Response
No Body
DELETE /chats/:id/participants/:member_mrn undocumented

/chats/:id/participants/:member_mrn

DELETE /chats/:id/participants/:member_mrn — remove from a group, or leave.

Handled by api_remove_participant
Parameters
id string · path
required
member_mrn string · path
required
Responses
200Successful Response
DELETE /chats/example/participants/example
1curl -X DELETE "http://localhost:8000/chats/example/participants/example"
1fetch("http://localhost:8000/chats/example/participants/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/example/participants/example")
4print(response.json())
200 Example Response
No Body
DELETE /chats/lists/:list_id undocumented

/chats/lists/:list_id

DELETE /chats/lists/:list_id — delete a personal list. chat_list_items.list_id cascades, so memberships go with it instead of lingering as tags pointing at a list that no longer exists.

Handled by api_delete_chat_list
Parameters
list_id string · path
required
Responses
200Successful Response
DELETE /chats/lists/example
1curl -X DELETE "http://localhost:8000/chats/lists/example"
1fetch("http://localhost:8000/chats/lists/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/lists/example")
4print(response.json())
200 Example Response
No Body
DELETE /chats/:id/favourite undocumented

/chats/:id/favourite

DELETE /chats/:id/favourite — remove the favourite mark (per-user).

Handled by api_unfavourite_chat
Parameters
id string · path
required
Responses
200Successful Response
DELETE /chats/example/favourite
1curl -X DELETE "http://localhost:8000/chats/example/favourite"
1fetch("http://localhost:8000/chats/example/favourite", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/example/favourite")
4print(response.json())
200 Example Response
No Body
DELETE /chats/:id/lists/:list_id undocumented

/chats/:id/lists/:list_id

DELETE /chats/:id/lists/:list_id — remove the chat from one of the lists.

Handled by api_remove_chat_from_list
Parameters
id string · path
required
list_id string · path
required
Responses
200Successful Response
DELETE /chats/example/lists/example
1curl -X DELETE "http://localhost:8000/chats/example/lists/example"
1fetch("http://localhost:8000/chats/example/lists/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/chats/example/lists/example")
4print(response.json())
200 Example Response
No Body
GET /chats undocumented

/chats

GET /chats — the caller's conversations, newest first.

Handled by api_list_chats
Responses
200Successful Response
GET /chats
1curl "http://localhost:8000/chats"
1fetch("http://localhost:8000/chats")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/chats")
4print(response.json())
200 Example Response
No Body
GET /chats/:id undocumented

/chats/:id

GET /chats/:id — conversation details.

Handled by api_get_chat
Parameters
id string · path
required
Responses
200Successful Response
GET /chats/example
1curl "http://localhost:8000/chats/example"
1fetch("http://localhost:8000/chats/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/chats/example")
4print(response.json())
200 Example Response
No Body
GET /chats/:id/messages undocumented

/chats/:id/messages

GET /chats/:id/messages — messages in a conversation.

Handled by api_list_messages
Parameters
id string · path
required
Responses
200Successful Response
GET /chats/example/messages
1curl "http://localhost:8000/chats/example/messages"
1fetch("http://localhost:8000/chats/example/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/chats/example/messages")
4print(response.json())
200 Example Response
No Body
GET /chats/:id/messages/:msg_id/receipts undocumented

/chats/:id/messages/:msg_id/receipts

GET /chats/:id/messages/:msg_id/receipts — who has read a message.

Handled by api_message_receipts
Parameters
id string · path
required
msg_id string · path
required
Responses
200Successful Response
GET /chats/example/messages/example/receipts
1curl "http://localhost:8000/chats/example/messages/example/receipts"
1fetch("http://localhost:8000/chats/example/messages/example/receipts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/chats/example/messages/example/receipts")
4print(response.json())
200 Example Response
No Body
GET /chats/:id/participants undocumented

/chats/:id/participants

GET /chats/:id/participants — list participants.

Handled by api_list_participants
Parameters
id string · path
required
Responses
200Successful Response
GET /chats/example/participants
1curl "http://localhost:8000/chats/example/participants"
1fetch("http://localhost:8000/chats/example/participants")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/chats/example/participants")
4print(response.json())
200 Example Response
No Body
GET /chats/lists undocumented

/chats/lists

GET /chats/lists — the caller's personal chat lists, ordered.

Handled by api_list_chat_lists
Responses
200Successful Response
GET /chats/lists
1curl "http://localhost:8000/chats/lists"
1fetch("http://localhost:8000/chats/lists")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/chats/lists")
4print(response.json())
200 Example Response
No Body
PUT /chats/:id/read undocumented

/chats/:id/read

PUT /chats/:id/read — mark a conversation as read.

Handled by api_mark_read
Parameters
id string · path
required
Responses
200Successful Response
PUT /chats/example/read
1curl -X PUT "http://localhost:8000/chats/example/read"
1fetch("http://localhost:8000/chats/example/read", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/chats/example/read")
4print(response.json())
200 Example Response
No Body
PUT /chats/:id/favourite undocumented

/chats/:id/favourite

PUT /chats/:id/favourite — mark the chat as a favourite (per-user).

Handled by api_favourite_chat
Parameters
id string · path
required
Responses
200Successful Response
PUT /chats/example/favourite
1curl -X PUT "http://localhost:8000/chats/example/favourite"
1fetch("http://localhost:8000/chats/example/favourite", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/chats/example/favourite")
4print(response.json())
200 Example Response
No Body
PUT /chats/:id/lists/:list_id undocumented

/chats/:id/lists/:list_id

PUT /chats/:id/lists/:list_id — add the chat to one of the caller's lists.

Handled by api_add_chat_to_list
Parameters
id string · path
required
list_id string · path
required
Responses
200Successful Response
PUT /chats/example/lists/example
1curl -X PUT "http://localhost:8000/chats/example/lists/example"
1fetch("http://localhost:8000/chats/example/lists/example", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/chats/example/lists/example")
4print(response.json())
200 Example Response
No Body
PATCH /checklists/:checklist_id/workers/:worker_id/items/:item_id

Toggle an assignment item

Handled by api_toggle_assignment_item
Parameters
checklist_id string · path
required
worker_id string · path
required
item_id string · path
required
Body · UpdateAssignmentItemapplication/json
completed
required
propertyName anything
Responses
200Successful Response
PATCH /checklists/example/workers/example/items/example
1curl -X PATCH "http://localhost:8000/checklists/example/workers/example/items/example" \
2 -H "Content-Type: application/json" \
3 -d '{"completed":null}'
1fetch("http://localhost:8000/checklists/example/workers/example/items/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "completed": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/checklists/example/workers/example/items/example",
5 json={"completed":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /checklists/:checklist_id/workers

Assign a checklist to a worker

Handled by api_assign_checklist
Parameters
checklist_id string · path
required
Body · AssignChecklistapplication/json
worker_id string · min length: 1
required
due_date string
anchor_date string · max length: 10
responsible_worker_id string
propertyName anything
Responses
200Successful Response
POST /checklists/example/workers
1curl -X POST "http://localhost:8000/checklists/example/workers" \
2 -H "Content-Type: application/json" \
3 -d '{"worker_id":"string","due_date":"string","anchor_date":"string","responsible_worker_id":"string"}'
1fetch("http://localhost:8000/checklists/example/workers", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "worker_id": "string",
6 "due_date": "string",
7 "anchor_date": "string",
8 "responsible_worker_id": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/checklists/example/workers",
5 json={"worker_id":"string","due_date":"string","anchor_date":"string","responsible_worker_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /checklists/:checklist_id/workers/:worker_id

Update assignment status

Handled by api_update_assignment
Parameters
checklist_id string · path
required
worker_id string · path
required
Body · UpdateAssignmentapplication/json
status
due_date string
anchor_date string · max length: 10
responsible_worker_id string
propertyName anything
Responses
200Successful Response
PUT /checklists/example/workers/example
1curl -X PUT "http://localhost:8000/checklists/example/workers/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null,"due_date":"string","anchor_date":"string","responsible_worker_id":"string"}'
1fetch("http://localhost:8000/checklists/example/workers/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null,
6 "due_date": "string",
7 "anchor_date": "string",
8 "responsible_worker_id": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/checklists/example/workers/example",
5 json={"status":null,"due_date":"string","anchor_date":"string","responsible_worker_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /checklists/:checklist_id undocumented

/checklists/:checklist_id

Handled by api_delete_checklist
Parameters
checklist_id string · path
required
Responses
200Successful Response
DELETE /checklists/example
1curl -X DELETE "http://localhost:8000/checklists/example"
1fetch("http://localhost:8000/checklists/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/checklists/example")
4print(response.json())
200 Example Response
No Body
DELETE /checklists/:checklist_id/workers/:worker_id undocumented

/checklists/:checklist_id/workers/:worker_id

Handled by api_delete_assignment
Parameters
checklist_id string · path
required
worker_id string · path
required
Responses
200Successful Response
DELETE /checklists/example/workers/example
1curl -X DELETE "http://localhost:8000/checklists/example/workers/example"
1fetch("http://localhost:8000/checklists/example/workers/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/checklists/example/workers/example")
4print(response.json())
200 Example Response
No Body
GET /checklists undocumented

/checklists

Handled by api_list_checklists
Responses
200Successful Response
GET /checklists
1curl "http://localhost:8000/checklists"
1fetch("http://localhost:8000/checklists")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/checklists")
4print(response.json())
200 Example Response
No Body
GET /checklists/:checklist_id undocumented

/checklists/:checklist_id

Handled by api_get_checklist
Parameters
checklist_id string · path
required
Responses
200Successful Response
GET /checklists/example
1curl "http://localhost:8000/checklists/example"
1fetch("http://localhost:8000/checklists/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/checklists/example")
4print(response.json())
200 Example Response
No Body
GET /checklists/:checklist_id/workers undocumented

/checklists/:checklist_id/workers

Handled by api_list_assignments
Parameters
checklist_id string · path
required
Responses
200Successful Response
GET /checklists/example/workers
1curl "http://localhost:8000/checklists/example/workers"
1fetch("http://localhost:8000/checklists/example/workers")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/checklists/example/workers")
4print(response.json())
200 Example Response
No Body
POST /checklists

Create a checklist template

Handled by api_create_checklist
Body · CreateChecklistapplication/json
type
required
title string · min length: 1 · max length: 200
required
items array
auto_assign object
propertyName anything
Responses
200Successful Response
POST /checklists
1curl -X POST "http://localhost:8000/checklists" \
2 -H "Content-Type: application/json" \
3 -d '{"type":null,"title":"string","items":[{"name":"string","id":"string","description":"string","link":"string","owner_kind":null,"owner_worker_id":"string","due_offset_days":1}],"auto_assign":{"enabled":null,"trigger":null,"department_ids":["string"]}}'
1fetch("http://localhost:8000/checklists", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "type": null,
6 "title": "string",
7 "items": [
8 {
9 "name": "string",
10 "id": "string",
11 "description": "string",
12 "link": "string",
13 "owner_kind": null,
14 "owner_worker_id": "string",
15 "due_offset_days": 1
16 }
17 ],
18 "auto_assign": {
19 "enabled": null,
20 "trigger": null,
21 "department_ids": [
22 "string"
23 ]
24 }
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/checklists",
5 json={"type":null,"title":"string","items":[{"name":"string","id":"string","description":"string","link":"string","owner_kind":null,"owner_worker_id":"string","due_offset_days":1}],"auto_assign":{"enabled":null,"trigger":null,"department_ids":["string"]}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /checklists/:checklist_id

Update a checklist template

Handled by api_update_checklist
Parameters
checklist_id string · path
required
Body · UpdateChecklistapplication/json
title string · min length: 1 · max length: 200
type
items array
auto_assign object
propertyName anything
Responses
200Successful Response
PUT /checklists/example
1curl -X PUT "http://localhost:8000/checklists/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","type":null,"items":[{"name":"string","id":"string","description":"string","link":"string","owner_kind":null,"owner_worker_id":"string","due_offset_days":1}],"auto_assign":{"enabled":null,"trigger":null,"department_ids":["string"]}}'
1fetch("http://localhost:8000/checklists/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "type": null,
7 "items": [
8 {
9 "name": "string",
10 "id": "string",
11 "description": "string",
12 "link": "string",
13 "owner_kind": null,
14 "owner_worker_id": "string",
15 "due_offset_days": 1
16 }
17 ],
18 "auto_assign": {
19 "enabled": null,
20 "trigger": null,
21 "department_ids": [
22 "string"
23 ]
24 }
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/checklists/example",
5 json={"title":"string","type":null,"items":[{"name":"string","id":"string","description":"string","link":"string","owner_kind":null,"owner_worker_id":"string","due_offset_days":1}],"auto_assign":{"enabled":null,"trigger":null,"department_ids":["string"]}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /companies/:company_id undocumented

/companies/:company_id

DELETE /companies/:company_id — delete company (fails if contacts still linked).

Handled by api_delete_company
Parameters
company_id string · path
required
Responses
200Successful Response
DELETE /companies/example
1curl -X DELETE "http://localhost:8000/companies/example"
1fetch("http://localhost:8000/companies/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/companies/example")
4print(response.json())
200 Example Response
No Body
GET /companies undocumented

/companies

GET /companies — list companies with filters.

Handled by api_list_companies
Responses
200Successful Response
GET /companies
1curl "http://localhost:8000/companies"
1fetch("http://localhost:8000/companies")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/companies")
4print(response.json())
200 Example Response
No Body
GET /companies/:company_id undocumented

/companies/:company_id

GET /companies/:company_id — get company with contacts and recent interactions.

Handled by api_get_company
Parameters
company_id string · path
required
Responses
200Successful Response
GET /companies/example
1curl "http://localhost:8000/companies/example"
1fetch("http://localhost:8000/companies/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/companies/example")
4print(response.json())
200 Example Response
No Body
GET /companies/:company_id/interactions undocumented

/companies/:company_id/interactions

GET /companies/:company_id/interactions — interactions for a company (across all contacts).

Handled by api_list_company_interactions
Parameters
company_id string · path
required
Responses
200Successful Response
GET /companies/example/interactions
1curl "http://localhost:8000/companies/example/interactions"
1fetch("http://localhost:8000/companies/example/interactions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/companies/example/interactions")
4print(response.json())
200 Example Response
No Body
POST /companies

Create a company

POST /companies — create a company.

Handled by api_create_company
Body · CreateCompanyapplication/json
name string · min length: 1 · max length: 200
required
domain string · max length: 200
industry string · max length: 100
size
website string · max length: 500
address string · max length: 500
phone string · max length: 50
annual_revenue string · max length: 50
tags array
owner_mrn string
notes string · max length: 5000
propertyName anything
Responses
200Successful Response
POST /companies
1curl -X POST "http://localhost:8000/companies" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","domain":"string","industry":"string","size":null,"website":"string","address":"string","phone":"string","annual_revenue":"string","tags":["string"],"owner_mrn":"string","notes":"string"}'
1fetch("http://localhost:8000/companies", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "domain": "string",
7 "industry": "string",
8 "size": null,
9 "website": "string",
10 "address": "string",
11 "phone": "string",
12 "annual_revenue": "string",
13 "tags": [
14 "string"
15 ],
16 "owner_mrn": "string",
17 "notes": "string"
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/companies",
5 json={"name":"string","domain":"string","industry":"string","size":null,"website":"string","address":"string","phone":"string","annual_revenue":"string","tags":["string"],"owner_mrn":"string","notes":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /companies/:company_id

Update a company

PUT /companies/:company_id — update a company.

Handled by api_update_company
Parameters
company_id string · path
required
Body · UpdateCompanyapplication/json
name string · min length: 1 · max length: 200
domain string · max length: 200
industry string · max length: 100
size
website string · max length: 500
address string · max length: 500
phone string · max length: 50
annual_revenue string · max length: 50
tags array
owner_mrn string
notes string · max length: 5000
propertyName anything
Responses
200Successful Response
PUT /companies/example
1curl -X PUT "http://localhost:8000/companies/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","domain":"string","industry":"string","size":null,"website":"string","address":"string","phone":"string","annual_revenue":"string","tags":["string"],"owner_mrn":"string","notes":"string"}'
1fetch("http://localhost:8000/companies/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "domain": "string",
7 "industry": "string",
8 "size": null,
9 "website": "string",
10 "address": "string",
11 "phone": "string",
12 "annual_revenue": "string",
13 "tags": [
14 "string"
15 ],
16 "owner_mrn": "string",
17 "notes": "string"
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/companies/example",
5 json={"name":"string","domain":"string","industry":"string","size":null,"website":"string","address":"string","phone":"string","annual_revenue":"string","tags":["string"],"owner_mrn":"string","notes":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /compensation/:compensation_id undocumented

/compensation/:compensation_id

Handled by api_delete_compensation
Parameters
compensation_id string · path
required
Responses
200Successful Response
DELETE /compensation/example
1curl -X DELETE "http://localhost:8000/compensation/example"
1fetch("http://localhost:8000/compensation/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/compensation/example")
4print(response.json())
200 Example Response
No Body
GET /compensation undocumented

/compensation

All workers with their latest compensation record.

Handled by api_list_all_compensation
Responses
200Successful Response
GET /compensation
1curl "http://localhost:8000/compensation"
1fetch("http://localhost:8000/compensation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/compensation")
4print(response.json())
200 Example Response
No Body
GET /compensation/changes undocumented

/compensation/changes

Recent compensation changes across all workers.

Handled by api_list_compensation_changes
Responses
200Successful Response
GET /compensation/changes
1curl "http://localhost:8000/compensation/changes"
1fetch("http://localhost:8000/compensation/changes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/compensation/changes")
4print(response.json())
200 Example Response
No Body
POST /workers/:worker_id/compensation

Add compensation record

Handled by api_create_compensation
Parameters
worker_id string · path
required
Body · CreateCompensationapplication/json
effective_date string · min length: 1
required
items array
required
reason string · max length: 500
notes string · max length: 2000
propertyName anything
Responses
200Successful Response
POST /workers/example/compensation
1curl -X POST "http://localhost:8000/workers/example/compensation" \
2 -H "Content-Type: application/json" \
3 -d '{"effective_date":"string","items":[{"type":"string","label":"string","amount":1.5,"currency":"string","frequency":null}],"reason":"string","notes":"string"}'
1fetch("http://localhost:8000/workers/example/compensation", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "effective_date": "string",
6 "items": [
7 {
8 "type": "string",
9 "label": "string",
10 "amount": 1.5,
11 "currency": "string",
12 "frequency": null
13 }
14 ],
15 "reason": "string",
16 "notes": "string"
17}),
18})
19 .then((res) => res.json())
20 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/example/compensation",
5 json={"effective_date":"string","items":[{"type":"string","label":"string","amount":1.5,"currency":"string","frequency":null}],"reason":"string","notes":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /contacts/suggestions/:suggestion_id undocumented

/contacts/suggestions/:suggestion_id

DELETE /contacts/suggestions/:suggestion_id — drop a suggestion outright.

Handled by api_delete_suggestion
Parameters
suggestion_id string · path
required
Responses
200Successful Response
DELETE /contacts/suggestions/example
1curl -X DELETE "http://localhost:8000/contacts/suggestions/example"
1fetch("http://localhost:8000/contacts/suggestions/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/contacts/suggestions/example")
4print(response.json())
200 Example Response
No Body
DELETE /contacts/:contact_id undocumented

/contacts/:contact_id

DELETE /contacts/:contact_id — delete a contact with soft warning if MRN-referenced.

Handled by api_delete_contact
Parameters
contact_id string · path
required
Responses
200Successful Response
DELETE /contacts/example
1curl -X DELETE "http://localhost:8000/contacts/example"
1fetch("http://localhost:8000/contacts/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/contacts/example")
4print(response.json())
200 Example Response
No Body
GET /contacts undocumented

/contacts

GET /contacts — list contacts with filters.

Handled by api_list_contacts
Responses
200Successful Response
GET /contacts
1curl "http://localhost:8000/contacts"
1fetch("http://localhost:8000/contacts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts")
4print(response.json())
200 Example Response
No Body
GET /contacts/search undocumented

/contacts/search

GET /contacts/search — unified search across contacts and companies.

Handled by api_search
Responses
200Successful Response
GET /contacts/search
1curl "http://localhost:8000/contacts/search"
1fetch("http://localhost:8000/contacts/search")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/search")
4print(response.json())
200 Example Response
No Body
GET /contacts/suggestions undocumented

/contacts/suggestions

GET /contacts/suggestions — the pending review queue, most active first.

Handled by api_list_suggestions
Responses
200Successful Response
GET /contacts/suggestions
1curl "http://localhost:8000/contacts/suggestions"
1fetch("http://localhost:8000/contacts/suggestions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/suggestions")
4print(response.json())
200 Example Response
No Body
GET /contacts/dashboard undocumented

/contacts/dashboard

GET /contacts/dashboard — everything the board renders, in one round trip. Every figure is aggregated in SQL rather than by counting serialized rows, so a workspace with fifty thousand contacts still renders a dashboard. The kit only ever fetches members and preferences itself; app data comes from here (specs/dashboard-kit.md, rule 1).

Handled by api_dashboard
Responses
200Successful Response
GET /contacts/dashboard
1curl "http://localhost:8000/contacts/dashboard"
1fetch("http://localhost:8000/contacts/dashboard")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/dashboard")
4print(response.json())
200 Example Response
No Body
GET /contacts/exports undocumented

/contacts/exports

GET /contacts/exports — CSV of contacts or companies, filters applied. The same filters the directory is showing, so what downloads is what the person is looking at rather than the whole table.

Handled by api_export_contacts
Responses
200Successful Response
GET /contacts/exports
1curl "http://localhost:8000/contacts/exports"
1fetch("http://localhost:8000/contacts/exports")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/exports")
4print(response.json())
200 Example Response
No Body
GET /contacts/duplicates undocumented

/contacts/duplicates

GET /contacts/duplicates — merge candidates, worth-a-look first. Two cheap heuristics, both from the spec: the same name under different addresses, and the same address differing only in casing. No fuzzy matching: a wrong suggestion here costs somebody a destructive merge.

Handled by api_list_duplicates
Responses
200Successful Response
GET /contacts/duplicates
1curl "http://localhost:8000/contacts/duplicates"
1fetch("http://localhost:8000/contacts/duplicates")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/duplicates")
4print(response.json())
200 Example Response
No Body
GET /contacts/settings undocumented

/contacts/settings

GET /contacts/settings — named embed configurations and snippets.

Handled by api_get_settings
Responses
200Successful Response
GET /contacts/settings
1curl "http://localhost:8000/contacts/settings"
1fetch("http://localhost:8000/contacts/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/settings")
4print(response.json())
200 Example Response
No Body
GET /contacts/:contact_id undocumented

/contacts/:contact_id

GET /contacts/:contact_id — get contact with company info and recent interactions.

Handled by api_get_contact
Parameters
contact_id string · path
required
Responses
200Successful Response
GET /contacts/example
1curl "http://localhost:8000/contacts/example"
1fetch("http://localhost:8000/contacts/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/example")
4print(response.json())
200 Example Response
No Body
GET /contacts/:contact_id/interactions undocumented

/contacts/:contact_id/interactions

GET /contacts/:contact_id/interactions — interactions for a contact.

Handled by api_list_contact_interactions
Parameters
contact_id string · path
required
Responses
200Successful Response
GET /contacts/example/interactions
1curl "http://localhost:8000/contacts/example/interactions"
1fetch("http://localhost:8000/contacts/example/interactions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/contacts/example/interactions")
4print(response.json())
200 Example Response
No Body
PATCH /contacts/suggestions/:suggestion_id

Accept or dismiss a contact suggestion

PATCH /contacts/suggestions/:suggestion_id — accept or dismiss. ``accepted`` promotes the address to a real contact (with domain/company auto-link, as a manual create would) and clears the suggestion. ``dismissed`` hides it for good — the upsert keeps it dismissed thereafter.

Handled by api_update_suggestion
Parameters
suggestion_id string · path
required
Body · UpdateSuggestionapplication/json
status
required
name string · min length: 1 · max length: 200
company_id string
propertyName anything
Responses
200Successful Response
PATCH /contacts/suggestions/example
1curl -X PATCH "http://localhost:8000/contacts/suggestions/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null,"name":"string","company_id":"string"}'
1fetch("http://localhost:8000/contacts/suggestions/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null,
6 "name": "string",
7 "company_id": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/contacts/suggestions/example",
5 json={"status":null,"name":"string","company_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /contacts

Create a contact

POST /contacts — create a contact with domain extraction and auto company linking.

Handled by api_create_contact
Body · CreateContactapplication/json
name string · min length: 1 · max length: 200
required
email string · min length: 1 · max length: 200
required
phone string · max length: 50
mobile string · max length: 50
secondary_email string · max length: 200
title string · max length: 100
department string · max length: 100
company_id string
linkedin_url string · max length: 500
website string · max length: 500
social_url string · max length: 500
address string · max length: 500
tags array
role string · max length: 50
lifecycle_stage
preferred_channel
timezone string · max length: 60
birthday string · max length: 10
avatar_url string · max length: 500
notes string · max length: 5000
custom_fields array
owner_mrn string
source
propertyName anything
Responses
200Successful Response
POST /contacts
1curl -X POST "http://localhost:8000/contacts" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","email":"string","phone":"string","mobile":"string","secondary_email":"string","title":"string","department":"string","company_id":"string","linkedin_url":"string","website":"string","social_url":"string","address":"string","tags":["string"],"role":"string","lifecycle_stage":null,"preferred_channel":null,"timezone":"string","birthday":"string","avatar_url":"string","notes":"string","custom_fields":[{"key":"string","value":"string"}],"owner_mrn":"string","source":null}'
1fetch("http://localhost:8000/contacts", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "email": "string",
7 "phone": "string",
8 "mobile": "string",
9 "secondary_email": "string",
10 "title": "string",
11 "department": "string",
12 "company_id": "string",
13 "linkedin_url": "string",
14 "website": "string",
15 "social_url": "string",
16 "address": "string",
17 "tags": [
18 "string"
19 ],
20 "role": "string",
21 "lifecycle_stage": null,
22 "preferred_channel": null,
23 "timezone": "string",
24 "birthday": "string",
25 "avatar_url": "string",
26 "notes": "string",
27 "custom_fields": [
28 {
29 "key": "string",
30 "value": "string"
31 }
32 ],
33 "owner_mrn": "string",
34 "source": null
35}),
36})
37 .then((res) => res.json())
38 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/contacts",
5 json={"name":"string","email":"string","phone":"string","mobile":"string","secondary_email":"string","title":"string","department":"string","company_id":"string","linkedin_url":"string","website":"string","social_url":"string","address":"string","tags":["string"],"role":"string","lifecycle_stage":null,"preferred_channel":null,"timezone":"string","birthday":"string","avatar_url":"string","notes":"string","custom_fields":[{"key":"string","value":"string"}],"owner_mrn":"string","source":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /contacts/imports

Import contacts from CSV

POST /contacts/imports — CSV import with a column mapping. Deduped by email: a row whose address already exists UPDATES that contact rather than creating a second one. That is the whole point. An import that silently doubles a directory is worse than one that refuses to run. Rows without a usable email are reported back rather than dropped silently, so the person importing can see exactly what did not land.

Handled by api_import_contacts
Body · ImportContactsapplication/json
csv string · min length: 1 · max length: 2000000
required
mappings array
required
has_header
company_id string
propertyName anything
Responses
200Successful Response
POST /contacts/imports
1curl -X POST "http://localhost:8000/contacts/imports" \
2 -H "Content-Type: application/json" \
3 -d '{"csv":"string","mappings":[{"column":"string","field":"string"}],"has_header":null,"company_id":"string"}'
1fetch("http://localhost:8000/contacts/imports", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "csv": "string",
6 "mappings": [
7 {
8 "column": "string",
9 "field": "string"
10 }
11 ],
12 "has_header": null,
13 "company_id": "string"
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/contacts/imports",
5 json={"csv":"string","mappings":[{"column":"string","field":"string"}],"has_header":null,"company_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /contacts/settings/widget-keys undocumented

/contacts/settings/widget-keys

POST /contacts/settings/widget-keys — rotate the first embed's key. Kept for callers that predate named embeds. Prefer ``POST /contacts/settings/embeds/:embed_id/rotate-key``.

Handled by api_rotate_widget_key
Responses
200Successful Response
POST /contacts/settings/widget-keys
1curl -X POST "http://localhost:8000/contacts/settings/widget-keys"
1fetch("http://localhost:8000/contacts/settings/widget-keys", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/contacts/settings/widget-keys")
4print(response.json())
200 Example Response
No Body
POST /contacts/settings/embeds/:embed_id/rotate-key undocumented

/contacts/settings/embeds/:embed_id/rotate-key

POST /contacts/settings/embeds/:embed_id/rotate-key — rotate one embed.

Handled by api_rotate_embed_key
Parameters
embed_id string · path
required
Responses
200Successful Response
POST /contacts/settings/embeds/example/rotate-key
1curl -X POST "http://localhost:8000/contacts/settings/embeds/example/rotate-key"
1fetch("http://localhost:8000/contacts/settings/embeds/example/rotate-key", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/contacts/settings/embeds/example/rotate-key")
4print(response.json())
200 Example Response
No Body
POST /contacts/:contact_id/merges

Merge a duplicate into this contact

POST /contacts/:id/merges — fold a duplicate into this contact. The survivor keeps everything it already had; blanks fill from the duplicate. Interactions, conversations and timeline rows re-point, then the duplicate row is deleted and consuming apps are told to re-point their party projections. Deliberately not reversible, and deliberately not a soft delete: a tombstone row would keep the duplicate resolvable through every lookup that made it a problem in the first place.

Handled by api_merge_contacts
Parameters
contact_id string · path
required
Body · MergeContactsapplication/json
duplicate_id string · min length: 1
required
propertyName anything
Responses
200Successful Response
POST /contacts/example/merges
1curl -X POST "http://localhost:8000/contacts/example/merges" \
2 -H "Content-Type: application/json" \
3 -d '{"duplicate_id":"string"}'
1fetch("http://localhost:8000/contacts/example/merges", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "duplicate_id": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/contacts/example/merges",
5 json={"duplicate_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /contacts/settings

Configure the website chat widget

PUT /contacts/settings — create or update named website chat embeds. Keys are never taken from the client. Enabling an embed for the first time mints one; rotation is its own endpoint.

Handled by api_update_settings
Body · UpdateContactsSettingsapplication/json
embeds array
widget object
propertyName anything
Responses
200Successful Response
PUT /contacts/settings
1curl -X PUT "http://localhost:8000/contacts/settings" \
2 -H "Content-Type: application/json" \
3 -d '{"embeds":[{"id":"string","name":"string","enabled":null,"allowed_origins":["string"],"greeting":"string","subtitle":"string","color":"string","position":null,"allow_uploads":null,"fields":{"name":null,"email":null,"phone":null}}],"widget":{"enabled":null,"allowed_origins":["string"],"greeting":"string","subtitle":"string","color":"string","position":null,"allow_uploads":null,"fields":{"name":null,"email":null,"phone":null}}}'
1fetch("http://localhost:8000/contacts/settings", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "embeds": [
6 {
7 "id": "string",
8 "name": "string",
9 "enabled": null,
10 "allowed_origins": [
11 "string"
12 ],
13 "greeting": "string",
14 "subtitle": "string",
15 "color": "string",
16 "position": null,
17 "allow_uploads": null,
18 "fields": {
19 "name": null,
20 "email": null,
21 "phone": null
22 }
23 }
24 ],
25 "widget": {
26 "enabled": null,
27 "allowed_origins": [
28 "string"
29 ],
30 "greeting": "string",
31 "subtitle": "string",
32 "color": "string",
33 "position": null,
34 "allow_uploads": null,
35 "fields": {
36 "name": null,
37 "email": null,
38 "phone": null
39 }
40 }
41}),
42})
43 .then((res) => res.json())
44 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/contacts/settings",
5 json={"embeds":[{"id":"string","name":"string","enabled":null,"allowed_origins":["string"],"greeting":"string","subtitle":"string","color":"string","position":null,"allow_uploads":null,"fields":{"name":null,"email":null,"phone":null}}],"widget":{"enabled":null,"allowed_origins":["string"],"greeting":"string","subtitle":"string","color":"string","position":null,"allow_uploads":null,"fields":{"name":null,"email":null,"phone":null}}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /contacts/:contact_id

Update a contact

PUT /contacts/:contact_id — update a contact.

Handled by api_update_contact
Parameters
contact_id string · path
required
Body · UpdateContactapplication/json
phone_number string · max length: 50
street string · max length: 300
city string · max length: 100
state string · max length: 100
postal_code string · max length: 20
country string · max length: 100
propertyName anything
Responses
200Successful Response
PUT /contacts/example
1curl -X PUT "http://localhost:8000/contacts/example" \
2 -H "Content-Type: application/json" \
3 -d '{"phone_number":"string","street":"string","city":"string","state":"string","postal_code":"string","country":"string"}'
1fetch("http://localhost:8000/contacts/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "phone_number": "string",
6 "street": "string",
7 "city": "string",
8 "state": "string",
9 "postal_code": "string",
10 "country": "string"
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/contacts/example",
5 json={"phone_number":"string","street":"string","city":"string","state":"string","postal_code":"string","country":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /contacts/:contact_id/state

Override a contact's state

PUT /contacts/:id/state — a human overriding the derived face. Recorded as ``manual`` and labelled as such in the UI, because a state somebody typed and a state the evidence produced are different claims. It lasts until the next real signal, which then takes the wheel back.

Handled by api_set_contact_state
Parameters
contact_id string · path
required
Body · SetContactStateapplication/json
state
required
reason string · max length: 200
propertyName anything
Responses
200Successful Response
PUT /contacts/example/state
1curl -X PUT "http://localhost:8000/contacts/example/state" \
2 -H "Content-Type: application/json" \
3 -d '{"state":null,"reason":"string"}'
1fetch("http://localhost:8000/contacts/example/state", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "state": null,
6 "reason": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/contacts/example/state",
5 json={"state":null,"reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /conversations undocumented

/conversations

GET /conversations — the inbox. Filters: status, assignee_mrn, priority, contact_id, channel, q.

Handled by api_list_conversations
Responses
200Successful Response
GET /conversations
1curl "http://localhost:8000/conversations"
1fetch("http://localhost:8000/conversations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/conversations")
4print(response.json())
200 Example Response
No Body
GET /conversations/:conversation_id undocumented

/conversations/:conversation_id

GET /conversations/:id — the thread, including internal notes. This is a staff route behind contacts.conversations.view; internal notes are stripped only on the visitor-facing widget routes.

Handled by api_get_conversation
Parameters
conversation_id string · path
required
Responses
200Successful Response
GET /conversations/example
1curl "http://localhost:8000/conversations/example"
1fetch("http://localhost:8000/conversations/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/conversations/example")
4print(response.json())
200 Example Response
No Body
PATCH /conversations/:conversation_id

Assign, prioritise or resolve a conversation

PATCH /conversations/:id — status, assignee, priority and tag moves. Resolution is the CSAT moment: it stamps resolved_at, logs the thread as a touchpoint on the contact, and tells the spawning surface to prompt for a rating.

Handled by api_update_conversation
Parameters
conversation_id string · path
required
Body · UpdateConversationapplication/json
status
priority
assignee_mrn string · max length: 200
tags array
contact_id string · max length: 60
propertyName anything
Responses
200Successful Response
PATCH /conversations/example
1curl -X PATCH "http://localhost:8000/conversations/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null,"priority":null,"assignee_mrn":"string","tags":["string"],"contact_id":"string"}'
1fetch("http://localhost:8000/conversations/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null,
6 "priority": null,
7 "assignee_mrn": "string",
8 "tags": [
9 "string"
10 ],
11 "contact_id": "string"
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/conversations/example",
5 json={"status":null,"priority":null,"assignee_mrn":"string","tags":["string"],"contact_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /conversations/:conversation_id/messages

Reply in a conversation or add an internal note

POST /conversations/:id/messages — a staff reply, or an internal note. Any holder of contacts.conversations.manage may reply in any thread; assignee_mrn is ownership, never exclusivity. An internal note is stored and shown to colleagues but never emitted and never delivered to the visitor.

Handled by api_create_conversation_message
Parameters
conversation_id string · path
required
Body · CreateConversationMessageapplication/json
body string · min length: 1 · max length: 10000
required
is_internal
propertyName anything
Responses
200Successful Response
POST /conversations/example/messages
1curl -X POST "http://localhost:8000/conversations/example/messages" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string","is_internal":null}'
1fetch("http://localhost:8000/conversations/example/messages", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string",
6 "is_internal": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/conversations/example/messages",
5 json={"body":"string","is_internal":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /coupons/:code/redemptions undocumented

/coupons/:code/redemptions

POST /coupons/:code/redemptions — apply a coupon to the current workspace.

Handled by api_redeem_coupon
Parameters
code string · path
required
Responses
200Successful Response
POST /coupons/example/redemptions
1curl -X POST "http://localhost:8000/coupons/example/redemptions"
1fetch("http://localhost:8000/coupons/example/redemptions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/coupons/example/redemptions")
4print(response.json())
200 Example Response
No Body
PATCH /finance/credit-notes/:entry_id

Issue/void credit note

Handled by api_patch_credit_note
Parameters
entry_id string · path
required
Body · UpdateCreditNoteStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/credit-notes/example
1curl -X PATCH "http://localhost:8000/finance/credit-notes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/credit-notes/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/credit-notes/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/credit-notes

Create a credit note

Handled by api_create_credit_note
Body · CreateCreditNoteapplication/json
date string · min length: 10
required
items array
source_entry_id string · min length: 1
required
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
memo string · max length: 5000
adjustments array
dimensions
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/credit-notes
1curl -X POST "http://localhost:8000/finance/credit-notes" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"source_entry_id":"string","contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/credit-notes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "source_entry_id": "string",
26 "contact_mrn": "string",
27 "company_mrn": "string",
28 "currency": "string",
29 "exchange_rate": 1.5,
30 "memo": "string",
31 "adjustments": [
32 {
33 "label": "string",
34 "type": null,
35 "value": 1.5,
36 "amount": 1.5,
37 "account_code": "string"
38 }
39 ],
40 "dimensions": null,
41 "idempotency_key": "string"
42}),
43})
44 .then((res) => res.json())
45 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/credit-notes",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"source_entry_id":"string","contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/credit-notes/:entry_id/allocations

Set credit against an invoice

Handled by api_create_credit_note_allocation
Parameters
entry_id string · path
required
Body · CreateCreditNoteAllocationapplication/json
entry_id string · min length: 1
required
amount number
required
entry_amount number
propertyName anything
Responses
200Successful Response
POST /finance/credit-notes/example/allocations
1curl -X POST "http://localhost:8000/finance/credit-notes/example/allocations" \
2 -H "Content-Type: application/json" \
3 -d '{"entry_id":"string","amount":1.5,"entry_amount":1.5}'
1fetch("http://localhost:8000/finance/credit-notes/example/allocations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "entry_id": "string",
6 "amount": 1.5,
7 "entry_amount": 1.5
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/credit-notes/example/allocations",
5 json={"entry_id":"string","amount":1.5,"entry_amount":1.5},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/credit-notes/:entry_id/pdfs

Generate credit note PDF

Handled by api_create_credit_note_pdf
Parameters
entry_id string · path
required
Body · GeneratePdfapplication/json
template string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/credit-notes/example/pdfs
1curl -X POST "http://localhost:8000/finance/credit-notes/example/pdfs" \
2 -H "Content-Type: application/json" \
3 -d '{"template":"string"}'
1fetch("http://localhost:8000/finance/credit-notes/example/pdfs", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "template": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/credit-notes/example/pdfs",
5 json={"template":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/credit-notes/:entry_id/sends

Email a credit note

Handled by api_send_credit_note
Parameters
entry_id string · path
required
Body · SendCreditNoteapplication/json
to string · min length: 1 · max length: 500
required
cc string · max length: 500
subject string · max length: 300
message string · max length: 5000
propertyName anything
Responses
200Successful Response
POST /finance/credit-notes/example/sends
1curl -X POST "http://localhost:8000/finance/credit-notes/example/sends" \
2 -H "Content-Type: application/json" \
3 -d '{"to":"string","cc":"string","subject":"string","message":"string"}'
1fetch("http://localhost:8000/finance/credit-notes/example/sends", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to": "string",
6 "cc": "string",
7 "subject": "string",
8 "message": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/credit-notes/example/sends",
5 json={"to":"string","cc":"string","subject":"string","message":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/credit-notes/:entry_id

Update a credit note

Handled by api_update_credit_note
Parameters
entry_id string · path
required
Body · UpdateCreditNoteapplication/json
date string · min length: 10
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
memo string · max length: 5000
adjustments array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/credit-notes/example
1curl -X PUT "http://localhost:8000/finance/credit-notes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null}'
1fetch("http://localhost:8000/finance/credit-notes/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "memo": "string",
30 "adjustments": [
31 {
32 "label": "string",
33 "type": null,
34 "value": 1.5,
35 "amount": 1.5,
36 "account_code": "string"
37 }
38 ],
39 "dimensions": null
40}),
41})
42 .then((res) => res.json())
43 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/credit-notes/example",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /crm/leads undocumented

/crm/leads

Handled by api_list_leads
Responses
200Successful Response
GET /crm/leads
1curl "http://localhost:8000/crm/leads"
1fetch("http://localhost:8000/crm/leads")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/leads")
4print(response.json())
200 Example Response
No Body
GET /crm/reports/pipeline undocumented

/crm/reports/pipeline

Handled by api_report_pipeline
Responses
200Successful Response
GET /crm/reports/pipeline
1curl "http://localhost:8000/crm/reports/pipeline"
1fetch("http://localhost:8000/crm/reports/pipeline")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/reports/pipeline")
4print(response.json())
200 Example Response
No Body
GET /crm/reports/performance undocumented

/crm/reports/performance

Handled by api_report_performance
Responses
200Successful Response
GET /crm/reports/performance
1curl "http://localhost:8000/crm/reports/performance"
1fetch("http://localhost:8000/crm/reports/performance")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/reports/performance")
4print(response.json())
200 Example Response
No Body
GET /crm/reports/forecast undocumented

/crm/reports/forecast

Handled by api_report_forecast
Responses
200Successful Response
GET /crm/reports/forecast
1curl "http://localhost:8000/crm/reports/forecast"
1fetch("http://localhost:8000/crm/reports/forecast")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/reports/forecast")
4print(response.json())
200 Example Response
No Body
GET /crm/reports/activity undocumented

/crm/reports/activity

Activity report: target progress per rep.

Handled by api_report_activity
Responses
200Successful Response
GET /crm/reports/activity
1curl "http://localhost:8000/crm/reports/activity"
1fetch("http://localhost:8000/crm/reports/activity")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/reports/activity")
4print(response.json())
200 Example Response
No Body
GET /crm/reports/funnel undocumented

/crm/reports/funnel

Stage entry counts + conversion, from the indexed timeline.

Handled by api_report_funnel
Responses
200Successful Response
GET /crm/reports/funnel
1curl "http://localhost:8000/crm/reports/funnel"
1fetch("http://localhost:8000/crm/reports/funnel")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/reports/funnel")
4print(response.json())
200 Example Response
No Body
GET /crm/reports/trends undocumented

/crm/reports/trends

Monthly won/lost counts and won value (grouped by currency), last 12 months.

Handled by api_report_trends
Responses
200Successful Response
GET /crm/reports/trends
1curl "http://localhost:8000/crm/reports/trends"
1fetch("http://localhost:8000/crm/reports/trends")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/reports/trends")
4print(response.json())
200 Example Response
No Body
GET /crm/reports/losses undocumented

/crm/reports/losses

Loss reasons breakdown (count + value by currency).

Handled by api_report_losses
Responses
200Successful Response
GET /crm/reports/losses
1curl "http://localhost:8000/crm/reports/losses"
1fetch("http://localhost:8000/crm/reports/losses")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/crm/reports/losses")
4print(response.json())
200 Example Response
No Body
DELETE /deals/:deal_id undocumented

/deals/:deal_id

Handled by api_delete_deal
Parameters
deal_id string · path
required
Responses
200Successful Response
DELETE /deals/example
1curl -X DELETE "http://localhost:8000/deals/example"
1fetch("http://localhost:8000/deals/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/deals/example")
4print(response.json())
200 Example Response
No Body
DELETE /deals/:deal_id/line-items/:item_id undocumented

/deals/:deal_id/line-items/:item_id

Handled by api_delete_line_item
Parameters
deal_id string · path
required
item_id string · path
required
Responses
200Successful Response
DELETE /deals/example/line-items/example
1curl -X DELETE "http://localhost:8000/deals/example/line-items/example"
1fetch("http://localhost:8000/deals/example/line-items/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/deals/example/line-items/example")
4print(response.json())
200 Example Response
No Body
DELETE /deals/:deal_id/links/:link_id undocumented

/deals/:deal_id/links/:link_id

Handled by api_revoke_deal_link
Parameters
deal_id string · path
required
link_id string · path
required
Responses
200Successful Response
DELETE /deals/example/links/example
1curl -X DELETE "http://localhost:8000/deals/example/links/example"
1fetch("http://localhost:8000/deals/example/links/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/deals/example/links/example")
4print(response.json())
200 Example Response
No Body
DELETE /deals/:deal_id/attachments/:file_id undocumented

/deals/:deal_id/attachments/:file_id

Handled by api_remove_deal_attachment
Parameters
deal_id string · path
required
file_id string · path
required
Responses
200Successful Response
DELETE /deals/example/attachments/example
1curl -X DELETE "http://localhost:8000/deals/example/attachments/example"
1fetch("http://localhost:8000/deals/example/attachments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/deals/example/attachments/example")
4print(response.json())
200 Example Response
No Body
DELETE /deals/:deal_id/checklist-items/:item_id undocumented

/deals/:deal_id/checklist-items/:item_id

Handled by api_delete_checklist_item
Parameters
deal_id string · path
required
item_id string · path
required
Responses
200Successful Response
DELETE /deals/example/checklist-items/example
1curl -X DELETE "http://localhost:8000/deals/example/checklist-items/example"
1fetch("http://localhost:8000/deals/example/checklist-items/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/deals/example/checklist-items/example")
4print(response.json())
200 Example Response
No Body
GET /deals undocumented

/deals

Global deal list. pipeline_id is an optional filter, no longer mandatory.

Handled by api_list_deals
Responses
200Successful Response
GET /deals
1curl "http://localhost:8000/deals"
1fetch("http://localhost:8000/deals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/deals")
4print(response.json())
200 Example Response
No Body
GET /deals/:deal_id undocumented

/deals/:deal_id

Handled by api_get_deal
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /deals/example
1curl "http://localhost:8000/deals/example"
1fetch("http://localhost:8000/deals/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/deals/example")
4print(response.json())
200 Example Response
No Body
GET /deals/:deal_id/line-items undocumented

/deals/:deal_id/line-items

Handled by api_list_line_items
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /deals/example/line-items
1curl "http://localhost:8000/deals/example/line-items"
1fetch("http://localhost:8000/deals/example/line-items")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/deals/example/line-items")
4print(response.json())
200 Example Response
No Body
GET /deals/:deal_id/links undocumented

/deals/:deal_id/links

Handled by api_list_deal_links
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /deals/example/links
1curl "http://localhost:8000/deals/example/links"
1fetch("http://localhost:8000/deals/example/links")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/deals/example/links")
4print(response.json())
200 Example Response
No Body
GET /deals/:deal_id/activities undocumented

/deals/:deal_id/activities

Handled by api_list_activities
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /deals/example/activities
1curl "http://localhost:8000/deals/example/activities"
1fetch("http://localhost:8000/deals/example/activities")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/deals/example/activities")
4print(response.json())
200 Example Response
No Body
GET /deals/:deal_id/checklist-items undocumented

/deals/:deal_id/checklist-items

Handled by api_list_checklist_items
Parameters
deal_id string · path
required
Responses
200Successful Response
GET /deals/example/checklist-items
1curl "http://localhost:8000/deals/example/checklist-items"
1fetch("http://localhost:8000/deals/example/checklist-items")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/deals/example/checklist-items")
4print(response.json())
200 Example Response
No Body
PATCH /deals/:deal_id/stage

Move a deal to another stage

Handled by api_move_deal_stage
Parameters
deal_id string · path
required
Body · MoveDealStageapplication/json
stage_id string · min length: 1
required
pipeline_id string
loss_reason string · max length: 1000
propertyName anything
Responses
200Successful Response
PATCH /deals/example/stage
1curl -X PATCH "http://localhost:8000/deals/example/stage" \
2 -H "Content-Type: application/json" \
3 -d '{"stage_id":"string","pipeline_id":"string","loss_reason":"string"}'
1fetch("http://localhost:8000/deals/example/stage", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "stage_id": "string",
6 "pipeline_id": "string",
7 "loss_reason": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/deals/example/stage",
5 json={"stage_id":"string","pipeline_id":"string","loss_reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /deals

Create a deal

Handled by api_create_deal
Body · CreateDealapplication/json
pipeline_id string
required
title string · min length: 1 · max length: 300
required
value number
currency string
stage_id string
contact_mrn string
company_mrn string
owner_mrn string
expected_close_date string
source
line_items array
tags array
propertyName anything
Responses
200Successful Response
POST /deals
1curl -X POST "http://localhost:8000/deals" \
2 -H "Content-Type: application/json" \
3 -d '{"pipeline_id":"string","title":"string","value":1.5,"currency":"string","stage_id":"string","contact_mrn":"string","company_mrn":"string","owner_mrn":"string","expected_close_date":"string","source":null,"line_items":[{"name":"string","product_mrn":"string","quantity":1.5,"unit_price":1.5,"currency":"string","period":null}],"tags":["string"]}'
1fetch("http://localhost:8000/deals", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "pipeline_id": "string",
6 "title": "string",
7 "value": 1.5,
8 "currency": "string",
9 "stage_id": "string",
10 "contact_mrn": "string",
11 "company_mrn": "string",
12 "owner_mrn": "string",
13 "expected_close_date": "string",
14 "source": null,
15 "line_items": [
16 {
17 "name": "string",
18 "product_mrn": "string",
19 "quantity": 1.5,
20 "unit_price": 1.5,
21 "currency": "string",
22 "period": null
23 }
24 ],
25 "tags": [
26 "string"
27 ]
28}),
29})
30 .then((res) => res.json())
31 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deals",
5 json={"pipeline_id":"string","title":"string","value":1.5,"currency":"string","stage_id":"string","contact_mrn":"string","company_mrn":"string","owner_mrn":"string","expected_close_date":"string","source":null,"line_items":[{"name":"string","product_mrn":"string","quantity":1.5,"unit_price":1.5,"currency":"string","period":null}],"tags":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /deals/:deal_id/line-items

Add a line item to a deal

Handled by api_create_line_item
Parameters
deal_id string · path
required
Body · LineItemInapplication/json
name string · min length: 1 · max length: 200
required
product_mrn string
quantity number
unit_price number
currency string
period
propertyName anything
Responses
200Successful Response
POST /deals/example/line-items
1curl -X POST "http://localhost:8000/deals/example/line-items" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","product_mrn":"string","quantity":1.5,"unit_price":1.5,"currency":"string","period":null}'
1fetch("http://localhost:8000/deals/example/line-items", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "product_mrn": "string",
7 "quantity": 1.5,
8 "unit_price": 1.5,
9 "currency": "string",
10 "period": null
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deals/example/line-items",
5 json={"name":"string","product_mrn":"string","quantity":1.5,"unit_price":1.5,"currency":"string","period":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /deals/:deal_id/links

Mint a deal room link for a customer

Handled by api_create_deal_link
Parameters
deal_id string · path
required
Body · CreateDealLinkapplication/json
label string · max length: 200
propertyName anything
Responses
200Successful Response
POST /deals/example/links
1curl -X POST "http://localhost:8000/deals/example/links" \
2 -H "Content-Type: application/json" \
3 -d '{"label":"string"}'
1fetch("http://localhost:8000/deals/example/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "label": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deals/example/links",
5 json={"label":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /deals/:deal_id/attachments

Attach a shared file to the deal room

Handled by api_add_deal_attachment
Parameters
deal_id string · path
required
Body · CreateDealAttachmentapplication/json
mrn string · min length: 15 · max length: 200
required
name string · min length: 1 · max length: 300
required
url string · min length: 1 · max length: 500
required
share_id string · max length: 100
propertyName anything
Responses
200Successful Response
POST /deals/example/attachments
1curl -X POST "http://localhost:8000/deals/example/attachments" \
2 -H "Content-Type: application/json" \
3 -d '{"mrn":"string","name":"string","url":"string","share_id":"string"}'
1fetch("http://localhost:8000/deals/example/attachments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "mrn": "string",
6 "name": "string",
7 "url": "string",
8 "share_id": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deals/example/attachments",
5 json={"mrn":"string","name":"string","url":"string","share_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /deals/:deal_id/activities

Add a note to a deal

Handled by api_create_note
Parameters
deal_id string · path
required
Body · CreateNoteapplication/json
content string · min length: 1 · max length: 10000
required
propertyName anything
Responses
200Successful Response
POST /deals/example/activities
1curl -X POST "http://localhost:8000/deals/example/activities" \
2 -H "Content-Type: application/json" \
3 -d '{"content":"string"}'
1fetch("http://localhost:8000/deals/example/activities", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "content": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deals/example/activities",
5 json={"content":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /deals/:deal_id/checklist-items

Add a checklist item to a deal

Handled by api_create_checklist_item
Parameters
deal_id string · path
required
Body · CreateChecklistItemapplication/json
label string · min length: 1 · max length: 200
required
stage_id string
assignee_mrn string
due_date string
propertyName anything
Responses
200Successful Response
POST /deals/example/checklist-items
1curl -X POST "http://localhost:8000/deals/example/checklist-items" \
2 -H "Content-Type: application/json" \
3 -d '{"label":"string","stage_id":"string","assignee_mrn":"string","due_date":"string"}'
1fetch("http://localhost:8000/deals/example/checklist-items", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "label": "string",
6 "stage_id": "string",
7 "assignee_mrn": "string",
8 "due_date": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deals/example/checklist-items",
5 json={"label":"string","stage_id":"string","assignee_mrn":"string","due_date":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /deals/:deal_id/quote-requests

Ask Finance to draft a quote from this deal

POST /deals/:deal_id/quote-requests. Emits deal.quote_requested; Finance drafts the quote from the line items (apps/finance/events.py).

Handled by api_create_quote_request
Parameters
deal_id string · path
required
Body · CreateQuoteRequestapplication/json
memo string · max length: 2000
propertyName anything
Responses
200Successful Response
POST /deals/example/quote-requests
1curl -X POST "http://localhost:8000/deals/example/quote-requests" \
2 -H "Content-Type: application/json" \
3 -d '{"memo":"string"}'
1fetch("http://localhost:8000/deals/example/quote-requests", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "memo": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deals/example/quote-requests",
5 json={"memo":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /deals/:deal_id

Update a deal

Handled by api_update_deal
Parameters
deal_id string · path
required
Body · UpdateDealapplication/json
title string · min length: 1 · max length: 300
value number
currency string
contact_mrn string
company_mrn string
owner_mrn string
expected_close_date string
source
tags array
loss_reason string
proposal string · max length: 100000
propertyName anything
Responses
200Successful Response
PUT /deals/example
1curl -X PUT "http://localhost:8000/deals/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","value":1.5,"currency":"string","contact_mrn":"string","company_mrn":"string","owner_mrn":"string","expected_close_date":"string","source":null,"tags":["string"],"loss_reason":"string","proposal":"string"}'
1fetch("http://localhost:8000/deals/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "value": 1.5,
7 "currency": "string",
8 "contact_mrn": "string",
9 "company_mrn": "string",
10 "owner_mrn": "string",
11 "expected_close_date": "string",
12 "source": null,
13 "tags": [
14 "string"
15 ],
16 "loss_reason": "string",
17 "proposal": "string"
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/deals/example",
5 json={"title":"string","value":1.5,"currency":"string","contact_mrn":"string","company_mrn":"string","owner_mrn":"string","expected_close_date":"string","source":null,"tags":["string"],"loss_reason":"string","proposal":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /deals/:deal_id/line-items/:item_id

Update a deal line item

Handled by api_update_line_item
Parameters
deal_id string · path
required
item_id string · path
required
Body · UpdateLineItemapplication/json
name string · min length: 1 · max length: 200
product_mrn string
quantity number
unit_price number
currency string
period
position integer
propertyName anything
Responses
200Successful Response
PUT /deals/example/line-items/example
1curl -X PUT "http://localhost:8000/deals/example/line-items/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","product_mrn":"string","quantity":1.5,"unit_price":1.5,"currency":"string","period":null,"position":1}'
1fetch("http://localhost:8000/deals/example/line-items/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "product_mrn": "string",
7 "quantity": 1.5,
8 "unit_price": 1.5,
9 "currency": "string",
10 "period": null,
11 "position": 1
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/deals/example/line-items/example",
5 json={"name":"string","product_mrn":"string","quantity":1.5,"unit_price":1.5,"currency":"string","period":null,"position":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /deals/:deal_id/checklist-items/:item_id

Update a deal checklist item

Handled by api_update_checklist_item
Parameters
deal_id string · path
required
item_id string · path
required
Body · UpdateChecklistItemapplication/json
done
label string · min length: 1 · max length: 200
assignee_mrn string
due_date string
position integer
propertyName anything
Responses
200Successful Response
PUT /deals/example/checklist-items/example
1curl -X PUT "http://localhost:8000/deals/example/checklist-items/example" \
2 -H "Content-Type: application/json" \
3 -d '{"done":null,"label":"string","assignee_mrn":"string","due_date":"string","position":1}'
1fetch("http://localhost:8000/deals/example/checklist-items/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "done": null,
6 "label": "string",
7 "assignee_mrn": "string",
8 "due_date": "string",
9 "position": 1
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/deals/example/checklist-items/example",
5 json={"done":null,"label":"string","assignee_mrn":"string","due_date":"string","position":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /decks/trash undocumented

/decks/trash

DELETE /decks/trash. Destroy every trashed deck the caller manages.

Handled by api_empty_trash
Responses
200Successful Response
DELETE /decks/trash
1curl -X DELETE "http://localhost:8000/decks/trash"
1fetch("http://localhost:8000/decks/trash", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/decks/trash")
4print(response.json())
200 Example Response
No Body
DELETE /decks/trash/:id undocumented

/decks/trash/:id

DELETE /decks/trash/:id. Destroy a trashed deck. Gate loaded ctx.authz.deck.

Handled by api_purge_deck
Parameters
id string · path
required
Responses
200Successful Response
DELETE /decks/trash/example
1curl -X DELETE "http://localhost:8000/decks/trash/example"
1fetch("http://localhost:8000/decks/trash/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/decks/trash/example")
4print(response.json())
200 Example Response
No Body
DELETE /decks/:id undocumented

/decks/:id

DELETE /decks/:id. Soft-delete. Grants stay so restore still works.

Handled by api_delete_deck
Parameters
id string · path
required
Responses
200Successful Response
DELETE /decks/example
1curl -X DELETE "http://localhost:8000/decks/example"
1fetch("http://localhost:8000/decks/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/decks/example")
4print(response.json())
200 Example Response
No Body
GET /decks undocumented

/decks

GET /decks. Decks the caller can access.

Handled by api_list_decks
Responses
200Successful Response
GET /decks
1curl "http://localhost:8000/decks"
1fetch("http://localhost:8000/decks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/decks")
4print(response.json())
200 Example Response
No Body
GET /decks/trash undocumented

/decks/trash

GET /decks/trash. Decks in the trash that the caller can restore.

Handled by api_list_trash
Responses
200Successful Response
GET /decks/trash
1curl "http://localhost:8000/decks/trash"
1fetch("http://localhost:8000/decks/trash")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/decks/trash")
4print(response.json())
200 Example Response
No Body
GET /decks/:id undocumented

/decks/:id

GET /decks/:id. Metadata + deck_json. Gate loaded ctx.authz.deck.

Handled by api_get_deck
Parameters
id string · path
required
Responses
200Successful Response
GET /decks/example
1curl "http://localhost:8000/decks/example"
1fetch("http://localhost:8000/decks/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/decks/example")
4print(response.json())
200 Example Response
No Body
GET /decks/:id/assets undocumented

/decks/:id/assets

GET /decks/:id/assets. Images uploaded to this deck. Gate loaded ctx.authz.deck.

Handled by api_list_assets
Parameters
id string · path
required
Responses
200Successful Response
GET /decks/example/assets
1curl "http://localhost:8000/decks/example/assets"
1fetch("http://localhost:8000/decks/example/assets")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/decks/example/assets")
4print(response.json())
200 Example Response
No Body
GET / undocumented

/

Handled by landing
Responses
200Successful Response
GET /
1curl "http://localhost:8000/"
1fetch("http://localhost:8000/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/")
4print(response.json())
200 Example Response
No Body
GET / undocumented

/

GET / — admin dashboard with stats + tabbed workspace/invoice/thread lists.

Handled by index
Responses
200Successful Response
GET /
1curl "http://localhost:8000/"
1fetch("http://localhost:8000/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/")
4print(response.json())
200 Example Response
No Body
GET / undocumented

/

Handled by index
Responses
200Successful Response
GET /
1curl "http://localhost:8000/"
1fetch("http://localhost:8000/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/")
4print(response.json())
200 Example Response
No Body
GET / undocumented

/

GET / on workspace subdomain — render the shell with initial workscreen state.

Handled by index
Responses
200Successful Response
GET /
1curl "http://localhost:8000/"
1fetch("http://localhost:8000/")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/")
4print(response.json())
200 Example Response
No Body
POST / undocumented

/

Account tab default view. The Lobby is the workspace home now; Account is a normal tab opened from a Lobby button, so its entry point lands on the member's own profile settings.

Handled by index
Responses
200Successful Response
POST /
1curl -X POST "http://localhost:8000/"
1fetch("http://localhost:8000/", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/")
4print(response.json())
200 Example Response
No Body
DELETE /deliverables/:deliverable_id undocumented

/deliverables/:deliverable_id

Delete a deliverable. Linked tasks keep existing — their deliverable link clears via the ON DELETE SET NULL foreign key.

Handled by api_delete_deliverable
Parameters
deliverable_id string · path
required
Responses
200Successful Response
DELETE /deliverables/example
1curl -X DELETE "http://localhost:8000/deliverables/example"
1fetch("http://localhost:8000/deliverables/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/deliverables/example")
4print(response.json())
200 Example Response
No Body
GET /deliverables undocumented

/deliverables

GET /deliverables?board_id=...&q=... — list a board's deliverables.

Handled by api_list_deliverables
Responses
200Successful Response
GET /deliverables
1curl "http://localhost:8000/deliverables"
1fetch("http://localhost:8000/deliverables")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/deliverables")
4print(response.json())
200 Example Response
No Body
POST /deliverables

Create a deliverable

Handled by api_create_deliverable
Body · CreateDeliverableapplication/json
board_id string
required
name string · min length: 1 · max length: 200
required
due_date string · min length: 1
required
description string · max length: 5000
status
schedule_id string
owner_mrn string
propertyName anything
Responses
200Successful Response
POST /deliverables
1curl -X POST "http://localhost:8000/deliverables" \
2 -H "Content-Type: application/json" \
3 -d '{"board_id":"string","name":"string","due_date":"string","description":"string","status":null,"schedule_id":"string","owner_mrn":"string"}'
1fetch("http://localhost:8000/deliverables", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "board_id": "string",
6 "name": "string",
7 "due_date": "string",
8 "description": "string",
9 "status": null,
10 "schedule_id": "string",
11 "owner_mrn": "string"
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/deliverables",
5 json={"board_id":"string","name":"string","due_date":"string","description":"string","status":null,"schedule_id":"string","owner_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /deliverables/:deliverable_id

Update a deliverable

Handled by api_update_deliverable
Parameters
deliverable_id string · path
required
Body · UpdateDeliverableapplication/json
name string · min length: 1 · max length: 200
description string · max length: 5000
due_date string
status
schedule_id string
owner_mrn string
propertyName anything
Responses
200Successful Response
PUT /deliverables/example
1curl -X PUT "http://localhost:8000/deliverables/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","due_date":"string","status":null,"schedule_id":"string","owner_mrn":"string"}'
1fetch("http://localhost:8000/deliverables/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "due_date": "string",
8 "status": null,
9 "schedule_id": "string",
10 "owner_mrn": "string"
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/deliverables/example",
5 json={"name":"string","description":"string","due_date":"string","status":null,"schedule_id":"string","owner_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /demo-requests/availability undocumented

/demo-requests/availability

GET /demo-requests/availability — open demo slots for the next weekdays.

Handled by availability
Responses
200Successful Response
GET /demo-requests/availability
1curl "http://localhost:8000/demo-requests/availability"
1fetch("http://localhost:8000/demo-requests/availability")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/demo-requests/availability")
4print(response.json())
200 Example Response
No Body
DELETE /departments/:department_id undocumented

/departments/:department_id

Handled by api_delete_department
Parameters
department_id string · path
required
Responses
200Successful Response
DELETE /departments/example
1curl -X DELETE "http://localhost:8000/departments/example"
1fetch("http://localhost:8000/departments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/departments/example")
4print(response.json())
200 Example Response
No Body
GET /departments undocumented

/departments

Handled by api_list_departments
Responses
200Successful Response
GET /departments
1curl "http://localhost:8000/departments"
1fetch("http://localhost:8000/departments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/departments")
4print(response.json())
200 Example Response
No Body
GET /departments/:department_id undocumented

/departments/:department_id

Handled by api_get_department
Parameters
department_id string · path
required
Responses
200Successful Response
GET /departments/example
1curl "http://localhost:8000/departments/example"
1fetch("http://localhost:8000/departments/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/departments/example")
4print(response.json())
200 Example Response
No Body
PATCH /departments/:department_id

Update a department

Handled by api_update_department
Parameters
department_id string · path
required
Body · UpdateDepartmentapplication/json
name string · min length: 1 · max length: 100
description string · max length: 1000
parent_id string
head_mrn string
propertyName anything
Responses
200Successful Response
PATCH /departments/example
1curl -X PATCH "http://localhost:8000/departments/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","parent_id":"string","head_mrn":"string"}'
1fetch("http://localhost:8000/departments/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "parent_id": "string",
8 "head_mrn": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/departments/example",
5 json={"name":"string","description":"string","parent_id":"string","head_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /departments

Create a department

Handled by api_create_department
Body · CreateDepartmentapplication/json
name string · min length: 1 · max length: 100
required
description string · max length: 1000
parent_id string
head_mrn string
propertyName anything
Responses
200Successful Response
POST /departments
1curl -X POST "http://localhost:8000/departments" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","parent_id":"string","head_mrn":"string"}'
1fetch("http://localhost:8000/departments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "parent_id": "string",
8 "head_mrn": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/departments",
5 json={"name":"string","description":"string","parent_id":"string","head_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /developers undocumented

/developers

Developer docs landing page.

Handled by home
Responses
200Successful Response
GET /developers
1curl "http://localhost:8000/developers"
1fetch("http://localhost:8000/developers")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/developers")
4print(response.json())
200 Example Response
No Body
GET /developers/:section undocumented

/developers/:section

Single-segment paths under /developers: the search index, or a section slug that redirects to the section's first page.

Handled by section
Parameters
section string · path
required
Responses
200Successful Response
GET /developers/example
1curl "http://localhost:8000/developers/example"
1fetch("http://localhost:8000/developers/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/developers/example")
4print(response.json())
200 Example Response
No Body
GET /developers/:section/:page undocumented

/developers/:section/:page

Handled by page
Parameters
section string · path
required
page string · path
required
Responses
200Successful Response
GET /developers/example/example
1curl "http://localhost:8000/developers/example/example"
1fetch("http://localhost:8000/developers/example/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/developers/example/example")
4print(response.json())
200 Example Response
No Body
PATCH /finance/dimensions/:dimension_key

Update a dimension

Handled by api_patch_dimension
Parameters
dimension_key string · path
required
Body · DimensionDefapplication/json
name string · min length: 1 · max length: 100
required
key string · min length: 1 · max length: 50
required
values array
required
propertyName anything
Responses
200Successful Response
PATCH /finance/dimensions/example
1curl -X PATCH "http://localhost:8000/finance/dimensions/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","key":"string","values":["string"]}'
1fetch("http://localhost:8000/finance/dimensions/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "key": "string",
7 "values": [
8 "string"
9 ]
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/dimensions/example",
5 json={"name":"string","key":"string","values":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/dimensions

Define a dimension

Handled by api_create_dimension
Body · DimensionDefapplication/json
name string · min length: 1 · max length: 100
required
key string · min length: 1 · max length: 50
required
values array
required
propertyName anything
Responses
200Successful Response
POST /finance/dimensions
1curl -X POST "http://localhost:8000/finance/dimensions" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","key":"string","values":["string"]}'
1fetch("http://localhost:8000/finance/dimensions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "key": "string",
7 "values": [
8 "string"
9 ]
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/dimensions",
5 json={"name":"string","key":"string","values":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /sign/envelopes/:envelope_id

Update document metadata

PATCH /sign/envelopes/:envelope_id — update metadata OR transition state (sent/voided).

Handled by api_update_envelope
Parameters
envelope_id string · path
required
Body · UpdateEnvelopeapplication/json
title string · min length: 1 · max length: 300
subject string · max length: 300
message string · max length: 2000
signing_order_mode
jurisdiction string · max length: 10
expires_at string
status
reason string · max length: 1000
propertyName anything
Responses
200Successful Response
PATCH /sign/envelopes/example
1curl -X PATCH "http://localhost:8000/sign/envelopes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","subject":"string","message":"string","signing_order_mode":null,"jurisdiction":"string","expires_at":"string","status":null,"reason":"string"}'
1fetch("http://localhost:8000/sign/envelopes/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "subject": "string",
7 "message": "string",
8 "signing_order_mode": null,
9 "jurisdiction": "string",
10 "expires_at": "string",
11 "status": null,
12 "reason": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/sign/envelopes/example",
5 json={"title":"string","subject":"string","message":"string","signing_order_mode":null,"jurisdiction":"string","expires_at":"string","status":null,"reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sign/envelopes

Create a draft document

POST /sign/envelopes — create a draft (optionally cloning ?template_id).

Handled by api_create_envelope
Body · CreateEnvelopeapplication/json
title string · min length: 1 · max length: 300
required
subject string · max length: 300
message string · max length: 2000
template_id string
signing_order_mode
jurisdiction string · max length: 10
is_template
source_mrn string · max length: 200
propertyName anything
Responses
200Successful Response
POST /sign/envelopes
1curl -X POST "http://localhost:8000/sign/envelopes" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","subject":"string","message":"string","template_id":"string","signing_order_mode":null,"jurisdiction":"string","is_template":null,"source_mrn":"string"}'
1fetch("http://localhost:8000/sign/envelopes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "subject": "string",
7 "message": "string",
8 "template_id": "string",
9 "signing_order_mode": null,
10 "jurisdiction": "string",
11 "is_template": null,
12 "source_mrn": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sign/envelopes",
5 json={"title":"string","subject":"string","message":"string","template_id":"string","signing_order_mode":null,"jurisdiction":"string","is_template":null,"source_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sign/envelopes/:envelope_id/documents

Append a source PDF to the envelope

POST /sign/envelopes/:envelope_id/documents {storage_key, title, page_count} — append a source PDF. The first add on a legacy envelope promotes its single PDF into a row, so an envelope is always pure-legacy or pure-rows.

Handled by api_add_document
Parameters
envelope_id string · path
required
Body · AttachDocumentapplication/json
storage_key string · min length: 1 · max length: 500
required
title string · max length: 300
page_count integer
propertyName anything
Responses
200Successful Response
POST /sign/envelopes/example/documents
1curl -X POST "http://localhost:8000/sign/envelopes/example/documents" \
2 -H "Content-Type: application/json" \
3 -d '{"storage_key":"string","title":"string","page_count":1}'
1fetch("http://localhost:8000/sign/envelopes/example/documents", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "storage_key": "string",
6 "title": "string",
7 "page_count": 1
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sign/envelopes/example/documents",
5 json={"storage_key":"string","title":"string","page_count":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sign/envelopes/:envelope_id/exports

Save sealed document to Files

POST /sign/envelopes/:envelope_id/exports {target:"files"} — copy the sealed PDF into the caller's Files. Sign never auto-mirrors; this explicit action is the only path.

Handled by api_create_export
Parameters
envelope_id string · path
required
Body · ExportEnvelopeapplication/json
target
required
propertyName anything
Responses
200Successful Response
POST /sign/envelopes/example/exports
1curl -X POST "http://localhost:8000/sign/envelopes/example/exports" \
2 -H "Content-Type: application/json" \
3 -d '{"target":null}'
1fetch("http://localhost:8000/sign/envelopes/example/exports", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "target": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sign/envelopes/example/exports",
5 json={"target":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /sign/envelopes/:envelope_id/source

Attach the uploaded source PDF

PUT /sign/envelopes/:envelope_id/source {storage_key, page_count} — attach the uploaded source PDF SYNCHRONOUSLY. The client calls this right after PUTting the file to R2, so the document is attached deterministically instead of depending on the async upload-confirmed event (which, if the event bus doesn't deliver it, leaves the PDF unattached forever). The key must live under this workspace's own sign/ prefix — a client can't point the envelope at another workspace's or app's object.

Handled by api_attach_source
Parameters
envelope_id string · path
required
Body · AttachSourceapplication/json
storage_key string · min length: 1 · max length: 500
required
page_count integer
propertyName anything
Responses
200Successful Response
PUT /sign/envelopes/example/source
1curl -X PUT "http://localhost:8000/sign/envelopes/example/source" \
2 -H "Content-Type: application/json" \
3 -d '{"storage_key":"string","page_count":1}'
1fetch("http://localhost:8000/sign/envelopes/example/source", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "storage_key": "string",
6 "page_count": 1
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/sign/envelopes/example/source",
5 json={"storage_key":"string","page_count":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /sign/settings

Choose the contract template

PUT /sign/settings {contract_template_id}: choose the contract template. An empty value clears the choice, which switches the cross-app handoff off: requests then arrive and are ignored rather than drafting the wrong document. Written through the registered config contract so the platform Settings editor and this picker stay one document with one validator.

Handled by api_update_settings
Body · UpdateSignSettingsapplication/json
contract_template_id string · max length: 64
propertyName anything
Responses
200Successful Response
PUT /sign/settings
1curl -X PUT "http://localhost:8000/sign/settings" \
2 -H "Content-Type: application/json" \
3 -d '{"contract_template_id":"string"}'
1fetch("http://localhost:8000/sign/settings", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "contract_template_id": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/sign/settings",
5 json={"contract_template_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /elevations undocumented

/elevations

DELETE /elevations — leave admin mode without waiting for the timer.

Handled by api_end_elevation
Responses
200Successful Response
DELETE /elevations
1curl -X DELETE "http://localhost:8000/elevations"
1fetch("http://localhost:8000/elevations", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/elevations")
4print(response.json())
200 Example Response
No Body
GET /elevations/current undocumented

/elevations/current

GET /elevations/current — the caller's window, for the shell's ring. `totp_enabled` says which factor the prompt should ask for, because only the server knows. Without it the modal had to guess, guessed password, and an account with TOTP paid for a password that api_start_elevation never even looks at before being asked for a code anyway. Having a second factor should cost fewer steps, not more.

Handled by api_current_elevation
Responses
200Successful Response
GET /elevations/current
1curl "http://localhost:8000/elevations/current"
1fetch("http://localhost:8000/elevations/current")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/elevations/current")
4print(response.json())
200 Example Response
No Body
POST /workers/:worker_id/employment

Add an employment record

Handled by api_create_employment
Parameters
worker_id string · path
required
Body · CreateEmploymentapplication/json
job_title string · min length: 1 · max length: 200
required
start_date string · min length: 1 · max length: 10
required
employment_type
end_date string · max length: 10
reason string · max length: 500
reminder_enabled
reminder_days_before integer
propertyName anything
Responses
200Successful Response
POST /workers/example/employment
1curl -X POST "http://localhost:8000/workers/example/employment" \
2 -H "Content-Type: application/json" \
3 -d '{"job_title":"string","start_date":"string","employment_type":null,"end_date":"string","reason":"string","reminder_enabled":null,"reminder_days_before":1}'
1fetch("http://localhost:8000/workers/example/employment", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "job_title": "string",
6 "start_date": "string",
7 "employment_type": null,
8 "end_date": "string",
9 "reason": "string",
10 "reminder_enabled": null,
11 "reminder_days_before": 1
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/example/employment",
5 json={"job_title":"string","start_date":"string","employment_type":null,"end_date":"string","reason":"string","reminder_enabled":null,"reminder_days_before":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workers/:worker_id/employment/termination

Terminate a worker's employment

Terminate employment: close every open/future contract at the effective date, set status=terminated, and fire the terminated event. Reason is required.

Handled by api_terminate_worker
Parameters
worker_id string · path
required
Body · TerminateWorkerapplication/json
reason string · min length: 1 · max length: 500
required
effective_date string · min length: 1 · max length: 10
required
propertyName anything
Responses
200Successful Response
POST /workers/example/employment/termination
1curl -X POST "http://localhost:8000/workers/example/employment/termination" \
2 -H "Content-Type: application/json" \
3 -d '{"reason":"string","effective_date":"string"}'
1fetch("http://localhost:8000/workers/example/employment/termination", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "reason": "string",
6 "effective_date": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/example/employment/termination",
5 json={"reason":"string","effective_date":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /workers/:worker_id/employment/:record_id

Update an employment record

Handled by api_update_employment
Parameters
worker_id string · path
required
record_id string · path
required
Body · UpdateEmploymentapplication/json
job_title string · min length: 1 · max length: 200
employment_type
start_date string · max length: 10
end_date string · max length: 10
reason string · max length: 500
reminder_enabled
reminder_days_before integer
propertyName anything
Responses
200Successful Response
PUT /workers/example/employment/example
1curl -X PUT "http://localhost:8000/workers/example/employment/example" \
2 -H "Content-Type: application/json" \
3 -d '{"job_title":"string","employment_type":null,"start_date":"string","end_date":"string","reason":"string","reminder_enabled":null,"reminder_days_before":1}'
1fetch("http://localhost:8000/workers/example/employment/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "job_title": "string",
6 "employment_type": null,
7 "start_date": "string",
8 "end_date": "string",
9 "reason": "string",
10 "reminder_enabled": null,
11 "reminder_days_before": 1
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/workers/example/employment/example",
5 json={"job_title":"string","employment_type":null,"start_date":"string","end_date":"string","reason":"string","reminder_enabled":null,"reminder_days_before":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /events/:action undocumented

/events/:action

Internal webhook receiver — Amebo delivers events here. Route: POST /events/:action Amebo signs the JSON body with our HMAC secret and sends it as x-amebo-signature. We verify before processing.

Handled by receive_event
Parameters
action string · path
required
Responses
200Successful Response
POST /events/example
1curl -X POST "http://localhost:8000/events/example"
1fetch("http://localhost:8000/events/example", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/example")
4print(response.json())
200 Example Response
No Body
POST /events/attendance-location-backfill-requested undocumented

/events/attendance-location-backfill-requested

system.attendance.location.backfill.requested — re-emit every location. A projection consumer (the Workers app) calls this when its attendance_location_index has drifted: locations emitted before it first subscribed (Amebo never replays history to a late subscriber) or deliveries that exhausted their retries while the app was restarting. We re-emit each current location as system.attendance.location.created; the consumer's existing upsert handler rebuilds the projection. Idempotent on purpose: we pass NO deduper, so Amebo always redelivers (unlike _emit_location, whose per-state deduper would suppress a replay), and the consumer's ON CONFLICT upsert collapses repeats. This is the source side of the leaves worker_index backfill pattern. See specs/attendance-locations.md.

Handled by on_location_backfill_requested
Responses
200Successful Response
POST /events/attendance-location-backfill-requested
1curl -X POST "http://localhost:8000/events/attendance-location-backfill-requested"
1fetch("http://localhost:8000/events/attendance-location-backfill-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/attendance-location-backfill-requested")
4print(response.json())
200 Example Response
No Body
POST /events/attendance-autoclockout-due undocumented

/events/attendance-autoclockout-due

Close a session left open past the worker's daily hours. Staged by Workers on clock-in (Amebo sleep_until) to fire when the day's cumulative hours would reach the worker's expected_hours_per_day. We close the session at that mark — clock_in + the minutes this entry was allowed before the daily target — NOT "now", so a forgotten clock-out records the correct end time. expected_minutes (the worker's daily target) rides in the payload so core never reads worker data. Fully idempotent: a no-op when the entry was already closed (manual clock-out, fresh session, or duplicate delivery), and the punched_out deduper matches the manual one so they can't double-count.

Handled by on_autoclockout_due
Responses
200Successful Response
POST /events/attendance-autoclockout-due
1curl -X POST "http://localhost:8000/events/attendance-autoclockout-due"
1fetch("http://localhost:8000/events/attendance-autoclockout-due", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/attendance-autoclockout-due")
4print(response.json())
200 Example Response
No Body
POST /events/calendar/reminder-due undocumented

/events/calendar/reminder-due

Fire the reminder toast to every current attendee at fires_at, then (for recurring meetings) schedule the next occurrence via sleep_until. Drops stale fires — deleted, cancelled, paused, or occurrence no longer matches the rule after an edit.

Handled by on_meeting_reminder
Responses
200Successful Response
POST /events/calendar/reminder-due
1curl -X POST "http://localhost:8000/events/calendar/reminder-due"
1fetch("http://localhost:8000/events/calendar/reminder-due", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/calendar/reminder-due")
4print(response.json())
200 Example Response
No Body
POST /events/calendar/reminder-sweep undocumented

/events/calendar/reminder-sweep

Walks every active meeting and re-seeds its reminder event. Idempotent: deduper keyed on fires_at makes duplicate emits harmless. Heals chains severed by webhook failures.

Handled by on_reminder_sweep
Responses
200Successful Response
POST /events/calendar/reminder-sweep
1curl -X POST "http://localhost:8000/events/calendar/reminder-sweep"
1fetch("http://localhost:8000/events/calendar/reminder-sweep", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/calendar/reminder-sweep")
4print(response.json())
200 Example Response
No Body
POST /events/system-workspace-member-removed-rooms undocumented

/events/system-workspace-member-removed-rooms

When a workspace member is removed, remove them from all rooms and disconnect if connected.

Handled by on_workspace_member_removed
Responses
200Successful Response
POST /events/system-workspace-member-removed-rooms
1curl -X POST "http://localhost:8000/events/system-workspace-member-removed-rooms"
1fetch("http://localhost:8000/events/system-workspace-member-removed-rooms", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-workspace-member-removed-rooms")
4print(response.json())
200 Example Response
No Body
POST /events/core-people-member-removed-mail undocumented

/events/core-people-member-removed-mail

A workspace member was removed → disconnect their mail accounts + group memberships.

Handled by on_member_removed
Responses
200Successful Response
POST /events/core-people-member-removed-mail
1curl -X POST "http://localhost:8000/events/core-people-member-removed-mail"
1fetch("http://localhost:8000/events/core-people-member-removed-mail", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-people-member-removed-mail")
4print(response.json())
200 Example Response
No Body
POST /events/system-mx-message-delivered undocumented

/events/system-mx-message-delivered

New mail landed on the MX box → sync it into the cache and nudge open clients.

Handled by on_mx_message_delivered
Responses
200Successful Response
POST /events/system-mx-message-delivered
1curl -X POST "http://localhost:8000/events/system-mx-message-delivered"
1fetch("http://localhost:8000/events/system-mx-message-delivered", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-mx-message-delivered")
4print(response.json())
200 Example Response
No Body
POST /events/chat-call-requested undocumented

/events/chat-call-requested

Handled by on_chat_call_requested
Responses
200Successful Response
POST /events/chat-call-requested
1curl -X POST "http://localhost:8000/events/chat-call-requested"
1fetch("http://localhost:8000/events/chat-call-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/chat-call-requested")
4print(response.json())
200 Example Response
No Body
POST /events/calls-call-reminder undocumented

/events/calls-call-reminder

Fire a persistent toast to every participant of a scheduled call. Mirrors the meeting reminder path — honours each recipient's preferences.notifications.calls settings (enabled / toast / sound) so a silenced recipient drops out cleanly.

Handled by on_call_reminder
Responses
200Successful Response
POST /events/calls-call-reminder
1curl -X POST "http://localhost:8000/events/calls-call-reminder"
1fetch("http://localhost:8000/events/calls-call-reminder", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/calls-call-reminder")
4print(response.json())
200 Example Response
No Body
POST /events/system-workspace-member-removed undocumented

/events/system-workspace-member-removed

Handled by on_workspace_member_removed
Responses
200Successful Response
POST /events/system-workspace-member-removed
1curl -X POST "http://localhost:8000/events/system-workspace-member-removed"
1fetch("http://localhost:8000/events/system-workspace-member-removed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-workspace-member-removed")
4print(response.json())
200 Example Response
No Body
POST /events/system-meeting-created undocumented

/events/system-meeting-created

Handled by on_meeting_created
Responses
200Successful Response
POST /events/system-meeting-created
1curl -X POST "http://localhost:8000/events/system-meeting-created"
1fetch("http://localhost:8000/events/system-meeting-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-meeting-created")
4print(response.json())
200 Example Response
No Body
POST /events/system-meeting-deleted undocumented

/events/system-meeting-deleted

Handled by on_meeting_deleted
Responses
200Successful Response
POST /events/system-meeting-deleted
1curl -X POST "http://localhost:8000/events/system-meeting-deleted"
1fetch("http://localhost:8000/events/system-meeting-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-meeting-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/system-meeting-invitee-added undocumented

/events/system-meeting-invitee-added

Handled by on_meeting_invitee_added
Responses
200Successful Response
POST /events/system-meeting-invitee-added
1curl -X POST "http://localhost:8000/events/system-meeting-invitee-added"
1fetch("http://localhost:8000/events/system-meeting-invitee-added", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-meeting-invitee-added")
4print(response.json())
200 Example Response
No Body
POST /events/calls-staleness-check undocumented

/events/calls-staleness-check

Held ~30 minutes by Amebo, then fired to re-check a call that went empty. Calls never auto-end on disconnect anymore, so this is a soft janitor only: if the call is still active and has people in it again, re-arm another delayed check; if it is empty (stale) we leave it active for the host to delete manually and let the chain stop. A broken chain is acceptable: the call just stays on the caller's calls list for manual cleanup.

Handled by on_call_staleness_check
Responses
200Successful Response
POST /events/calls-staleness-check
1curl -X POST "http://localhost:8000/events/calls-staleness-check"
1fetch("http://localhost:8000/events/calls-staleness-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/calls-staleness-check")
4print(response.json())
200 Example Response
No Body
POST /events/account-profile-updated undocumented

/events/account-profile-updated

Handled by on_profile_updated
Responses
200Successful Response
POST /events/account-profile-updated
1curl -X POST "http://localhost:8000/events/account-profile-updated"
1fetch("http://localhost:8000/events/account-profile-updated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/account-profile-updated")
4print(response.json())
200 Example Response
No Body
POST /events/system-canvas-upload-confirmed undocumented

/events/system-canvas-upload-confirmed

system.canvas.upload.confirmed -> create the canvas_assets row for a board image. Backup path: the editor registers the asset synchronously via POST /canvas/boards/:board_id/assets; this covers uploads confirmed by other clients or missed registrations. ensure_asset_row is idempotent.

Handled by on_upload_confirmed
Responses
200Successful Response
POST /events/system-canvas-upload-confirmed
1curl -X POST "http://localhost:8000/events/system-canvas-upload-confirmed"
1fetch("http://localhost:8000/events/system-canvas-upload-confirmed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-canvas-upload-confirmed")
4print(response.json())
200 Example Response
No Body
POST /events/core-canvas-board-purge-due undocumented

/events/core-canvas-board-purge-due

core.canvas.board.purge_due (delayed 30 days) -> hard-delete the board. No-op if the board no longer exists or was restored in the meantime; purge_board only touches boards still marked is_deleted.

Handled by on_board_purge_due
Responses
200Successful Response
POST /events/core-canvas-board-purge-due
1curl -X POST "http://localhost:8000/events/core-canvas-board-purge-due"
1fetch("http://localhost:8000/events/core-canvas-board-purge-due", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-canvas-board-purge-due")
4print(response.json())
200 Example Response
No Body
POST /events/chat-message-sent undocumented

/events/chat-message-sent

Handle core.chat.message.sent. Acknowledge so Amebo marks the event delivered. Future: push notifications, unread badges, etc.

Handled by on_message_sent
Responses
200Successful Response
POST /events/chat-message-sent
1curl -X POST "http://localhost:8000/events/chat-message-sent"
1fetch("http://localhost:8000/events/chat-message-sent", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/chat-message-sent")
4print(response.json())
200 Example Response
No Body
POST /events/system-chat-upload-confirmed undocumented

/events/system-chat-upload-confirmed

Handle system.chat.upload.confirmed. Chat stores media inline in message JSON — no separate media table. The client attaches the storage_key when sending the message. This handler acknowledges the confirmation so Amebo marks it delivered.

Handled by on_upload_confirmed
Responses
200Successful Response
POST /events/system-chat-upload-confirmed
1curl -X POST "http://localhost:8000/events/system-chat-upload-confirmed"
1fetch("http://localhost:8000/events/system-chat-upload-confirmed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-chat-upload-confirmed")
4print(response.json())
200 Example Response
No Body
POST /events/chat-member-removed undocumented

/events/chat-member-removed

Handle system.workspace.member.removed — drop the removed member from every chat's participant list in this workspace, so they no longer appear in DMs or groups. Without this, a removed member's MRN lingers in chats.participants and still resolves to their name.

Handled by on_member_removed
Responses
200Successful Response
POST /events/chat-member-removed
1curl -X POST "http://localhost:8000/events/chat-member-removed"
1fetch("http://localhost:8000/events/chat-member-removed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/chat-member-removed")
4print(response.json())
200 Example Response
No Body
POST /events/calls-call-started undocumented

/events/calls-call-started

Handle core.calls.call.started — record a call card in the conversation.

Handled by on_call_started
Responses
200Successful Response
POST /events/calls-call-started
1curl -X POST "http://localhost:8000/events/calls-call-started"
1fetch("http://localhost:8000/events/calls-call-started", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/calls-call-started")
4print(response.json())
200 Example Response
No Body
POST /events/calls-call-ended undocumented

/events/calls-call-ended

Handle core.calls.call.ended — flip the call card to its ended state.

Handled by on_call_ended
Responses
200Successful Response
POST /events/calls-call-ended
1curl -X POST "http://localhost:8000/events/calls-call-ended"
1fetch("http://localhost:8000/events/calls-call-ended", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/calls-call-ended")
4print(response.json())
200 Example Response
No Body
POST /events/core-mail-email-sent undocumented

/events/core-mail-email-sent

Handle core.mail.email.sent — log an interaction per known recipient, and queue a contact suggestion for each recipient who isn't a contact yet. The mail app emits ``to_addresses`` (a list); older callers may send ``to``.

Handled by on_email_sent
Responses
200Successful Response
POST /events/core-mail-email-sent
1curl -X POST "http://localhost:8000/events/core-mail-email-sent"
1fetch("http://localhost:8000/events/core-mail-email-sent", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-mail-email-sent")
4print(response.json())
200 Example Response
No Body
POST /events/core-mail-email-received undocumented

/events/core-mail-email-received

Handle core.mail.email.received — log an inbound interaction if the sender is a known contact, otherwise queue them as a contact suggestion.

Handled by on_email_received
Responses
200Successful Response
POST /events/core-mail-email-received
1curl -X POST "http://localhost:8000/events/core-mail-email-received"
1fetch("http://localhost:8000/events/core-mail-email-received", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-mail-email-received")
4print(response.json())
200 Example Response
No Body
POST /events/core-calendar-event-completed undocumented

/events/core-calendar-event-completed

Handle core.calendar.event.completed — auto-log meeting interaction for attendees.

Handled by on_calendar_event_completed
Responses
200Successful Response
POST /events/core-calendar-event-completed
1curl -X POST "http://localhost:8000/events/core-calendar-event-completed"
1fetch("http://localhost:8000/events/core-calendar-event-completed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-calendar-event-completed")
4print(response.json())
200 Example Response
No Body
POST /events/core-calls-call-ended undocumented

/events/core-calls-call-ended

Handle core.calls.call.ended — auto-log call interaction.

Handled by on_call_ended
Responses
200Successful Response
POST /events/core-calls-call-ended
1curl -X POST "http://localhost:8000/events/core-calls-call-ended"
1fetch("http://localhost:8000/events/core-calls-call-ended", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-calls-call-ended")
4print(response.json())
200 Example Response
No Body
POST /events/core-crm-deal-won undocumented

/events/core-crm-deal-won

Handle core.crm.deal.won — auto-tag company as 'customer'.

Handled by on_deal_won
Responses
200Successful Response
POST /events/core-crm-deal-won
1curl -X POST "http://localhost:8000/events/core-crm-deal-won"
1fetch("http://localhost:8000/events/core-crm-deal-won", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-crm-deal-won")
4print(response.json())
200 Example Response
No Body
POST /events/core-crm-deal-lost undocumented

/events/core-crm-deal-lost

Handle core.crm.deal.lost — log a note interaction on the contact.

Handled by on_deal_lost
Responses
200Successful Response
POST /events/core-crm-deal-lost
1curl -X POST "http://localhost:8000/events/core-crm-deal-lost"
1fetch("http://localhost:8000/events/core-crm-deal-lost", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-crm-deal-lost")
4print(response.json())
200 Example Response
No Body
POST /events/core-suppliers-rfq-sent undocumented

/events/core-suppliers-rfq-sent

Handle core.suppliers.rfq.sent — auto-log RFQ interaction.

Handled by on_rfq_sent
Responses
200Successful Response
POST /events/core-suppliers-rfq-sent
1curl -X POST "http://localhost:8000/events/core-suppliers-rfq-sent"
1fetch("http://localhost:8000/events/core-suppliers-rfq-sent", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-suppliers-rfq-sent")
4print(response.json())
200 Example Response
No Body
POST /events/core-suppliers-po-issued undocumented

/events/core-suppliers-po-issued

Handle core.suppliers.po.issued — auto-log PO interaction.

Handled by on_po_issued
Responses
200Successful Response
POST /events/core-suppliers-po-issued
1curl -X POST "http://localhost:8000/events/core-suppliers-po-issued"
1fetch("http://localhost:8000/events/core-suppliers-po-issued", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-suppliers-po-issued")
4print(response.json())
200 Example Response
No Body
POST /events/core-finance-party-index-requested undocumented

/events/core-finance-party-index-requested

Replay current companies and contacts for a projection consumer. Bound to both core.finance.party_index.requested and core.crm.party_index.requested: any app that keeps a party projection asks for current state at install time and we answer with one company.created / contact.created per row, so the consumer's normal handlers do the projecting without a dedicated backfill event type. The payloads carry the same fields as a live create, so a consumer that projects lifecycle or firmographics backfills them too.

Handled by on_party_index_requested
Responses
200Successful Response
POST /events/core-finance-party-index-requested
1curl -X POST "http://localhost:8000/events/core-finance-party-index-requested"
1fetch("http://localhost:8000/events/core-finance-party-index-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-finance-party-index-requested")
4print(response.json())
200 Example Response
No Body
POST /events/core-crm-party-index-requested undocumented

/events/core-crm-party-index-requested

Replay current companies and contacts for a projection consumer. Bound to both core.finance.party_index.requested and core.crm.party_index.requested: any app that keeps a party projection asks for current state at install time and we answer with one company.created / contact.created per row, so the consumer's normal handlers do the projecting without a dedicated backfill event type. The payloads carry the same fields as a live create, so a consumer that projects lifecycle or firmographics backfills them too.

Handled by on_party_index_requested
Responses
200Successful Response
POST /events/core-crm-party-index-requested
1curl -X POST "http://localhost:8000/events/core-crm-party-index-requested"
1fetch("http://localhost:8000/events/core-crm-party-index-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-crm-party-index-requested")
4print(response.json())
200 Example Response
No Body
POST /events/core-vendibles-conversation-started undocumented

/events/core-vendibles-conversation-started

Handle core.vendibles.conversation.started — open a conversation. Idempotent on the visitor token: a redelivered event appends nothing and re-reports the conversation that already exists.

Handled by on_surface_conversation_started
Responses
200Successful Response
POST /events/core-vendibles-conversation-started
1curl -X POST "http://localhost:8000/events/core-vendibles-conversation-started"
1fetch("http://localhost:8000/events/core-vendibles-conversation-started", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-vendibles-conversation-started")
4print(response.json())
200 Example Response
No Body
POST /events/core-vendibles-conversation-message undocumented

/events/core-vendibles-conversation-message

Handle core.vendibles.conversation.message — append a visitor follow-up.

Handled by on_surface_conversation_message
Responses
200Successful Response
POST /events/core-vendibles-conversation-message
1curl -X POST "http://localhost:8000/events/core-vendibles-conversation-message"
1fetch("http://localhost:8000/events/core-vendibles-conversation-message", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-vendibles-conversation-message")
4print(response.json())
200 Example Response
No Body
POST /events/core-vendibles-conversation-rated undocumented

/events/core-vendibles-conversation-rated

Handle core.vendibles.conversation.rated — store CSAT and log it. The rating is the resolution's receipt: it lands on the conversation, on the contact's timeline as a ``csat`` interaction, and (from phase 2) on the state ladder.

Handled by on_surface_conversation_rated
Responses
200Successful Response
POST /events/core-vendibles-conversation-rated
1curl -X POST "http://localhost:8000/events/core-vendibles-conversation-rated"
1fetch("http://localhost:8000/events/core-vendibles-conversation-rated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-vendibles-conversation-rated")
4print(response.json())
200 Example Response
No Body
POST /events/core-vendibles-order-placed undocumented

/events/core-vendibles-order-placed

Handle core.vendibles.order.placed — project the purchase, resolve the buyer.

Handled by on_order_placed
Responses
200Successful Response
POST /events/core-vendibles-order-placed
1curl -X POST "http://localhost:8000/events/core-vendibles-order-placed"
1fetch("http://localhost:8000/events/core-vendibles-order-placed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-vendibles-order-placed")
4print(response.json())
200 Example Response
No Body
POST /events/core-vendibles-order-paid undocumented

/events/core-vendibles-order-paid

Handle core.vendibles.order.paid — a paid order lifts the ladder, and the third one is proof of advocacy. Repeat purchase is the behavioural half of "promoter": someone who keeps buying is voting with money, which is harder evidence than a good mood.

Handled by on_order_paid
Responses
200Successful Response
POST /events/core-vendibles-order-paid
1curl -X POST "http://localhost:8000/events/core-vendibles-order-paid"
1fetch("http://localhost:8000/events/core-vendibles-order-paid", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-vendibles-order-paid")
4print(response.json())
200 Example Response
No Body
POST /events/core-vendibles-order-refunded undocumented

/events/core-vendibles-order-refunded

Handle core.vendibles.order.refunded — a refund pushes the ladder down.

Handled by on_order_refunded
Responses
200Successful Response
POST /events/core-vendibles-order-refunded
1curl -X POST "http://localhost:8000/events/core-vendibles-order-refunded"
1fetch("http://localhost:8000/events/core-vendibles-order-refunded", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-vendibles-order-refunded")
4print(response.json())
200 Example Response
No Body
POST /events/core-finance-invoice-issued undocumented

/events/core-finance-invoice-issued

Handle core.finance.invoice.issued — project the invoice.

Handled by on_invoice_issued
Responses
200Successful Response
POST /events/core-finance-invoice-issued
1curl -X POST "http://localhost:8000/events/core-finance-invoice-issued"
1fetch("http://localhost:8000/events/core-finance-invoice-issued", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-finance-invoice-issued")
4print(response.json())
200 Example Response
No Body
POST /events/core-finance-invoice-paid undocumented

/events/core-finance-invoice-paid

Handle core.finance.invoice.paid — project the settlement.

Handled by on_invoice_paid
Responses
200Successful Response
POST /events/core-finance-invoice-paid
1curl -X POST "http://localhost:8000/events/core-finance-invoice-paid"
1fetch("http://localhost:8000/events/core-finance-invoice-paid", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-finance-invoice-paid")
4print(response.json())
200 Example Response
No Body
POST /events/core-finance-payment-received undocumented

/events/core-finance-payment-received

Handle core.finance.payment.received — project money in from a contact.

Handled by on_payment_received
Responses
200Successful Response
POST /events/core-finance-payment-received
1curl -X POST "http://localhost:8000/events/core-finance-payment-received"
1fetch("http://localhost:8000/events/core-finance-payment-received", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-finance-payment-received")
4print(response.json())
200 Example Response
No Body
POST /events/core-sign-document-completed undocumented

/events/core-sign-document-completed

Handle core.sign.document.completed — project the signature. Sign addresses recipients by email rather than contact MRN, so the person is matched the same way the mail handlers match one.

Handled by on_document_completed
Responses
200Successful Response
POST /events/core-sign-document-completed
1curl -X POST "http://localhost:8000/events/core-sign-document-completed"
1fetch("http://localhost:8000/events/core-sign-document-completed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-sign-document-completed")
4print(response.json())
200 Example Response
No Body
POST /events/core-contacts-state-decay-check undocumented

/events/core-contacts-state-decay-check

Handle core.contacts.state.decay_check — drift quiet contacts to neutral. Silence is not evidence of feeling either way. A contact nobody has touched for the configured window moves one step toward zero per elapsed window, so an old complaint stops branding someone angry forever, and an old delight stops flattering the numbers. Idempotent by construction: the step count is computed from how long the contact has actually been quiet, so running the sweep twice in one day applies the same result as running it once.

Handled by on_state_decay_check
Responses
200Successful Response
POST /events/core-contacts-state-decay-check
1curl -X POST "http://localhost:8000/events/core-contacts-state-decay-check"
1fetch("http://localhost:8000/events/core-contacts-state-decay-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/core-contacts-state-decay-check")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-contacts-contact-created undocumented

/events/crm/core-contacts-contact-created

core.contacts.contact.created / .updated: project the contact.

Handled by on_contact_upserted
Responses
200Successful Response
POST /events/crm/core-contacts-contact-created
1curl -X POST "http://localhost:8000/events/crm/core-contacts-contact-created"
1fetch("http://localhost:8000/events/crm/core-contacts-contact-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-contacts-contact-created")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-contacts-contact-updated undocumented

/events/crm/core-contacts-contact-updated

core.contacts.contact.created / .updated: project the contact.

Handled by on_contact_upserted
Responses
200Successful Response
POST /events/crm/core-contacts-contact-updated
1curl -X POST "http://localhost:8000/events/crm/core-contacts-contact-updated"
1fetch("http://localhost:8000/events/crm/core-contacts-contact-updated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-contacts-contact-updated")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-contacts-contact-deleted undocumented

/events/crm/core-contacts-contact-deleted

core.contacts.contact.deleted: drop the projected contact.

Handled by on_contact_deleted
Responses
200Successful Response
POST /events/crm/core-contacts-contact-deleted
1curl -X POST "http://localhost:8000/events/crm/core-contacts-contact-deleted"
1fetch("http://localhost:8000/events/crm/core-contacts-contact-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-contacts-contact-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-contacts-company-created undocumented

/events/crm/core-contacts-company-created

core.contacts.company.created / .updated: project the company. Also refreshes the cached company_name on every contact pointing at it, so a rename shows up on deal cards without waiting for a contact update.

Handled by on_company_upserted
Responses
200Successful Response
POST /events/crm/core-contacts-company-created
1curl -X POST "http://localhost:8000/events/crm/core-contacts-company-created"
1fetch("http://localhost:8000/events/crm/core-contacts-company-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-contacts-company-created")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-contacts-company-updated undocumented

/events/crm/core-contacts-company-updated

core.contacts.company.created / .updated: project the company. Also refreshes the cached company_name on every contact pointing at it, so a rename shows up on deal cards without waiting for a contact update.

Handled by on_company_upserted
Responses
200Successful Response
POST /events/crm/core-contacts-company-updated
1curl -X POST "http://localhost:8000/events/crm/core-contacts-company-updated"
1fetch("http://localhost:8000/events/crm/core-contacts-company-updated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-contacts-company-updated")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-contacts-company-deleted undocumented

/events/crm/core-contacts-company-deleted

core.contacts.company.deleted: drop the projected company.

Handled by on_company_deleted
Responses
200Successful Response
POST /events/crm/core-contacts-company-deleted
1curl -X POST "http://localhost:8000/events/crm/core-contacts-company-deleted"
1fetch("http://localhost:8000/events/crm/core-contacts-company-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-contacts-company-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-contacts-interaction-created undocumented

/events/crm/core-contacts-interaction-created

core.contacts.interaction.created. Three effects: credit the actor's matching activity target, bump the party's interaction stats, and stamp last_interaction_at on the related deals so the going-cold sweep has something to read.

Handled by on_interaction_created
Responses
200Successful Response
POST /events/crm/core-contacts-interaction-created
1curl -X POST "http://localhost:8000/events/crm/core-contacts-interaction-created"
1fetch("http://localhost:8000/events/crm/core-contacts-interaction-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-contacts-interaction-created")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-quote-created undocumented

/events/crm/core-finance-quote-created

core.finance.quote.created / .sent / .accepted / .rejected on the deal timeline. The `event` data key is what the drawer's quote-state derivation reads; labels are display-only. A sent event also stamps deals.room_quote so the customer's deal room can link the quote portal.

Handled by on_quote_event
Responses
200Successful Response
POST /events/crm/core-finance-quote-created
1curl -X POST "http://localhost:8000/events/crm/core-finance-quote-created"
1fetch("http://localhost:8000/events/crm/core-finance-quote-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-quote-created")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-quote-sent undocumented

/events/crm/core-finance-quote-sent

core.finance.quote.created / .sent / .accepted / .rejected on the deal timeline. The `event` data key is what the drawer's quote-state derivation reads; labels are display-only. A sent event also stamps deals.room_quote so the customer's deal room can link the quote portal.

Handled by on_quote_event
Responses
200Successful Response
POST /events/crm/core-finance-quote-sent
1curl -X POST "http://localhost:8000/events/crm/core-finance-quote-sent"
1fetch("http://localhost:8000/events/crm/core-finance-quote-sent", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-quote-sent")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-quote-accepted undocumented

/events/crm/core-finance-quote-accepted

core.finance.quote.created / .sent / .accepted / .rejected on the deal timeline. The `event` data key is what the drawer's quote-state derivation reads; labels are display-only. A sent event also stamps deals.room_quote so the customer's deal room can link the quote portal.

Handled by on_quote_event
Responses
200Successful Response
POST /events/crm/core-finance-quote-accepted
1curl -X POST "http://localhost:8000/events/crm/core-finance-quote-accepted"
1fetch("http://localhost:8000/events/crm/core-finance-quote-accepted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-quote-accepted")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-quote-rejected undocumented

/events/crm/core-finance-quote-rejected

core.finance.quote.created / .sent / .accepted / .rejected on the deal timeline. The `event` data key is what the drawer's quote-state derivation reads; labels are display-only. A sent event also stamps deals.room_quote so the customer's deal room can link the quote portal.

Handled by on_quote_event
Responses
200Successful Response
POST /events/crm/core-finance-quote-rejected
1curl -X POST "http://localhost:8000/events/crm/core-finance-quote-rejected"
1fetch("http://localhost:8000/events/crm/core-finance-quote-rejected", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-quote-rejected")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-invoice-issued undocumented

/events/crm/core-finance-invoice-issued

core.finance.invoice.issued / .paid on the deal timeline. Issued also stamps deals.room_invoice (portal path from portal_token) so the deal room can offer the customer the pay link; paid flips it to a receipt line.

Handled by on_invoice_event
Responses
200Successful Response
POST /events/crm/core-finance-invoice-issued
1curl -X POST "http://localhost:8000/events/crm/core-finance-invoice-issued"
1fetch("http://localhost:8000/events/crm/core-finance-invoice-issued", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-invoice-issued")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-invoice-paid undocumented

/events/crm/core-finance-invoice-paid

core.finance.invoice.issued / .paid on the deal timeline. Issued also stamps deals.room_invoice (portal path from portal_token) so the deal room can offer the customer the pay link; paid flips it to a receipt line.

Handled by on_invoice_event
Responses
200Successful Response
POST /events/crm/core-finance-invoice-paid
1curl -X POST "http://localhost:8000/events/crm/core-finance-invoice-paid"
1fetch("http://localhost:8000/events/crm/core-finance-invoice-paid", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-invoice-paid")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-payment-received undocumented

/events/crm/core-finance-payment-received

core.finance.payment.received on the deal timeline.

Handled by on_payment_received
Responses
200Successful Response
POST /events/crm/core-finance-payment-received
1curl -X POST "http://localhost:8000/events/crm/core-finance-payment-received"
1fetch("http://localhost:8000/events/crm/core-finance-payment-received", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-payment-received")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-finance-portal-viewed undocumented

/events/crm/core-finance-portal-viewed

core.finance.portal.viewed: the customer opened the quote or invoice.

Handled by on_portal_viewed
Responses
200Successful Response
POST /events/crm/core-finance-portal-viewed
1curl -X POST "http://localhost:8000/events/crm/core-finance-portal-viewed"
1fetch("http://localhost:8000/events/crm/core-finance-portal-viewed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-finance-portal-viewed")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-sign-document-prepared undocumented

/events/crm/core-sign-document-prepared

core.sign.document.prepared: a draft contract is waiting for the deal owner. Separate from on_signature_event because this one is a call to action rather than a status report: the contract does NOT go out until its owner sends it.

Handled by on_signature_prepared
Responses
200Successful Response
POST /events/crm/core-sign-document-prepared
1curl -X POST "http://localhost:8000/events/crm/core-sign-document-prepared"
1fetch("http://localhost:8000/events/crm/core-sign-document-prepared", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-sign-document-prepared")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-sign-document-viewed undocumented

/events/crm/core-sign-document-viewed

core.sign.document.viewed / .signed / .declined / .completed.

Handled by on_signature_event
Responses
200Successful Response
POST /events/crm/core-sign-document-viewed
1curl -X POST "http://localhost:8000/events/crm/core-sign-document-viewed"
1fetch("http://localhost:8000/events/crm/core-sign-document-viewed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-sign-document-viewed")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-sign-document-signed undocumented

/events/crm/core-sign-document-signed

core.sign.document.viewed / .signed / .declined / .completed.

Handled by on_signature_event
Responses
200Successful Response
POST /events/crm/core-sign-document-signed
1curl -X POST "http://localhost:8000/events/crm/core-sign-document-signed"
1fetch("http://localhost:8000/events/crm/core-sign-document-signed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-sign-document-signed")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-sign-document-declined undocumented

/events/crm/core-sign-document-declined

core.sign.document.viewed / .signed / .declined / .completed.

Handled by on_signature_event
Responses
200Successful Response
POST /events/crm/core-sign-document-declined
1curl -X POST "http://localhost:8000/events/crm/core-sign-document-declined"
1fetch("http://localhost:8000/events/crm/core-sign-document-declined", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-sign-document-declined")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-sign-document-completed undocumented

/events/crm/core-sign-document-completed

core.sign.document.viewed / .signed / .declined / .completed.

Handled by on_signature_event
Responses
200Successful Response
POST /events/crm/core-sign-document-completed
1curl -X POST "http://localhost:8000/events/crm/core-sign-document-completed"
1fetch("http://localhost:8000/events/crm/core-sign-document-completed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-sign-document-completed")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-crm-deal-won undocumented

/events/crm/core-crm-deal-won

core.crm.deal.won: credit the owner's revenue target for the period. Subscribing to our own event means every close path (API, deal room, automation) credits quota through exactly one code path.

Handled by on_deal_won
Responses
200Successful Response
POST /events/crm/core-crm-deal-won
1curl -X POST "http://localhost:8000/events/crm/core-crm-deal-won"
1fetch("http://localhost:8000/events/crm/core-crm-deal-won", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-crm-deal-won")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-crm-deal-health-check undocumented

/events/crm/core-crm-deal-health-check

core.crm.deal.health_check: the daily deal sweep. Emits stale / overdue / going_cold for open deals that crossed a configured threshold, refreshes stored deal scores, emits score threshold crossings, then re-arms tomorrow's sweep.

Handled by on_deal_health_check
Responses
200Successful Response
POST /events/crm/core-crm-deal-health-check
1curl -X POST "http://localhost:8000/events/crm/core-crm-deal-health-check"
1fetch("http://localhost:8000/events/crm/core-crm-deal-health-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-crm-deal-health-check")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-crm-target-period-check undocumented

/events/crm/core-crm-target-period-check

core.crm.target.period_check: the daily quota sweep. Closes out periods that ended (achieved / missed) and flags active targets that are behind pace with the clock running down, then re-arms.

Handled by on_target_period_check
Responses
200Successful Response
POST /events/crm/core-crm-target-period-check
1curl -X POST "http://localhost:8000/events/crm/core-crm-target-period-check"
1fetch("http://localhost:8000/events/crm/core-crm-target-period-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-crm-target-period-check")
4print(response.json())
200 Example Response
No Body
POST /events/crm/core-settings-application-installed undocumented

/events/crm/core-settings-application-installed

core.settings.application.installed. When CRM lands in a workspace that already has contacts, ask the contacts app to replay current state (the finance party_index handshake), and arm the two daily sweeps.

Handled by on_application_installed
Responses
200Successful Response
POST /events/crm/core-settings-application-installed
1curl -X POST "http://localhost:8000/events/crm/core-settings-application-installed"
1fetch("http://localhost:8000/events/crm/core-settings-application-installed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/crm/core-settings-application-installed")
4print(response.json())
200 Example Response
No Body
POST /events/system-feeds-upload-confirmed undocumented

/events/system-feeds-upload-confirmed

Handle system.feeds.upload.confirmed — insert feed_media row.

Handled by on_upload_confirmed
Responses
200Successful Response
POST /events/system-feeds-upload-confirmed
1curl -X POST "http://localhost:8000/events/system-feeds-upload-confirmed"
1fetch("http://localhost:8000/events/system-feeds-upload-confirmed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-feeds-upload-confirmed")
4print(response.json())
200 Example Response
No Body
POST /events/system-files-upload-confirmed undocumented

/events/system-files-upload-confirmed

Handle system.files.upload.confirmed — create the file row. The platform confirm endpoint has already verified the storage key sits in this workspace's namespace and HEAD-verified the object; this handler adds the app-level checks the platform cannot know about: the uploader must be able to write into the target folder, and a name collision suffixes to "name (1).ext" instead of silently replacing the existing file.

Handled by on_upload_confirmed
Responses
200Successful Response
POST /events/system-files-upload-confirmed
1curl -X POST "http://localhost:8000/events/system-files-upload-confirmed"
1fetch("http://localhost:8000/events/system-files-upload-confirmed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-files-upload-confirmed")
4print(response.json())
200 Example Response
No Body
POST /events/files-chat-file-shared undocumented

/events/files-chat-file-shared

Ingest a chat attachment for the sender AND everyone in the conversation. An attachment was shared *with people*, so it mirrors that audience: the sender gets it under My Apps/Chat, each other participant under My Apps/Chat/Shared with me. The participant list is a snapshot taken when the message was sent, which is why it rides on the event rather than being looked up here (Files may not read chat's tables).

Handled by on_chat_file_shared
Responses
200Successful Response
POST /events/files-chat-file-shared
1curl -X POST "http://localhost:8000/events/files-chat-file-shared"
1fetch("http://localhost:8000/events/files-chat-file-shared", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-chat-file-shared")
4print(response.json())
200 Example Response
No Body
POST /events/files-canvas-board-exported undocumented

/events/files-canvas-board-exported

Ingest a Canvas board the exporter explicitly saved to Files (exporter only).

Handled by on_canvas_board_exported
Responses
200Successful Response
POST /events/files-canvas-board-exported
1curl -X POST "http://localhost:8000/events/files-canvas-board-exported"
1fetch("http://localhost:8000/events/files-canvas-board-exported", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-canvas-board-exported")
4print(response.json())
200 Example Response
No Body
POST /events/files-sign-document-exported undocumented

/events/files-sign-document-exported

Ingest a sealed document exported from Sign into the exporter's My Apps/Sign. Sign never auto-mirrors; this only fires on the user's explicit 'Save to Files', which is a one-person act, so nobody else gets a row. The file points at Sign's sealed R2 object (source_ref = mrn:sign:envelope:{id}).

Handled by on_sign_document_exported
Responses
200Successful Response
POST /events/files-sign-document-exported
1curl -X POST "http://localhost:8000/events/files-sign-document-exported"
1fetch("http://localhost:8000/events/files-sign-document-exported", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-sign-document-exported")
4print(response.json())
200 Example Response
No Body
POST /events/files-chat-message-deleted undocumented

/events/files-chat-message-deleted

A deleted chat message takes its attachments out of everyone's Files.

Handled by on_chat_message_deleted
Responses
200Successful Response
POST /events/files-chat-message-deleted
1curl -X POST "http://localhost:8000/events/files-chat-message-deleted"
1fetch("http://localhost:8000/events/files-chat-message-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-chat-message-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/files-chat-participant-removed undocumented

/events/files-chat-participant-removed

Someone left (or was removed from) a conversation: their links go too. Scoped to that one conversation and that one member. Attachments they received elsewhere, and everyone else's rows for this conversation, stay.

Handled by on_chat_participant_removed
Responses
200Successful Response
POST /events/files-chat-participant-removed
1curl -X POST "http://localhost:8000/events/files-chat-participant-removed"
1fetch("http://localhost:8000/events/files-chat-participant-removed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-chat-participant-removed")
4print(response.json())
200 Example Response
No Body
POST /events/files-sign-envelope-deleted undocumented

/events/files-sign-envelope-deleted

A deleted Sign envelope takes its saved copy out of Files.

Handled by on_sign_envelope_deleted
Responses
200Successful Response
POST /events/files-sign-envelope-deleted
1curl -X POST "http://localhost:8000/events/files-sign-envelope-deleted"
1fetch("http://localhost:8000/events/files-sign-envelope-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-sign-envelope-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/files-canvas-board-deleted undocumented

/events/files-canvas-board-deleted

A deleted Canvas board takes its exports out of Files.

Handled by on_canvas_board_deleted
Responses
200Successful Response
POST /events/files-canvas-board-deleted
1curl -X POST "http://localhost:8000/events/files-canvas-board-deleted"
1fetch("http://localhost:8000/events/files-canvas-board-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-canvas-board-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/files-sign-export-revoked undocumented

/events/files-sign-export-revoked

Someone undid a 'Save to Files' in the app that owns the document. Shared by Sign and Canvas: both carry the same source_ref this app filed the copy under. This is the only way a deliberate export leaves Files, since Files itself will not delete anything another app owns.

Handled by on_export_revoked
Responses
200Successful Response
POST /events/files-sign-export-revoked
1curl -X POST "http://localhost:8000/events/files-sign-export-revoked"
1fetch("http://localhost:8000/events/files-sign-export-revoked", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-sign-export-revoked")
4print(response.json())
200 Example Response
No Body
POST /events/files-canvas-export-revoked undocumented

/events/files-canvas-export-revoked

Someone undid a 'Save to Files' in the app that owns the document. Shared by Sign and Canvas: both carry the same source_ref this app filed the copy under. This is the only way a deliberate export leaves Files, since Files itself will not delete anything another app owns.

Handled by on_export_revoked
Responses
200Successful Response
POST /events/files-canvas-export-revoked
1curl -X POST "http://localhost:8000/events/files-canvas-export-revoked"
1fetch("http://localhost:8000/events/files-canvas-export-revoked", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-canvas-export-revoked")
4print(response.json())
200 Example Response
No Body
POST /events/files-member-removed undocumented

/events/files-member-removed

Handled by on_member_removed
Responses
200Successful Response
POST /events/files-member-removed
1curl -X POST "http://localhost:8000/events/files-member-removed"
1fetch("http://localhost:8000/events/files-member-removed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-member-removed")
4print(response.json())
200 Example Response
No Body
POST /events/files-file-deleted undocumented

/events/files-file-deleted

Handle core.files.file.deleted — clean up R2 storage key.

Handled by on_file_deleted
Responses
200Successful Response
POST /events/files-file-deleted
1curl -X POST "http://localhost:8000/events/files-file-deleted"
1fetch("http://localhost:8000/events/files-file-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-file-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/files-folder-deleted undocumented

/events/files-folder-deleted

Handle core.files.folder.deleted — clean up R2 storage keys for all files in folder tree.

Handled by on_folder_deleted
Responses
200Successful Response
POST /events/files-folder-deleted
1curl -X POST "http://localhost:8000/events/files-folder-deleted"
1fetch("http://localhost:8000/events/files-folder-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/files-folder-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-workers-payrun-executed undocumented

/events/finance/core-workers-payrun-executed

core.workers.payrun.executed → auto-create a draft journal entry. Expected payload: ``{"payrun_id", "period", "gross_total", "net_total", "tax_total", "actor_mrn"}``. We draft a balanced journal (debit Salaries, credit Cash / Tax Payable / Net Pay). The workspace operator posts it when they're ready — payroll isn't automatically reflected on the ledger until approved.

Handled by on_payrun_executed
Responses
200Successful Response
POST /events/finance/core-workers-payrun-executed
1curl -X POST "http://localhost:8000/events/finance/core-workers-payrun-executed"
1fetch("http://localhost:8000/events/finance/core-workers-payrun-executed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-workers-payrun-executed")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-inventory-stock-issued undocumented

/events/finance/core-inventory-stock-issued

core.inventory.stock.issued → post COGS (debit 5100, credit 1300). Expected payload: ``{"movement_id", "cost", "currency", "sku", "location", "lot", "actor_mrn"}``. Cost is the inventory valuation (FIFO/LIFO/avg) computed by the Inventory app.

Handled by on_inventory_stock_issued
Responses
200Successful Response
POST /events/finance/core-inventory-stock-issued
1curl -X POST "http://localhost:8000/events/finance/core-inventory-stock-issued"
1fetch("http://localhost:8000/events/finance/core-inventory-stock-issued", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-inventory-stock-issued")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-inventory-stock-received undocumented

/events/finance/core-inventory-stock-received

core.inventory.stock.received → if no bill exists yet, post Goods Received Not Invoiced: debit Inventory (1300), credit Accrued Expenses (2300). When the bill later approves, it reverses that accrual.

Handled by on_inventory_stock_received
Responses
200Successful Response
POST /events/finance/core-inventory-stock-received
1curl -X POST "http://localhost:8000/events/finance/core-inventory-stock-received"
1fetch("http://localhost:8000/events/finance/core-inventory-stock-received", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-inventory-stock-received")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-inventory-stock-adjusted undocumented

/events/finance/core-inventory-stock-adjusted

core.inventory.stock.adjusted → post inventory variance. Expected payload: ``{"movement_id", "delta", "currency", "sku", "location", "lot", "actor_mrn"}``. Positive delta = write-up (debit Inventory, credit Inventory Adjustments). Negative = write-down.

Handled by on_inventory_stock_adjusted
Responses
200Successful Response
POST /events/finance/core-inventory-stock-adjusted
1curl -X POST "http://localhost:8000/events/finance/core-inventory-stock-adjusted"
1fetch("http://localhost:8000/events/finance/core-inventory-stock-adjusted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-inventory-stock-adjusted")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-crm-deal-won undocumented

/events/finance/core-crm-deal-won

core.crm.deal.won → create a draft invoice for the deal. The deal payload is a *fact* (already happened); Finance responds by drafting an invoice the workspace can review and issue. We do not auto- issue — revenue recognition stays under human control. If the deal has no company_mrn (contacts app not installed, or missing customer record), we skip silently — no draft is created.

Handled by on_deal_won
Responses
200Successful Response
POST /events/finance/core-crm-deal-won
1curl -X POST "http://localhost:8000/events/finance/core-crm-deal-won"
1fetch("http://localhost:8000/events/finance/core-crm-deal-won", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-crm-deal-won")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-crm-deal-quote-requested undocumented

/events/finance/core-crm-deal-quote-requested

core.crm.deal.quote_requested → draft a quote from the deal's line items. Mirror of on_deal_won: CRM states a fact (a rep wants a quote) and Finance, the authority for money documents, drafts one for a human to review and send. The deal MRN goes into ``sources`` so every later quote event can carry it back and land on the deal timeline. Re-requesting is idempotent while the quote is still a draft.

Handled by on_deal_quote_requested
Responses
200Successful Response
POST /events/finance/core-crm-deal-quote-requested
1curl -X POST "http://localhost:8000/events/finance/core-crm-deal-quote-requested"
1fetch("http://localhost:8000/events/finance/core-crm-deal-quote-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-crm-deal-quote-requested")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-crm-deal-lost undocumented

/events/finance/core-crm-deal-lost

core.crm.deal.lost → delete the auto-drafted invoice if it's still a draft. If the invoice has already been issued, we leave it alone — that's a human decision to bill regardless of deal outcome.

Handled by on_deal_lost
Responses
200Successful Response
POST /events/finance/core-crm-deal-lost
1curl -X POST "http://localhost:8000/events/finance/core-crm-deal-lost"
1fetch("http://localhost:8000/events/finance/core-crm-deal-lost", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-crm-deal-lost")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-crm-deal-value-changed undocumented

/events/finance/core-crm-deal-value-changed

core.crm.deal.value_changed → resize the auto-drafted invoice if still draft.

Handled by on_deal_value_changed
Responses
200Successful Response
POST /events/finance/core-crm-deal-value-changed
1curl -X POST "http://localhost:8000/events/finance/core-crm-deal-value-changed"
1fetch("http://localhost:8000/events/finance/core-crm-deal-value-changed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-crm-deal-value-changed")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-finance-invoice-due-check undocumented

/events/finance/core-finance-invoice-due-check

core.finance.invoice.due_check → emit invoice.overdue if still unpaid.

Handled by on_invoice_due_check
Responses
200Successful Response
POST /events/finance/core-finance-invoice-due-check
1curl -X POST "http://localhost:8000/events/finance/core-finance-invoice-due-check"
1fetch("http://localhost:8000/events/finance/core-finance-invoice-due-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-finance-invoice-due-check")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-finance-bill-due-check undocumented

/events/finance/core-finance-bill-due-check

core.finance.bill.due_check → emit bill.overdue if still unpaid.

Handled by on_bill_due_check
Responses
200Successful Response
POST /events/finance/core-finance-bill-due-check
1curl -X POST "http://localhost:8000/events/finance/core-finance-bill-due-check"
1fetch("http://localhost:8000/events/finance/core-finance-bill-due-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-finance-bill-due-check")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-finance-quote-expiry-check undocumented

/events/finance/core-finance-quote-expiry-check

core.finance.quote.expiry_check → emit quote.expired if still open.

Handled by on_quote_expiry_check
Responses
200Successful Response
POST /events/finance/core-finance-quote-expiry-check
1curl -X POST "http://localhost:8000/events/finance/core-finance-quote-expiry-check"
1fetch("http://localhost:8000/events/finance/core-finance-quote-expiry-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-finance-quote-expiry-check")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-finance-recurring-due-check undocumented

/events/finance/core-finance-recurring-due-check

core.finance.recurring.due_check → run the recurring entry, advance, re-emit. Self-perpetuating schedule: each firing creates the draft entry, advances the stored ``next_date``, and re-emits another ``due_check`` for the new date. Deletion of the recurring row naturally cancels the chain — when the delayed webhook arrives and the row is gone, this handler no-ops.

Handled by on_recurring_due_check
Responses
200Successful Response
POST /events/finance/core-finance-recurring-due-check
1curl -X POST "http://localhost:8000/events/finance/core-finance-recurring-due-check"
1fetch("http://localhost:8000/events/finance/core-finance-recurring-due-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-finance-recurring-due-check")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-finance-period-revalue-reverse undocumented

/events/finance/core-finance-period-revalue-reverse

core.finance.period.revalue_reverse → post the reversing JE. Idempotent: if the revaluation record already has ``reversed_at`` set, or the period/reval was deleted before delivery, the handler no-ops.

Handled by on_period_revalue_reverse
Responses
200Successful Response
POST /events/finance/core-finance-period-revalue-reverse
1curl -X POST "http://localhost:8000/events/finance/core-finance-period-revalue-reverse"
1fetch("http://localhost:8000/events/finance/core-finance-period-revalue-reverse", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-finance-period-revalue-reverse")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-finance-period-close-reminder undocumented

/events/finance/core-finance-period-close-reminder

core.finance.period.close_reminder → nudge operative if period still has no revaluation run past period_end. Emits ``core.finance.period.close_due`` which Notifications surfaces in-app. If this is the first nudge (``nudge=1``), schedules a second nudge 7 days later. Handler no-ops once a revaluation exists or the period was closed/deleted.

Handled by on_period_close_reminder
Responses
200Successful Response
POST /events/finance/core-finance-period-close-reminder
1curl -X POST "http://localhost:8000/events/finance/core-finance-period-close-reminder"
1fetch("http://localhost:8000/events/finance/core-finance-period-close-reminder", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-finance-period-close-reminder")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-contacts-company-created undocumented

/events/finance/core-contacts-company-created

core.contacts.company.created / .updated → project company name.

Handled by on_company_upserted
Responses
200Successful Response
POST /events/finance/core-contacts-company-created
1curl -X POST "http://localhost:8000/events/finance/core-contacts-company-created"
1fetch("http://localhost:8000/events/finance/core-contacts-company-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-contacts-company-created")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-contacts-company-updated undocumented

/events/finance/core-contacts-company-updated

core.contacts.company.created / .updated → project company name.

Handled by on_company_upserted
Responses
200Successful Response
POST /events/finance/core-contacts-company-updated
1curl -X POST "http://localhost:8000/events/finance/core-contacts-company-updated"
1fetch("http://localhost:8000/events/finance/core-contacts-company-updated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-contacts-company-updated")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-contacts-company-deleted undocumented

/events/finance/core-contacts-company-deleted

core.contacts.company.deleted → drop the projected name.

Handled by on_company_deleted
Responses
200Successful Response
POST /events/finance/core-contacts-company-deleted
1curl -X POST "http://localhost:8000/events/finance/core-contacts-company-deleted"
1fetch("http://localhost:8000/events/finance/core-contacts-company-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-contacts-company-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-contacts-contact-created undocumented

/events/finance/core-contacts-contact-created

core.contacts.contact.created / .updated → project contact name.

Handled by on_contact_upserted
Responses
200Successful Response
POST /events/finance/core-contacts-contact-created
1curl -X POST "http://localhost:8000/events/finance/core-contacts-contact-created"
1fetch("http://localhost:8000/events/finance/core-contacts-contact-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-contacts-contact-created")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-contacts-contact-updated undocumented

/events/finance/core-contacts-contact-updated

core.contacts.contact.created / .updated → project contact name.

Handled by on_contact_upserted
Responses
200Successful Response
POST /events/finance/core-contacts-contact-updated
1curl -X POST "http://localhost:8000/events/finance/core-contacts-contact-updated"
1fetch("http://localhost:8000/events/finance/core-contacts-contact-updated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-contacts-contact-updated")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-contacts-contact-deleted undocumented

/events/finance/core-contacts-contact-deleted

core.contacts.contact.deleted → drop the projected name.

Handled by on_contact_deleted
Responses
200Successful Response
POST /events/finance/core-contacts-contact-deleted
1curl -X POST "http://localhost:8000/events/finance/core-contacts-contact-deleted"
1fetch("http://localhost:8000/events/finance/core-contacts-contact-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-contacts-contact-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/finance/core-account-application-installed undocumented

/events/finance/core-account-application-installed

core.settings.application.installed → backfill the party index on first install. When finance is installed into a workspace that already has contacts/companies, ask the contacts app to re-emit current state so we can populate the projection. Contacts responds by emitting company.created / contact.created per row, which the handlers above project.

Handled by on_application_installed
Responses
200Successful Response
POST /events/finance/core-account-application-installed
1curl -X POST "http://localhost:8000/events/finance/core-account-application-installed"
1fetch("http://localhost:8000/events/finance/core-account-application-installed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance/core-account-application-installed")
4print(response.json())
200 Example Response
No Body
POST /events/growth-worker-created undocumented

/events/growth-worker-created

Handled by on_worker_created
Responses
200Successful Response
POST /events/growth-worker-created
1curl -X POST "http://localhost:8000/events/growth-worker-created"
1fetch("http://localhost:8000/events/growth-worker-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-worker-created")
4print(response.json())
200 Example Response
No Body
POST /events/growth-worker-updated undocumented

/events/growth-worker-updated

Handled by on_worker_updated
Responses
200Successful Response
POST /events/growth-worker-updated
1curl -X POST "http://localhost:8000/events/growth-worker-updated"
1fetch("http://localhost:8000/events/growth-worker-updated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-worker-updated")
4print(response.json())
200 Example Response
No Body
POST /events/growth-worker-terminated undocumented

/events/growth-worker-terminated

Handled by on_worker_terminated
Responses
200Successful Response
POST /events/growth-worker-terminated
1curl -X POST "http://localhost:8000/events/growth-worker-terminated"
1fetch("http://localhost:8000/events/growth-worker-terminated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-worker-terminated")
4print(response.json())
200 Example Response
No Body
POST /events/growth-account-application-installed undocumented

/events/growth-account-application-installed

core.settings.application.installed — backfill the worker projection on first install.

Handled by on_application_installed
Responses
200Successful Response
POST /events/growth-account-application-installed
1curl -X POST "http://localhost:8000/events/growth-account-application-installed"
1fetch("http://localhost:8000/events/growth-account-application-installed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-account-application-installed")
4print(response.json())
200 Example Response
No Body
POST /events/growth-task-created undocumented

/events/growth-task-created

Handled by on_task_created
Responses
200Successful Response
POST /events/growth-task-created
1curl -X POST "http://localhost:8000/events/growth-task-created"
1fetch("http://localhost:8000/events/growth-task-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-task-created")
4print(response.json())
200 Example Response
No Body
POST /events/growth-task-completed undocumented

/events/growth-task-completed

Handled by on_task_completed
Responses
200Successful Response
POST /events/growth-task-completed
1curl -X POST "http://localhost:8000/events/growth-task-completed"
1fetch("http://localhost:8000/events/growth-task-completed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-task-completed")
4print(response.json())
200 Example Response
No Body
POST /events/growth-task-deleted undocumented

/events/growth-task-deleted

Handled by on_task_deleted
Responses
200Successful Response
POST /events/growth-task-deleted
1curl -X POST "http://localhost:8000/events/growth-task-deleted"
1fetch("http://localhost:8000/events/growth-task-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-task-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/worker-created undocumented

/events/worker-created

Handled by on_worker_created
Responses
200Successful Response
POST /events/worker-created
1curl -X POST "http://localhost:8000/events/worker-created"
1fetch("http://localhost:8000/events/worker-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/worker-created")
4print(response.json())
200 Example Response
No Body
POST /events/worker-updated undocumented

/events/worker-updated

Handled by on_worker_updated
Responses
200Successful Response
POST /events/worker-updated
1curl -X POST "http://localhost:8000/events/worker-updated"
1fetch("http://localhost:8000/events/worker-updated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/worker-updated")
4print(response.json())
200 Example Response
No Body
POST /events/worker-terminated undocumented

/events/worker-terminated

Handled by on_worker_terminated
Responses
200Successful Response
POST /events/worker-terminated
1curl -X POST "http://localhost:8000/events/worker-terminated"
1fetch("http://localhost:8000/events/worker-terminated", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/worker-terminated")
4print(response.json())
200 Example Response
No Body
POST /events/account-application-installed undocumented

/events/account-application-installed

Handled by on_application_installed
Responses
200Successful Response
POST /events/account-application-installed
1curl -X POST "http://localhost:8000/events/account-application-installed"
1fetch("http://localhost:8000/events/account-application-installed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/account-application-installed")
4print(response.json())
200 Example Response
No Body
POST /events/leaves-attendance-location-upserted undocumented

/events/leaves-attendance-location-upserted

system.attendance.location.created/updated — mirror the location locally.

Handled by on_attendance_location_upserted
Responses
200Successful Response
POST /events/leaves-attendance-location-upserted
1curl -X POST "http://localhost:8000/events/leaves-attendance-location-upserted"
1fetch("http://localhost:8000/events/leaves-attendance-location-upserted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/leaves-attendance-location-upserted")
4print(response.json())
200 Example Response
No Body
POST /events/leaves-attendance-location-deleted undocumented

/events/leaves-attendance-location-deleted

system.attendance.location.deleted — drop the projected copy.

Handled by on_attendance_location_deleted
Responses
200Successful Response
POST /events/leaves-attendance-location-deleted
1curl -X POST "http://localhost:8000/events/leaves-attendance-location-deleted"
1fetch("http://localhost:8000/events/leaves-attendance-location-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/leaves-attendance-location-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/calls-call-scheduled undocumented

/events/calls-call-scheduled

Handled by on_calls_call_scheduled
Responses
200Successful Response
POST /events/calls-call-scheduled
1curl -X POST "http://localhost:8000/events/calls-call-scheduled"
1fetch("http://localhost:8000/events/calls-call-scheduled", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/calls-call-scheduled")
4print(response.json())
200 Example Response
No Body
POST /events/feeds-post-created undocumented

/events/feeds-post-created

Handled by on_feeds_post_created
Responses
200Successful Response
POST /events/feeds-post-created
1curl -X POST "http://localhost:8000/events/feeds-post-created"
1fetch("http://localhost:8000/events/feeds-post-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/feeds-post-created")
4print(response.json())
200 Example Response
No Body
POST /events/feeds-post-shared undocumented

/events/feeds-post-shared

Handled by on_feeds_post_shared
Responses
200Successful Response
POST /events/feeds-post-shared
1curl -X POST "http://localhost:8000/events/feeds-post-shared"
1fetch("http://localhost:8000/events/feeds-post-shared", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/feeds-post-shared")
4print(response.json())
200 Example Response
No Body
POST /events/feeds-follow-created undocumented

/events/feeds-follow-created

Handled by on_feeds_follow_created
Responses
200Successful Response
POST /events/feeds-follow-created
1curl -X POST "http://localhost:8000/events/feeds-follow-created"
1fetch("http://localhost:8000/events/feeds-follow-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/feeds-follow-created")
4print(response.json())
200 Example Response
No Body
POST /events/feeds-follow-deleted undocumented

/events/feeds-follow-deleted

Handled by on_feeds_follow_deleted
Responses
200Successful Response
POST /events/feeds-follow-deleted
1curl -X POST "http://localhost:8000/events/feeds-follow-deleted"
1fetch("http://localhost:8000/events/feeds-follow-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/feeds-follow-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/member-mentioned undocumented

/events/member-mentioned

Handled by on_member_mentioned
Responses
200Successful Response
POST /events/member-mentioned
1curl -X POST "http://localhost:8000/events/member-mentioned"
1fetch("http://localhost:8000/events/member-mentioned", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/member-mentioned")
4print(response.json())
200 Example Response
No Body
POST /events/leaves-pto-created undocumented

/events/leaves-pto-created

Handled by on_leaves_pto_created
Responses
200Successful Response
POST /events/leaves-pto-created
1curl -X POST "http://localhost:8000/events/leaves-pto-created"
1fetch("http://localhost:8000/events/leaves-pto-created", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/leaves-pto-created")
4print(response.json())
200 Example Response
No Body
POST /events/tasks-task-assigned undocumented

/events/tasks-task-assigned

Handled by on_tasks_task_assigned
Responses
200Successful Response
POST /events/tasks-task-assigned
1curl -X POST "http://localhost:8000/events/tasks-task-assigned"
1fetch("http://localhost:8000/events/tasks-task-assigned", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/tasks-task-assigned")
4print(response.json())
200 Example Response
No Body
POST /events/tasks-task-resolved undocumented

/events/tasks-task-resolved

Handled by on_tasks_task_resolved
Responses
200Successful Response
POST /events/tasks-task-resolved
1curl -X POST "http://localhost:8000/events/tasks-task-resolved"
1fetch("http://localhost:8000/events/tasks-task-resolved", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/tasks-task-resolved")
4print(response.json())
200 Example Response
No Body
POST /events/finance-bill-received undocumented

/events/finance-bill-received

Handled by on_finance_bill_received
Responses
200Successful Response
POST /events/finance-bill-received
1curl -X POST "http://localhost:8000/events/finance-bill-received"
1fetch("http://localhost:8000/events/finance-bill-received", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance-bill-received")
4print(response.json())
200 Example Response
No Body
POST /events/finance-bill-approved undocumented

/events/finance-bill-approved

Handled by on_finance_bill_approved
Responses
200Successful Response
POST /events/finance-bill-approved
1curl -X POST "http://localhost:8000/events/finance-bill-approved"
1fetch("http://localhost:8000/events/finance-bill-approved", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/finance-bill-approved")
4print(response.json())
200 Example Response
No Body
POST /events/chat-conversation-activity undocumented

/events/chat-conversation-activity

Handled by on_chat_conversation_activity
Responses
200Successful Response
POST /events/chat-conversation-activity
1curl -X POST "http://localhost:8000/events/chat-conversation-activity"
1fetch("http://localhost:8000/events/chat-conversation-activity", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/chat-conversation-activity")
4print(response.json())
200 Example Response
No Body
POST /events/contacts-conversation-started undocumented

/events/contacts-conversation-started

A visitor opened a conversation. Everyone who can answer gets told. Unassigned by definition at this point, so the whole answering pool is notified; assignment later narrows it to one person.

Handled by on_contacts_conversation_started
Responses
200Successful Response
POST /events/contacts-conversation-started
1curl -X POST "http://localhost:8000/events/contacts-conversation-started"
1fetch("http://localhost:8000/events/contacts-conversation-started", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/contacts-conversation-started")
4print(response.json())
200 Example Response
No Body
POST /events/contacts-conversation-message undocumented

/events/contacts-conversation-message

A visitor wrote back. Tell whoever owns the thread, or the whole pool if nobody does: an updated conversation is as much a person waiting as a new one is.

Handled by on_contacts_conversation_message
Responses
200Successful Response
POST /events/contacts-conversation-message
1curl -X POST "http://localhost:8000/events/contacts-conversation-message"
1fetch("http://localhost:8000/events/contacts-conversation-message", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/contacts-conversation-message")
4print(response.json())
200 Example Response
No Body
POST /events/contacts-conversation-assigned undocumented

/events/contacts-conversation-assigned

A conversation now has an owner. Clear the pool's "new conversation" rows and tell the assignee it is theirs.

Handled by on_contacts_conversation_assigned
Responses
200Successful Response
POST /events/contacts-conversation-assigned
1curl -X POST "http://localhost:8000/events/contacts-conversation-assigned"
1fetch("http://localhost:8000/events/contacts-conversation-assigned", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/contacts-conversation-assigned")
4print(response.json())
200 Example Response
No Body
POST /events/contacts-conversation-resolved undocumented

/events/contacts-conversation-resolved

Resolved: drop the "Needs you" row so a closed thread stops nagging.

Handled by on_contacts_conversation_resolved
Responses
200Successful Response
POST /events/contacts-conversation-resolved
1curl -X POST "http://localhost:8000/events/contacts-conversation-resolved"
1fetch("http://localhost:8000/events/contacts-conversation-resolved", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/contacts-conversation-resolved")
4print(response.json())
200 Example Response
No Body
POST /events/billing-payment-failed undocumented

/events/billing-payment-failed

Handled by on_billing_payment_failed
Responses
200Successful Response
POST /events/billing-payment-failed
1curl -X POST "http://localhost:8000/events/billing-payment-failed"
1fetch("http://localhost:8000/events/billing-payment-failed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/billing-payment-failed")
4print(response.json())
200 Example Response
No Body
POST /events/billing-suspend-check undocumented

/events/billing-suspend-check

Handled by on_billing_suspend_check
Responses
200Successful Response
POST /events/billing-suspend-check
1curl -X POST "http://localhost:8000/events/billing-suspend-check"
1fetch("http://localhost:8000/events/billing-suspend-check", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/billing-suspend-check")
4print(response.json())
200 Example Response
No Body
POST /events/billing-charge-retry undocumented

/events/billing-charge-retry

Delayed event (fires on days 3 and 7 after a failed charge). Re-attempts the invoice on the default card; idempotent — a paid invoice is a no-op.

Handled by on_billing_charge_retry
Responses
200Successful Response
POST /events/billing-charge-retry
1curl -X POST "http://localhost:8000/events/billing-charge-retry"
1fetch("http://localhost:8000/events/billing-charge-retry", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/billing-charge-retry")
4print(response.json())
200 Example Response
No Body
POST /events/billing-trial-expiring undocumented

/events/billing-trial-expiring

Delayed event (fires 3 days before trial end). Notifies workspace admins.

Handled by on_billing_trial_expiring
Responses
200Successful Response
POST /events/billing-trial-expiring
1curl -X POST "http://localhost:8000/events/billing-trial-expiring"
1fetch("http://localhost:8000/events/billing-trial-expiring", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/billing-trial-expiring")
4print(response.json())
200 Example Response
No Body
POST /events/billing-trial-ended undocumented

/events/billing-trial-ended

Delayed event (fires at trial end). Activates or suspends based on card_on_file.

Handled by on_billing_trial_ended
Responses
200Successful Response
POST /events/billing-trial-ended
1curl -X POST "http://localhost:8000/events/billing-trial-ended"
1fetch("http://localhost:8000/events/billing-trial-ended", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/billing-trial-ended")
4print(response.json())
200 Example Response
No Body
POST /events/billing-invoice-due undocumented

/events/billing-invoice-due

Delayed event (fires every 30 or 365 days). Generates the invoice and charges the card. The billing interval is read FRESH from the subscription — never from the event payload — so a monthly↔annual switch takes effect on the loop's next firing. The payload's invoice_type identifies which loop this firing belongs to; a 'seats' firing under a now-monthly subscription retires itself (the monthly loop carries the billing), and an 'all' firing under a now-annual subscription continues as the 'usage' loop.

Handled by on_billing_invoice_due
Responses
200Successful Response
POST /events/billing-invoice-due
1curl -X POST "http://localhost:8000/events/billing-invoice-due"
1fetch("http://localhost:8000/events/billing-invoice-due", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/billing-invoice-due")
4print(response.json())
200 Example Response
No Body
POST /events/billing-seat-changed undocumented

/events/billing-seat-changed

Immediate event. Handles annual proration when seats increase.

Handled by on_billing_seat_changed
Responses
200Successful Response
POST /events/billing-seat-changed
1curl -X POST "http://localhost:8000/events/billing-seat-changed"
1fetch("http://localhost:8000/events/billing-seat-changed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/billing-seat-changed")
4print(response.json())
200 Example Response
No Body
POST /events/system-sign-upload-confirmed undocumented

/events/system-sign-upload-confirmed

Handle system.sign.upload.confirmed — attach the uploaded source PDF to its envelope. Idempotent (a plain UPDATE keyed by envelope id) per the at-least-once event contract. The document SHA-256 fingerprint is computed later at seal time, when the bytes are downloaded anyway — not here, to avoid a large synchronous R2 read on the event loop.

Handled by on_upload_confirmed
Responses
200Successful Response
POST /events/system-sign-upload-confirmed
1curl -X POST "http://localhost:8000/events/system-sign-upload-confirmed"
1fetch("http://localhost:8000/events/system-sign-upload-confirmed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-sign-upload-confirmed")
4print(response.json())
200 Example Response
No Body
POST /events/sign/core-crm-deal-signature-requested undocumented

/events/sign/core-crm-deal-signature-requested

core.crm.deal.signature_requested — prepare a draft contract for the deal. A DRAFT, deliberately, never an automatic send. This fires when a customer accepts a proposal, and nobody has yet checked which template applies, whether terms moved during negotiation, or that the right people are on it. A wrong contract auto-sent to a customer is very hard to walk back, so Sign prepares it and the deal owner sends it. Mirrors finance.on_deal_quote_requested, where the same reasoning keeps revenue documents under human control. Silent no-op (204) whenever the workspace has not configured a contract template, since a workspace that has not chosen one should never have a contract prepared on its behalf.

Handled by on_deal_signature_requested
Responses
200Successful Response
POST /events/sign/core-crm-deal-signature-requested
1curl -X POST "http://localhost:8000/events/sign/core-crm-deal-signature-requested"
1fetch("http://localhost:8000/events/sign/core-crm-deal-signature-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/sign/core-crm-deal-signature-requested")
4print(response.json())
200 Example Response
No Body
POST /events/system-slides-upload-confirmed undocumented

/events/system-slides-upload-confirmed

system.slides.upload.confirmed: create the slide_assets row for a deck image. Backup path. The editor registers the asset synchronously through POST /decks/:id/assets so the picture is servable at once; this covers an upload confirmed by another client, or a registration call that never landed. ensure_asset_row is idempotent, so both paths running is not a problem.

Handled by on_upload_confirmed
Responses
200Successful Response
POST /events/system-slides-upload-confirmed
1curl -X POST "http://localhost:8000/events/system-slides-upload-confirmed"
1fetch("http://localhost:8000/events/system-slides-upload-confirmed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-slides-upload-confirmed")
4print(response.json())
200 Example Response
No Body
POST /events/system-tasks-upload-confirmed undocumented

/events/system-tasks-upload-confirmed

Handle system.tasks.upload.confirmed. Tasks stores attachments inline as JSON on the task row — no separate media table. The client attaches the storage_key when creating/updating the task. This handler acknowledges the confirmation so Amebo marks it delivered.

Handled by on_upload_confirmed
Responses
200Successful Response
POST /events/system-tasks-upload-confirmed
1curl -X POST "http://localhost:8000/events/system-tasks-upload-confirmed"
1fetch("http://localhost:8000/events/system-tasks-upload-confirmed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/system-tasks-upload-confirmed")
4print(response.json())
200 Example Response
No Body
POST /events/tasks-growth-action-item-promoted undocumented

/events/tasks-growth-action-item-promoted

Handle core.growth.action_item.promoted. Growth turns a 1:1 action item into a real task here rather than calling the Tasks API (rule 6). The task carries source_mrn back to the growth signal so the emitted core.tasks.task.created lets growth mirror it into its own projection. Idempotent: Amebo may redeliver, and a duplicate task for the same action item would be worse than a dropped one, so an existing source_mrn wins.

Handled by on_growth_action_item_promoted
Responses
200Successful Response
POST /events/tasks-growth-action-item-promoted
1curl -X POST "http://localhost:8000/events/tasks-growth-action-item-promoted"
1fetch("http://localhost:8000/events/tasks-growth-action-item-promoted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/tasks-growth-action-item-promoted")
4print(response.json())
200 Example Response
No Body
POST /events/account-member-removed undocumented

/events/account-member-removed

Handle core.settings.member.removed — purge the removed member from all wiki_pages.shares arrays in the workspace. The shares column is JSONB. We filter out entries where type='member' AND id=removed_member_id, leaving role-based shares intact.

Handled by on_member_removed
Responses
200Successful Response
POST /events/account-member-removed
1curl -X POST "http://localhost:8000/events/account-member-removed"
1fetch("http://localhost:8000/events/account-member-removed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/account-member-removed")
4print(response.json())
200 Example Response
No Body
POST /events/leaves-worker-index-requested undocumented

/events/leaves-worker-index-requested

Re-emit core.workers.worker.updated so a consumer can backfill its index. Triggered by leaves (or any future projection consumer) when it needs to backfill its local index. worker.updated carries full current state (event-carried state transfer), so consumers' existing handlers project each row without a separate event type. If the payload carries a ``member_mrn``, only that member's worker is re-emitted — a targeted self-heal for a single drifted row (e.g. leaves couldn't resolve a requester). Without it, the whole table is re-emitted (install / cron backfill).

Handled by on_leaves_worker_index_requested
Responses
200Successful Response
POST /events/leaves-worker-index-requested
1curl -X POST "http://localhost:8000/events/leaves-worker-index-requested"
1fetch("http://localhost:8000/events/leaves-worker-index-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/leaves-worker-index-requested")
4print(response.json())
200 Example Response
No Body
POST /events/growth-worker-index-requested undocumented

/events/growth-worker-index-requested

Re-emit core.workers.worker.updated so a consumer can backfill its index. Triggered by leaves (or any future projection consumer) when it needs to backfill its local index. worker.updated carries full current state (event-carried state transfer), so consumers' existing handlers project each row without a separate event type. If the payload carries a ``member_mrn``, only that member's worker is re-emitted — a targeted self-heal for a single drifted row (e.g. leaves couldn't resolve a requester). Without it, the whole table is re-emitted (install / cron backfill).

Handled by on_leaves_worker_index_requested
Responses
200Successful Response
POST /events/growth-worker-index-requested
1curl -X POST "http://localhost:8000/events/growth-worker-index-requested"
1fetch("http://localhost:8000/events/growth-worker-index-requested", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/growth-worker-index-requested")
4print(response.json())
200 Example Response
No Body
POST /events/attendance-punched-in undocumented

/events/attendance-punched-in

system.attendance.punched_in — schedule an auto clock-out safety net. If the worker has expected_hours_per_day set, stage a delayed system.attendance.autoclockout.due (held by Amebo via sleep_until) for the moment the worker's CUMULATIVE hours for the day would reach that target — so a lunch break doesn't reset the clock. Core attendance closes the session then, only if it's still the open one. No expected hours, no worker record, or the daily target already met => no timer. Idempotent: the deduper is per entry, and a manual clock-out or a fresh session makes the fired event a no-op for the now-closed entry.

Handled by on_attendance_punched_in
Responses
200Successful Response
POST /events/attendance-punched-in
1curl -X POST "http://localhost:8000/events/attendance-punched-in"
1fetch("http://localhost:8000/events/attendance-punched-in", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/attendance-punched-in")
4print(response.json())
200 Example Response
No Body
POST /events/attendance-punched-out undocumented

/events/attendance-punched-out

system.attendance.punched_out — project the day's hours onto the worker. Sets (not increments) worked_minutes from the day running total in the payload, so redelivery and backfill stay idempotent. Leave status, set by the PTO handlers, always wins over a bare presence reading.

Handled by on_attendance_punched_out
Responses
200Successful Response
POST /events/attendance-punched-out
1curl -X POST "http://localhost:8000/events/attendance-punched-out"
1fetch("http://localhost:8000/events/attendance-punched-out", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/attendance-punched-out")
4print(response.json())
200 Example Response
No Body
POST /events/leaves-pto-approved undocumented

/events/leaves-pto-approved

core.leaves.pto.approved — mark each covered WORKING day as on-leave. Only the worker's location working days are marked on-leave: a weekend or other non-working day inside a leave span is not "on leave" — the worker wasn't expected anyway. Non-working days are scrubbed of any stale leave marker (so a re-emit after a working-pattern change rebuilds correctly): a pure leave-marker row is dropped back to blank, a row with real presence keeps it. Idempotent — safe to redeliver.

Handled by on_pto_approved
Responses
200Successful Response
POST /events/leaves-pto-approved
1curl -X POST "http://localhost:8000/events/leaves-pto-approved"
1fetch("http://localhost:8000/events/leaves-pto-approved", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/leaves-pto-approved")
4print(response.json())
200 Example Response
No Body
POST /events/leaves-pto-cancelled undocumented

/events/leaves-pto-cancelled

Handled by on_pto_cancelled
Responses
200Successful Response
POST /events/leaves-pto-cancelled
1curl -X POST "http://localhost:8000/events/leaves-pto-cancelled"
1fetch("http://localhost:8000/events/leaves-pto-cancelled", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/leaves-pto-cancelled")
4print(response.json())
200 Example Response
No Body
POST /events/leaves-pto-revoked undocumented

/events/leaves-pto-revoked

Handled by on_pto_revoked
Responses
200Successful Response
POST /events/leaves-pto-revoked
1curl -X POST "http://localhost:8000/events/leaves-pto-revoked"
1fetch("http://localhost:8000/events/leaves-pto-revoked", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/leaves-pto-revoked")
4print(response.json())
200 Example Response
No Body
POST /events/attendance-location-upserted undocumented

/events/attendance-location-upserted

system.attendance.location.created/updated — mirror the location locally. Full-state events (event-carried state transfer): upsert every field. The attendance_page reads timezone + workdays to derive absence in the worker's own timezone; the Hours report also reads work_start/work_end to split worked time into payable (in-window) vs off-hours. Carries only what's read (rule 5).

Handled by on_attendance_location_upserted
Responses
200Successful Response
POST /events/attendance-location-upserted
1curl -X POST "http://localhost:8000/events/attendance-location-upserted"
1fetch("http://localhost:8000/events/attendance-location-upserted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/attendance-location-upserted")
4print(response.json())
200 Example Response
No Body
POST /events/attendance-location-deleted undocumented

/events/attendance-location-deleted

system.attendance.location.deleted — drop the projected copy. Workers assigned to the location are reassigned by the delete flow before this fires, so removing the index row leaves no dangling reads.

Handled by on_attendance_location_deleted
Responses
200Successful Response
POST /events/attendance-location-deleted
1curl -X POST "http://localhost:8000/events/attendance-location-deleted"
1fetch("http://localhost:8000/events/attendance-location-deleted", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/attendance-location-deleted")
4print(response.json())
200 Example Response
No Body
POST /events/workers-account-application-installed undocumented

/events/workers-account-application-installed

core.settings.application.installed — self-heal the location projection. When the Workers app is (re)installed we ask attendance to re-emit every location, rebuilding attendance_location_index from scratch. This closes the gap where locations created before Workers first subscribed never reached the projection (Amebo never replays history to a late subscriber). Mirrors the leaves install-time backfill. Idempotent — attendance's re-emit upserts.

Handled by on_application_installed
Responses
200Successful Response
POST /events/workers-account-application-installed
1curl -X POST "http://localhost:8000/events/workers-account-application-installed"
1fetch("http://localhost:8000/events/workers-account-application-installed", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/workers-account-application-installed")
4print(response.json())
200 Example Response
No Body
POST /events/workers-employment-reminder undocumented

/events/workers-employment-reminder

core.workers.employment.reminder — a scheduled contract-expiry reminder fired. Fire-and-no-op: only notify when the record still exists, still ends on the date the reminder was scheduled for, and reminders are still enabled. Otherwise this is a stale schedule (the contract was edited, deleted, or the reminder switched off) and we silently skip — we never cancel scheduled events.

Handled by on_employment_reminder
Responses
200Successful Response
POST /events/workers-employment-reminder
1curl -X POST "http://localhost:8000/events/workers-employment-reminder"
1fetch("http://localhost:8000/events/workers-employment-reminder", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/workers-employment-reminder")
4print(response.json())
200 Example Response
No Body
POST /events/workers-employment-transition undocumented

/events/workers-employment-transition

core.workers.employment.transition — re-snapshot at a contract boundary. A future-dated contract becoming active (or an active one ending) changes the worker's snapshot with no user action. Fire-and-no-op: recompute from the current records and only write / emit when something actually drifted. The lazy self-heal on the worker page is the backstop if a tick is ever missed.

Handled by on_employment_transition
Responses
200Successful Response
POST /events/workers-employment-transition
1curl -X POST "http://localhost:8000/events/workers-employment-transition"
1fetch("http://localhost:8000/events/workers-employment-transition", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/workers-employment-transition")
4print(response.json())
200 Example Response
No Body
POST /events/workers-audit undocumented

/events/workers-audit

Append a row to the worker audit trail for each subscribed Workers event. One handler for many actions (the delivered envelope carries ``action``). Idempotent enough for an append log: redelivery only happens on handler failure, and the normal 2xx path inserts exactly once.

Handled by on_worker_audit_event
Responses
200Successful Response
POST /events/workers-audit
1curl -X POST "http://localhost:8000/events/workers-audit"
1fetch("http://localhost:8000/events/workers-audit", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/workers-audit")
4print(response.json())
200 Example Response
No Body
POST /events/workers-checklist-autoassign undocumented

/events/workers-checklist-autoassign

core.workers.worker.2026-06-23.created / .terminated — auto-assign checklists. Templates opt in via checklists.auto_assign ({enabled, trigger, department_ids}). Hire-triggered templates anchor item due-offsets to the worker's hire date; termination-triggered ones to their end date. Idempotent: an existing assignment for (checklist, worker) is skipped, so redelivery never duplicates (and never re-emits checklist.assigned).

Handled by on_worker_lifecycle_autoassign
Responses
200Successful Response
POST /events/workers-checklist-autoassign
1curl -X POST "http://localhost:8000/events/workers-checklist-autoassign"
1fetch("http://localhost:8000/events/workers-checklist-autoassign", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/events/workers-checklist-autoassign")
4print(response.json())
200 Example Response
No Body
GET /exchanges/:exchange_id undocumented

/exchanges/:exchange_id

GET /exchanges/:exchange_id — one audit row, for the mint-capable caller only, which since the shared-only amendment means a workspace owner/admin. Anyone else gets the same 404 as a nonexistent id. No list-all-workspace-exchanges in V1.

Handled by api_get_exchange
Parameters
exchange_id string · path
required
Responses
200Successful Response
GET /exchanges/example
1curl "http://localhost:8000/exchanges/example"
1fetch("http://localhost:8000/exchanges/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/exchanges/example")
4print(response.json())
200 Example Response
No Body
DELETE /feeds/:post_id undocumented

/feeds/:post_id

DELETE /feeds/:post_id — soft-delete a post (author only).

Handled by api_delete_post
Parameters
post_id string · path
required
Responses
200Successful Response
DELETE /feeds/example
1curl -X DELETE "http://localhost:8000/feeds/example"
1fetch("http://localhost:8000/feeds/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/feeds/example")
4print(response.json())
200 Example Response
No Body
DELETE /feeds/:post_id/reactions/:reaction_type undocumented

/feeds/:post_id/reactions/:reaction_type

DELETE /feeds/:post_id/react — remove a reaction.

Handled by api_unreact
Parameters
post_id string · path
required
reaction_type string · path
required
Responses
200Successful Response
DELETE /feeds/example/reactions/example
1curl -X DELETE "http://localhost:8000/feeds/example/reactions/example"
1fetch("http://localhost:8000/feeds/example/reactions/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/feeds/example/reactions/example")
4print(response.json())
200 Example Response
No Body
DELETE /feeds/:post_id/bookmarks undocumented

/feeds/:post_id/bookmarks

DELETE /feeds/:post_id/bookmark — remove bookmark.

Handled by api_unbookmark
Parameters
post_id string · path
required
Responses
200Successful Response
DELETE /feeds/example/bookmarks
1curl -X DELETE "http://localhost:8000/feeds/example/bookmarks"
1fetch("http://localhost:8000/feeds/example/bookmarks", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/feeds/example/bookmarks")
4print(response.json())
200 Example Response
No Body
GET /feeds undocumented

/feeds

GET /feeds — list top-level posts (timeline).

Handled by api_list_posts
Responses
200Successful Response
GET /feeds
1curl "http://localhost:8000/feeds"
1fetch("http://localhost:8000/feeds")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/feeds")
4print(response.json())
200 Example Response
No Body
GET /feeds/:post_id undocumented

/feeds/:post_id

GET /feeds/:post_id — get a single post.

Handled by api_get_post
Parameters
post_id string · path
required
Responses
200Successful Response
GET /feeds/example
1curl "http://localhost:8000/feeds/example"
1fetch("http://localhost:8000/feeds/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/feeds/example")
4print(response.json())
200 Example Response
No Body
GET /feeds/:post_id/replies undocumented

/feeds/:post_id/replies

GET /feeds/:post_id/replies — list replies to a post.

Handled by api_list_replies
Parameters
post_id string · path
required
Responses
200Successful Response
GET /feeds/example/replies
1curl "http://localhost:8000/feeds/example/replies"
1fetch("http://localhost:8000/feeds/example/replies")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/feeds/example/replies")
4print(response.json())
200 Example Response
No Body
GET /feeds/:post_id/shares undocumented

/feeds/:post_id/shares

GET /feeds/:post_id/shares — list people the current user shared this post with.

Handled by api_list_shares
Parameters
post_id string · path
required
Responses
200Successful Response
GET /feeds/example/shares
1curl "http://localhost:8000/feeds/example/shares"
1fetch("http://localhost:8000/feeds/example/shares")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/feeds/example/shares")
4print(response.json())
200 Example Response
No Body
GET /feeds/bookmarks undocumented

/feeds/bookmarks

GET /feeds/bookmarks — list bookmarked posts.

Handled by api_list_bookmarks
Responses
200Successful Response
GET /feeds/bookmarks
1curl "http://localhost:8000/feeds/bookmarks"
1fetch("http://localhost:8000/feeds/bookmarks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/feeds/bookmarks")
4print(response.json())
200 Example Response
No Body
POST /feeds

Create a post

POST /feeds — create a new post.

Handled by api_create_post
Body · CreatePostapplication/json
content string · max length: 5000
media array
propertyName anything
Responses
200Successful Response
POST /feeds
1curl -X POST "http://localhost:8000/feeds" \
2 -H "Content-Type: application/json" \
3 -d '{"content":"string","media":[{"key":"string","url":"string","type":"string","filename":"string"}]}'
1fetch("http://localhost:8000/feeds", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "content": "string",
6 "media": [
7 {
8 "key": "string",
9 "url": "string",
10 "type": "string",
11 "filename": "string"
12 }
13 ]
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/feeds",
5 json={"content":"string","media":[{"key":"string","url":"string","type":"string","filename":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /feeds/:post_id/replies

Reply to a post

POST /feeds/:post_id/replies — reply to a post.

Handled by api_create_reply
Parameters
post_id string · path
required
Body · CreateReplyapplication/json
content string · max length: 5000
media array
propertyName anything
Responses
200Successful Response
POST /feeds/example/replies
1curl -X POST "http://localhost:8000/feeds/example/replies" \
2 -H "Content-Type: application/json" \
3 -d '{"content":"string","media":[{"key":"string","url":"string","type":"string","filename":"string"}]}'
1fetch("http://localhost:8000/feeds/example/replies", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "content": "string",
6 "media": [
7 {
8 "key": "string",
9 "url": "string",
10 "type": "string",
11 "filename": "string"
12 }
13 ]
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/feeds/example/replies",
5 json={"content":"string","media":[{"key":"string","url":"string","type":"string","filename":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /feeds/:post_id/reactions undocumented

/feeds/:post_id/reactions

POST /feeds/:post_id/react — add a reaction.

Handled by api_react
Parameters
post_id string · path
required
Responses
200Successful Response
POST /feeds/example/reactions
1curl -X POST "http://localhost:8000/feeds/example/reactions"
1fetch("http://localhost:8000/feeds/example/reactions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/feeds/example/reactions")
4print(response.json())
200 Example Response
No Body
POST /feeds/:post_id/shares

Share a post with specific people

POST /feeds/:post_id/shares — share a post with specific people.

Handled by api_share_post
Parameters
post_id string · path
required
Body · SharePostapplication/json
recipient_mrns array
required
message string · max length: 500
propertyName anything
Responses
200Successful Response
POST /feeds/example/shares
1curl -X POST "http://localhost:8000/feeds/example/shares" \
2 -H "Content-Type: application/json" \
3 -d '{"recipient_mrns":["string"],"message":"string"}'
1fetch("http://localhost:8000/feeds/example/shares", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "recipient_mrns": [
6 "string"
7 ],
8 "message": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/feeds/example/shares",
5 json={"recipient_mrns":["string"],"message":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /feeds/:post_id/bookmarks undocumented

/feeds/:post_id/bookmarks

POST /feeds/:post_id/bookmark — bookmark a post.

Handled by api_bookmark
Parameters
post_id string · path
required
Responses
200Successful Response
POST /feeds/example/bookmarks
1curl -X POST "http://localhost:8000/feeds/example/bookmarks"
1fetch("http://localhost:8000/feeds/example/bookmarks", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/feeds/example/bookmarks")
4print(response.json())
200 Example Response
No Body
PATCH /sign/envelopes/:envelope_id/fields/:field_id

Move/resize/reassign a field

PATCH /sign/envelopes/:envelope_id/fields/:field_id — move/resize/reassign a field.

Handled by api_update_field
Parameters
envelope_id string · path
required
field_id string · path
required
Body · UpdateFieldapplication/json
role string · min length: 1 · max length: 100
recipient_id string
kind
page_number integer
nx number
ny number
nw number
nh number
label string · max length: 200
required
default_value string
options object
propertyName anything
Responses
200Successful Response
PATCH /sign/envelopes/example/fields/example
1curl -X PATCH "http://localhost:8000/sign/envelopes/example/fields/example" \
2 -H "Content-Type: application/json" \
3 -d '{"role":"string","recipient_id":"string","kind":null,"page_number":1,"nx":1.5,"ny":1.5,"nw":1.5,"nh":1.5,"label":"string","required":null,"default_value":"string","options":{"choices":["string"],"show_if":{"field_id":"string","equals":"string"}}}'
1fetch("http://localhost:8000/sign/envelopes/example/fields/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "role": "string",
6 "recipient_id": "string",
7 "kind": null,
8 "page_number": 1,
9 "nx": 1.5,
10 "ny": 1.5,
11 "nw": 1.5,
12 "nh": 1.5,
13 "label": "string",
14 "required": null,
15 "default_value": "string",
16 "options": {
17 "choices": [
18 "string"
19 ],
20 "show_if": {
21 "field_id": "string",
22 "equals": "string"
23 }
24 }
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/sign/envelopes/example/fields/example",
5 json={"role":"string","recipient_id":"string","kind":null,"page_number":1,"nx":1.5,"ny":1.5,"nw":1.5,"nh":1.5,"label":"string","required":null,"default_value":"string","options":{"choices":["string"],"show_if":{"field_id":"string","equals":"string"}}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sign/envelopes/:envelope_id/fields

Add field placements

POST /sign/envelopes/:envelope_id/fields — add one or more field placements (bulk).

Handled by api_create_fields
Parameters
envelope_id string · path
required
Body · CreateFieldsapplication/json
fields array
required
propertyName anything
Responses
200Successful Response
POST /sign/envelopes/example/fields
1curl -X POST "http://localhost:8000/sign/envelopes/example/fields" \
2 -H "Content-Type: application/json" \
3 -d '{"fields":[{"role":"string","recipient_id":"string","kind":null,"page_number":1,"nx":1.5,"ny":1.5,"nw":1.5,"nh":1.5,"label":"string","required":null,"default_value":"string","options":{"choices":["string"],"show_if":{"field_id":"string","equals":"string"}}}]}'
1fetch("http://localhost:8000/sign/envelopes/example/fields", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "fields": [
6 {
7 "role": "string",
8 "recipient_id": "string",
9 "kind": null,
10 "page_number": 1,
11 "nx": 1.5,
12 "ny": 1.5,
13 "nw": 1.5,
14 "nh": 1.5,
15 "label": "string",
16 "required": null,
17 "default_value": "string",
18 "options": {
19 "choices": [
20 "string"
21 ],
22 "show_if": {
23 "field_id": "string",
24 "equals": "string"
25 }
26 }
27 }
28 ]
29}),
30})
31 .then((res) => res.json())
32 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sign/envelopes/example/fields",
5 json={"fields":[{"role":"string","recipient_id":"string","kind":null,"page_number":1,"nx":1.5,"ny":1.5,"nw":1.5,"nh":1.5,"label":"string","required":null,"default_value":"string","options":{"choices":["string"],"show_if":{"field_id":"string","equals":"string"}}}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /file-statistics undocumented

/file-statistics

GET /file-statistics — the caller's own storage and sharing overview. One call, because the dashboard draws every widget at once and a dozen round trips would show a dozen skeletons resolving at different times. Each aggregate is indexed on (workspace_id, owner_mrn, ...).

Handled by api_file_statistics
Responses
200Successful Response
GET /file-statistics
1curl "http://localhost:8000/file-statistics"
1fetch("http://localhost:8000/file-statistics")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/file-statistics")
4print(response.json())
200 Example Response
No Body
DELETE /files/:file_id undocumented

/files/:file_id

Handled by api_delete_file
Parameters
file_id string · path
required
Responses
200Successful Response
DELETE /files/example
1curl -X DELETE "http://localhost:8000/files/example"
1fetch("http://localhost:8000/files/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/files/example")
4print(response.json())
200 Example Response
No Body
DELETE /files/:file_id/stars undocumented

/files/:file_id/stars

DELETE /files/:file_id/stars — remove the current member's star.

Handled by api_unstar_file
Parameters
file_id string · path
required
Responses
200Successful Response
DELETE /files/example/stars
1curl -X DELETE "http://localhost:8000/files/example/stars"
1fetch("http://localhost:8000/files/example/stars", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/files/example/stars")
4print(response.json())
200 Example Response
No Body
DELETE /files/:file_id/permissions undocumented

/files/:file_id/permissions

Handled by api_revoke_file_permission
Parameters
file_id string · path
required
Responses
200Successful Response
DELETE /files/example/permissions
1curl -X DELETE "http://localhost:8000/files/example/permissions"
1fetch("http://localhost:8000/files/example/permissions", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/files/example/permissions")
4print(response.json())
200 Example Response
No Body
GET /files undocumented

/files

Handled by api_list_files
Responses
200Successful Response
GET /files
1curl "http://localhost:8000/files"
1fetch("http://localhost:8000/files")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/files")
4print(response.json())
200 Example Response
No Body
GET /files/:file_id undocumented

/files/:file_id

Handled by api_get_file
Parameters
file_id string · path
required
Responses
200Successful Response
GET /files/example
1curl "http://localhost:8000/files/example"
1fetch("http://localhost:8000/files/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/files/example")
4print(response.json())
200 Example Response
No Body
GET /files/:file_id/download undocumented

/files/:file_id/download

Handled by api_download_file
Parameters
file_id string · path
required
Responses
200Successful Response
GET /files/example/download
1curl "http://localhost:8000/files/example/download"
1fetch("http://localhost:8000/files/example/download")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/files/example/download")
4print(response.json())
200 Example Response
No Body
GET /files/:file_id/preview undocumented

/files/:file_id/preview

GET /files/:file_id/preview — presigned URL for inline preview.

Handled by api_preview_file
Parameters
file_id string · path
required
Responses
200Successful Response
GET /files/example/preview
1curl "http://localhost:8000/files/example/preview"
1fetch("http://localhost:8000/files/example/preview")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/files/example/preview")
4print(response.json())
200 Example Response
No Body
GET /files/:file_id/versions undocumented

/files/:file_id/versions

GET /files/:file_id/versions — version history, newest first.

Handled by api_list_file_versions
Parameters
file_id string · path
required
Responses
200Successful Response
GET /files/example/versions
1curl "http://localhost:8000/files/example/versions"
1fetch("http://localhost:8000/files/example/versions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/files/example/versions")
4print(response.json())
200 Example Response
No Body
GET /files/:file_id/permissions undocumented

/files/:file_id/permissions

Handled by api_list_file_permissions
Parameters
file_id string · path
required
Responses
200Successful Response
GET /files/example/permissions
1curl "http://localhost:8000/files/example/permissions"
1fetch("http://localhost:8000/files/example/permissions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/files/example/permissions")
4print(response.json())
200 Example Response
No Body
PATCH /files/:file_id

Update a file

Handled by api_update_file
Parameters
file_id string · path
required
Body · UpdateFileapplication/json
name string · min length: 1 · max length: 255
folder_id string
is_starred
restore_version_id string
propertyName anything
Responses
200Successful Response
PATCH /files/example
1curl -X PATCH "http://localhost:8000/files/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","folder_id":"string","is_starred":null,"restore_version_id":"string"}'
1fetch("http://localhost:8000/files/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "folder_id": "string",
7 "is_starred": null,
8 "restore_version_id": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/files/example",
5 json={"name":"string","folder_id":"string","is_starred":null,"restore_version_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /files/:file_id/stars undocumented

/files/:file_id/stars

POST /files/:file_id/stars — star a file for the current member.

Handled by api_star_file
Parameters
file_id string · path
required
Responses
200Successful Response
POST /files/example/stars
1curl -X POST "http://localhost:8000/files/example/stars"
1fetch("http://localhost:8000/files/example/stars", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/files/example/stars")
4print(response.json())
200 Example Response
No Body
POST /files/:file_id/copies

Copy a file

POST /files/:file_id/copies — duplicate a file (optionally into another folder). View access on the source suffices; the destination needs write.

Handled by api_copy_file
Parameters
file_id string · path
required
Body · CopyFileapplication/json
folder_id string
propertyName anything
Responses
200Successful Response
POST /files/example/copies
1curl -X POST "http://localhost:8000/files/example/copies" \
2 -H "Content-Type: application/json" \
3 -d '{"folder_id":"string"}'
1fetch("http://localhost:8000/files/example/copies", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "folder_id": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/files/example/copies",
5 json={"folder_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /files/bulk

Bulk file operation

Handled by api_bulk_operation
Body · BulkOperationapplication/json
action
required
ids array
required
folder_id string
propertyName anything
Responses
200Successful Response
POST /files/bulk
1curl -X POST "http://localhost:8000/files/bulk" \
2 -H "Content-Type: application/json" \
3 -d '{"action":null,"ids":["string"],"folder_id":"string"}'
1fetch("http://localhost:8000/files/bulk", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "action": null,
6 "ids": [
7 "string"
8 ],
9 "folder_id": "string"
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/files/bulk",
5 json={"action":null,"ids":["string"],"folder_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /finance/quotes/:entry_id undocumented

/finance/quotes/:entry_id

Handled by api_delete_quote
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/quotes/example
1curl -X DELETE "http://localhost:8000/finance/quotes/example"
1fetch("http://localhost:8000/finance/quotes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/quotes/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/purchase-orders/:entry_id undocumented

/finance/purchase-orders/:entry_id

Handled by api_delete_purchase_order
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/purchase-orders/example
1curl -X DELETE "http://localhost:8000/finance/purchase-orders/example"
1fetch("http://localhost:8000/finance/purchase-orders/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/purchase-orders/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/orders/:entry_id undocumented

/finance/orders/:entry_id

Handled by api_delete_order
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/orders/example
1curl -X DELETE "http://localhost:8000/finance/orders/example"
1fetch("http://localhost:8000/finance/orders/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/orders/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/invoices/:entry_id undocumented

/finance/invoices/:entry_id

Handled by api_delete_invoice
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/invoices/example
1curl -X DELETE "http://localhost:8000/finance/invoices/example"
1fetch("http://localhost:8000/finance/invoices/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/invoices/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/invoices/:entry_id/attachments/:attachment_id undocumented

/finance/invoices/:entry_id/attachments/:attachment_id

Handled by api_delete_invoice_attachment
Parameters
entry_id string · path
required
attachment_id string · path
required
Responses
200Successful Response
DELETE /finance/invoices/example/attachments/example
1curl -X DELETE "http://localhost:8000/finance/invoices/example/attachments/example"
1fetch("http://localhost:8000/finance/invoices/example/attachments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/invoices/example/attachments/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/bills/:entry_id undocumented

/finance/bills/:entry_id

Handled by api_delete_bill
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/bills/example
1curl -X DELETE "http://localhost:8000/finance/bills/example"
1fetch("http://localhost:8000/finance/bills/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/bills/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/credit-notes/:entry_id undocumented

/finance/credit-notes/:entry_id

Handled by api_delete_credit_note
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/credit-notes/example
1curl -X DELETE "http://localhost:8000/finance/credit-notes/example"
1fetch("http://localhost:8000/finance/credit-notes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/credit-notes/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/credit-notes/:entry_id/allocations/:target_entry_id undocumented

/finance/credit-notes/:entry_id/allocations/:target_entry_id

Handled by api_delete_credit_note_allocation
Parameters
entry_id string · path
required
target_entry_id string · path
required
Responses
200Successful Response
DELETE /finance/credit-notes/example/allocations/example
1curl -X DELETE "http://localhost:8000/finance/credit-notes/example/allocations/example"
1fetch("http://localhost:8000/finance/credit-notes/example/allocations/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/credit-notes/example/allocations/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/credit-notes/:entry_id/attachments/:attachment_id undocumented

/finance/credit-notes/:entry_id/attachments/:attachment_id

Handled by api_delete_credit_note_attachment
Parameters
entry_id string · path
required
attachment_id string · path
required
Responses
200Successful Response
DELETE /finance/credit-notes/example/attachments/example
1curl -X DELETE "http://localhost:8000/finance/credit-notes/example/attachments/example"
1fetch("http://localhost:8000/finance/credit-notes/example/attachments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/credit-notes/example/attachments/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/purchase-credit-notes/:entry_id undocumented

/finance/purchase-credit-notes/:entry_id

Handled by api_delete_purchase_credit_note
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/purchase-credit-notes/example
1curl -X DELETE "http://localhost:8000/finance/purchase-credit-notes/example"
1fetch("http://localhost:8000/finance/purchase-credit-notes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/purchase-credit-notes/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/purchase-credit-notes/:entry_id/allocations/:target_entry_id undocumented

/finance/purchase-credit-notes/:entry_id/allocations/:target_entry_id

Handled by api_delete_purchase_credit_note_allocation
Parameters
entry_id string · path
required
target_entry_id string · path
required
Responses
200Successful Response
DELETE /finance/purchase-credit-notes/example/allocations/example
1curl -X DELETE "http://localhost:8000/finance/purchase-credit-notes/example/allocations/example"
1fetch("http://localhost:8000/finance/purchase-credit-notes/example/allocations/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/purchase-credit-notes/example/allocations/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/journal-entries/:entry_id undocumented

/finance/journal-entries/:entry_id

Handled by api_delete_journal_entry
Parameters
entry_id string · path
required
Responses
200Successful Response
DELETE /finance/journal-entries/example
1curl -X DELETE "http://localhost:8000/finance/journal-entries/example"
1fetch("http://localhost:8000/finance/journal-entries/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/journal-entries/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/accounts/:account_id undocumented

/finance/accounts/:account_id

Handled by api_delete_account
Parameters
account_id string · path
required
Responses
200Successful Response
DELETE /finance/accounts/example
1curl -X DELETE "http://localhost:8000/finance/accounts/example"
1fetch("http://localhost:8000/finance/accounts/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/accounts/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/bank-imports/:import_id undocumented

/finance/bank-imports/:import_id

Handled by api_delete_bank_import
Parameters
import_id string · path
required
Responses
200Successful Response
DELETE /finance/bank-imports/example
1curl -X DELETE "http://localhost:8000/finance/bank-imports/example"
1fetch("http://localhost:8000/finance/bank-imports/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/bank-imports/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/requests/:request_id undocumented

/finance/requests/:request_id

DELETE /finance/requests/:id — the owner withdraws a submitted request.

Handled by api_cancel_request
Parameters
request_id string · path
required
Responses
200Successful Response
DELETE /finance/requests/example
1curl -X DELETE "http://localhost:8000/finance/requests/example"
1fetch("http://localhost:8000/finance/requests/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/requests/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/links/:link_id undocumented

/finance/links/:link_id

Handled by api_revoke_link
Parameters
link_id string · path
required
Responses
200Successful Response
DELETE /finance/links/example
1curl -X DELETE "http://localhost:8000/finance/links/example"
1fetch("http://localhost:8000/finance/links/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/links/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/payment-credentials/:provider undocumented

/finance/payment-credentials/:provider

Handled by api_delete_payment_credentials
Parameters
provider string · path
required
Responses
200Successful Response
DELETE /finance/payment-credentials/example
1curl -X DELETE "http://localhost:8000/finance/payment-credentials/example"
1fetch("http://localhost:8000/finance/payment-credentials/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/payment-credentials/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/bank-connections/:id undocumented

/finance/bank-connections/:id

Handled by api_delete_bank_connection
Parameters
id string · path
required
Responses
200Successful Response
DELETE /finance/bank-connections/example
1curl -X DELETE "http://localhost:8000/finance/bank-connections/example"
1fetch("http://localhost:8000/finance/bank-connections/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/bank-connections/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/settings/logo undocumented

/finance/settings/logo

DELETE /finance/settings/logo: take the logo off every document. Deletes the object for real, because "remove my logo" has to mean the image stops being served, not merely that documents stop pointing at it. The key is dropped too, so the next upload mints a fresh unguessable one rather than resurrecting a URL that was already handed out.

Handled by api_delete_logo
Responses
200Successful Response
DELETE /finance/settings/logo
1curl -X DELETE "http://localhost:8000/finance/settings/logo"
1fetch("http://localhost:8000/finance/settings/logo", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/settings/logo")
4print(response.json())
200 Example Response
No Body
DELETE /finance/fiscal-periods/:period_id undocumented

/finance/fiscal-periods/:period_id

Handled by api_delete_fiscal_period
Parameters
period_id string · path
required
Responses
200Successful Response
DELETE /finance/fiscal-periods/example
1curl -X DELETE "http://localhost:8000/finance/fiscal-periods/example"
1fetch("http://localhost:8000/finance/fiscal-periods/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/fiscal-periods/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/dimensions/:dimension_key undocumented

/finance/dimensions/:dimension_key

Handled by api_delete_dimension
Parameters
dimension_key string · path
required
Responses
200Successful Response
DELETE /finance/dimensions/example
1curl -X DELETE "http://localhost:8000/finance/dimensions/example"
1fetch("http://localhost:8000/finance/dimensions/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/dimensions/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/tax-rates/:tax_id undocumented

/finance/tax-rates/:tax_id

Handled by handler
Parameters
tax_id string · path
required
Responses
200Successful Response
DELETE /finance/tax-rates/example
1curl -X DELETE "http://localhost:8000/finance/tax-rates/example"
1fetch("http://localhost:8000/finance/tax-rates/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/tax-rates/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/payment-terms/:term_id undocumented

/finance/payment-terms/:term_id

Handled by handler
Parameters
term_id string · path
required
Responses
200Successful Response
DELETE /finance/payment-terms/example
1curl -X DELETE "http://localhost:8000/finance/payment-terms/example"
1fetch("http://localhost:8000/finance/payment-terms/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/payment-terms/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/bank-rules/:rule_id undocumented

/finance/bank-rules/:rule_id

Handled by handler
Parameters
rule_id string · path
required
Responses
200Successful Response
DELETE /finance/bank-rules/example
1curl -X DELETE "http://localhost:8000/finance/bank-rules/example"
1fetch("http://localhost:8000/finance/bank-rules/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/bank-rules/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/budgets/:budget_id undocumented

/finance/budgets/:budget_id

Handled by handler
Parameters
budget_id string · path
required
Responses
200Successful Response
DELETE /finance/budgets/example
1curl -X DELETE "http://localhost:8000/finance/budgets/example"
1fetch("http://localhost:8000/finance/budgets/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/budgets/example")
4print(response.json())
200 Example Response
No Body
DELETE /finance/recurring-entries/:recurring_id undocumented

/finance/recurring-entries/:recurring_id

Handled by handler
Parameters
recurring_id string · path
required
Responses
200Successful Response
DELETE /finance/recurring-entries/example
1curl -X DELETE "http://localhost:8000/finance/recurring-entries/example"
1fetch("http://localhost:8000/finance/recurring-entries/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/finance/recurring-entries/example")
4print(response.json())
200 Example Response
No Body
GET /finance/quotes undocumented

/finance/quotes

Handled by api_list_quotes
Responses
200Successful Response
GET /finance/quotes
1curl "http://localhost:8000/finance/quotes"
1fetch("http://localhost:8000/finance/quotes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/quotes")
4print(response.json())
200 Example Response
No Body
GET /finance/quotes/:entry_id undocumented

/finance/quotes/:entry_id

Handled by api_get_quote
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/quotes/example
1curl "http://localhost:8000/finance/quotes/example"
1fetch("http://localhost:8000/finance/quotes/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/quotes/example")
4print(response.json())
200 Example Response
No Body
GET /finance/purchase-orders undocumented

/finance/purchase-orders

Handled by api_list_purchase_orders
Responses
200Successful Response
GET /finance/purchase-orders
1curl "http://localhost:8000/finance/purchase-orders"
1fetch("http://localhost:8000/finance/purchase-orders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/purchase-orders")
4print(response.json())
200 Example Response
No Body
GET /finance/purchase-orders/:entry_id undocumented

/finance/purchase-orders/:entry_id

Handled by api_get_purchase_order
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/purchase-orders/example
1curl "http://localhost:8000/finance/purchase-orders/example"
1fetch("http://localhost:8000/finance/purchase-orders/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/purchase-orders/example")
4print(response.json())
200 Example Response
No Body
GET /finance/purchase-orders/:entry_id/receipts undocumented

/finance/purchase-orders/:entry_id/receipts

Handled by api_list_receipts
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/purchase-orders/example/receipts
1curl "http://localhost:8000/finance/purchase-orders/example/receipts"
1fetch("http://localhost:8000/finance/purchase-orders/example/receipts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/purchase-orders/example/receipts")
4print(response.json())
200 Example Response
No Body
GET /finance/orders undocumented

/finance/orders

Handled by api_list_orders
Responses
200Successful Response
GET /finance/orders
1curl "http://localhost:8000/finance/orders"
1fetch("http://localhost:8000/finance/orders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/orders")
4print(response.json())
200 Example Response
No Body
GET /finance/orders/:entry_id undocumented

/finance/orders/:entry_id

Handled by api_get_order
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/orders/example
1curl "http://localhost:8000/finance/orders/example"
1fetch("http://localhost:8000/finance/orders/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/orders/example")
4print(response.json())
200 Example Response
No Body
GET /finance/orders/:entry_id/fulfillments undocumented

/finance/orders/:entry_id/fulfillments

Handled by api_list_fulfillments
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/orders/example/fulfillments
1curl "http://localhost:8000/finance/orders/example/fulfillments"
1fetch("http://localhost:8000/finance/orders/example/fulfillments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/orders/example/fulfillments")
4print(response.json())
200 Example Response
No Body
GET /finance/invoices undocumented

/finance/invoices

Handled by api_list_invoices
Responses
200Successful Response
GET /finance/invoices
1curl "http://localhost:8000/finance/invoices"
1fetch("http://localhost:8000/finance/invoices")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/invoices")
4print(response.json())
200 Example Response
No Body
GET /finance/invoices/:entry_id undocumented

/finance/invoices/:entry_id

Handled by api_get_invoice
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/invoices/example
1curl "http://localhost:8000/finance/invoices/example"
1fetch("http://localhost:8000/finance/invoices/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/invoices/example")
4print(response.json())
200 Example Response
No Body
GET /finance/invoices/:entry_id/payments undocumented

/finance/invoices/:entry_id/payments

Handled by api_list_invoice_payments
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/invoices/example/payments
1curl "http://localhost:8000/finance/invoices/example/payments"
1fetch("http://localhost:8000/finance/invoices/example/payments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/invoices/example/payments")
4print(response.json())
200 Example Response
No Body
GET /finance/invoices/:entry_id/ledger-lines undocumented

/finance/invoices/:entry_id/ledger-lines

Handled by api_list_invoice_ledger_lines
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/invoices/example/ledger-lines
1curl "http://localhost:8000/finance/invoices/example/ledger-lines"
1fetch("http://localhost:8000/finance/invoices/example/ledger-lines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/invoices/example/ledger-lines")
4print(response.json())
200 Example Response
No Body
GET /finance/invoices/:entry_id/pdfs undocumented

/finance/invoices/:entry_id/pdfs

Handled by api_list_invoice_pdfs
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/invoices/example/pdfs
1curl "http://localhost:8000/finance/invoices/example/pdfs"
1fetch("http://localhost:8000/finance/invoices/example/pdfs")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/invoices/example/pdfs")
4print(response.json())
200 Example Response
No Body
GET /finance/bills undocumented

/finance/bills

Handled by api_list_bills
Responses
200Successful Response
GET /finance/bills
1curl "http://localhost:8000/finance/bills"
1fetch("http://localhost:8000/finance/bills")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bills")
4print(response.json())
200 Example Response
No Body
GET /finance/bills/:entry_id undocumented

/finance/bills/:entry_id

Handled by api_get_bill
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/bills/example
1curl "http://localhost:8000/finance/bills/example"
1fetch("http://localhost:8000/finance/bills/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bills/example")
4print(response.json())
200 Example Response
No Body
GET /finance/bills/:entry_id/payments undocumented

/finance/bills/:entry_id/payments

Handled by api_list_bill_payments
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/bills/example/payments
1curl "http://localhost:8000/finance/bills/example/payments"
1fetch("http://localhost:8000/finance/bills/example/payments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bills/example/payments")
4print(response.json())
200 Example Response
No Body
GET /finance/bills/:entry_id/ledger-lines undocumented

/finance/bills/:entry_id/ledger-lines

Handled by api_list_bill_ledger_lines
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/bills/example/ledger-lines
1curl "http://localhost:8000/finance/bills/example/ledger-lines"
1fetch("http://localhost:8000/finance/bills/example/ledger-lines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bills/example/ledger-lines")
4print(response.json())
200 Example Response
No Body
GET /finance/credit-notes undocumented

/finance/credit-notes

Handled by api_list_credit_notes
Responses
200Successful Response
GET /finance/credit-notes
1curl "http://localhost:8000/finance/credit-notes"
1fetch("http://localhost:8000/finance/credit-notes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/credit-notes")
4print(response.json())
200 Example Response
No Body
GET /finance/credit-notes/:entry_id undocumented

/finance/credit-notes/:entry_id

Handled by api_get_credit_note
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/credit-notes/example
1curl "http://localhost:8000/finance/credit-notes/example"
1fetch("http://localhost:8000/finance/credit-notes/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/credit-notes/example")
4print(response.json())
200 Example Response
No Body
GET /finance/credit-notes/:entry_id/ledger-lines undocumented

/finance/credit-notes/:entry_id/ledger-lines

Handled by api_list_credit_note_ledger_lines
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/credit-notes/example/ledger-lines
1curl "http://localhost:8000/finance/credit-notes/example/ledger-lines"
1fetch("http://localhost:8000/finance/credit-notes/example/ledger-lines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/credit-notes/example/ledger-lines")
4print(response.json())
200 Example Response
No Body
GET /finance/credit-notes/:entry_id/pdfs undocumented

/finance/credit-notes/:entry_id/pdfs

Handled by api_list_credit_note_pdfs
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/credit-notes/example/pdfs
1curl "http://localhost:8000/finance/credit-notes/example/pdfs"
1fetch("http://localhost:8000/finance/credit-notes/example/pdfs")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/credit-notes/example/pdfs")
4print(response.json())
200 Example Response
No Body
GET /finance/purchase-credit-notes undocumented

/finance/purchase-credit-notes

Handled by api_list_purchase_credit_notes
Responses
200Successful Response
GET /finance/purchase-credit-notes
1curl "http://localhost:8000/finance/purchase-credit-notes"
1fetch("http://localhost:8000/finance/purchase-credit-notes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/purchase-credit-notes")
4print(response.json())
200 Example Response
No Body
GET /finance/purchase-credit-notes/:entry_id undocumented

/finance/purchase-credit-notes/:entry_id

Handled by api_get_purchase_credit_note
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/purchase-credit-notes/example
1curl "http://localhost:8000/finance/purchase-credit-notes/example"
1fetch("http://localhost:8000/finance/purchase-credit-notes/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/purchase-credit-notes/example")
4print(response.json())
200 Example Response
No Body
GET /finance/purchase-credit-notes/:entry_id/ledger-lines undocumented

/finance/purchase-credit-notes/:entry_id/ledger-lines

Handled by api_list_purchase_credit_note_ledger_lines
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/purchase-credit-notes/example/ledger-lines
1curl "http://localhost:8000/finance/purchase-credit-notes/example/ledger-lines"
1fetch("http://localhost:8000/finance/purchase-credit-notes/example/ledger-lines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/purchase-credit-notes/example/ledger-lines")
4print(response.json())
200 Example Response
No Body
GET /finance/journal-entries undocumented

/finance/journal-entries

Handled by api_list_journal_entries
Responses
200Successful Response
GET /finance/journal-entries
1curl "http://localhost:8000/finance/journal-entries"
1fetch("http://localhost:8000/finance/journal-entries")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/journal-entries")
4print(response.json())
200 Example Response
No Body
GET /finance/journal-entries/:entry_id undocumented

/finance/journal-entries/:entry_id

Handled by api_get_journal_entry
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/journal-entries/example
1curl "http://localhost:8000/finance/journal-entries/example"
1fetch("http://localhost:8000/finance/journal-entries/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/journal-entries/example")
4print(response.json())
200 Example Response
No Body
GET /finance/journal-entries/:entry_id/ledger-lines undocumented

/finance/journal-entries/:entry_id/ledger-lines

Handled by api_list_journal_ledger_lines
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/journal-entries/example/ledger-lines
1curl "http://localhost:8000/finance/journal-entries/example/ledger-lines"
1fetch("http://localhost:8000/finance/journal-entries/example/ledger-lines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/journal-entries/example/ledger-lines")
4print(response.json())
200 Example Response
No Body
GET /finance/accounts undocumented

/finance/accounts

List the chart of accounts. Filters: ?type=, ?active=, ?bank=true, ?q= (matches code or name — the Lookup widget in every account picker sends q). Raw SQL because supersql renders OR conditions unparenthesized, which would break workspace scoping.

Handled by api_list_accounts
Responses
200Successful Response
GET /finance/accounts
1curl "http://localhost:8000/finance/accounts"
1fetch("http://localhost:8000/finance/accounts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/accounts")
4print(response.json())
200 Example Response
No Body
GET /finance/accounts/:account_id undocumented

/finance/accounts/:account_id

Handled by api_get_account
Parameters
account_id string · path
required
Responses
200Successful Response
GET /finance/accounts/example
1curl "http://localhost:8000/finance/accounts/example"
1fetch("http://localhost:8000/finance/accounts/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/accounts/example")
4print(response.json())
200 Example Response
No Body
GET /finance/accounts/:account_id/ledger-lines undocumented

/finance/accounts/:account_id/ledger-lines

Handled by api_list_account_ledger_lines
Parameters
account_id string · path
required
Responses
200Successful Response
GET /finance/accounts/example/ledger-lines
1curl "http://localhost:8000/finance/accounts/example/ledger-lines"
1fetch("http://localhost:8000/finance/accounts/example/ledger-lines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/accounts/example/ledger-lines")
4print(response.json())
200 Example Response
No Body
GET /finance/chart-advice undocumented

/finance/chart-advice

Advisory guidance for the new-account form (see core.forms Form.advice). Returns the derived normal balance, a suggested free code in the chosen type's block, and a warning when the typed code sits in a different type's block. Nothing here rejects anything, because the code-range convention is advisory by design (ACCOUNT_CODE_RANGES explains why), and the rule that IS enforceable is enforced in api_create_account instead.

Handled by api_chart_advice
Responses
200Successful Response
GET /finance/chart-advice
1curl "http://localhost:8000/finance/chart-advice"
1fetch("http://localhost:8000/finance/chart-advice")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/chart-advice")
4print(response.json())
200 Example Response
No Body
GET /finance/ledger undocumented

/finance/ledger

Handled by api_list_ledger_lines
Responses
200Successful Response
GET /finance/ledger
1curl "http://localhost:8000/finance/ledger"
1fetch("http://localhost:8000/finance/ledger")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/ledger")
4print(response.json())
200 Example Response
No Body
GET /finance/ledger/:line_id undocumented

/finance/ledger/:line_id

Handled by api_get_ledger_line
Parameters
line_id string · path
required
Responses
200Successful Response
GET /finance/ledger/example
1curl "http://localhost:8000/finance/ledger/example"
1fetch("http://localhost:8000/finance/ledger/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/ledger/example")
4print(response.json())
200 Example Response
No Body
GET /finance/payments undocumented

/finance/payments

Handled by api_list_payments
Responses
200Successful Response
GET /finance/payments
1curl "http://localhost:8000/finance/payments"
1fetch("http://localhost:8000/finance/payments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/payments")
4print(response.json())
200 Example Response
No Body
GET /finance/payments/:payment_id undocumented

/finance/payments/:payment_id

Handled by api_get_payment
Parameters
payment_id string · path
required
Responses
200Successful Response
GET /finance/payments/example
1curl "http://localhost:8000/finance/payments/example"
1fetch("http://localhost:8000/finance/payments/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/payments/example")
4print(response.json())
200 Example Response
No Body
GET /finance/payments/:payment_id/reversals undocumented

/finance/payments/:payment_id/reversals

Handled by api_list_payment_reversals
Parameters
payment_id string · path
required
Responses
200Successful Response
GET /finance/payments/example/reversals
1curl "http://localhost:8000/finance/payments/example/reversals"
1fetch("http://localhost:8000/finance/payments/example/reversals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/payments/example/reversals")
4print(response.json())
200 Example Response
No Body
GET /finance/bank-imports undocumented

/finance/bank-imports

Handled by api_list_bank_imports
Responses
200Successful Response
GET /finance/bank-imports
1curl "http://localhost:8000/finance/bank-imports"
1fetch("http://localhost:8000/finance/bank-imports")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bank-imports")
4print(response.json())
200 Example Response
No Body
GET /finance/bank-imports/:import_id undocumented

/finance/bank-imports/:import_id

Handled by api_get_bank_import
Parameters
import_id string · path
required
Responses
200Successful Response
GET /finance/bank-imports/example
1curl "http://localhost:8000/finance/bank-imports/example"
1fetch("http://localhost:8000/finance/bank-imports/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bank-imports/example")
4print(response.json())
200 Example Response
No Body
GET /finance/bank-imports/:import_id/matches undocumented

/finance/bank-imports/:import_id/matches

Handled by api_list_bank_import_matches
Parameters
import_id string · path
required
Responses
200Successful Response
GET /finance/bank-imports/example/matches
1curl "http://localhost:8000/finance/bank-imports/example/matches"
1fetch("http://localhost:8000/finance/bank-imports/example/matches")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bank-imports/example/matches")
4print(response.json())
200 Example Response
No Body
GET /finance/requests undocumented

/finance/requests

GET /finance/requests — reviewers see all, everyone else their own. The scope is deposited by the authz chain (scope_requests).

Handled by api_list_requests
Responses
200Successful Response
GET /finance/requests
1curl "http://localhost:8000/finance/requests"
1fetch("http://localhost:8000/finance/requests")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/requests")
4print(response.json())
200 Example Response
No Body
GET /finance/requests/:request_id undocumented

/finance/requests/:request_id

Handled by api_get_request
Parameters
request_id string · path
required
Responses
200Successful Response
GET /finance/requests/example
1curl "http://localhost:8000/finance/requests/example"
1fetch("http://localhost:8000/finance/requests/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/requests/example")
4print(response.json())
200 Example Response
No Body
GET /finance/quotes/:entry_id/links undocumented

/finance/quotes/:entry_id/links

Handled by api_list_quote_links
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/quotes/example/links
1curl "http://localhost:8000/finance/quotes/example/links"
1fetch("http://localhost:8000/finance/quotes/example/links")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/quotes/example/links")
4print(response.json())
200 Example Response
No Body
GET /finance/invoices/:entry_id/links undocumented

/finance/invoices/:entry_id/links

Handled by api_list_invoice_links
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/invoices/example/links
1curl "http://localhost:8000/finance/invoices/example/links"
1fetch("http://localhost:8000/finance/invoices/example/links")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/invoices/example/links")
4print(response.json())
200 Example Response
No Body
GET /finance/credit-notes/:entry_id/links undocumented

/finance/credit-notes/:entry_id/links

Handled by api_list_credit_note_links
Parameters
entry_id string · path
required
Responses
200Successful Response
GET /finance/credit-notes/example/links
1curl "http://localhost:8000/finance/credit-notes/example/links"
1fetch("http://localhost:8000/finance/credit-notes/example/links")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/credit-notes/example/links")
4print(response.json())
200 Example Response
No Body
GET /finance/payment-credentials undocumented

/finance/payment-credentials

Handled by api_list_payment_credentials
Responses
200Successful Response
GET /finance/payment-credentials
1curl "http://localhost:8000/finance/payment-credentials"
1fetch("http://localhost:8000/finance/payment-credentials")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/payment-credentials")
4print(response.json())
200 Example Response
No Body
GET /finance/bank-connections undocumented

/finance/bank-connections

Handled by api_list_bank_connections
Responses
200Successful Response
GET /finance/bank-connections
1curl "http://localhost:8000/finance/bank-connections"
1fetch("http://localhost:8000/finance/bank-connections")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bank-connections")
4print(response.json())
200 Example Response
No Body
GET /finance/reconciliations undocumented

/finance/reconciliations

Handled by api_list_reconciliations
Responses
200Successful Response
GET /finance/reconciliations
1curl "http://localhost:8000/finance/reconciliations"
1fetch("http://localhost:8000/finance/reconciliations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reconciliations")
4print(response.json())
200 Example Response
No Body
GET /finance/reconciliations/:recon_id undocumented

/finance/reconciliations/:recon_id

Handled by api_get_reconciliation
Parameters
recon_id string · path
required
Responses
200Successful Response
GET /finance/reconciliations/example
1curl "http://localhost:8000/finance/reconciliations/example"
1fetch("http://localhost:8000/finance/reconciliations/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reconciliations/example")
4print(response.json())
200 Example Response
No Body
GET /finance/settings undocumented

/finance/settings

Handled by api_get_settings
Responses
200Successful Response
GET /finance/settings
1curl "http://localhost:8000/finance/settings"
1fetch("http://localhost:8000/finance/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/settings")
4print(response.json())
200 Example Response
No Body
GET /finance/fiscal-periods undocumented

/finance/fiscal-periods

Handled by api_list_fiscal_periods
Responses
200Successful Response
GET /finance/fiscal-periods
1curl "http://localhost:8000/finance/fiscal-periods"
1fetch("http://localhost:8000/finance/fiscal-periods")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/fiscal-periods")
4print(response.json())
200 Example Response
No Body
GET /finance/fiscal-periods/:period_id/revaluation-preview undocumented

/finance/fiscal-periods/:period_id/revaluation-preview

GET /finance/fiscal-periods/:period_id/revaluation-preview?as_of=...

Handled by api_preview_revaluation
Parameters
period_id string · path
required
Responses
200Successful Response
GET /finance/fiscal-periods/example/revaluation-preview
1curl "http://localhost:8000/finance/fiscal-periods/example/revaluation-preview"
1fetch("http://localhost:8000/finance/fiscal-periods/example/revaluation-preview")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/fiscal-periods/example/revaluation-preview")
4print(response.json())
200 Example Response
No Body
GET /finance/fiscal-periods/:period_id/revaluations undocumented

/finance/fiscal-periods/:period_id/revaluations

GET /finance/fiscal-periods/:period_id/revaluations

Handled by api_list_revaluations
Parameters
period_id string · path
required
Responses
200Successful Response
GET /finance/fiscal-periods/example/revaluations
1curl "http://localhost:8000/finance/fiscal-periods/example/revaluations"
1fetch("http://localhost:8000/finance/fiscal-periods/example/revaluations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/fiscal-periods/example/revaluations")
4print(response.json())
200 Example Response
No Body
GET /finance/dimensions undocumented

/finance/dimensions

Handled by api_list_dimensions
Responses
200Successful Response
GET /finance/dimensions
1curl "http://localhost:8000/finance/dimensions"
1fetch("http://localhost:8000/finance/dimensions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/dimensions")
4print(response.json())
200 Example Response
No Body
GET /finance/dimensions/:dimension_key/values undocumented

/finance/dimensions/:dimension_key/values

Handled by api_list_dimension_values
Parameters
dimension_key string · path
required
Responses
200Successful Response
GET /finance/dimensions/example/values
1curl "http://localhost:8000/finance/dimensions/example/values"
1fetch("http://localhost:8000/finance/dimensions/example/values")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/dimensions/example/values")
4print(response.json())
200 Example Response
No Body
GET /finance/tax-rates undocumented

/finance/tax-rates

Handled by handler
Responses
200Successful Response
GET /finance/tax-rates
1curl "http://localhost:8000/finance/tax-rates"
1fetch("http://localhost:8000/finance/tax-rates")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/tax-rates")
4print(response.json())
200 Example Response
No Body
GET /finance/payment-terms undocumented

/finance/payment-terms

Handled by handler
Responses
200Successful Response
GET /finance/payment-terms
1curl "http://localhost:8000/finance/payment-terms"
1fetch("http://localhost:8000/finance/payment-terms")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/payment-terms")
4print(response.json())
200 Example Response
No Body
GET /finance/bank-rules undocumented

/finance/bank-rules

Handled by handler
Responses
200Successful Response
GET /finance/bank-rules
1curl "http://localhost:8000/finance/bank-rules"
1fetch("http://localhost:8000/finance/bank-rules")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/bank-rules")
4print(response.json())
200 Example Response
No Body
GET /finance/budgets undocumented

/finance/budgets

Handled by handler
Responses
200Successful Response
GET /finance/budgets
1curl "http://localhost:8000/finance/budgets"
1fetch("http://localhost:8000/finance/budgets")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/budgets")
4print(response.json())
200 Example Response
No Body
GET /finance/recurring-entries undocumented

/finance/recurring-entries

Handled by handler
Responses
200Successful Response
GET /finance/recurring-entries
1curl "http://localhost:8000/finance/recurring-entries"
1fetch("http://localhost:8000/finance/recurring-entries")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/recurring-entries")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/trial-balance undocumented

/finance/reports/trial-balance

Handled by api_report_trial_balance
Responses
200Successful Response
GET /finance/reports/trial-balance
1curl "http://localhost:8000/finance/reports/trial-balance"
1fetch("http://localhost:8000/finance/reports/trial-balance")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/trial-balance")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/income-statement undocumented

/finance/reports/income-statement

Handled by api_report_income_statement
Responses
200Successful Response
GET /finance/reports/income-statement
1curl "http://localhost:8000/finance/reports/income-statement"
1fetch("http://localhost:8000/finance/reports/income-statement")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/income-statement")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/balance-sheet undocumented

/finance/reports/balance-sheet

Handled by api_report_balance_sheet
Responses
200Successful Response
GET /finance/reports/balance-sheet
1curl "http://localhost:8000/finance/reports/balance-sheet"
1fetch("http://localhost:8000/finance/reports/balance-sheet")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/balance-sheet")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/aged-receivables undocumented

/finance/reports/aged-receivables

Handled by api_report_aged_receivables
Responses
200Successful Response
GET /finance/reports/aged-receivables
1curl "http://localhost:8000/finance/reports/aged-receivables"
1fetch("http://localhost:8000/finance/reports/aged-receivables")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/aged-receivables")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/aged-payables undocumented

/finance/reports/aged-payables

Handled by api_report_aged_payables
Responses
200Successful Response
GET /finance/reports/aged-payables
1curl "http://localhost:8000/finance/reports/aged-payables"
1fetch("http://localhost:8000/finance/reports/aged-payables")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/aged-payables")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/cash-flow undocumented

/finance/reports/cash-flow

Handled by api_report_cash_flow
Responses
200Successful Response
GET /finance/reports/cash-flow
1curl "http://localhost:8000/finance/reports/cash-flow"
1fetch("http://localhost:8000/finance/reports/cash-flow")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/cash-flow")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/revenue-by-customer undocumented

/finance/reports/revenue-by-customer

Handled by api_report_revenue_by_customer
Responses
200Successful Response
GET /finance/reports/revenue-by-customer
1curl "http://localhost:8000/finance/reports/revenue-by-customer"
1fetch("http://localhost:8000/finance/reports/revenue-by-customer")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/revenue-by-customer")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/budget-vs-actuals undocumented

/finance/reports/budget-vs-actuals

Handled by api_report_budget_vs_actuals
Responses
200Successful Response
GET /finance/reports/budget-vs-actuals
1curl "http://localhost:8000/finance/reports/budget-vs-actuals"
1fetch("http://localhost:8000/finance/reports/budget-vs-actuals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/budget-vs-actuals")
4print(response.json())
200 Example Response
No Body
GET /finance/reports/dimensions/:dimension_key undocumented

/finance/reports/dimensions/:dimension_key

Handled by api_report_dimension_breakdown
Parameters
dimension_key string · path
required
Responses
200Successful Response
GET /finance/reports/dimensions/example
1curl "http://localhost:8000/finance/reports/dimensions/example"
1fetch("http://localhost:8000/finance/reports/dimensions/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/finance/reports/dimensions/example")
4print(response.json())
200 Example Response
No Body
POST /finance/bank-connections/:id/syncs undocumented

/finance/bank-connections/:id/syncs

Handled by api_sync_bank_connection
Parameters
id string · path
required
Responses
200Successful Response
POST /finance/bank-connections/example/syncs
1curl -X POST "http://localhost:8000/finance/bank-connections/example/syncs"
1fetch("http://localhost:8000/finance/bank-connections/example/syncs", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/finance/bank-connections/example/syncs")
4print(response.json())
200 Example Response
No Body
POST /finance/fiscal-periods/:period_id/year-end-close undocumented

/finance/fiscal-periods/:period_id/year-end-close

POST /finance/fiscal-periods/:period_id/year-end-close Posts the closing JE for the fiscal year whose last day matches ``period.end``. No request body — the period alone is the command.

Handled by api_year_end_close
Parameters
period_id string · path
required
Responses
200Successful Response
POST /finance/fiscal-periods/example/year-end-close
1curl -X POST "http://localhost:8000/finance/fiscal-periods/example/year-end-close"
1fetch("http://localhost:8000/finance/fiscal-periods/example/year-end-close", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/finance/fiscal-periods/example/year-end-close")
4print(response.json())
200 Example Response
No Body
POST /finance/recurring-entries/:recurring_id/runs undocumented

/finance/recurring-entries/:recurring_id/runs

Manually trigger a recurring entry — creates a draft invoice or bill. Does NOT advance ``next_date`` or reschedule — that's the scheduled path's job. Manual run is an operator override for off-cycle generation.

Handled by api_run_recurring
Parameters
recurring_id string · path
required
Responses
200Successful Response
POST /finance/recurring-entries/example/runs
1curl -X POST "http://localhost:8000/finance/recurring-entries/example/runs"
1fetch("http://localhost:8000/finance/recurring-entries/example/runs", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/finance/recurring-entries/example/runs")
4print(response.json())
200 Example Response
No Body
PUT /finance/settings/logo undocumented

/finance/settings/logo

PUT /finance/settings/logo: replace the logo shown on every document. The object key is generated ONCE and then reused for the life of the workspace, so a replacement overwrites in place. That is deliberate: a new key per upload would orphan the old object and, worse, break the logo in every invoice email already sitting in a customer's inbox. One workspace, one object, one stable URL. The key is flat, extensionless and 128 bits of randomness. Flat and random because the public bucket serves anyone holding the URL, so unguessability is the whole security boundary (listing is disabled, so the key is the only handle). Extensionless because the content type lives in R2 object metadata, which is what browsers, weasyprint and mail clients actually read: keeping an extension would mean a PNG-to-SVG switch silently orphaned the old object. The stored URL carries a ?v= token regenerated on every upload. Overwriting bytes under a cached URL would otherwise keep serving the old logo until the edge TTL lapsed, which reads as a broken save.

Handled by api_put_logo
Responses
200Successful Response
PUT /finance/settings/logo
1curl -X PUT "http://localhost:8000/finance/settings/logo"
1fetch("http://localhost:8000/finance/settings/logo", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/finance/settings/logo")
4print(response.json())
200 Example Response
No Body
DELETE /folders/:folder_id undocumented

/folders/:folder_id

Handled by api_delete_folder
Parameters
folder_id string · path
required
Responses
200Successful Response
DELETE /folders/example
1curl -X DELETE "http://localhost:8000/folders/example"
1fetch("http://localhost:8000/folders/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/folders/example")
4print(response.json())
200 Example Response
No Body
DELETE /folders/:folder_id/permissions undocumented

/folders/:folder_id/permissions

Handled by api_revoke_folder_permission
Parameters
folder_id string · path
required
Responses
200Successful Response
DELETE /folders/example/permissions
1curl -X DELETE "http://localhost:8000/folders/example/permissions"
1fetch("http://localhost:8000/folders/example/permissions", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/folders/example/permissions")
4print(response.json())
200 Example Response
No Body
GET /folders undocumented

/folders

Handled by api_list_folders
Responses
200Successful Response
GET /folders
1curl "http://localhost:8000/folders"
1fetch("http://localhost:8000/folders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/folders")
4print(response.json())
200 Example Response
No Body
GET /folders/:folder_id undocumented

/folders/:folder_id

Handled by api_get_folder
Parameters
folder_id string · path
required
Responses
200Successful Response
GET /folders/example
1curl "http://localhost:8000/folders/example"
1fetch("http://localhost:8000/folders/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/folders/example")
4print(response.json())
200 Example Response
No Body
GET /folders/:folder_id/files undocumented

/folders/:folder_id/files

Handled by api_list_folder_files
Parameters
folder_id string · path
required
Responses
200Successful Response
GET /folders/example/files
1curl "http://localhost:8000/folders/example/files"
1fetch("http://localhost:8000/folders/example/files")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/folders/example/files")
4print(response.json())
200 Example Response
No Body
GET /folders/:folder_id/permissions undocumented

/folders/:folder_id/permissions

Handled by api_list_folder_permissions
Parameters
folder_id string · path
required
Responses
200Successful Response
GET /folders/example/permissions
1curl "http://localhost:8000/folders/example/permissions"
1fetch("http://localhost:8000/folders/example/permissions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/folders/example/permissions")
4print(response.json())
200 Example Response
No Body
GET /folders/:folder_id/archive undocumented

/folders/:folder_id/archive

GET /folders/:folder_id/archive — the folder tree as a ZIP download.

Handled by api_folder_archive
Parameters
folder_id string · path
required
Responses
200Successful Response
GET /folders/example/archive
1curl "http://localhost:8000/folders/example/archive"
1fetch("http://localhost:8000/folders/example/archive")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/folders/example/archive")
4print(response.json())
200 Example Response
No Body
PATCH /folders/:folder_id

Update a folder

Handled by api_update_folder
Parameters
folder_id string · path
required
Body · UpdateFolderapplication/json
name string · min length: 1 · max length: 255
parent_id string
color string
is_pinned
propertyName anything
Responses
200Successful Response
PATCH /folders/example
1curl -X PATCH "http://localhost:8000/folders/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","parent_id":"string","color":"string","is_pinned":null}'
1fetch("http://localhost:8000/folders/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "parent_id": "string",
7 "color": "string",
8 "is_pinned": null
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/folders/example",
5 json={"name":"string","parent_id":"string","color":"string","is_pinned":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /folders

Create a folder

Handled by api_create_folder
Body · CreateFolderapplication/json
name string · min length: 1 · max length: 255
required
parent_id string
color string
propertyName anything
Responses
200Successful Response
POST /folders
1curl -X POST "http://localhost:8000/folders" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","parent_id":"string","color":"string"}'
1fetch("http://localhost:8000/folders", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "parent_id": "string",
7 "color": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/folders",
5 json={"name":"string","parent_id":"string","color":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /follows/:target_mrn undocumented

/follows/:target_mrn

DELETE /feeds/follow/:target_mrn — unfollow a member or team.

Handled by api_unfollow
Parameters
target_mrn string · path
required
Responses
200Successful Response
DELETE /follows/example
1curl -X DELETE "http://localhost:8000/follows/example"
1fetch("http://localhost:8000/follows/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/follows/example")
4print(response.json())
200 Example Response
No Body
GET /follows undocumented

/follows

GET /feeds/following — list who the current user follows.

Handled by api_list_following
Responses
200Successful Response
GET /follows
1curl "http://localhost:8000/follows"
1fetch("http://localhost:8000/follows")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/follows")
4print(response.json())
200 Example Response
No Body
POST /follows

Follow a member

POST /feeds/follow — follow a member or team.

Handled by api_follow
Body · FollowTargetapplication/json
target_mrn string · min length: 1
required
propertyName anything
Responses
200Successful Response
POST /follows
1curl -X POST "http://localhost:8000/follows" \
2 -H "Content-Type: application/json" \
3 -d '{"target_mrn":"string"}'
1fetch("http://localhost:8000/follows", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "target_mrn": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/follows",
5 json={"target_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /grants/:id undocumented

/grants/:id

DELETE /grants/:id — revoke a grant. The grant row was loaded + authorized by can_manage_grant_by_id. Ownership grants are not revocable here.

Handled by api_delete_grant
Parameters
id string · path
required
Responses
200Successful Response
DELETE /grants/example
1curl -X DELETE "http://localhost:8000/grants/example"
1fetch("http://localhost:8000/grants/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/grants/example")
4print(response.json())
200 Example Response
No Body
GET /grants undocumented

/grants

GET /grants?resource_mrn=… — who has access to a record (members + roles, each with their level), plus whether the caller may manage it.

Handled by api_list_grants
Responses
200Successful Response
GET /grants
1curl "http://localhost:8000/grants"
1fetch("http://localhost:8000/grants")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/grants")
4print(response.json())
200 Example Response
No Body
POST /grants

Grant access to a record

POST /grants — grant a member or role access to a record. Caps at the read/edit/manage ladder; ownership is never grantable here.

Handled by api_create_grant
Body · CreateGrantapplication/json
resource_mrn string · min length: 5 · max length: 255
required
principal_type
required
principal_id string · min length: 1 · max length: 100
required
action
required
propertyName anything
Responses
200Successful Response
POST /grants
1curl -X POST "http://localhost:8000/grants" \
2 -H "Content-Type: application/json" \
3 -d '{"resource_mrn":"string","principal_type":null,"principal_id":"string","action":null}'
1fetch("http://localhost:8000/grants", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "resource_mrn": "string",
6 "principal_type": null,
7 "principal_id": "string",
8 "action": null
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/grants",
5 json={"resource_mrn":"string","principal_type":null,"principal_id":"string","action":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /growth/goals/:id undocumented

/growth/goals/:id

Handled by api_delete_goal
Parameters
id string · path
required
Responses
200Successful Response
DELETE /growth/goals/example
1curl -X DELETE "http://localhost:8000/growth/goals/example"
1fetch("http://localhost:8000/growth/goals/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/growth/goals/example")
4print(response.json())
200 Example Response
No Body
DELETE /growth/plans/:id undocumented

/growth/plans/:id

Handled by api_delete_plan
Parameters
id string · path
required
Responses
200Successful Response
DELETE /growth/plans/example
1curl -X DELETE "http://localhost:8000/growth/plans/example"
1fetch("http://localhost:8000/growth/plans/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/growth/plans/example")
4print(response.json())
200 Example Response
No Body
DELETE /growth/signals/:id undocumented

/growth/signals/:id

Handled by api_delete_signal
Parameters
id string · path
required
Responses
200Successful Response
DELETE /growth/signals/example
1curl -X DELETE "http://localhost:8000/growth/signals/example"
1fetch("http://localhost:8000/growth/signals/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/growth/signals/example")
4print(response.json())
200 Example Response
No Body
DELETE /growth/attributes/:id undocumented

/growth/attributes/:id

Handled by api_delete_attribute
Parameters
id string · path
required
Responses
200Successful Response
DELETE /growth/attributes/example
1curl -X DELETE "http://localhost:8000/growth/attributes/example"
1fetch("http://localhost:8000/growth/attributes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/growth/attributes/example")
4print(response.json())
200 Example Response
No Body
DELETE /growth/role-profiles/:id undocumented

/growth/role-profiles/:id

Handled by api_delete_role_profile
Parameters
id string · path
required
Responses
200Successful Response
DELETE /growth/role-profiles/example
1curl -X DELETE "http://localhost:8000/growth/role-profiles/example"
1fetch("http://localhost:8000/growth/role-profiles/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/growth/role-profiles/example")
4print(response.json())
200 Example Response
No Body
DELETE /growth/review-tasks/:id undocumented

/growth/review-tasks/:id

Handled by api_delete_review_task
Parameters
id string · path
required
Responses
200Successful Response
DELETE /growth/review-tasks/example
1curl -X DELETE "http://localhost:8000/growth/review-tasks/example"
1fetch("http://localhost:8000/growth/review-tasks/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/growth/review-tasks/example")
4print(response.json())
200 Example Response
No Body
DELETE /growth/meeting-series/:id undocumented

/growth/meeting-series/:id

Handled by api_delete_meeting_series
Parameters
id string · path
required
Responses
200Successful Response
DELETE /growth/meeting-series/example
1curl -X DELETE "http://localhost:8000/growth/meeting-series/example"
1fetch("http://localhost:8000/growth/meeting-series/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/growth/meeting-series/example")
4print(response.json())
200 Example Response
No Body
GET /growth/campaigns undocumented

/growth/campaigns

Handled by api_list_campaigns
Responses
200Successful Response
GET /growth/campaigns
1curl "http://localhost:8000/growth/campaigns"
1fetch("http://localhost:8000/growth/campaigns")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/campaigns")
4print(response.json())
200 Example Response
No Body
GET /growth/campaigns/:id/results undocumented

/growth/campaigns/:id/results

Aggregated, min-group-size-suppressed engagement results for a campaign.

Handled by api_campaign_results
Parameters
id string · path
required
Responses
200Successful Response
GET /growth/campaigns/example/results
1curl "http://localhost:8000/growth/campaigns/example/results"
1fetch("http://localhost:8000/growth/campaigns/example/results")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/campaigns/example/results")
4print(response.json())
200 Example Response
No Body
GET /growth/goals undocumented

/growth/goals

Handled by api_list_goals
Responses
200Successful Response
GET /growth/goals
1curl "http://localhost:8000/growth/goals"
1fetch("http://localhost:8000/growth/goals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/goals")
4print(response.json())
200 Example Response
No Body
GET /growth/goals/summary undocumented

/growth/goals/summary

Handled by api_goals_summary
Responses
200Successful Response
GET /growth/goals/summary
1curl "http://localhost:8000/growth/goals/summary"
1fetch("http://localhost:8000/growth/goals/summary")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/goals/summary")
4print(response.json())
200 Example Response
No Body
GET /growth/plans undocumented

/growth/plans

Handled by api_list_plans
Responses
200Successful Response
GET /growth/plans
1curl "http://localhost:8000/growth/plans"
1fetch("http://localhost:8000/growth/plans")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/plans")
4print(response.json())
200 Example Response
No Body
GET /growth/signals undocumented

/growth/signals

Handled by api_list_signals
Responses
200Successful Response
GET /growth/signals
1curl "http://localhost:8000/growth/signals"
1fetch("http://localhost:8000/growth/signals")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/signals")
4print(response.json())
200 Example Response
No Body
GET /growth/signals/:id undocumented

/growth/signals/:id

One signal. The full-page 1:1 view loads an interaction through here.

Handled by api_get_signal
Parameters
id string · path
required
Responses
200Successful Response
GET /growth/signals/example
1curl "http://localhost:8000/growth/signals/example"
1fetch("http://localhost:8000/growth/signals/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/signals/example")
4print(response.json())
200 Example Response
No Body
GET /growth/signals/:id/action-items/tasks undocumented

/growth/signals/:id/action-items/tasks

GET /growth/signals/:id/action-items/tasks — the tasks this 1:1's action items were promoted into, read from the local projection (never from Tasks).

Handled by api_list_promoted_tasks
Parameters
id string · path
required
Responses
200Successful Response
GET /growth/signals/example/action-items/tasks
1curl "http://localhost:8000/growth/signals/example/action-items/tasks"
1fetch("http://localhost:8000/growth/signals/example/action-items/tasks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/signals/example/action-items/tasks")
4print(response.json())
200 Example Response
No Body
GET /growth/attributes undocumented

/growth/attributes

Handled by api_list_attributes
Responses
200Successful Response
GET /growth/attributes
1curl "http://localhost:8000/growth/attributes"
1fetch("http://localhost:8000/growth/attributes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/attributes")
4print(response.json())
200 Example Response
No Body
GET /growth/role-profiles undocumented

/growth/role-profiles

Handled by api_list_role_profiles
Responses
200Successful Response
GET /growth/role-profiles
1curl "http://localhost:8000/growth/role-profiles"
1fetch("http://localhost:8000/growth/role-profiles")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/role-profiles")
4print(response.json())
200 Example Response
No Body
GET /growth/role-profiles/:id undocumented

/growth/role-profiles/:id

GET /growth/role-profiles/:id — one career framework, ready to render. Carries the grid, the competencies its rows are drawn from, and the people who sit in the role. Those people come from growth_worker_index, growth's own projection of workers state (rule 5): matching is on the job title the worker events already carry, so nothing here reaches into the workers app.

Handled by api_get_role_profile
Parameters
id string · path
required
Responses
200Successful Response
GET /growth/role-profiles/example
1curl "http://localhost:8000/growth/role-profiles/example"
1fetch("http://localhost:8000/growth/role-profiles/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/role-profiles/example")
4print(response.json())
200 Example Response
No Body
GET /growth/review-tasks undocumented

/growth/review-tasks

Handled by api_list_review_tasks
Responses
200Successful Response
GET /growth/review-tasks
1curl "http://localhost:8000/growth/review-tasks"
1fetch("http://localhost:8000/growth/review-tasks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/review-tasks")
4print(response.json())
200 Example Response
No Body
GET /growth/meeting-series undocumented

/growth/meeting-series

Handled by api_list_meeting_series
Responses
200Successful Response
GET /growth/meeting-series
1curl "http://localhost:8000/growth/meeting-series"
1fetch("http://localhost:8000/growth/meeting-series")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/meeting-series")
4print(response.json())
200 Example Response
No Body
GET /growth/skill-matrix undocumented

/growth/skill-matrix

Per-worker competency levels aggregated from structured review ratings. Attributed data, gated to growth.results.view in AUTHZ.

Handled by api_skill_matrix
Responses
200Successful Response
GET /growth/skill-matrix
1curl "http://localhost:8000/growth/skill-matrix"
1fetch("http://localhost:8000/growth/skill-matrix")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/skill-matrix")
4print(response.json())
200 Example Response
No Body
GET /growth/concerns undocumented

/growth/concerns

GET /growth/concerns — the staff triage list: both streams, newest first. Gated to growth.results.view in AUTHZ (same crowd that reads anonymous pulse comments).

Handled by api_list_concerns
Responses
200Successful Response
GET /growth/concerns
1curl "http://localhost:8000/growth/concerns"
1fetch("http://localhost:8000/growth/concerns")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/concerns")
4print(response.json())
200 Example Response
No Body
GET /growth/overview undocumented

/growth/overview

Handled by api_overview
Responses
200Successful Response
GET /growth/overview
1curl "http://localhost:8000/growth/overview"
1fetch("http://localhost:8000/growth/overview")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/growth/overview")
4print(response.json())
200 Example Response
No Body
POST /growth/campaigns

Create a survey

Handled by api_create_campaign
Body · CreateCampaignapplication/json
title string · min length: 1 · max length: 120
required
kind
frequency
drivers array
custom_questions array
question_ids array
review_kinds array
enps
comment
starts_at string
ends_at string
propertyName anything
Responses
200Successful Response
POST /growth/campaigns
1curl -X POST "http://localhost:8000/growth/campaigns" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","kind":null,"frequency":null,"drivers":[null],"custom_questions":[{"label":"string"}],"question_ids":["string"],"review_kinds":[null],"enps":null,"comment":null,"starts_at":"string","ends_at":"string"}'
1fetch("http://localhost:8000/growth/campaigns", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "kind": null,
7 "frequency": null,
8 "drivers": [
9 null
10 ],
11 "custom_questions": [
12 {
13 "label": "string"
14 }
15 ],
16 "question_ids": [
17 "string"
18 ],
19 "review_kinds": [
20 null
21 ],
22 "enps": null,
23 "comment": null,
24 "starts_at": "string",
25 "ends_at": "string"
26}),
27})
28 .then((res) => res.json())
29 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/campaigns",
5 json={"title":"string","kind":null,"frequency":null,"drivers":[null],"custom_questions":[{"label":"string"}],"question_ids":["string"],"review_kinds":[null],"enps":null,"comment":null,"starts_at":"string","ends_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/responses

Submit an anonymous pulse response

Submit an anonymous pulse response. NO identity is stored. ``actor_mrn`` is used ONLY to look up the respondent's coarse segment tags from the projection; it is never written to the response or the emitted event.

Handled by api_submit_response
Body · SubmitResponseapplication/json
campaign_id string · min length: 1
required
scores object
custom_scores array
enps integer · min: 0 · max: 10
comment string · max length: 2000
propertyName anything
Responses
200Successful Response
POST /growth/responses
1curl -X POST "http://localhost:8000/growth/responses" \
2 -H "Content-Type: application/json" \
3 -d '{"campaign_id":"string","scores":{"recognition":1,"workload":1,"growth":1,"autonomy":1,"belonging":1,"management":1,"purpose":1,"voice":1},"custom_scores":[1],"enps":1,"comment":"string"}'
1fetch("http://localhost:8000/growth/responses", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "campaign_id": "string",
6 "scores": {
7 "recognition": 1,
8 "workload": 1,
9 "growth": 1,
10 "autonomy": 1,
11 "belonging": 1,
12 "management": 1,
13 "purpose": 1,
14 "voice": 1
15 },
16 "custom_scores": [
17 1
18 ],
19 "enps": 1,
20 "comment": "string"
21}),
22})
23 .then((res) => res.json())
24 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/responses",
5 json={"campaign_id":"string","scores":{"recognition":1,"workload":1,"growth":1,"autonomy":1,"belonging":1,"management":1,"purpose":1,"voice":1},"custom_scores":[1],"enps":1,"comment":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/responses/:id/replies

Reply to an anonymous comment

Reply to an anonymous comment. The reply is attributed (manager); the respondent stays anonymous. Routed by the opaque response id.

Handled by api_reply
Parameters
id string · path
required
Body · ReplyToCommentapplication/json
body string · min length: 1 · max length: 2000
required
propertyName anything
Responses
200Successful Response
POST /growth/responses/example/replies
1curl -X POST "http://localhost:8000/growth/responses/example/replies" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string"}'
1fetch("http://localhost:8000/growth/responses/example/replies", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/responses/example/replies",
5 json={"body":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/goals

Create a goal, KR or KPI

Handled by api_create_goal
Body · CreateGoalapplication/json
title string · min length: 1 · max length: 200
required
kind
scope
subject_mrn string · max length: 200
owner_mrn string · max length: 200
parent_id string · max length: 80
target object
metric string · max length: 120
start_value number
target_value number
unit string · max length: 24
direction
period string · max length: 40
starts_at string
due_at string
propertyName anything
Responses
200Successful Response
POST /growth/goals
1curl -X POST "http://localhost:8000/growth/goals" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","kind":null,"scope":null,"subject_mrn":"string","owner_mrn":"string","parent_id":"string","target":{"metric":"string","start_value":1.5,"target_value":1.5,"unit":"string","direction":null},"metric":"string","start_value":1.5,"target_value":1.5,"unit":"string","direction":null,"period":"string","starts_at":"string","due_at":"string"}'
1fetch("http://localhost:8000/growth/goals", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "kind": null,
7 "scope": null,
8 "subject_mrn": "string",
9 "owner_mrn": "string",
10 "parent_id": "string",
11 "target": {
12 "metric": "string",
13 "start_value": 1.5,
14 "target_value": 1.5,
15 "unit": "string",
16 "direction": null
17 },
18 "metric": "string",
19 "start_value": 1.5,
20 "target_value": 1.5,
21 "unit": "string",
22 "direction": null,
23 "period": "string",
24 "starts_at": "string",
25 "due_at": "string"
26}),
27})
28 .then((res) => res.json())
29 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/goals",
5 json={"title":"string","kind":null,"scope":null,"subject_mrn":"string","owner_mrn":"string","parent_id":"string","target":{"metric":"string","start_value":1.5,"target_value":1.5,"unit":"string","direction":null},"metric":"string","start_value":1.5,"target_value":1.5,"unit":"string","direction":null,"period":"string","starts_at":"string","due_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/goals/:id/progress

Log goal progress

Handled by api_log_goal_progress
Parameters
id string · path
required
Body · LogGoalProgressapplication/json
value number
required
note string · max length: 500
propertyName anything
Responses
200Successful Response
POST /growth/goals/example/progress
1curl -X POST "http://localhost:8000/growth/goals/example/progress" \
2 -H "Content-Type: application/json" \
3 -d '{"value":1.5,"note":"string"}'
1fetch("http://localhost:8000/growth/goals/example/progress", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "value": 1.5,
6 "note": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/goals/example/progress",
5 json={"value":1.5,"note":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/plans

Create a development plan or PIP

Handled by api_create_plan
Body · CreatePlanapplication/json
title string · min length: 1 · max length: 200
required
kind
subject_type
subject_mrn string · max length: 200
owner_mrn string · max length: 200
reason string · max length: 4000
detail object
milestones array
starts_at string
ends_at string
propertyName anything
Responses
200Successful Response
POST /growth/plans
1curl -X POST "http://localhost:8000/growth/plans" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","kind":null,"subject_type":null,"subject_mrn":"string","owner_mrn":"string","reason":"string","detail":{"milestones":[{"title":"string","done":null,"due_at":"string"}],"notes":"string","goal_ids":["string"],"driver":"string","campaign_id":"string","outcome":"string"},"milestones":["string"],"starts_at":"string","ends_at":"string"}'
1fetch("http://localhost:8000/growth/plans", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "kind": null,
7 "subject_type": null,
8 "subject_mrn": "string",
9 "owner_mrn": "string",
10 "reason": "string",
11 "detail": {
12 "milestones": [
13 {
14 "title": "string",
15 "done": null,
16 "due_at": "string"
17 }
18 ],
19 "notes": "string",
20 "goal_ids": [
21 "string"
22 ],
23 "driver": "string",
24 "campaign_id": "string",
25 "outcome": "string"
26 },
27 "milestones": [
28 "string"
29 ],
30 "starts_at": "string",
31 "ends_at": "string"
32}),
33})
34 .then((res) => res.json())
35 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/plans",
5 json={"title":"string","kind":null,"subject_type":null,"subject_mrn":"string","owner_mrn":"string","reason":"string","detail":{"milestones":[{"title":"string","done":null,"due_at":"string"}],"notes":"string","goal_ids":["string"],"driver":"string","campaign_id":"string","outcome":"string"},"milestones":["string"],"starts_at":"string","ends_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/signals

Give feedback, praise, a 1:1 note or review

Handled by api_create_signal
Body · CreateSignalapplication/json
kind
required
subject_mrn string · max length: 200
campaign_id string · max length: 80
parent_id string · max length: 80
series_id string · max length: 80
visibility
body object
text string · max length: 8000
values array
competencies array
competency_ratings array
agenda array
action_items array
check_in_items array
private_note string · max length: 8000
rating number · min: 0 · max: 5
occurred_at string
propertyName anything
Responses
200Successful Response
POST /growth/signals
1curl -X POST "http://localhost:8000/growth/signals" \
2 -H "Content-Type: application/json" \
3 -d '{"kind":null,"subject_mrn":"string","campaign_id":"string","parent_id":"string","series_id":"string","visibility":null,"body":{"text":"string","competencies":["string"],"competency_ratings":[{"attribute_id":"string","level":1}],"values":["string"],"agenda":["string"],"action_items":["string"],"check_in_items":[{"text":"string","done":null,"added_at":"string"}],"private_notes":[{"author_mrn":"string","text":"string"}]},"text":"string","values":["string"],"competencies":["string"],"competency_ratings":[{"attribute_id":"string","level":1}],"agenda":["string"],"action_items":["string"],"check_in_items":[{"text":"string","done":null,"added_at":"string"}],"private_note":"string","rating":1.5,"occurred_at":"string"}'
1fetch("http://localhost:8000/growth/signals", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "kind": null,
6 "subject_mrn": "string",
7 "campaign_id": "string",
8 "parent_id": "string",
9 "series_id": "string",
10 "visibility": null,
11 "body": {
12 "text": "string",
13 "competencies": [
14 "string"
15 ],
16 "competency_ratings": [
17 {
18 "attribute_id": "string",
19 "level": 1
20 }
21 ],
22 "values": [
23 "string"
24 ],
25 "agenda": [
26 "string"
27 ],
28 "action_items": [
29 "string"
30 ],
31 "check_in_items": [
32 {
33 "text": "string",
34 "done": null,
35 "added_at": "string"
36 }
37 ],
38 "private_notes": [
39 {
40 "author_mrn": "string",
41 "text": "string"
42 }
43 ]
44 },
45 "text": "string",
46 "values": [
47 "string"
48 ],
49 "competencies": [
50 "string"
51 ],
52 "competency_ratings": [
53 {
54 "attribute_id": "string",
55 "level": 1
56 }
57 ],
58 "agenda": [
59 "string"
60 ],
61 "action_items": [
62 "string"
63 ],
64 "check_in_items": [
65 {
66 "text": "string",
67 "done": null,
68 "added_at": "string"
69 }
70 ],
71 "private_note": "string",
72 "rating": 1.5,
73 "occurred_at": "string"
74}),
75})
76 .then((res) => res.json())
77 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/signals",
5 json={"kind":null,"subject_mrn":"string","campaign_id":"string","parent_id":"string","series_id":"string","visibility":null,"body":{"text":"string","competencies":["string"],"competency_ratings":[{"attribute_id":"string","level":1}],"values":["string"],"agenda":["string"],"action_items":["string"],"check_in_items":[{"text":"string","done":null,"added_at":"string"}],"private_notes":[{"author_mrn":"string","text":"string"}]},"text":"string","values":["string"],"competencies":["string"],"competency_ratings":[{"attribute_id":"string","level":1}],"agenda":["string"],"action_items":["string"],"check_in_items":[{"text":"string","done":null,"added_at":"string"}],"private_note":"string","rating":1.5,"occurred_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/signals/:id/action-items/:index/task

Turn a 1:1 action item into a task

POST /growth/signals/:id/action-items/:index/task — make this action item a real task. Growth never calls the Tasks API (rule 6): it emits, Tasks creates, and the resulting core.tasks.task.created comes back round the bus into growth_task_projection. So this answers 202, not 201 — the task does not exist yet when we reply.

Handled by api_promote_action_item
Parameters
id string · path
required
index string · path
required
Body · PromoteActionItemapplication/json
board_id string · min length: 1
required
propertyName anything
Responses
200Successful Response
POST /growth/signals/example/action-items/example/task
1curl -X POST "http://localhost:8000/growth/signals/example/action-items/example/task" \
2 -H "Content-Type: application/json" \
3 -d '{"board_id":"string"}'
1fetch("http://localhost:8000/growth/signals/example/action-items/example/task", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "board_id": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/signals/example/action-items/example/task",
5 json={"board_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/attributes

Create a competency, value or bank question

Handled by api_create_attribute
Body · CreateAttributeapplication/json
kind
required
name string · min length: 1 · max length: 120
required
description string · max length: 2000
category string · max length: 80
levels array
driver
scale integer · min: 2 · max: 10
sort integer · min: 0 · max: 999
propertyName anything
Responses
200Successful Response
POST /growth/attributes
1curl -X POST "http://localhost:8000/growth/attributes" \
2 -H "Content-Type: application/json" \
3 -d '{"kind":null,"name":"string","description":"string","category":"string","levels":[{"level":1,"name":"string","description":"string"}],"driver":null,"scale":1,"sort":1}'
1fetch("http://localhost:8000/growth/attributes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "kind": null,
6 "name": "string",
7 "description": "string",
8 "category": "string",
9 "levels": [
10 {
11 "level": 1,
12 "name": "string",
13 "description": "string"
14 }
15 ],
16 "driver": null,
17 "scale": 1,
18 "sort": 1
19}),
20})
21 .then((res) => res.json())
22 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/attributes",
5 json={"kind":null,"name":"string","description":"string","category":"string","levels":[{"level":1,"name":"string","description":"string"}],"driver":null,"scale":1,"sort":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/role-profiles

Create a role profile

Handled by api_create_role_profile
Body · CreateRoleProfileapplication/json
title string · min length: 1 · max length: 120
required
track string · max length: 80
level string · max length: 40
description string · max length: 2000
expectations array
job_titles array
propertyName anything
Responses
200Successful Response
POST /growth/role-profiles
1curl -X POST "http://localhost:8000/growth/role-profiles" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","track":"string","level":"string","description":"string","expectations":[{"attribute_id":"string","level":1}],"job_titles":["string"]}'
1fetch("http://localhost:8000/growth/role-profiles", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "track": "string",
7 "level": "string",
8 "description": "string",
9 "expectations": [
10 {
11 "attribute_id": "string",
12 "level": 1
13 }
14 ],
15 "job_titles": [
16 "string"
17 ]
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/role-profiles",
5 json={"title":"string","track":"string","level":"string","description":"string","expectations":[{"attribute_id":"string","level":1}],"job_titles":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/review-tasks

Nominate a peer or upward reviewer

Peer / upward nomination. Self and manager tasks come from cycle launch.

Handled by api_create_review_task
Body · CreateReviewTaskapplication/json
campaign_id string · min length: 1 · max length: 80
required
kind
reviewer_mrn string · min length: 1 · max length: 200
required
subject_mrn string · max length: 200
due_at string
propertyName anything
Responses
200Successful Response
POST /growth/review-tasks
1curl -X POST "http://localhost:8000/growth/review-tasks" \
2 -H "Content-Type: application/json" \
3 -d '{"campaign_id":"string","kind":null,"reviewer_mrn":"string","subject_mrn":"string","due_at":"string"}'
1fetch("http://localhost:8000/growth/review-tasks", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "campaign_id": "string",
6 "kind": null,
7 "reviewer_mrn": "string",
8 "subject_mrn": "string",
9 "due_at": "string"
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/review-tasks",
5 json={"campaign_id":"string","kind":null,"reviewer_mrn":"string","subject_mrn":"string","due_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/meeting-series

Start a recurring 1:1

Handled by api_create_meeting_series
Body · CreateMeetingSeriesapplication/json
participant_mrn string · min length: 1 · max length: 200
required
title string · max length: 120
cadence
next_at string
agenda array
propertyName anything
Responses
200Successful Response
POST /growth/meeting-series
1curl -X POST "http://localhost:8000/growth/meeting-series" \
2 -H "Content-Type: application/json" \
3 -d '{"participant_mrn":"string","title":"string","cadence":null,"next_at":"string","agenda":["string"]}'
1fetch("http://localhost:8000/growth/meeting-series", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "participant_mrn": "string",
6 "title": "string",
7 "cadence": null,
8 "next_at": "string",
9 "agenda": [
10 "string"
11 ]
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/meeting-series",
5 json={"participant_mrn":"string","title":"string","cadence":null,"next_at":"string","agenda":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /growth/concerns

Raise a concern, anonymously or named

POST /growth/concerns — file a concern, anonymously or named. Anonymous: actor_mrn is used ONLY to derive coarse segment tags (exactly like a pulse response); no identity is stored on the row or the event. Named: a complaint signal authored by the caller, visible to managers/HR.

Handled by api_create_concern
Body · CreateConcernapplication/json
body string · min length: 1 · max length: 4000
required
anonymous
propertyName anything
Responses
200Successful Response
POST /growth/concerns
1curl -X POST "http://localhost:8000/growth/concerns" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string","anonymous":null}'
1fetch("http://localhost:8000/growth/concerns", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string",
6 "anonymous": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/growth/concerns",
5 json={"body":"string","anonymous":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/campaigns/:id

Update or launch a survey

Handled by api_update_campaign
Parameters
id string · path
required
Body · UpdateCampaignapplication/json
title string · min length: 1 · max length: 120
status
frequency
drivers array
custom_questions array
question_ids array
review_kinds array
enps
comment
starts_at string
ends_at string
propertyName anything
Responses
200Successful Response
PUT /growth/campaigns/example
1curl -X PUT "http://localhost:8000/growth/campaigns/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","status":null,"frequency":null,"drivers":[null],"custom_questions":[{"label":"string"}],"question_ids":["string"],"review_kinds":[null],"enps":null,"comment":null,"starts_at":"string","ends_at":"string"}'
1fetch("http://localhost:8000/growth/campaigns/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "status": null,
7 "frequency": null,
8 "drivers": [
9 null
10 ],
11 "custom_questions": [
12 {
13 "label": "string"
14 }
15 ],
16 "question_ids": [
17 "string"
18 ],
19 "review_kinds": [
20 null
21 ],
22 "enps": null,
23 "comment": null,
24 "starts_at": "string",
25 "ends_at": "string"
26}),
27})
28 .then((res) => res.json())
29 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/campaigns/example",
5 json={"title":"string","status":null,"frequency":null,"drivers":[null],"custom_questions":[{"label":"string"}],"question_ids":["string"],"review_kinds":[null],"enps":null,"comment":null,"starts_at":"string","ends_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/goals/:id

Update a goal

Handled by api_update_goal
Parameters
id string · path
required
Body · UpdateGoalapplication/json
title string · min length: 1 · max length: 200
status
owner_mrn string · max length: 200
parent_id string · max length: 80
target object
period string · max length: 40
due_at string
propertyName anything
Responses
200Successful Response
PUT /growth/goals/example
1curl -X PUT "http://localhost:8000/growth/goals/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","status":null,"owner_mrn":"string","parent_id":"string","target":{"metric":"string","start_value":1.5,"target_value":1.5,"unit":"string","direction":null},"period":"string","due_at":"string"}'
1fetch("http://localhost:8000/growth/goals/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "status": null,
7 "owner_mrn": "string",
8 "parent_id": "string",
9 "target": {
10 "metric": "string",
11 "start_value": 1.5,
12 "target_value": 1.5,
13 "unit": "string",
14 "direction": null
15 },
16 "period": "string",
17 "due_at": "string"
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/goals/example",
5 json={"title":"string","status":null,"owner_mrn":"string","parent_id":"string","target":{"metric":"string","start_value":1.5,"target_value":1.5,"unit":"string","direction":null},"period":"string","due_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/plans/:id

Update a plan

Handled by api_update_plan
Parameters
id string · path
required
Body · UpdatePlanapplication/json
title string · min length: 1 · max length: 200
status
owner_mrn string · max length: 200
reason string · max length: 4000
detail object
starts_at string
ends_at string
propertyName anything
Responses
200Successful Response
PUT /growth/plans/example
1curl -X PUT "http://localhost:8000/growth/plans/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","status":null,"owner_mrn":"string","reason":"string","detail":{"milestones":[{"title":"string","done":null,"due_at":"string"}],"notes":"string","goal_ids":["string"],"driver":"string","campaign_id":"string","outcome":"string"},"starts_at":"string","ends_at":"string"}'
1fetch("http://localhost:8000/growth/plans/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "status": null,
7 "owner_mrn": "string",
8 "reason": "string",
9 "detail": {
10 "milestones": [
11 {
12 "title": "string",
13 "done": null,
14 "due_at": "string"
15 }
16 ],
17 "notes": "string",
18 "goal_ids": [
19 "string"
20 ],
21 "driver": "string",
22 "campaign_id": "string",
23 "outcome": "string"
24 },
25 "starts_at": "string",
26 "ends_at": "string"
27}),
28})
29 .then((res) => res.json())
30 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/plans/example",
5 json={"title":"string","status":null,"owner_mrn":"string","reason":"string","detail":{"milestones":[{"title":"string","done":null,"due_at":"string"}],"notes":"string","goal_ids":["string"],"driver":"string","campaign_id":"string","outcome":"string"},"starts_at":"string","ends_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/signals/:id

Update a signal

Handled by api_update_signal
Parameters
id string · path
required
Body · UpdateSignalapplication/json
visibility
body object
rating number · min: 0 · max: 5
status
series_id string · max length: 80
private_note string · max length: 8000
propertyName anything
Responses
200Successful Response
PUT /growth/signals/example
1curl -X PUT "http://localhost:8000/growth/signals/example" \
2 -H "Content-Type: application/json" \
3 -d '{"visibility":null,"body":{"text":"string","competencies":["string"],"competency_ratings":[{"attribute_id":"string","level":1}],"values":["string"],"agenda":["string"],"action_items":["string"],"check_in_items":[{"text":"string","done":null,"added_at":"string"}],"private_notes":[{"author_mrn":"string","text":"string"}]},"rating":1.5,"status":null,"series_id":"string","private_note":"string"}'
1fetch("http://localhost:8000/growth/signals/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "visibility": null,
6 "body": {
7 "text": "string",
8 "competencies": [
9 "string"
10 ],
11 "competency_ratings": [
12 {
13 "attribute_id": "string",
14 "level": 1
15 }
16 ],
17 "values": [
18 "string"
19 ],
20 "agenda": [
21 "string"
22 ],
23 "action_items": [
24 "string"
25 ],
26 "check_in_items": [
27 {
28 "text": "string",
29 "done": null,
30 "added_at": "string"
31 }
32 ],
33 "private_notes": [
34 {
35 "author_mrn": "string",
36 "text": "string"
37 }
38 ]
39 },
40 "rating": 1.5,
41 "status": null,
42 "series_id": "string",
43 "private_note": "string"
44}),
45})
46 .then((res) => res.json())
47 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/signals/example",
5 json={"visibility":null,"body":{"text":"string","competencies":["string"],"competency_ratings":[{"attribute_id":"string","level":1}],"values":["string"],"agenda":["string"],"action_items":["string"],"check_in_items":[{"text":"string","done":null,"added_at":"string"}],"private_notes":[{"author_mrn":"string","text":"string"}]},"rating":1.5,"status":null,"series_id":"string","private_note":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/attributes/:id

Update a competency, value or question

Handled by api_update_attribute
Parameters
id string · path
required
Body · UpdateAttributeapplication/json
name string · min length: 1 · max length: 120
description string · max length: 2000
category string · max length: 80
levels array
driver
scale integer · min: 2 · max: 10
sort integer · min: 0 · max: 999
status
propertyName anything
Responses
200Successful Response
PUT /growth/attributes/example
1curl -X PUT "http://localhost:8000/growth/attributes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","category":"string","levels":[{"level":1,"name":"string","description":"string"}],"driver":null,"scale":1,"sort":1,"status":null}'
1fetch("http://localhost:8000/growth/attributes/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "category": "string",
8 "levels": [
9 {
10 "level": 1,
11 "name": "string",
12 "description": "string"
13 }
14 ],
15 "driver": null,
16 "scale": 1,
17 "sort": 1,
18 "status": null
19}),
20})
21 .then((res) => res.json())
22 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/attributes/example",
5 json={"name":"string","description":"string","category":"string","levels":[{"level":1,"name":"string","description":"string"}],"driver":null,"scale":1,"sort":1,"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/role-profiles/:id

Update a role profile

Handled by api_update_role_profile
Parameters
id string · path
required
Body · UpdateRoleProfileapplication/json
title string · min length: 1 · max length: 120
track string · max length: 80
level string · max length: 40
description string · max length: 2000
expectations array
job_titles array
matrix object
status
propertyName anything
Responses
200Successful Response
PUT /growth/role-profiles/example
1curl -X PUT "http://localhost:8000/growth/role-profiles/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","track":"string","level":"string","description":"string","expectations":[{"attribute_id":"string","level":1}],"job_titles":["string"],"matrix":{"levels":[{"key":"string","label":"string"}],"cells":[{"attribute_id":"string","level_key":"string","text":"string","format":{"bold":null,"italic":null,"underline":null,"color":"string","background":"string","align":null}}],"columns":[{"level_key":"string","width":1}]},"status":null}'
1fetch("http://localhost:8000/growth/role-profiles/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "track": "string",
7 "level": "string",
8 "description": "string",
9 "expectations": [
10 {
11 "attribute_id": "string",
12 "level": 1
13 }
14 ],
15 "job_titles": [
16 "string"
17 ],
18 "matrix": {
19 "levels": [
20 {
21 "key": "string",
22 "label": "string"
23 }
24 ],
25 "cells": [
26 {
27 "attribute_id": "string",
28 "level_key": "string",
29 "text": "string",
30 "format": {
31 "bold": null,
32 "italic": null,
33 "underline": null,
34 "color": "string",
35 "background": "string",
36 "align": null
37 }
38 }
39 ],
40 "columns": [
41 {
42 "level_key": "string",
43 "width": 1
44 }
45 ]
46 },
47 "status": null
48}),
49})
50 .then((res) => res.json())
51 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/role-profiles/example",
5 json={"title":"string","track":"string","level":"string","description":"string","expectations":[{"attribute_id":"string","level":1}],"job_titles":["string"],"matrix":{"levels":[{"key":"string","label":"string"}],"cells":[{"attribute_id":"string","level_key":"string","text":"string","format":{"bold":null,"italic":null,"underline":null,"color":"string","background":"string","align":null}}],"columns":[{"level_key":"string","width":1}]},"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/review-tasks/:id

Update a review task

Handled by api_update_review_task
Parameters
id string · path
required
Body · UpdateReviewTaskapplication/json
status
due_at string
extension_until string
extension_note string · max length: 500
extension
propertyName anything
Responses
200Successful Response
PUT /growth/review-tasks/example
1curl -X PUT "http://localhost:8000/growth/review-tasks/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null,"due_at":"string","extension_until":"string","extension_note":"string","extension":null}'
1fetch("http://localhost:8000/growth/review-tasks/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null,
6 "due_at": "string",
7 "extension_until": "string",
8 "extension_note": "string",
9 "extension": null
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/review-tasks/example",
5 json={"status":null,"due_at":"string","extension_until":"string","extension_note":"string","extension":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /growth/meeting-series/:id

Update a 1:1 series

Handled by api_update_meeting_series
Parameters
id string · path
required
Body · UpdateMeetingSeriesapplication/json
title string · max length: 120
cadence
next_at string
agenda array
status
propertyName anything
Responses
200Successful Response
PUT /growth/meeting-series/example
1curl -X PUT "http://localhost:8000/growth/meeting-series/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","cadence":null,"next_at":"string","agenda":[{"text":"string","kind":null,"done":null,"added_at":"string"}],"status":null}'
1fetch("http://localhost:8000/growth/meeting-series/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "cadence": null,
7 "next_at": "string",
8 "agenda": [
9 {
10 "text": "string",
11 "kind": null,
12 "done": null,
13 "added_at": "string"
14 }
15 ],
16 "status": null
17}),
18})
19 .then((res) => res.json())
20 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/growth/meeting-series/example",
5 json={"title":"string","cadence":null,"next_at":"string","agenda":[{"text":"string","kind":null,"done":null,"added_at":"string"}],"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /health undocumented

/health

Handled by health
Responses
200Successful Response
GET /health
1curl "http://localhost:8000/health"
1fetch("http://localhost:8000/health")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/health")
4print(response.json())
200 Example Response
No Body
DELETE /holidays/:id undocumented

/holidays/:id

Handled by api_delete_holiday
Parameters
id string · path
required
Responses
200Successful Response
DELETE /holidays/example
1curl -X DELETE "http://localhost:8000/holidays/example"
1fetch("http://localhost:8000/holidays/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/holidays/example")
4print(response.json())
200 Example Response
No Body
GET /holidays undocumented

/holidays

Handled by api_list_holidays
Responses
200Successful Response
GET /holidays
1curl "http://localhost:8000/holidays"
1fetch("http://localhost:8000/holidays")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/holidays")
4print(response.json())
200 Example Response
No Body
POST /holidays

Create a holiday

Handled by api_create_holiday
Body · CreateHolidayapplication/json
name string · min length: 1 · max length: 100
required
date string · min length: 1
required
is_recurring
propertyName anything
Responses
200Successful Response
POST /holidays
1curl -X POST "http://localhost:8000/holidays" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","date":"string","is_recurring":null}'
1fetch("http://localhost:8000/holidays", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "date": "string",
7 "is_recurring": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/holidays",
5 json={"name":"string","date":"string","is_recurring":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /holidays/:id

Update a holiday

Handled by api_update_holiday
Parameters
id string · path
required
Body · UpdateHolidayapplication/json
name string · min length: 1 · max length: 100
date string · min length: 1
is_recurring
propertyName anything
Responses
200Successful Response
PUT /holidays/example
1curl -X PUT "http://localhost:8000/holidays/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","date":"string","is_recurring":null}'
1fetch("http://localhost:8000/holidays/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "date": "string",
7 "is_recurring": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/holidays/example",
5 json={"name":"string","date":"string","is_recurring":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /hooks/mxs undocumented

/hooks/mxs

POST /hooks/mxs — the MX box posts here when mail is delivered. Not session-authed; verified by HMAC over the raw body with MX_WEBHOOK_SECRET. Looks up the mailbox's workspace, syncs the new mail into the cache, and nudges its open clients.

Handled by on_mx_webhook
Responses
200Successful Response
POST /hooks/mxs
1curl -X POST "http://localhost:8000/hooks/mxs"
1fetch("http://localhost:8000/hooks/mxs", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/hooks/mxs")
4print(response.json())
200 Example Response
No Body
DELETE /installations/:slug undocumented

/installations/:slug

DELETE /installations/:slug — Uninstall an app (admin/owner only).

Handled by api_uninstall_app
Parameters
slug string · path
required
Responses
200Successful Response
DELETE /installations/example
1curl -X DELETE "http://localhost:8000/installations/example"
1fetch("http://localhost:8000/installations/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/installations/example")
4print(response.json())
200 Example Response
No Body
GET /installations undocumented

/installations

GET /installations — List installed apps for the workspace. Default view returns apps the current member can access (UI grid). Pass ?policy=1 (owner/admin only) to include access_policy + allowed_roles for every installed app — used by the App Access admin screen.

Handled by api_list_installed_apps
Responses
200Successful Response
GET /installations
1curl "http://localhost:8000/installations"
1fetch("http://localhost:8000/installations")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/installations")
4print(response.json())
200 Example Response
No Body
DELETE /interactions/:interaction_id undocumented

/interactions/:interaction_id

DELETE /interactions/:interaction_id — delete an interaction.

Handled by api_delete_interaction
Parameters
interaction_id string · path
required
Responses
200Successful Response
DELETE /interactions/example
1curl -X DELETE "http://localhost:8000/interactions/example"
1fetch("http://localhost:8000/interactions/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/interactions/example")
4print(response.json())
200 Example Response
No Body
GET /interactions undocumented

/interactions

GET /interactions — all interactions (activity reports).

Handled by api_list_interactions
Responses
200Successful Response
GET /interactions
1curl "http://localhost:8000/interactions"
1fetch("http://localhost:8000/interactions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/interactions")
4print(response.json())
200 Example Response
No Body
POST /interactions

Log an interaction

POST /interactions — log an interaction.

Handled by api_create_interaction
Body · CreateInteractionapplication/json
contact_id string
company_id string
source_mrn string
type
required
direction
subject string · max length: 200
content string · max length: 10000
occurred_at string
required
duration_minutes integer
rating object
propertyName anything
Responses
200Successful Response
POST /interactions
1curl -X POST "http://localhost:8000/interactions" \
2 -H "Content-Type: application/json" \
3 -d '{"contact_id":"string","company_id":"string","source_mrn":"string","type":null,"direction":null,"subject":"string","content":"string","occurred_at":"string","duration_minutes":1,"rating":{"score":1,"comment":"string"}}'
1fetch("http://localhost:8000/interactions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "contact_id": "string",
6 "company_id": "string",
7 "source_mrn": "string",
8 "type": null,
9 "direction": null,
10 "subject": "string",
11 "content": "string",
12 "occurred_at": "string",
13 "duration_minutes": 1,
14 "rating": {
15 "score": 1,
16 "comment": "string"
17 }
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/interactions",
5 json={"contact_id":"string","company_id":"string","source_mrn":"string","type":null,"direction":null,"subject":"string","content":"string","occurred_at":"string","duration_minutes":1,"rating":{"score":1,"comment":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /interactions/:interaction_id

Update an interaction

PUT /interactions/:interaction_id — update an interaction.

Handled by api_update_interaction
Parameters
interaction_id string · path
required
Body · UpdateInteractionapplication/json
subject string · max length: 200
content string · max length: 10000
occurred_at string
duration_minutes integer
propertyName anything
Responses
200Successful Response
PUT /interactions/example
1curl -X PUT "http://localhost:8000/interactions/example" \
2 -H "Content-Type: application/json" \
3 -d '{"subject":"string","content":"string","occurred_at":"string","duration_minutes":1}'
1fetch("http://localhost:8000/interactions/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "subject": "string",
6 "content": "string",
7 "occurred_at": "string",
8 "duration_minutes": 1
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/interactions/example",
5 json={"subject":"string","content":"string","occurred_at":"string","duration_minutes":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /invitations/:token undocumented

/invitations/:token

Handled by invitation_page
Parameters
token string · path
required
Responses
200Successful Response
GET /invitations/example
1curl "http://localhost:8000/invitations/example"
1fetch("http://localhost:8000/invitations/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/invitations/example")
4print(response.json())
200 Example Response
No Body
GET /invoices/:id undocumented

/invoices/:id

GET /invoices/:id — return full invoice data with line items.

Handled by api_get_invoice
Parameters
id string · path
required
Responses
200Successful Response
GET /invoices/example
1curl "http://localhost:8000/invoices/example"
1fetch("http://localhost:8000/invoices/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/invoices/example")
4print(response.json())
200 Example Response
No Body
PATCH /finance/invoices/:entry_id

Issue/void an invoice

Handled by api_patch_invoice
Parameters
entry_id string · path
required
Body · UpdateInvoiceStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/invoices/example
1curl -X PATCH "http://localhost:8000/finance/invoices/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/invoices/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/invoices/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/invoices

Create an invoice

Handled by api_create_invoice
Body · CreateInvoiceapplication/json
date string · min length: 10
required
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
required
exchange_rate number
due_date string · min length: 10
memo string · max length: 5000
tags array
sources array
adjustments array
dimensions
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/invoices
1curl -X POST "http://localhost:8000/finance/invoices" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"sources":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/invoices", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "due_date": "string",
30 "memo": "string",
31 "tags": [
32 "string"
33 ],
34 "sources": [
35 "string"
36 ],
37 "adjustments": [
38 {
39 "label": "string",
40 "type": null,
41 "value": 1.5,
42 "amount": 1.5,
43 "account_code": "string"
44 }
45 ],
46 "dimensions": null,
47 "idempotency_key": "string"
48}),
49})
50 .then((res) => res.json())
51 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/invoices",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"sources":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/invoices/:entry_id/pdfs

Generate invoice PDF

Handled by api_create_invoice_pdf
Parameters
entry_id string · path
required
Body · GeneratePdfapplication/json
template string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/invoices/example/pdfs
1curl -X POST "http://localhost:8000/finance/invoices/example/pdfs" \
2 -H "Content-Type: application/json" \
3 -d '{"template":"string"}'
1fetch("http://localhost:8000/finance/invoices/example/pdfs", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "template": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/invoices/example/pdfs",
5 json={"template":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/invoices/:entry_id/sends

Email an invoice

Handled by api_send_invoice
Parameters
entry_id string · path
required
Body · SendInvoiceapplication/json
to string · min length: 1 · max length: 500
required
cc string · max length: 500
subject string · max length: 300
message string · max length: 5000
attach_pdf
propertyName anything
Responses
200Successful Response
POST /finance/invoices/example/sends
1curl -X POST "http://localhost:8000/finance/invoices/example/sends" \
2 -H "Content-Type: application/json" \
3 -d '{"to":"string","cc":"string","subject":"string","message":"string","attach_pdf":null}'
1fetch("http://localhost:8000/finance/invoices/example/sends", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to": "string",
6 "cc": "string",
7 "subject": "string",
8 "message": "string",
9 "attach_pdf": null
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/invoices/example/sends",
5 json={"to":"string","cc":"string","subject":"string","message":"string","attach_pdf":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/invoices/:entry_id/reminders

Send an overdue reminder

Handled by api_send_reminder
Parameters
entry_id string · path
required
Body · SendReminderapplication/json
to string · min length: 1 · max length: 500
required
subject string · max length: 300
message string · max length: 5000
propertyName anything
Responses
200Successful Response
POST /finance/invoices/example/reminders
1curl -X POST "http://localhost:8000/finance/invoices/example/reminders" \
2 -H "Content-Type: application/json" \
3 -d '{"to":"string","subject":"string","message":"string"}'
1fetch("http://localhost:8000/finance/invoices/example/reminders", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to": "string",
6 "subject": "string",
7 "message": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/invoices/example/reminders",
5 json={"to":"string","subject":"string","message":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /invoices/:id/charges undocumented

/invoices/:id/charges

POST /invoices/:id/charges — retry charging the default payment method.

Handled by api_retry_invoice_charge
Parameters
id string · path
required
Responses
200Successful Response
POST /invoices/example/charges
1curl -X POST "http://localhost:8000/invoices/example/charges"
1fetch("http://localhost:8000/invoices/example/charges", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/invoices/example/charges")
4print(response.json())
200 Example Response
No Body
PUT /finance/invoices/:entry_id

Update a draft invoice

Handled by api_update_invoice
Parameters
entry_id string · path
required
Body · UpdateInvoiceapplication/json
date string · min length: 10
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
due_date string · min length: 10
memo string · max length: 5000
tags array
adjustments array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/invoices/example
1curl -X PUT "http://localhost:8000/finance/invoices/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null}'
1fetch("http://localhost:8000/finance/invoices/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "due_date": "string",
30 "memo": "string",
31 "tags": [
32 "string"
33 ],
34 "adjustments": [
35 {
36 "label": "string",
37 "type": null,
38 "value": 1.5,
39 "amount": 1.5,
40 "account_code": "string"
41 }
42 ],
43 "dimensions": null
44}),
45})
46 .then((res) => res.json())
47 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/invoices/example",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"due_date":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/journal-entries/:entry_id

Post/void a journal

Handled by api_patch_journal_entry
Parameters
entry_id string · path
required
Body · UpdateJournalStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/journal-entries/example
1curl -X PATCH "http://localhost:8000/finance/journal-entries/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/journal-entries/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/journal-entries/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/journal-entries

Create a journal entry

Handled by api_create_journal_entry
Body · CreateJournalEntryapplication/json
date string · min length: 10
required
lines array
required
memo string · max length: 5000
currency string · min length: 3 · max length: 3
required
exchange_rate number
tags array
dimensions
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/journal-entries
1curl -X POST "http://localhost:8000/finance/journal-entries" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","lines":[{"account_code":"string","description":"string","debit":1.5,"credit":1.5,"dimensions":null}],"memo":"string","currency":"string","exchange_rate":1.5,"tags":["string"],"dimensions":null,"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/journal-entries", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "lines": [
7 {
8 "account_code": "string",
9 "description": "string",
10 "debit": 1.5,
11 "credit": 1.5,
12 "dimensions": null
13 }
14 ],
15 "memo": "string",
16 "currency": "string",
17 "exchange_rate": 1.5,
18 "tags": [
19 "string"
20 ],
21 "dimensions": null,
22 "idempotency_key": "string"
23}),
24})
25 .then((res) => res.json())
26 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/journal-entries",
5 json={"date":"string","lines":[{"account_code":"string","description":"string","debit":1.5,"credit":1.5,"dimensions":null}],"memo":"string","currency":"string","exchange_rate":1.5,"tags":["string"],"dimensions":null,"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/journal-entries/:entry_id

Update a draft journal

Handled by api_update_journal_entry
Parameters
entry_id string · path
required
Body · UpdateJournalEntryapplication/json
date string · min length: 10
lines array
memo string · max length: 5000
currency string · min length: 3 · max length: 3
exchange_rate number
tags array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/journal-entries/example
1curl -X PUT "http://localhost:8000/finance/journal-entries/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","lines":[{"account_code":"string","description":"string","debit":1.5,"credit":1.5,"dimensions":null}],"memo":"string","currency":"string","exchange_rate":1.5,"tags":["string"],"dimensions":null}'
1fetch("http://localhost:8000/finance/journal-entries/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "lines": [
7 {
8 "account_code": "string",
9 "description": "string",
10 "debit": 1.5,
11 "credit": 1.5,
12 "dimensions": null
13 }
14 ],
15 "memo": "string",
16 "currency": "string",
17 "exchange_rate": 1.5,
18 "tags": [
19 "string"
20 ],
21 "dimensions": null
22}),
23})
24 .then((res) => res.json())
25 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/journal-entries/example",
5 json={"date":"string","lines":[{"account_code":"string","description":"string","debit":1.5,"credit":1.5,"dimensions":null}],"memo":"string","currency":"string","exchange_rate":1.5,"tags":["string"],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /leave-balances/:id/adjustments

Adjust a leave balance

Manual balance adjustment (admin only).

Handled by api_adjust_balance
Parameters
id string · path
required
Body · AdjustBalanceapplication/json
amount number
required
reason string · min length: 1 · max length: 500
required
propertyName anything
Responses
200Successful Response
POST /leave-balances/example/adjustments
1curl -X POST "http://localhost:8000/leave-balances/example/adjustments" \
2 -H "Content-Type: application/json" \
3 -d '{"amount":1.5,"reason":"string"}'
1fetch("http://localhost:8000/leave-balances/example/adjustments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "amount": 1.5,
6 "reason": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/leave-balances/example/adjustments",
5 json={"amount":1.5,"reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /leave-policies

Create a leave policy

Handled by api_create_policy
Body · CreatePolicyapplication/json
name string · min length: 1 · max length: 100
required
type
required
allowance number
required
description string · max length: 500
accrual
max_carry_over number
requires_approval
min_notice_days integer
max_consecutive_days integer
applies_to
cycle_start
default_approver_mrns array
propertyName anything
Responses
200Successful Response
POST /leave-policies
1curl -X POST "http://localhost:8000/leave-policies" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","type":null,"allowance":1.5,"description":"string","accrual":null,"max_carry_over":1.5,"requires_approval":null,"min_notice_days":1,"max_consecutive_days":1,"applies_to":null,"cycle_start":null,"default_approver_mrns":["string"]}'
1fetch("http://localhost:8000/leave-policies", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "type": null,
7 "allowance": 1.5,
8 "description": "string",
9 "accrual": null,
10 "max_carry_over": 1.5,
11 "requires_approval": null,
12 "min_notice_days": 1,
13 "max_consecutive_days": 1,
14 "applies_to": null,
15 "cycle_start": null,
16 "default_approver_mrns": [
17 "string"
18 ]
19}),
20})
21 .then((res) => res.json())
22 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/leave-policies",
5 json={"name":"string","type":null,"allowance":1.5,"description":"string","accrual":null,"max_carry_over":1.5,"requires_approval":null,"min_notice_days":1,"max_consecutive_days":1,"applies_to":null,"cycle_start":null,"default_approver_mrns":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /leave-policies/:id/members

Assign workers to a leave policy

POST /leave-policies/:id/members — Assign workers to a policy and provision balances.

Handled by api_add_policy_members
Parameters
id string · path
required
Body · AddPolicyMembersapplication/json
worker_mrns array
required
propertyName anything
Responses
200Successful Response
POST /leave-policies/example/members
1curl -X POST "http://localhost:8000/leave-policies/example/members" \
2 -H "Content-Type: application/json" \
3 -d '{"worker_mrns":["string"]}'
1fetch("http://localhost:8000/leave-policies/example/members", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "worker_mrns": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/leave-policies/example/members",
5 json={"worker_mrns":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /leave-policies/:id

Update a leave policy

Handled by api_update_policy
Parameters
id string · path
required
Body · UpdatePolicyapplication/json
name string · min length: 1 · max length: 100
description string · max length: 500
allowance number
accrual
max_carry_over number
requires_approval
min_notice_days integer
max_consecutive_days integer
applies_to
cycle_start
is_active
default_approver_mrns array
propertyName anything
Responses
200Successful Response
PUT /leave-policies/example
1curl -X PUT "http://localhost:8000/leave-policies/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","allowance":1.5,"accrual":null,"max_carry_over":1.5,"requires_approval":null,"min_notice_days":1,"max_consecutive_days":1,"applies_to":null,"cycle_start":null,"is_active":null,"default_approver_mrns":["string"]}'
1fetch("http://localhost:8000/leave-policies/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "allowance": 1.5,
8 "accrual": null,
9 "max_carry_over": 1.5,
10 "requires_approval": null,
11 "min_notice_days": 1,
12 "max_consecutive_days": 1,
13 "applies_to": null,
14 "cycle_start": null,
15 "is_active": null,
16 "default_approver_mrns": [
17 "string"
18 ]
19}),
20})
21 .then((res) => res.json())
22 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/leave-policies/example",
5 json={"name":"string","description":"string","allowance":1.5,"accrual":null,"max_carry_over":1.5,"requires_approval":null,"min_notice_days":1,"max_consecutive_days":1,"applies_to":null,"cycle_start":null,"is_active":null,"default_approver_mrns":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /leave-balances undocumented

/leave-balances

List balances for the current user's worker record. Self view: only balances for policies the worker is currently assigned to. Orphan rows (pre-membership provisioning, or kept after unassignment because days were used) stay in the table for history but are not returned here; the manager view (GET /leave-balances/:worker_mrn) still exposes them.

Handled by api_list_balances
Responses
200Successful Response
GET /leave-balances
1curl "http://localhost:8000/leave-balances"
1fetch("http://localhost:8000/leave-balances")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-balances")
4print(response.json())
200 Example Response
No Body
GET /leave-balances/:worker_mrn undocumented

/leave-balances/:worker_mrn

List balances for a specific worker (manager/admin).

Handled by api_get_worker_balances
Parameters
worker_mrn string · path
required
Responses
200Successful Response
GET /leave-balances/example
1curl "http://localhost:8000/leave-balances/example"
1fetch("http://localhost:8000/leave-balances/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-balances/example")
4print(response.json())
200 Example Response
No Body
GET /leave-calculate-days undocumented

/leave-calculate-days

Calculate working days between two dates.

Handled by api_calculate_days
Responses
200Successful Response
GET /leave-calculate-days
1curl "http://localhost:8000/leave-calculate-days"
1fetch("http://localhost:8000/leave-calculate-days")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-calculate-days")
4print(response.json())
200 Example Response
No Body
GET /leave-calendar undocumented

/leave-calendar

Team calendar — approved PTOs + holidays for a date range.

Handled by api_calendar
Responses
200Successful Response
GET /leave-calendar
1curl "http://localhost:8000/leave-calendar"
1fetch("http://localhost:8000/leave-calendar")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-calendar")
4print(response.json())
200 Example Response
No Body
DELETE /leave-policies/:id undocumented

/leave-policies/:id

Handled by api_delete_policy
Parameters
id string · path
required
Responses
200Successful Response
DELETE /leave-policies/example
1curl -X DELETE "http://localhost:8000/leave-policies/example"
1fetch("http://localhost:8000/leave-policies/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/leave-policies/example")
4print(response.json())
200 Example Response
No Body
DELETE /leave-policies/:id/members/:worker_mrn undocumented

/leave-policies/:id/members/:worker_mrn

DELETE /leave-policies/:id/members/:worker_mrn — Remove a worker from a policy.

Handled by api_remove_policy_member
Parameters
id string · path
required
worker_mrn string · path
required
Responses
200Successful Response
DELETE /leave-policies/example/members/example
1curl -X DELETE "http://localhost:8000/leave-policies/example/members/example"
1fetch("http://localhost:8000/leave-policies/example/members/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/leave-policies/example/members/example")
4print(response.json())
200 Example Response
No Body
GET /leave-policies undocumented

/leave-policies

Handled by api_list_policies
Responses
200Successful Response
GET /leave-policies
1curl "http://localhost:8000/leave-policies"
1fetch("http://localhost:8000/leave-policies")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-policies")
4print(response.json())
200 Example Response
No Body
GET /leave-policies/:id undocumented

/leave-policies/:id

Handled by api_get_policy
Parameters
id string · path
required
Responses
200Successful Response
GET /leave-policies/example
1curl "http://localhost:8000/leave-policies/example"
1fetch("http://localhost:8000/leave-policies/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-policies/example")
4print(response.json())
200 Example Response
No Body
GET /leave-policies/:id/members undocumented

/leave-policies/:id/members

GET /leave-policies/:id/members — List workers assigned to a policy.

Handled by api_list_policy_members
Parameters
id string · path
required
Responses
200Successful Response
GET /leave-policies/example/members
1curl "http://localhost:8000/leave-policies/example/members"
1fetch("http://localhost:8000/leave-policies/example/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-policies/example/members")
4print(response.json())
200 Example Response
No Body
GET /leave-reconciliation undocumented

/leave-reconciliation

GET /leave-reconciliation — future bookings whose day count changed under the current working pattern, with a read-only entitlement pro-ration hint.

Handled by api_reconciliation_preview
Responses
200Successful Response
GET /leave-reconciliation
1curl "http://localhost:8000/leave-reconciliation"
1fetch("http://localhost:8000/leave-reconciliation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/leave-reconciliation")
4print(response.json())
200 Example Response
No Body
POST /leave-reconciliation undocumented

/leave-reconciliation

POST /leave-reconciliation — recount every affected future booking and adjust its balance (admin sign-off). Past/in-progress untouched; approved bookings re-emit so the attendance projection rebuilds on the new pattern. Entitlement pro-ration is NOT done here — it's a separate audited adjustment.

Handled by api_apply_reconciliation
Responses
200Successful Response
POST /leave-reconciliation
1curl -X POST "http://localhost:8000/leave-reconciliation"
1fetch("http://localhost:8000/leave-reconciliation", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/leave-reconciliation")
4print(response.json())
200 Example Response
No Body
PATCH /calls/:id/links/:link_id

Update a join link

Handled by api_update_link
Parameters
id string · path
required
link_id string · path
required
Body · UpdateLinkapplication/json
is_active
external_join_mode
propertyName anything
Responses
200Successful Response
PATCH /calls/example/links/example
1curl -X PATCH "http://localhost:8000/calls/example/links/example" \
2 -H "Content-Type: application/json" \
3 -d '{"is_active":null,"external_join_mode":null}'
1fetch("http://localhost:8000/calls/example/links/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "is_active": null,
6 "external_join_mode": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/calls/example/links/example",
5 json={"is_active":null,"external_join_mode":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /calls/:id/links

Create a join link

Handled by api_create_link
Parameters
id string · path
required
Body · CreateLinkapplication/json
expires_at string
guest_name string · max length: 200
guest_email string · max length: 200
external_join_mode
propertyName anything
Responses
200Successful Response
POST /calls/example/links
1curl -X POST "http://localhost:8000/calls/example/links" \
2 -H "Content-Type: application/json" \
3 -d '{"expires_at":"string","guest_name":"string","guest_email":"string","external_join_mode":null}'
1fetch("http://localhost:8000/calls/example/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "expires_at": "string",
6 "guest_name": "string",
7 "guest_email": "string",
8 "external_join_mode": null
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/calls/example/links",
5 json={"expires_at":"string","guest_name":"string","guest_email":"string","external_join_mode":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /chats/lists/:list_id

Update a chat list

PATCH /chats/lists/:list_id — rename or reorder a list.

Handled by api_update_chat_list
Parameters
list_id string · path
required
Body · UpdateChatListapplication/json
name string · min length: 1 · max length: 50
position integer
propertyName anything
Responses
200Successful Response
PATCH /chats/lists/example
1curl -X PATCH "http://localhost:8000/chats/lists/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","position":1}'
1fetch("http://localhost:8000/chats/lists/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "position": 1
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/chats/lists/example",
5 json={"name":"string","position":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /chats/lists

Create a chat list

POST /chats/lists — create a personal chat list.

Handled by api_create_chat_list
Body · CreateChatListapplication/json
name string · min length: 1 · max length: 50
required
chat_ids array
propertyName anything
Responses
200Successful Response
POST /chats/lists
1curl -X POST "http://localhost:8000/chats/lists" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","chat_ids":["string"]}'
1fetch("http://localhost:8000/chats/lists", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "chat_ids": [
7 "string"
8 ]
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/chats/lists",
5 json={"name":"string","chat_ids":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /login undocumented

/login

GET / login on the ROOT domain: which workspace are you signing in to? There is no global login any more, so this page has no credential field. It takes a workspace name and forwards to that workspace's own sign-in page. It also lists any workspace this browser is already signed into, read straight out of the session. That is not the deferred "email me my workspaces" recovery flow, it is just showing what the cookie already knows, so somebody who is signed in never lands here with nothing to click.

Handled by workspace_finder_page
Responses
200Successful Response
GET /login
1curl "http://localhost:8000/login"
1fetch("http://localhost:8000/login")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/login")
4print(response.json())
200 Example Response
No Body
GET /login undocumented

/login

GET /login on a WORKSPACE subdomain: ask for the address, mail proof. The subdomain already names the workspace, so the page can say which one you are signing in to, and the session it eventually mints is scoped to it.

Handled by workspace_login_page
Responses
200Successful Response
GET /login
1curl "http://localhost:8000/login"
1fetch("http://localhost:8000/login")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/login")
4print(response.json())
200 Example Response
No Body
GET /logout undocumented

/logout

Handled by logout
Responses
200Successful Response
GET /logout
1curl "http://localhost:8000/logout"
1fetch("http://localhost:8000/logout")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/logout")
4print(response.json())
200 Example Response
No Body
POST /wands/macro-previews

Try a single macro against a sample event

Run a single macro against a sample event and return what it produced. The teaching sandbox behind the macro reference page. Reads run for real with the viewer's own permissions; anything that writes is simulated (dry_run is forced server-side and is not caller-controllable).

Handled by api_create_macro_preview
Body · MacroPreviewapplication/json
macro string · min length: 2 · max length: 40
required
args
payload
event_name string · max length: 200
propertyName anything
Responses
200Successful Response
POST /wands/macro-previews
1curl -X POST "http://localhost:8000/wands/macro-previews" \
2 -H "Content-Type: application/json" \
3 -d '{"macro":"string","args":null,"payload":null,"event_name":"string"}'
1fetch("http://localhost:8000/wands/macro-previews", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "macro": "string",
6 "args": null,
7 "payload": null,
8 "event_name": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/wands/macro-previews",
5 json={"macro":"string","args":null,"payload":null,"event_name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /mail/accounts/:account_id undocumented

/mail/accounts/:account_id

Handled by api_delete_account
Parameters
account_id string · path
required
Responses
200Successful Response
DELETE /mail/accounts/example
1curl -X DELETE "http://localhost:8000/mail/accounts/example"
1fetch("http://localhost:8000/mail/accounts/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/accounts/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/accounts/:account_id/messages/:message_id undocumented

/mail/accounts/:account_id/messages/:message_id

Handled by api_delete_message
Parameters
account_id string · path
required
message_id string · path
required
Responses
200Successful Response
DELETE /mail/accounts/example/messages/example
1curl -X DELETE "http://localhost:8000/mail/accounts/example/messages/example"
1fetch("http://localhost:8000/mail/accounts/example/messages/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/accounts/example/messages/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/accounts/:account_id/signatures/:signature_id undocumented

/mail/accounts/:account_id/signatures/:signature_id

Handled by api_delete_signature
Parameters
account_id string · path
required
signature_id string · path
required
Responses
200Successful Response
DELETE /mail/accounts/example/signatures/example
1curl -X DELETE "http://localhost:8000/mail/accounts/example/signatures/example"
1fetch("http://localhost:8000/mail/accounts/example/signatures/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/accounts/example/signatures/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/accounts/:account_id/filters/:filter_id undocumented

/mail/accounts/:account_id/filters/:filter_id

Handled by api_delete_filter
Parameters
account_id string · path
required
filter_id string · path
required
Responses
200Successful Response
DELETE /mail/accounts/example/filters/example
1curl -X DELETE "http://localhost:8000/mail/accounts/example/filters/example"
1fetch("http://localhost:8000/mail/accounts/example/filters/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/accounts/example/filters/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/accounts/:account_id/blocked-senders/:blocked_id undocumented

/mail/accounts/:account_id/blocked-senders/:blocked_id

Handled by api_delete_blocked_sender
Parameters
account_id string · path
required
blocked_id string · path
required
Responses
200Successful Response
DELETE /mail/accounts/example/blocked-senders/example
1curl -X DELETE "http://localhost:8000/mail/accounts/example/blocked-senders/example"
1fetch("http://localhost:8000/mail/accounts/example/blocked-senders/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/accounts/example/blocked-senders/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/domains/:domain_id undocumented

/mail/domains/:domain_id

Remove a domain (pending typo or live). Cleans the MX box (virtual domain + DKIM, cascading its mailboxes) best-effort, then removes the platform rows.

Handled by api_delete_domain
Parameters
domain_id string · path
required
Responses
200Successful Response
DELETE /mail/domains/example
1curl -X DELETE "http://localhost:8000/mail/domains/example"
1fetch("http://localhost:8000/mail/domains/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/domains/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/mailboxes/:mailbox_id undocumented

/mail/mailboxes/:mailbox_id

Handled by api_delete_mailbox
Parameters
mailbox_id string · path
required
Responses
200Successful Response
DELETE /mail/mailboxes/example
1curl -X DELETE "http://localhost:8000/mail/mailboxes/example"
1fetch("http://localhost:8000/mail/mailboxes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/mailboxes/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/groups/:group_id undocumented

/mail/groups/:group_id

Remove a shared mailbox: tear down its aliases + backing mailbox on the MX box, then drop the group, its members, and the mailbox row. Best-effort on the box so a local cleanup still completes if the server is unreachable.

Handled by api_delete_group
Parameters
group_id string · path
required
Responses
200Successful Response
DELETE /mail/groups/example
1curl -X DELETE "http://localhost:8000/mail/groups/example"
1fetch("http://localhost:8000/mail/groups/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/groups/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/groups/:group_id/members/:member_id undocumented

/mail/groups/:group_id/members/:member_id

Handled by api_remove_group_member
Parameters
group_id string · path
required
member_id string · path
required
Responses
200Successful Response
DELETE /mail/groups/example/members/example
1curl -X DELETE "http://localhost:8000/mail/groups/example/members/example"
1fetch("http://localhost:8000/mail/groups/example/members/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/groups/example/members/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/groups/:group_id/messages/:message_id undocumented

/mail/groups/:group_id/messages/:message_id

Handled by api_delete_group_message
Parameters
group_id string · path
required
message_id string · path
required
Responses
200Successful Response
DELETE /mail/groups/example/messages/example
1curl -X DELETE "http://localhost:8000/mail/groups/example/messages/example"
1fetch("http://localhost:8000/mail/groups/example/messages/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/groups/example/messages/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/drafts/:draft_id undocumented

/mail/drafts/:draft_id

Handled by api_delete_draft
Parameters
draft_id string · path
required
Responses
200Successful Response
DELETE /mail/drafts/example
1curl -X DELETE "http://localhost:8000/mail/drafts/example"
1fetch("http://localhost:8000/mail/drafts/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/drafts/example")
4print(response.json())
200 Example Response
No Body
DELETE /mail/mailboxes/:mailbox_id/outbox-keys/:key_id undocumented

/mail/mailboxes/:mailbox_id/outbox-keys/:key_id

Remove the audit row — only after revoke, same as API keys.

Handled by api_delete_outbox_key
Parameters
mailbox_id string · path
required
key_id string · path
required
Responses
200Successful Response
DELETE /mail/mailboxes/example/outbox-keys/example
1curl -X DELETE "http://localhost:8000/mail/mailboxes/example/outbox-keys/example"
1fetch("http://localhost:8000/mail/mailboxes/example/outbox-keys/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/mail/mailboxes/example/outbox-keys/example")
4print(response.json())
200 Example Response
No Body
GET /mail/oauth/:provider/authorize undocumented

/mail/oauth/:provider/authorize

Handled by authorize
Parameters
provider string · path
required
Responses
200Successful Response
GET /mail/oauth/example/authorize
1curl "http://localhost:8000/mail/oauth/example/authorize"
1fetch("http://localhost:8000/mail/oauth/example/authorize")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/oauth/example/authorize")
4print(response.json())
200 Example Response
No Body
GET /mail/oauth/:provider/callback undocumented

/mail/oauth/:provider/callback

Handled by callback
Parameters
provider string · path
required
Responses
200Successful Response
GET /mail/oauth/example/callback
1curl "http://localhost:8000/mail/oauth/example/callback"
1fetch("http://localhost:8000/mail/oauth/example/callback")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/oauth/example/callback")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts undocumented

/mail/accounts

Handled by api_list_accounts
Responses
200Successful Response
GET /mail/accounts
1curl "http://localhost:8000/mail/accounts"
1fetch("http://localhost:8000/mail/accounts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts")
4print(response.json())
200 Example Response
No Body
GET /mail/recipients undocumented

/mail/recipients

Typeahead source for the compose recipient fields: workspace members who have been assigned a mail account (a personal mailbox or a connected Gmail/Outlook). The contacts directory — people already emailed or received from — is merged client-side from the contacts app, so mail never reads another app's tables (rule 6).

Handled by api_recipient_suggestions
Responses
200Successful Response
GET /mail/recipients
1curl "http://localhost:8000/mail/recipients"
1fetch("http://localhost:8000/mail/recipients")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/recipients")
4print(response.json())
200 Example Response
No Body
GET /mail/unified/messages undocumented

/mail/unified/messages

Merge one folder (default inbox) across the member's accounts flagged show_in_unified plus any shared inboxes the member belongs to. The folder is selectable so the "All inboxes" view works for Sent, Archive, Spam, etc. — not just Inbox.

Handled by api_unified_inbox
Responses
200Successful Response
GET /mail/unified/messages
1curl "http://localhost:8000/mail/unified/messages"
1fetch("http://localhost:8000/mail/unified/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/unified/messages")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/messages undocumented

/mail/accounts/:account_id/messages

Handled by api_list_messages
Parameters
account_id string · path
required
Responses
200Successful Response
GET /mail/accounts/example/messages
1curl "http://localhost:8000/mail/accounts/example/messages"
1fetch("http://localhost:8000/mail/accounts/example/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/messages")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/messages/:message_id undocumented

/mail/accounts/:account_id/messages/:message_id

Handled by api_get_message
Parameters
account_id string · path
required
message_id string · path
required
Responses
200Successful Response
GET /mail/accounts/example/messages/example
1curl "http://localhost:8000/mail/accounts/example/messages/example"
1fetch("http://localhost:8000/mail/accounts/example/messages/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/messages/example")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/messages/:message_id/attachments/:index undocumented

/mail/accounts/:account_id/messages/:message_id/attachments/:index

Stream one attachment of a message as a download. Bytes live only in the IMAP message (not our storage), so they're fetched from the provider on demand.

Handled by api_get_message_attachment
Parameters
account_id string · path
required
message_id string · path
required
index string · path
required
Responses
200Successful Response
GET /mail/accounts/example/messages/example/attachments/example
1curl "http://localhost:8000/mail/accounts/example/messages/example/attachments/example"
1fetch("http://localhost:8000/mail/accounts/example/messages/example/attachments/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/messages/example/attachments/example")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/messages/:message_id/calendar undocumented

/mail/accounts/:account_id/messages/:message_id/calendar

Parse the calendar invite(s) (.ics) attached to a message into platform-calendar event fields, so the client can add them via POST /meetings. Attachment bytes are only fetched from Saasmail (MX) inboxes — the same limitation as attachment download.

Handled by api_message_calendar
Parameters
account_id string · path
required
message_id string · path
required
Responses
200Successful Response
GET /mail/accounts/example/messages/example/calendar
1curl "http://localhost:8000/mail/accounts/example/messages/example/calendar"
1fetch("http://localhost:8000/mail/accounts/example/messages/example/calendar")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/messages/example/calendar")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/folders undocumented

/mail/accounts/:account_id/folders

Handled by api_list_folders
Parameters
account_id string · path
required
Responses
200Successful Response
GET /mail/accounts/example/folders
1curl "http://localhost:8000/mail/accounts/example/folders"
1fetch("http://localhost:8000/mail/accounts/example/folders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/folders")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/signatures undocumented

/mail/accounts/:account_id/signatures

Handled by api_list_signatures
Parameters
account_id string · path
required
Responses
200Successful Response
GET /mail/accounts/example/signatures
1curl "http://localhost:8000/mail/accounts/example/signatures"
1fetch("http://localhost:8000/mail/accounts/example/signatures")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/signatures")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/filters undocumented

/mail/accounts/:account_id/filters

Handled by api_list_filters
Parameters
account_id string · path
required
Responses
200Successful Response
GET /mail/accounts/example/filters
1curl "http://localhost:8000/mail/accounts/example/filters"
1fetch("http://localhost:8000/mail/accounts/example/filters")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/filters")
4print(response.json())
200 Example Response
No Body
GET /mail/accounts/:account_id/blocked-senders undocumented

/mail/accounts/:account_id/blocked-senders

Handled by api_list_blocked_senders
Parameters
account_id string · path
required
Responses
200Successful Response
GET /mail/accounts/example/blocked-senders
1curl "http://localhost:8000/mail/accounts/example/blocked-senders"
1fetch("http://localhost:8000/mail/accounts/example/blocked-senders")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/accounts/example/blocked-senders")
4print(response.json())
200 Example Response
No Body
GET /mail/domains undocumented

/mail/domains

Handled by api_list_domains
Responses
200Successful Response
GET /mail/domains
1curl "http://localhost:8000/mail/domains"
1fetch("http://localhost:8000/mail/domains")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/domains")
4print(response.json())
200 Example Response
No Body
GET /mail/mailboxes undocumented

/mail/mailboxes

Handled by api_list_mailboxes
Responses
200Successful Response
GET /mail/mailboxes
1curl "http://localhost:8000/mail/mailboxes"
1fetch("http://localhost:8000/mail/mailboxes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/mailboxes")
4print(response.json())
200 Example Response
No Body
GET /mail/groups undocumented

/mail/groups

Handled by api_list_groups
Responses
200Successful Response
GET /mail/groups
1curl "http://localhost:8000/mail/groups"
1fetch("http://localhost:8000/mail/groups")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups")
4print(response.json())
200 Example Response
No Body
GET /mail/groups/:group_id/members undocumented

/mail/groups/:group_id/members

Handled by api_list_group_members
Parameters
group_id string · path
required
Responses
200Successful Response
GET /mail/groups/example/members
1curl "http://localhost:8000/mail/groups/example/members"
1fetch("http://localhost:8000/mail/groups/example/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups/example/members")
4print(response.json())
200 Example Response
No Body
GET /mail/groups/:group_id/drafts undocumented

/mail/groups/:group_id/drafts

In-progress (unsent) drafts for a group — co-editors open these to edit together. Reply tier required: read-only members don't see drafts still being composed.

Handled by api_list_group_drafts
Parameters
group_id string · path
required
Responses
200Successful Response
GET /mail/groups/example/drafts
1curl "http://localhost:8000/mail/groups/example/drafts"
1fetch("http://localhost:8000/mail/groups/example/drafts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups/example/drafts")
4print(response.json())
200 Example Response
No Body
GET /mail/groups/:group_id/thread undocumented

/mail/groups/:group_id/thread

The group conversation — sent drafts in order, each showing who sent it.

Handled by api_group_thread
Parameters
group_id string · path
required
Responses
200Successful Response
GET /mail/groups/example/thread
1curl "http://localhost:8000/mail/groups/example/thread"
1fetch("http://localhost:8000/mail/groups/example/thread")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups/example/thread")
4print(response.json())
200 Example Response
No Body
GET /mail/groups/:group_id/messages undocumented

/mail/groups/:group_id/messages

Handled by api_list_group_messages
Parameters
group_id string · path
required
Responses
200Successful Response
GET /mail/groups/example/messages
1curl "http://localhost:8000/mail/groups/example/messages"
1fetch("http://localhost:8000/mail/groups/example/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups/example/messages")
4print(response.json())
200 Example Response
No Body
GET /mail/groups/:group_id/messages/:message_id undocumented

/mail/groups/:group_id/messages/:message_id

Handled by api_get_group_message
Parameters
group_id string · path
required
message_id string · path
required
Responses
200Successful Response
GET /mail/groups/example/messages/example
1curl "http://localhost:8000/mail/groups/example/messages/example"
1fetch("http://localhost:8000/mail/groups/example/messages/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups/example/messages/example")
4print(response.json())
200 Example Response
No Body
GET /mail/groups/:group_id/messages/:message_id/attachments/:index undocumented

/mail/groups/:group_id/messages/:message_id/attachments/:index

Handled by api_get_group_message_attachment
Parameters
group_id string · path
required
message_id string · path
required
index string · path
required
Responses
200Successful Response
GET /mail/groups/example/messages/example/attachments/example
1curl "http://localhost:8000/mail/groups/example/messages/example/attachments/example"
1fetch("http://localhost:8000/mail/groups/example/messages/example/attachments/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups/example/messages/example/attachments/example")
4print(response.json())
200 Example Response
No Body
GET /mail/groups/:group_id/messages/:message_id/calendar undocumented

/mail/groups/:group_id/messages/:message_id/calendar

Parse the calendar invite(s) (.ics) attached to a shared-inbox message into platform-calendar event fields (same as the personal-account endpoint).

Handled by api_group_message_calendar
Parameters
group_id string · path
required
message_id string · path
required
Responses
200Successful Response
GET /mail/groups/example/messages/example/calendar
1curl "http://localhost:8000/mail/groups/example/messages/example/calendar"
1fetch("http://localhost:8000/mail/groups/example/messages/example/calendar")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/groups/example/messages/example/calendar")
4print(response.json())
200 Example Response
No Body
GET /mail/drafts undocumented

/mail/drafts

The member's own personal (non-group) unsent drafts, newest first.

Handled by api_list_drafts
Responses
200Successful Response
GET /mail/drafts
1curl "http://localhost:8000/mail/drafts"
1fetch("http://localhost:8000/mail/drafts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/drafts")
4print(response.json())
200 Example Response
No Body
GET /mail/mailboxes/:mailbox_id/outbox-keys undocumented

/mail/mailboxes/:mailbox_id/outbox-keys

List a mailbox's outbox keys (prefix, name, status, last used) — never the secret. 404 for a caller who fails the mint-identity gate.

Handled by api_list_outbox_keys
Parameters
mailbox_id string · path
required
Responses
200Successful Response
GET /mail/mailboxes/example/outbox-keys
1curl "http://localhost:8000/mail/mailboxes/example/outbox-keys"
1fetch("http://localhost:8000/mail/mailboxes/example/outbox-keys")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/mail/mailboxes/example/outbox-keys")
4print(response.json())
200 Example Response
No Body
PATCH /mail/accounts/:account_id

Update mail account

Handled by api_update_account
Parameters
account_id string · path
required
Body · UpdateAccountapplication/json
display_name string · max length: 200
show_in_unified
propertyName anything
Responses
200Successful Response
PATCH /mail/accounts/example
1curl -X PATCH "http://localhost:8000/mail/accounts/example" \
2 -H "Content-Type: application/json" \
3 -d '{"display_name":"string","show_in_unified":null}'
1fetch("http://localhost:8000/mail/accounts/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "display_name": "string",
6 "show_in_unified": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/mail/accounts/example",
5 json={"display_name":"string","show_in_unified":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /mail/accounts/:account_id/messages/:message_id

Modify a message

Handled by api_modify_message
Parameters
account_id string · path
required
message_id string · path
required
Body · UpdateMessageapplication/json
is_read
is_starred
folder string · min length: 1 · max length: 100
propertyName anything
Responses
200Successful Response
PATCH /mail/accounts/example/messages/example
1curl -X PATCH "http://localhost:8000/mail/accounts/example/messages/example" \
2 -H "Content-Type: application/json" \
3 -d '{"is_read":null,"is_starred":null,"folder":"string"}'
1fetch("http://localhost:8000/mail/accounts/example/messages/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "is_read": null,
6 "is_starred": null,
7 "folder": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/mail/accounts/example/messages/example",
5 json={"is_read":null,"is_starred":null,"folder":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /mail/groups/:group_id undocumented

/mail/groups/:group_id

Cosmetic group settings. Any member may set the shared inbox's badge color; only admins may rename it.

Handled by api_update_group
Parameters
group_id string · path
required
Responses
200Successful Response
PATCH /mail/groups/example
1curl -X PATCH "http://localhost:8000/mail/groups/example"
1fetch("http://localhost:8000/mail/groups/example", { method: "PATCH" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.patch("http://localhost:8000/mail/groups/example")
4print(response.json())
200 Example Response
No Body
PATCH /mail/groups/:group_id/messages/:message_id

Modify a shared-inbox message

Handled by api_modify_group_message
Parameters
group_id string · path
required
message_id string · path
required
Body · UpdateMessageapplication/json
is_read
is_starred
folder string · min length: 1 · max length: 100
propertyName anything
Responses
200Successful Response
PATCH /mail/groups/example/messages/example
1curl -X PATCH "http://localhost:8000/mail/groups/example/messages/example" \
2 -H "Content-Type: application/json" \
3 -d '{"is_read":null,"is_starred":null,"folder":"string"}'
1fetch("http://localhost:8000/mail/groups/example/messages/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "is_read": null,
6 "is_starred": null,
7 "folder": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/mail/groups/example/messages/example",
5 json={"is_read":null,"is_starred":null,"folder":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/accounts/:account_id/messages

Send a message

Handled by api_send_message
Parameters
account_id string · path
required
Body · SendMessageapplication/json
to array
required
cc array
bcc array
subject string · max length: 998
required
body_text string
body_html string
is_draft
signature_id string · min length: 1
attachments array
in_reply_to string · max length: 998
references string · max length: 8000
propertyName anything
Responses
200Successful Response
POST /mail/accounts/example/messages
1curl -X POST "http://localhost:8000/mail/accounts/example/messages" \
2 -H "Content-Type: application/json" \
3 -d '{"to":[{"email":"user@example.com","name":"string"}],"cc":[{"email":"user@example.com","name":"string"}],"bcc":[{"email":"user@example.com","name":"string"}],"subject":"string","body_text":"string","body_html":"string","is_draft":null,"signature_id":"string","attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"in_reply_to":"string","references":"string"}'
1fetch("http://localhost:8000/mail/accounts/example/messages", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to": [
6 {
7 "email": "user@example.com",
8 "name": "string"
9 }
10 ],
11 "cc": [
12 {
13 "email": "user@example.com",
14 "name": "string"
15 }
16 ],
17 "bcc": [
18 {
19 "email": "user@example.com",
20 "name": "string"
21 }
22 ],
23 "subject": "string",
24 "body_text": "string",
25 "body_html": "string",
26 "is_draft": null,
27 "signature_id": "string",
28 "attachments": [
29 {
30 "storage_key": "string",
31 "filename": "string",
32 "content_type": "string",
33 "size": 1
34 }
35 ],
36 "in_reply_to": "string",
37 "references": "string"
38}),
39})
40 .then((res) => res.json())
41 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/accounts/example/messages",
5 json={"to":[{"email":"user@example.com","name":"string"}],"cc":[{"email":"user@example.com","name":"string"}],"bcc":[{"email":"user@example.com","name":"string"}],"subject":"string","body_text":"string","body_html":"string","is_draft":null,"signature_id":"string","attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"in_reply_to":"string","references":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/accounts/:account_id/signatures

Create signature

Handled by api_create_signature
Parameters
account_id string · path
required
Body · CreateSignatureapplication/json
name string · min length: 1 · max length: 100
required
body_html string · max length: 40000
required
is_default
propertyName anything
Responses
200Successful Response
POST /mail/accounts/example/signatures
1curl -X POST "http://localhost:8000/mail/accounts/example/signatures" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","body_html":"string","is_default":null}'
1fetch("http://localhost:8000/mail/accounts/example/signatures", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "body_html": "string",
7 "is_default": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/accounts/example/signatures",
5 json={"name":"string","body_html":"string","is_default":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/accounts/:account_id/images undocumented

/mail/accounts/:account_id/images

POST an inline image (multipart) for use inside a signature or a composed message. Stored in R2 and returned as a permanent public URL so it renders in recipients' mail clients (hosted images, not data-URIs or CID attachments).

Handled by api_create_mail_image
Parameters
account_id string · path
required
Responses
200Successful Response
POST /mail/accounts/example/images
1curl -X POST "http://localhost:8000/mail/accounts/example/images"
1fetch("http://localhost:8000/mail/accounts/example/images", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/mail/accounts/example/images")
4print(response.json())
200 Example Response
No Body
POST /mail/accounts/:account_id/filters

Create filter

Handled by api_create_filter
Parameters
account_id string · path
required
Body · CreateFilterapplication/json
name string · min length: 1 · max length: 200
required
conditions object
required
actions object
required
propertyName anything
Responses
200Successful Response
POST /mail/accounts/example/filters
1curl -X POST "http://localhost:8000/mail/accounts/example/filters" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","conditions":{"from_address":"string","to_address":"string","subject_contains":"string","has_attachment":null},"actions":{"move_to":"string","mark_read":null,"star":null,"archive":null}}'
1fetch("http://localhost:8000/mail/accounts/example/filters", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "conditions": {
7 "from_address": "string",
8 "to_address": "string",
9 "subject_contains": "string",
10 "has_attachment": null
11 },
12 "actions": {
13 "move_to": "string",
14 "mark_read": null,
15 "star": null,
16 "archive": null
17 }
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/accounts/example/filters",
5 json={"name":"string","conditions":{"from_address":"string","to_address":"string","subject_contains":"string","has_attachment":null},"actions":{"move_to":"string","mark_read":null,"star":null,"archive":null}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/accounts/:account_id/blocked-senders

Block a sender

Handled by api_create_blocked_sender
Parameters
account_id string · path
required
Body · CreateBlockedSenderapplication/json
blocked string · min length: 3 · max length: 254
required
propertyName anything
Responses
200Successful Response
POST /mail/accounts/example/blocked-senders
1curl -X POST "http://localhost:8000/mail/accounts/example/blocked-senders" \
2 -H "Content-Type: application/json" \
3 -d '{"blocked":"string"}'
1fetch("http://localhost:8000/mail/accounts/example/blocked-senders", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "blocked": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/accounts/example/blocked-senders",
5 json={"blocked":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/domains/:domain_id/verifications undocumented

/mail/domains/:domain_id/verifications

Check DNS for the ownership token (+ the mail records). Only marks the domain verified/usable once the ownership TXT resolves.

Handled by api_verify_domain
Parameters
domain_id string · path
required
Responses
200Successful Response
POST /mail/domains/example/verifications
1curl -X POST "http://localhost:8000/mail/domains/example/verifications"
1fetch("http://localhost:8000/mail/domains/example/verifications", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/mail/domains/example/verifications")
4print(response.json())
200 Example Response
No Body
POST /mail/drafts

Create draft

Handled by api_create_draft
Body · SaveDraftapplication/json
subject string · max length: 998
body_html string
recipients object
attachments array
group_id string · min length: 1 · max length: 64
account_id string · min length: 1 · max length: 64
in_reply_to string · max length: 998
references string · max length: 8000
quoted_html string
propertyName anything
Responses
200Successful Response
POST /mail/drafts
1curl -X POST "http://localhost:8000/mail/drafts" \
2 -H "Content-Type: application/json" \
3 -d '{"subject":"string","body_html":"string","recipients":{"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"]},"attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"group_id":"string","account_id":"string","in_reply_to":"string","references":"string","quoted_html":"string"}'
1fetch("http://localhost:8000/mail/drafts", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "subject": "string",
6 "body_html": "string",
7 "recipients": {
8 "to": [
9 "user@example.com"
10 ],
11 "cc": [
12 "user@example.com"
13 ],
14 "bcc": [
15 "user@example.com"
16 ]
17 },
18 "attachments": [
19 {
20 "storage_key": "string",
21 "filename": "string",
22 "content_type": "string",
23 "size": 1
24 }
25 ],
26 "group_id": "string",
27 "account_id": "string",
28 "in_reply_to": "string",
29 "references": "string",
30 "quoted_html": "string"
31}),
32})
33 .then((res) => res.json())
34 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/drafts",
5 json={"subject":"string","body_html":"string","recipients":{"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"]},"attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"group_id":"string","account_id":"string","in_reply_to":"string","references":"string","quoted_html":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/drafts/:draft_id/send

Send draft

Handled by api_send_draft
Parameters
draft_id string · path
required
Body · SendDraftapplication/json
subject string · max length: 998
body_html string
recipients object
propertyName anything
Responses
200Successful Response
POST /mail/drafts/example/send
1curl -X POST "http://localhost:8000/mail/drafts/example/send" \
2 -H "Content-Type: application/json" \
3 -d '{"subject":"string","body_html":"string","recipients":{"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"]}}'
1fetch("http://localhost:8000/mail/drafts/example/send", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "subject": "string",
6 "body_html": "string",
7 "recipients": {
8 "to": [
9 "user@example.com"
10 ],
11 "cc": [
12 "user@example.com"
13 ],
14 "bcc": [
15 "user@example.com"
16 ]
17 }
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/drafts/example/send",
5 json={"subject":"string","body_html":"string","recipients":{"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"]}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /mail/accounts/:account_id/signatures/:signature_id

Update signature

Handled by api_update_signature
Parameters
account_id string · path
required
signature_id string · path
required
Body · UpdateSignatureapplication/json
name string · min length: 1 · max length: 100
body_html string · max length: 40000
is_default
propertyName anything
Responses
200Successful Response
PUT /mail/accounts/example/signatures/example
1curl -X PUT "http://localhost:8000/mail/accounts/example/signatures/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","body_html":"string","is_default":null}'
1fetch("http://localhost:8000/mail/accounts/example/signatures/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "body_html": "string",
7 "is_default": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/mail/accounts/example/signatures/example",
5 json={"name":"string","body_html":"string","is_default":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /mail/drafts/:draft_id

Save draft

Handled by api_save_draft
Parameters
draft_id string · path
required
Body · SaveDraftapplication/json
subject string · max length: 998
body_html string
recipients object
attachments array
group_id string · min length: 1 · max length: 64
account_id string · min length: 1 · max length: 64
in_reply_to string · max length: 998
references string · max length: 8000
quoted_html string
propertyName anything
Responses
200Successful Response
PUT /mail/drafts/example
1curl -X PUT "http://localhost:8000/mail/drafts/example" \
2 -H "Content-Type: application/json" \
3 -d '{"subject":"string","body_html":"string","recipients":{"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"]},"attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"group_id":"string","account_id":"string","in_reply_to":"string","references":"string","quoted_html":"string"}'
1fetch("http://localhost:8000/mail/drafts/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "subject": "string",
6 "body_html": "string",
7 "recipients": {
8 "to": [
9 "user@example.com"
10 ],
11 "cc": [
12 "user@example.com"
13 ],
14 "bcc": [
15 "user@example.com"
16 ]
17 },
18 "attachments": [
19 {
20 "storage_key": "string",
21 "filename": "string",
22 "content_type": "string",
23 "size": 1
24 }
25 ],
26 "group_id": "string",
27 "account_id": "string",
28 "in_reply_to": "string",
29 "references": "string",
30 "quoted_html": "string"
31}),
32})
33 .then((res) => res.json())
34 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/mail/drafts/example",
5 json={"subject":"string","body_html":"string","recipients":{"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"]},"attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"group_id":"string","account_id":"string","in_reply_to":"string","references":"string","quoted_html":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /mail/mailboxes/:mailbox_id/outbox-keys/:key_id/secret undocumented

/mail/mailboxes/:mailbox_id/outbox-keys/:key_id/secret

Replace the secret; the old one dies now. New secret shown once.

Handled by api_rotate_outbox_key
Parameters
mailbox_id string · path
required
key_id string · path
required
Responses
200Successful Response
PUT /mail/mailboxes/example/outbox-keys/example/secret
1curl -X PUT "http://localhost:8000/mail/mailboxes/example/outbox-keys/example/secret"
1fetch("http://localhost:8000/mail/mailboxes/example/outbox-keys/example/secret", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/mail/mailboxes/example/outbox-keys/example/secret")
4print(response.json())
200 Example Response
No Body
POST /exchanges

Send mail as a hosted mailbox

Send as a hosted mailbox. authz_exchange_send already passed the slk_ (steps 1-3 of the auth order); this handler runs steps 4-6 — the outbox key must hash to a live key on an active MX mailbox in this workspace — then validates the body, applies limits and idempotency, and submits through the existing MX path (postfix :587 as the mailbox, copy in Sent).

Handled by api_create_exchange
Body · CreateExchangeapplication/json
to array
required
cc array
bcc array
subject string · max length: 998
required
html string
text string
from_name string · max length: 200
reply_to string · max length: 254 · email
attachments array
in_reply_to string · max length: 998
references string · max length: 8000
propertyName anything
Responses
200Successful Response
POST /exchanges
1curl -X POST "http://localhost:8000/exchanges" \
2 -H "Content-Type: application/json" \
3 -d '{"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"],"subject":"string","html":"string","text":"string","from_name":"string","reply_to":"user@example.com","attachments":[{"filename":"string","content_type":"string","content_base64":"string"}],"in_reply_to":"string","references":"string"}'
1fetch("http://localhost:8000/exchanges", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to": [
6 "user@example.com"
7 ],
8 "cc": [
9 "user@example.com"
10 ],
11 "bcc": [
12 "user@example.com"
13 ],
14 "subject": "string",
15 "html": "string",
16 "text": "string",
17 "from_name": "string",
18 "reply_to": "user@example.com",
19 "attachments": [
20 {
21 "filename": "string",
22 "content_type": "string",
23 "content_base64": "string"
24 }
25 ],
26 "in_reply_to": "string",
27 "references": "string"
28}),
29})
30 .then((res) => res.json())
31 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/exchanges",
5 json={"to":["user@example.com"],"cc":["user@example.com"],"bcc":["user@example.com"],"subject":"string","html":"string","text":"string","from_name":"string","reply_to":"user@example.com","attachments":[{"filename":"string","content_type":"string","content_base64":"string"}],"in_reply_to":"string","references":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/mailboxes/:mailbox_id/outbox-keys

Mint an outbox key

Mint a named key for this shared mailbox. The secret appears in this response only; the row stores its sha256. kind is always 'shared' now (personal mailboxes have no keys) and the send path re-checks it.

Handled by api_mint_outbox_key
Parameters
mailbox_id string · path
required
Body · MintOutboxKeyapplication/json
name string · min length: 1 · max length: 100
required
expires_at string · max length: 64
propertyName anything
Responses
200Successful Response
POST /mail/mailboxes/example/outbox-keys
1curl -X POST "http://localhost:8000/mail/mailboxes/example/outbox-keys" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","expires_at":"string"}'
1fetch("http://localhost:8000/mail/mailboxes/example/outbox-keys", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "expires_at": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/mailboxes/example/outbox-keys",
5 json={"name":"string","expires_at":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /mail/mailboxes/:mailbox_id/outbox-keys/:key_id

Rename or revoke an outbox key

Rename and/or revoke a key. Revocation is soft and takes effect on the key's next send; the row stays as an audit record until deleted.

Handled by api_update_outbox_key
Parameters
mailbox_id string · path
required
key_id string · path
required
Body · UpdateOutboxKeyapplication/json
name string · min length: 1 · max length: 100
status string
propertyName anything
Responses
200Successful Response
PUT /mail/mailboxes/example/outbox-keys/example
1curl -X PUT "http://localhost:8000/mail/mailboxes/example/outbox-keys/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","status":"string"}'
1fetch("http://localhost:8000/mail/mailboxes/example/outbox-keys/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "status": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/mail/mailboxes/example/outbox-keys/example",
5 json={"name":"string","status":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /mail/domains/:domain_id

Set domain catch-all

Set/clear the wildcard catch-all address for a domain.

Handled by api_update_domain
Parameters
domain_id string · path
required
Body · SetCatchAllapplication/json
catch_all_to string · max length: 254
required
propertyName anything
Responses
200Successful Response
PATCH /mail/domains/example
1curl -X PATCH "http://localhost:8000/mail/domains/example" \
2 -H "Content-Type: application/json" \
3 -d '{"catch_all_to":"string"}'
1fetch("http://localhost:8000/mail/domains/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "catch_all_to": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/mail/domains/example",
5 json={"catch_all_to":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /mail/mailboxes/:mailbox_id

Assign a mailbox to a member

Assign (or unassign, with an empty member_mrn) a provisioned mailbox to a member. Keeps the member's connected-accounts mirror in sync so it appears in their client.

Handled by api_assign_mailbox
Parameters
mailbox_id string · path
required
Body · AssignMailboxapplication/json
member_mrn string · max length: 200
required
propertyName anything
Responses
200Successful Response
PATCH /mail/mailboxes/example
1curl -X PATCH "http://localhost:8000/mail/mailboxes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"member_mrn":"string"}'
1fetch("http://localhost:8000/mail/mailboxes/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "member_mrn": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/mail/mailboxes/example",
5 json={"member_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /mail/groups/:group_id/members/:member_id

Change member tier

Change an assignee's content-permission tier. Admins only — membership and tier assignment are group configuration, not a content capability.

Handled by api_update_group_member
Parameters
group_id string · path
required
member_id string · path
required
Body · UpdateGroupMemberapplication/json
role string
required
propertyName anything
Responses
200Successful Response
PATCH /mail/groups/example/members/example
1curl -X PATCH "http://localhost:8000/mail/groups/example/members/example" \
2 -H "Content-Type: application/json" \
3 -d '{"role":"string"}'
1fetch("http://localhost:8000/mail/groups/example/members/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "role": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/mail/groups/example/members/example",
5 json={"role":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/domains

Add a mail domain

Register a domain as PENDING and return the DNS to publish. Nothing is activated and no DNS is written on the owner's behalf — they publish the records, then verify.

Handled by api_add_domain
Body · AddDomainapplication/json
domain string · min length: 3 · max length: 253
required
propertyName anything
Responses
200Successful Response
POST /mail/domains
1curl -X POST "http://localhost:8000/mail/domains" \
2 -H "Content-Type: application/json" \
3 -d '{"domain":"string"}'
1fetch("http://localhost:8000/mail/domains", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "domain": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/domains",
5 json={"domain":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/mailboxes

Provision a mailbox

Handled by api_provision_mailbox
Body · ProvisionMailboxapplication/json
local_part string · min length: 1 · max length: 64
required
member_mrn string · max length: 200
display_name string · max length: 200
quota_mb integer · min: 10 · max: 51200
propertyName anything
Responses
200Successful Response
POST /mail/mailboxes
1curl -X POST "http://localhost:8000/mail/mailboxes" \
2 -H "Content-Type: application/json" \
3 -d '{"local_part":"string","member_mrn":"string","display_name":"string","quota_mb":1}'
1fetch("http://localhost:8000/mail/mailboxes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "local_part": "string",
6 "member_mrn": "string",
7 "display_name": "string",
8 "quota_mb": 1
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/mailboxes",
5 json={"local_part":"string","member_mrn":"string","display_name":"string","quota_mb":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/mailboxes/bulk

Provision many mailboxes

Create many addresses on one verified domain at once (editable grid / CSV upload). Each row is validated and provisioned independently: a malformed local-part or an address that already exists is reported back under `skipped` (with a reason) while the rest are still created — partial success, never an all-or-nothing batch.

Handled by api_bulk_provision_mailboxes
Body · BulkProvisionMailboxesapplication/json
domain_id string · min length: 1 · max length: 64
required
mailboxes array
required
propertyName anything
Responses
200Successful Response
POST /mail/mailboxes/bulk
1curl -X POST "http://localhost:8000/mail/mailboxes/bulk" \
2 -H "Content-Type: application/json" \
3 -d '{"domain_id":"string","mailboxes":[{"local_part":"string","member_mrn":"string"}]}'
1fetch("http://localhost:8000/mail/mailboxes/bulk", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "domain_id": "string",
6 "mailboxes": [
7 {
8 "local_part": "string",
9 "member_mrn": "string"
10 }
11 ]
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/mailboxes/bulk",
5 json={"domain_id":"string","mailboxes":[{"local_part":"string","member_mrn":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/groups

Create group mailbox

Handled by api_create_group
Body · CreateGroupapplication/json
name string · min length: 1 · max length: 120
required
local_part string · min length: 1 · max length: 64
required
domain_id string · min length: 1 · max length: 64
aliases array
member_mrns array
propertyName anything
Responses
200Successful Response
POST /mail/groups
1curl -X POST "http://localhost:8000/mail/groups" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","local_part":"string","domain_id":"string","aliases":["string"],"member_mrns":["string"]}'
1fetch("http://localhost:8000/mail/groups", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "local_part": "string",
7 "domain_id": "string",
8 "aliases": [
9 "string"
10 ],
11 "member_mrns": [
12 "string"
13 ]
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/groups",
5 json={"name":"string","local_part":"string","domain_id":"string","aliases":["string"],"member_mrns":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /mail/groups/:group_id/members

Add group member

Handled by api_add_group_member
Parameters
group_id string · path
required
Body · AddGroupMemberapplication/json
member_mrn string · min length: 1 · max length: 200
required
role string
propertyName anything
Responses
200Successful Response
POST /mail/groups/example/members
1curl -X POST "http://localhost:8000/mail/groups/example/members" \
2 -H "Content-Type: application/json" \
3 -d '{"member_mrn":"string","role":"string"}'
1fetch("http://localhost:8000/mail/groups/example/members", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "member_mrn": "string",
6 "role": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/mail/groups/example/members",
5 json={"member_mrn":"string","role":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /demo-requests

Request a demo

POST /demo-requests — public lead capture for "Book a demo" (no auth).

Handled by create_demo_request
Body · DemoRequestapplication/json
name string · min length: 1 · max length: 120
required
work_email string · min length: 1 · email
required
slot string · min length: 1 · max length: 40
required
company string · max length: 200
team_size string · max length: 40
message string · max length: 1000
timezone string · max length: 64
website string · max length: 200
propertyName anything
Responses
200Successful Response
POST /demo-requests
1curl -X POST "http://localhost:8000/demo-requests" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","work_email":"user@example.com","slot":"string","company":"string","team_size":"string","message":"string","timezone":"string","website":"string"}'
1fetch("http://localhost:8000/demo-requests", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "work_email": "user@example.com",
7 "slot": "string",
8 "company": "string",
9 "team_size": "string",
10 "message": "string",
11 "timezone": "string",
12 "website": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/demo-requests",
5 json={"name":"string","work_email":"user@example.com","slot":"string","company":"string","team_size":"string","message":"string","timezone":"string","website":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /me undocumented

/me

Handled by me
Responses
200Successful Response
GET /me
1curl "http://localhost:8000/me"
1fetch("http://localhost:8000/me")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/me")
4print(response.json())
200 Example Response
No Body
GET /me/notification-preferences undocumented

/me/notification-preferences

Handled by api_get_notification_prefs
Responses
200Successful Response
GET /me/notification-preferences
1curl "http://localhost:8000/me/notification-preferences"
1fetch("http://localhost:8000/me/notification-preferences")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/me/notification-preferences")
4print(response.json())
200 Example Response
No Body
DELETE /meetings/:id undocumented

/meetings/:id

Handled by api_delete_meeting
Parameters
id string · path
required
Responses
200Successful Response
DELETE /meetings/example
1curl -X DELETE "http://localhost:8000/meetings/example"
1fetch("http://localhost:8000/meetings/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/meetings/example")
4print(response.json())
200 Example Response
No Body
DELETE /meetings/:id/attendees/:attendee_id undocumented

/meetings/:id/attendees/:attendee_id

Handled by api_remove_attendee
Parameters
id string · path
required
attendee_id string · path
required
Responses
200Successful Response
DELETE /meetings/example/attendees/example
1curl -X DELETE "http://localhost:8000/meetings/example/attendees/example"
1fetch("http://localhost:8000/meetings/example/attendees/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/meetings/example/attendees/example")
4print(response.json())
200 Example Response
No Body
GET /meetings undocumented

/meetings

Handled by api_list_meetings
Responses
200Successful Response
GET /meetings
1curl "http://localhost:8000/meetings"
1fetch("http://localhost:8000/meetings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/meetings")
4print(response.json())
200 Example Response
No Body
GET /meetings/:id/attendees undocumented

/meetings/:id/attendees

Handled by api_list_attendees
Parameters
id string · path
required
Responses
200Successful Response
GET /meetings/example/attendees
1curl "http://localhost:8000/meetings/example/attendees"
1fetch("http://localhost:8000/meetings/example/attendees")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/meetings/example/attendees")
4print(response.json())
200 Example Response
No Body
PATCH /meetings/:id

Update a meeting

Handled by api_update_meeting
Parameters
id string · path
required
Body · UpdateMeetingapplication/json
title string · min length: 1 · max length: 300
description string
start_datetime string
end_datetime string
timezone string
is_all_day
color string
type string
status string
recurrence_rule string
visibility string
propertyName anything
Responses
200Successful Response
PATCH /meetings/example
1curl -X PATCH "http://localhost:8000/meetings/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","description":"string","start_datetime":"string","end_datetime":"string","timezone":"string","is_all_day":null,"color":"string","type":"string","status":"string","recurrence_rule":"string","visibility":"string"}'
1fetch("http://localhost:8000/meetings/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "description": "string",
7 "start_datetime": "string",
8 "end_datetime": "string",
9 "timezone": "string",
10 "is_all_day": null,
11 "color": "string",
12 "type": "string",
13 "status": "string",
14 "recurrence_rule": "string",
15 "visibility": "string"
16}),
17})
18 .then((res) => res.json())
19 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/meetings/example",
5 json={"title":"string","description":"string","start_datetime":"string","end_datetime":"string","timezone":"string","is_all_day":null,"color":"string","type":"string","status":"string","recurrence_rule":"string","visibility":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /meetings

Create a meeting

Handled by api_create_meeting
Body · CreateMeetingapplication/json
title string · min length: 1 · max length: 300
required
start_datetime string · min length: 1
required
end_datetime string · min length: 1
required
description string
timezone string
is_all_day
color string
type string
status string
create_call
recurrence_rule string
visibility string
attendees array
external_invitees array
propertyName anything
Responses
200Successful Response
POST /meetings
1curl -X POST "http://localhost:8000/meetings" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","start_datetime":"string","end_datetime":"string","description":"string","timezone":"string","is_all_day":null,"color":"string","type":"string","status":"string","create_call":null,"recurrence_rule":"string","visibility":"string","attendees":["string"],"external_invitees":[{"email":"user@example.com","name":"string"}]}'
1fetch("http://localhost:8000/meetings", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "start_datetime": "string",
7 "end_datetime": "string",
8 "description": "string",
9 "timezone": "string",
10 "is_all_day": null,
11 "color": "string",
12 "type": "string",
13 "status": "string",
14 "create_call": null,
15 "recurrence_rule": "string",
16 "visibility": "string",
17 "attendees": [
18 "string"
19 ],
20 "external_invitees": [
21 {
22 "email": "user@example.com",
23 "name": "string"
24 }
25 ]
26}),
27})
28 .then((res) => res.json())
29 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/meetings",
5 json={"title":"string","start_datetime":"string","end_datetime":"string","description":"string","timezone":"string","is_all_day":null,"color":"string","type":"string","status":"string","create_call":null,"recurrence_rule":"string","visibility":"string","attendees":["string"],"external_invitees":[{"email":"user@example.com","name":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /meetings/:id/attendees undocumented

/meetings/:id/attendees

Handled by api_add_attendee
Parameters
id string · path
required
Responses
200Successful Response
POST /meetings/example/attendees
1curl -X POST "http://localhost:8000/meetings/example/attendees"
1fetch("http://localhost:8000/meetings/example/attendees", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/meetings/example/attendees")
4print(response.json())
200 Example Response
No Body
POST /meetings/:id/call undocumented

/meetings/:id/call

Handled by api_create_meeting_call
Parameters
id string · path
required
Responses
200Successful Response
POST /meetings/example/call
1curl -X POST "http://localhost:8000/meetings/example/call"
1fetch("http://localhost:8000/meetings/example/call", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/meetings/example/call")
4print(response.json())
200 Example Response
No Body
PUT /meetings/:id/rsvp

Set your RSVP for a meeting

PUT /meetings/:id/rsvp — the authenticated caller sets their own RSVP.

Handled by api_set_rsvp
Parameters
id string · path
required
Body · Rsvpapplication/json
status
required
propertyName anything
Responses
200Successful Response
PUT /meetings/example/rsvp
1curl -X PUT "http://localhost:8000/meetings/example/rsvp" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/meetings/example/rsvp", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/meetings/example/rsvp",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /members/:member_id undocumented

/members/:member_id

DELETE /accounts/organisation/members/:member_id — Remove a member.

Handled by api_remove_member
Parameters
member_id string · path
required
Responses
200Successful Response
DELETE /members/example
1curl -X DELETE "http://localhost:8000/members/example"
1fetch("http://localhost:8000/members/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/members/example")
4print(response.json())
200 Example Response
No Body
GET /members undocumented

/members

GET /members — Search workspace members by name or email.

Handled by api_search_members
Responses
200Successful Response
GET /members
1curl "http://localhost:8000/members"
1fetch("http://localhost:8000/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/members")
4print(response.json())
200 Example Response
No Body
PATCH /members/:member_id undocumented

/members/:member_id

PATCH /accounts/organisation/members/:member_id — Change platform role.

Handled by api_update_member_role
Parameters
member_id string · path
required
Responses
200Successful Response
PATCH /members/example
1curl -X PATCH "http://localhost:8000/members/example"
1fetch("http://localhost:8000/members/example", { method: "PATCH" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.patch("http://localhost:8000/members/example")
4print(response.json())
200 Example Response
No Body
POST /members

Invite member

POST /accounts/organisation/members — Invite a member.

Handled by api_invite_member
Body · InviteMemberapplication/json
email string · min length: 1 · email
required
full_name string · max length: 200
role
propertyName anything
Responses
200Successful Response
POST /members
1curl -X POST "http://localhost:8000/members" \
2 -H "Content-Type: application/json" \
3 -d '{"email":"user@example.com","full_name":"string","role":null}'
1fetch("http://localhost:8000/members", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "email": "user@example.com",
6 "full_name": "string",
7 "role": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/members",
5 json={"email":"user@example.com","full_name":"string","role":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /members/bulk

Bulk invite members

POST /members/bulk — Invite multiple members at once.

Handled by api_bulk_invite_members
Body · BulkInviteMembersapplication/json
members array
required
propertyName anything
Responses
200Successful Response
POST /members/bulk
1curl -X POST "http://localhost:8000/members/bulk" \
2 -H "Content-Type: application/json" \
3 -d '{"members":[{"first_name":"string","last_name":"string","email":"user@example.com","role":null}]}'
1fetch("http://localhost:8000/members/bulk", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "members": [
6 {
7 "first_name": "string",
8 "last_name": "string",
9 "email": "user@example.com",
10 "role": null
11 }
12 ]
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/members/bulk",
5 json={"members":[{"first_name":"string","last_name":"string","email":"user@example.com","role":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /members/:member_id/invitations undocumented

/members/:member_id/invitations

POST /members/:member_id/invitations — Re-invite a member with a fresh token.

Handled by api_reinvite_member
Parameters
member_id string · path
required
Responses
200Successful Response
POST /members/example/invitations
1curl -X POST "http://localhost:8000/members/example/invitations"
1fetch("http://localhost:8000/members/example/invitations", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/members/example/invitations")
4print(response.json())
200 Example Response
No Body
POST /members/:member_id/password-resets undocumented

/members/:member_id/password-resets

POST /members/:member_id/password-resets — Send a 'Set Your Password' email.

Handled by api_send_set_password
Parameters
member_id string · path
required
Responses
200Successful Response
POST /members/example/password-resets
1curl -X POST "http://localhost:8000/members/example/password-resets"
1fetch("http://localhost:8000/members/example/password-resets", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/members/example/password-resets")
4print(response.json())
200 Example Response
No Body
POST /members/:member_id/sessions

Force logout member

POST /members/:member_id/sessions — really sign a member out of THIS workspace. This used to push a WebSocket frame and hope the browser was listening, which a closed tab, an offline client, or anyone holding the cookie in curl simply ignored. Then it rotated the profile's security stamp, which worked but was per IDENTITY: the same person signed into another workspace under the same email got kicked out of that one too, by an admin with no authority there. Since migration 079 every session has its own row tagged with the workspace it belongs to, so this revokes exactly the rows for this workspace. The socket push stays as the courtesy, not the mechanism.

Handled by api_force_logout_member
Parameters
member_id string · path
required
Body · ForceLogoutapplication/json
action
required
propertyName anything
Responses
200Successful Response
POST /members/example/sessions
1curl -X POST "http://localhost:8000/members/example/sessions" \
2 -H "Content-Type: application/json" \
3 -d '{"action":null}'
1fetch("http://localhost:8000/members/example/sessions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "action": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/members/example/sessions",
5 json={"action":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /messages undocumented

/messages

GET /messages — support threads list page.

Handled by messages_page
Responses
200Successful Response
GET /messages
1curl "http://localhost:8000/messages"
1fetch("http://localhost:8000/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/messages")
4print(response.json())
200 Example Response
No Body
GET /messages/:thread_id undocumented

/messages/:thread_id

GET /messages/:thread_id — thread conversation page.

Handled by thread_detail
Parameters
thread_id string · path
required
Responses
200Successful Response
GET /messages/example
1curl "http://localhost:8000/messages/example"
1fetch("http://localhost:8000/messages/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/messages/example")
4print(response.json())
200 Example Response
No Body
PATCH /chats/:id/messages/:msg_id

Edit a message

PATCH /chats/:id/messages/:msg_id — edit a message.

Handled by api_edit_message
Parameters
id string · path
required
msg_id string · path
required
Body · EditMessageapplication/json
content string · min length: 1 · max length: 10000
required
propertyName anything
Responses
200Successful Response
PATCH /chats/example/messages/example
1curl -X PATCH "http://localhost:8000/chats/example/messages/example" \
2 -H "Content-Type: application/json" \
3 -d '{"content":"string"}'
1fetch("http://localhost:8000/chats/example/messages/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "content": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/chats/example/messages/example",
5 json={"content":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /calls/:id/messages

Send a chat message

Handled by api_create_message
Parameters
id string · path
required
Body · CreateMessageapplication/json
content string · min length: 1 · max length: 2000
required
propertyName anything
Responses
200Successful Response
POST /calls/example/messages
1curl -X POST "http://localhost:8000/calls/example/messages" \
2 -H "Content-Type: application/json" \
3 -d '{"content":"string"}'
1fetch("http://localhost:8000/calls/example/messages", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "content": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/calls/example/messages",
5 json={"content":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /chats/:id/messages

Send a message

POST /chats/:id/messages — send a message.

Handled by api_send_message
Parameters
id string · path
required
Body · SendMessageapplication/json
to array
required
cc array
bcc array
subject string · max length: 998
required
body_text string
body_html string
is_draft
signature_id string · min length: 1
attachments array
in_reply_to string · max length: 998
references string · max length: 8000
propertyName anything
Responses
200Successful Response
POST /chats/example/messages
1curl -X POST "http://localhost:8000/chats/example/messages" \
2 -H "Content-Type: application/json" \
3 -d '{"to":[{"email":"user@example.com","name":"string"}],"cc":[{"email":"user@example.com","name":"string"}],"bcc":[{"email":"user@example.com","name":"string"}],"subject":"string","body_text":"string","body_html":"string","is_draft":null,"signature_id":"string","attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"in_reply_to":"string","references":"string"}'
1fetch("http://localhost:8000/chats/example/messages", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to": [
6 {
7 "email": "user@example.com",
8 "name": "string"
9 }
10 ],
11 "cc": [
12 {
13 "email": "user@example.com",
14 "name": "string"
15 }
16 ],
17 "bcc": [
18 {
19 "email": "user@example.com",
20 "name": "string"
21 }
22 ],
23 "subject": "string",
24 "body_text": "string",
25 "body_html": "string",
26 "is_draft": null,
27 "signature_id": "string",
28 "attachments": [
29 {
30 "storage_key": "string",
31 "filename": "string",
32 "content_type": "string",
33 "size": 1
34 }
35 ],
36 "in_reply_to": "string",
37 "references": "string"
38}),
39})
40 .then((res) => res.json())
41 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/chats/example/messages",
5 json={"to":[{"email":"user@example.com","name":"string"}],"cc":[{"email":"user@example.com","name":"string"}],"bcc":[{"email":"user@example.com","name":"string"}],"subject":"string","body_text":"string","body_html":"string","is_draft":null,"signature_id":"string","attachments":[{"storage_key":"string","filename":"string","content_type":"string","size":1}],"in_reply_to":"string","references":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /notifications/:id undocumented

/notifications/:id

Hard-delete a single notification.

Handled by delete_notification
Parameters
id string · path
required
Responses
200Successful Response
DELETE /notifications/example
1curl -X DELETE "http://localhost:8000/notifications/example"
1fetch("http://localhost:8000/notifications/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/notifications/example")
4print(response.json())
200 Example Response
No Body
GET /notifications undocumented

/notifications

Handled by list_notifications
Responses
200Successful Response
GET /notifications
1curl "http://localhost:8000/notifications"
1fetch("http://localhost:8000/notifications")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/notifications")
4print(response.json())
200 Example Response
No Body
GET /notifications/unread-count undocumented

/notifications/unread-count

Handled by unread_count
Responses
200Successful Response
GET /notifications/unread-count
1curl "http://localhost:8000/notifications/unread-count"
1fetch("http://localhost:8000/notifications/unread-count")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/notifications/unread-count")
4print(response.json())
200 Example Response
No Body
PATCH /notifications/:id undocumented

/notifications/:id

Mark a single notification as read.

Handled by mark_read
Parameters
id string · path
required
Responses
200Successful Response
PATCH /notifications/example
1curl -X PATCH "http://localhost:8000/notifications/example"
1fetch("http://localhost:8000/notifications/example", { method: "PATCH" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.patch("http://localhost:8000/notifications/example")
4print(response.json())
200 Example Response
No Body
PATCH /notifications undocumented

/notifications

Mark all notifications as read for the authenticated member.

Handled by mark_all_read
Responses
200Successful Response
PATCH /notifications
1curl -X PATCH "http://localhost:8000/notifications"
1fetch("http://localhost:8000/notifications", { method: "PATCH" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.patch("http://localhost:8000/notifications")
4print(response.json())
200 Example Response
No Body
DELETE /o1/calls/:token/sessions undocumented

/o1/calls/:token/sessions

Guest gave up waiting or left the lobby page. Marks the participant row as 'left' and clears the waiting-guest entry for hosts.

Handled by api_guest_cancel_join
Parameters
token string · path
required
Responses
200Successful Response
DELETE /o1/calls/example/sessions
1curl -X DELETE "http://localhost:8000/o1/calls/example/sessions"
1fetch("http://localhost:8000/o1/calls/example/sessions", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/o1/calls/example/sessions")
4print(response.json())
200 Example Response
No Body
GET /o1/calendar/rsvp/:token undocumented

/o1/calendar/rsvp/:token

GET /o1/calendar/rsvp/:token — public one-click RSVP from an invite email. Anonymous (the /o1/ namespace skips the session); enforce_workspace injects a workspace-scoped ctx.db. A `?status=` records the response, then a confirmation page lets the invitee change it.

Handled by rsvp_via_token_page
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/calendar/rsvp/example
1curl "http://localhost:8000/o1/calendar/rsvp/example"
1fetch("http://localhost:8000/o1/calendar/rsvp/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/calendar/rsvp/example")
4print(response.json())
200 Example Response
No Body
GET /o1/calls/:token undocumented

/o1/calls/:token

Public guest lobby page at /o1/calls/:token. Unauthenticated — core.tenant.enforce_workspace injects ctx.db via the subdomain slug but does not require a session. Renders a standalone page (no shell) with a camera preview and display-name input. Invalid/expired tokens and ended calls both render the generic 'not_found' state.

Handled by guest_join_page
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/calls/example
1curl "http://localhost:8000/o1/calls/example"
1fetch("http://localhost:8000/o1/calls/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/calls/example")
4print(response.json())
200 Example Response
No Body
GET /o1/calls/:token/admission undocumented

/o1/calls/:token/admission

Poll endpoint. Returns one of: - {state: 'waiting'} — host hasn't decided yet - {state: 'admitted', lk_token, lk_url, lk_room_name, participant_id, call_id} - {state: 'denied'} — host declined - {state: 'not_found'} — link expired / call ended while waiting

Handled by api_guest_admission_status
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/calls/example/admission
1curl "http://localhost:8000/o1/calls/example/admission"
1fetch("http://localhost:8000/o1/calls/example/admission")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/calls/example/admission")
4print(response.json())
200 Example Response
No Body
GET /o1/calls/:token/messages undocumented

/o1/calls/:token/messages

Chat history for an in-call guest. Same call_messages space as members.

Handled by api_guest_list_messages
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/calls/example/messages
1curl "http://localhost:8000/o1/calls/example/messages"
1fetch("http://localhost:8000/o1/calls/example/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/calls/example/messages")
4print(response.json())
200 Example Response
No Body
GET /o1/contacts/widget.js undocumented

/o1/contacts/widget.js

GET /o1/contacts/widget.js — the loader the customer pastes on their site. Deliberately key-agnostic: it reads ``data-key`` off its own script tag at runtime, so one cached script serves every workspace. It injects a bubble and an iframe pointed at this origin, which is why the host page needs no CORS setup and never touches our cookies.

Handled by widget_loader
Responses
200Successful Response
GET /o1/contacts/widget.js
1curl "http://localhost:8000/o1/contacts/widget.js"
1fetch("http://localhost:8000/o1/contacts/widget.js")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/contacts/widget.js")
4print(response.json())
200 Example Response
No Body
GET /o1/contacts/widget/:key undocumented

/o1/contacts/widget/:key

GET /o1/contacts/widget/:key — the iframe panel: form, then thread. ``frame-ancestors`` is the enforcement point for allowed_origins: an unlisted site can load the script but cannot frame the panel.

Handled by widget_panel
Parameters
key string · path
required
Responses
200Successful Response
GET /o1/contacts/widget/example
1curl "http://localhost:8000/o1/contacts/widget/example"
1fetch("http://localhost:8000/o1/contacts/widget/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/contacts/widget/example")
4print(response.json())
200 Example Response
No Body
GET /o1/contacts/widget/:key/conversation/messages undocumented

/o1/contacts/widget/:key/conversation/messages

GET /o1/contacts/widget/:key/conversation/messages — thread poll. Internal notes are excluded in the query, not the template: a colleague's aside must not be one rendering bug away from the visitor.

Handled by api_widget_messages
Parameters
key string · path
required
Responses
200Successful Response
GET /o1/contacts/widget/example/conversation/messages
1curl "http://localhost:8000/o1/contacts/widget/example/conversation/messages"
1fetch("http://localhost:8000/o1/contacts/widget/example/conversation/messages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/contacts/widget/example/conversation/messages")
4print(response.json())
200 Example Response
No Body
GET /o1/crm/:token undocumented

/o1/crm/:token

Handled by room_page
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/crm/example
1curl "http://localhost:8000/o1/crm/example"
1fetch("http://localhost:8000/o1/crm/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/crm/example")
4print(response.json())
200 Example Response
No Body
GET /o1/files/s/:token undocumented

/o1/files/s/:token

GET /o1/files/s/:token — public share page (file or folder).

Handled by public_share_page
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/files/s/example
1curl "http://localhost:8000/o1/files/s/example"
1fetch("http://localhost:8000/o1/files/s/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/files/s/example")
4print(response.json())
200 Example Response
No Body
GET /o1/files/s/:token/download undocumented

/o1/files/s/:token/download

GET /o1/files/s/:token/download — count the download, redirect to R2. For folder shares ``?file_id=`` names the file, which must live inside the shared subtree. The download counter increments atomically with the max_downloads guard so the limit cannot be raced past.

Handled by public_share_download
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/files/s/example/download
1curl "http://localhost:8000/o1/files/s/example/download"
1fetch("http://localhost:8000/o1/files/s/example/download")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/files/s/example/download")
4print(response.json())
200 Example Response
No Body
GET /o1/finance/:token undocumented

/o1/finance/:token

Handled by portal_page
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/finance/example
1curl "http://localhost:8000/o1/finance/example"
1fetch("http://localhost:8000/o1/finance/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/finance/example")
4print(response.json())
200 Example Response
No Body
GET /o1/finance/:token/pdf undocumented

/o1/finance/:token/pdf

Redirect to a short-lived presigned URL for the latest stored PDF.

Handled by portal_pdf
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/finance/example/pdf
1curl "http://localhost:8000/o1/finance/example/pdf"
1fetch("http://localhost:8000/o1/finance/example/pdf")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/finance/example/pdf")
4print(response.json())
200 Example Response
No Body
GET /o1/sign/:token undocumented

/o1/sign/:token

GET /o1/sign/:token — the public signing room. Never leaks whether a document exists: unknown/expired/used tokens all render the generic not-found state. On the first open of an actionable room the recipient is marked viewed (audit + core.sign.document.viewed).

Handled by guest_signing_room
Parameters
token string · path
required
Responses
200Successful Response
GET /o1/sign/example
1curl "http://localhost:8000/o1/sign/example"
1fetch("http://localhost:8000/o1/sign/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/sign/example")
4print(response.json())
200 Example Response
No Body
GET /o1/sign/links/:link_token undocumented

/o1/sign/links/:link_token

GET /o1/sign/links/:link_token — the public self-serve start page: the visitor enters their own name and email; submitting clones the template into their own envelope and forwards them to its signing room.

Handled by self_serve_page
Parameters
link_token string · path
required
Responses
200Successful Response
GET /o1/sign/links/example
1curl "http://localhost:8000/o1/sign/links/example"
1fetch("http://localhost:8000/o1/sign/links/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/o1/sign/links/example")
4print(response.json())
200 Example Response
No Body
POST /o1/calls/:token/sessions undocumented

/o1/calls/:token/sessions

Guest posts `{display_name}` to request admission. In auto mode the response contains an LK token immediately; in lobby mode the response is `{state: 'waiting'}` and the guest polls the admission endpoint until a host admits them (or denies).

Handled by api_guest_request_join
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/calls/example/sessions
1curl -X POST "http://localhost:8000/o1/calls/example/sessions"
1fetch("http://localhost:8000/o1/calls/example/sessions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/calls/example/sessions")
4print(response.json())
200 Example Response
No Body
POST /o1/calls/:token/sessions/leave undocumented

/o1/calls/:token/sessions/leave

Guest gave up waiting or left the lobby page. Marks the participant row as 'left' and clears the waiting-guest entry for hosts.

Handled by api_guest_cancel_join
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/calls/example/sessions/leave
1curl -X POST "http://localhost:8000/o1/calls/example/sessions/leave"
1fetch("http://localhost:8000/o1/calls/example/sessions/leave", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/calls/example/sessions/leave")
4print(response.json())
200 Example Response
No Body
POST /o1/calls/:token/hand undocumented

/o1/calls/:token/hand

A view-only guest in a broadcast call asks to speak (or lowers their hand). Relayed to the room so hosts can promote them. Body: {raised: bool}.

Handled by api_guest_raise_hand
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/calls/example/hand
1curl -X POST "http://localhost:8000/o1/calls/example/hand"
1fetch("http://localhost:8000/o1/calls/example/hand", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/calls/example/hand")
4print(response.json())
200 Example Response
No Body
POST /o1/calls/:token/reactions undocumented

/o1/calls/:token/reactions

A guest sends an emoji reaction. Relayed to the whole room (members and other guests) as an ephemeral floating reaction. Body: {emoji: str}. The emoji must be one of the allowed reactions, so the broadcast never carries arbitrary content.

Handled by api_guest_send_reaction
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/calls/example/reactions
1curl -X POST "http://localhost:8000/o1/calls/example/reactions"
1fetch("http://localhost:8000/o1/calls/example/reactions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/calls/example/reactions")
4print(response.json())
200 Example Response
No Body
POST /o1/calls/:token/messages undocumented

/o1/calls/:token/messages

A guest posts into the shared call chat. Persisted to the same call_messages table as members and delivered to members (their WS) and other guests (the per-call guest sockets).

Handled by api_guest_send_message
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/calls/example/messages
1curl -X POST "http://localhost:8000/o1/calls/example/messages"
1fetch("http://localhost:8000/o1/calls/example/messages", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/calls/example/messages")
4print(response.json())
200 Example Response
No Body
POST /o1/contacts/widget/:key/attest undocumented

/o1/contacts/widget/:key/attest

POST /o1/contacts/widget/:key/attest — bind this iframe to a parent site. Called from inside the panel after the parent loader postMessages its origin, or from ``document.referrer`` when Referrer-Policy stripped the navigation Referer. Only mints the cookie when the claimed parent host is on this embed's allowlist.

Handled by api_widget_attest
Parameters
key string · path
required
Responses
200Successful Response
POST /o1/contacts/widget/example/attest
1curl -X POST "http://localhost:8000/o1/contacts/widget/example/attest"
1fetch("http://localhost:8000/o1/contacts/widget/example/attest", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/contacts/widget/example/attest")
4print(response.json())
200 Example Response
No Body
POST /o1/contacts/widget/:key/conversations undocumented

/o1/contacts/widget/:key/conversations

POST /o1/contacts/widget/:key/conversations — open a conversation. Name and message are required, email is optional: a visitor who will not identify themselves still gets answered, their thread simply stays guest.

Handled by api_widget_open
Parameters
key string · path
required
Responses
200Successful Response
POST /o1/contacts/widget/example/conversations
1curl -X POST "http://localhost:8000/o1/contacts/widget/example/conversations"
1fetch("http://localhost:8000/o1/contacts/widget/example/conversations", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/contacts/widget/example/conversations")
4print(response.json())
200 Example Response
No Body
POST /o1/contacts/widget/:key/conversation/messages undocumented

/o1/contacts/widget/:key/conversation/messages

POST /o1/contacts/widget/:key/conversation/messages — visitor reply.

Handled by api_widget_reply
Parameters
key string · path
required
Responses
200Successful Response
POST /o1/contacts/widget/example/conversation/messages
1curl -X POST "http://localhost:8000/o1/contacts/widget/example/conversation/messages"
1fetch("http://localhost:8000/o1/contacts/widget/example/conversation/messages", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/contacts/widget/example/conversation/messages")
4print(response.json())
200 Example Response
No Body
POST /o1/contacts/widget/:key/conversation/attachments undocumented

/o1/contacts/widget/:key/conversation/attachments

POST /o1/contacts/widget/:key/conversation/attachments A visitor sending a file. Doubly gated: the workspace must have ticked "allow uploads", and the caller must hold this conversation's visitor token, so nothing can be written until a real conversation exists. The allow-list, the byte cap and the per-conversation cap are all enforced server-side against the actual bytes received, never against a client-declared size or content type. The extension is derived from the sniffed type rather than the supplied filename, so "invoice.pdf.exe" cannot name its own destiny.

Handled by api_widget_attachment
Parameters
key string · path
required
Responses
200Successful Response
POST /o1/contacts/widget/example/conversation/attachments
1curl -X POST "http://localhost:8000/o1/contacts/widget/example/conversation/attachments"
1fetch("http://localhost:8000/o1/contacts/widget/example/conversation/attachments", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/contacts/widget/example/conversation/attachments")
4print(response.json())
200 Example Response
No Body
POST /o1/contacts/widget/:key/conversation/rating undocumented

/o1/contacts/widget/:key/conversation/rating

POST /o1/contacts/widget/:key/conversation/rating — post-resolution CSAT. Only a resolved thread can be rated, and only once: the rating is the receipt for a specific resolution, not a running score.

Handled by api_widget_rating
Parameters
key string · path
required
Responses
200Successful Response
POST /o1/contacts/widget/example/conversation/rating
1curl -X POST "http://localhost:8000/o1/contacts/widget/example/conversation/rating"
1fetch("http://localhost:8000/o1/contacts/widget/example/conversation/rating", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/contacts/widget/example/conversation/rating")
4print(response.json())
200 Example Response
No Body
POST /o1/crm/:token/responses undocumented

/o1/crm/:token/responses

Accept or decline the proposal. The transition runs here, server-side.

Handled by api_room_response
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/crm/example/responses
1curl -X POST "http://localhost:8000/o1/crm/example/responses"
1fetch("http://localhost:8000/o1/crm/example/responses", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/crm/example/responses")
4print(response.json())
200 Example Response
No Body
POST /o1/files/s/:token undocumented

/o1/files/s/:token

POST /o1/files/s/:token — verify the share password, set the proof cookie.

Handled by public_share_verify
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/files/s/example
1curl -X POST "http://localhost:8000/o1/files/s/example"
1fetch("http://localhost:8000/o1/files/s/example", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/files/s/example")
4print(response.json())
200 Example Response
No Body
POST /o1/finance/:token/responses undocumented

/o1/finance/:token/responses

Quote accept/decline. Runs the same transition core as the staff PATCH, attributed to the portal link.

Handled by api_portal_response
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/finance/example/responses
1curl -X POST "http://localhost:8000/o1/finance/example/responses"
1fetch("http://localhost:8000/o1/finance/example/responses", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/finance/example/responses")
4print(response.json())
200 Example Response
No Body
POST /o1/finance/:token/checkouts undocumented

/o1/finance/:token/checkouts

Start a hosted checkout with the workspace's own provider for the invoice's outstanding balance.

Handled by api_portal_checkout
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/finance/example/checkouts
1curl -X POST "http://localhost:8000/o1/finance/example/checkouts"
1fetch("http://localhost:8000/o1/finance/example/checkouts", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/finance/example/checkouts")
4print(response.json())
200 Example Response
No Body
POST /o1/finance/:token/payments undocumented

/o1/finance/:token/payments

Verify pending checkouts against the provider and record the payment. Idempotent on the provider reference: re-verifying a settled checkout (or a double redirect) returns the recorded state without booking twice.

Handled by api_portal_payments
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/finance/example/payments
1curl -X POST "http://localhost:8000/o1/finance/example/payments"
1fetch("http://localhost:8000/o1/finance/example/payments", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/finance/example/payments")
4print(response.json())
200 Example Response
No Body
POST /o1/sign/:token/session undocumented

/o1/sign/:token/session

POST /o1/sign/:token/session — unlock + bootstrap the signing room. Verifies the access code (when required), then returns the presigned source-PDF URL, the recipient's own fields, and the branding the room renders. Consolidates the spec's separate /verification + /document steps (guests have no session to remember a prior unlock across requests).

Handled by api_guest_bootstrap
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/sign/example/session
1curl -X POST "http://localhost:8000/o1/sign/example/session"
1fetch("http://localhost:8000/o1/sign/example/session", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/sign/example/session")
4print(response.json())
200 Example Response
No Body
POST /o1/sign/:token/signature undocumented

/o1/sign/:token/signature

POST /o1/sign/:token/signature — capture consent + field values + drawn marks. Signature/initials marks arrive as base64 (guests can't use the session-based presign) and are uploaded server-side to Sign's private R2 prefix. Idempotent: a re-submit after signing returns the signed state rather than double-writing.

Handled by api_submit_signature
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/sign/example/signature
1curl -X POST "http://localhost:8000/o1/sign/example/signature"
1fetch("http://localhost:8000/o1/sign/example/signature", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/sign/example/signature")
4print(response.json())
200 Example Response
No Body
POST /o1/sign/:token/declination undocumented

/o1/sign/:token/declination

POST /o1/sign/:token/declination — a signer declines, stopping the envelope.

Handled by api_decline
Parameters
token string · path
required
Responses
200Successful Response
POST /o1/sign/example/declination
1curl -X POST "http://localhost:8000/o1/sign/example/declination"
1fetch("http://localhost:8000/o1/sign/example/declination", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/sign/example/declination")
4print(response.json())
200 Example Response
No Body
POST /o1/sign/links/:link_token/envelopes undocumented

/o1/sign/links/:link_token/envelopes

POST /o1/sign/links/:link_token/envelopes {name, email} — public: clone the template into a fresh envelope for this visitor and hand back their signing URL.

Handled by api_self_serve_submit
Parameters
link_token string · path
required
Responses
200Successful Response
POST /o1/sign/links/example/envelopes
1curl -X POST "http://localhost:8000/o1/sign/links/example/envelopes"
1fetch("http://localhost:8000/o1/sign/links/example/envelopes", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/o1/sign/links/example/envelopes")
4print(response.json())
200 Example Response
No Body
GET /onboarding/handle-check undocumented

/onboarding/handle-check

GET /onboarding/handle-check?handle=xxx — Check if a workspace handle is available.

Handled by check_handle
Responses
200Successful Response
GET /onboarding/handle-check
1curl "http://localhost:8000/onboarding/handle-check"
1fetch("http://localhost:8000/onboarding/handle-check")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/onboarding/handle-check")
4print(response.json())
200 Example Response
No Body
POST /onboarding/payments

Capture onboarding payment

POST /accounts/onboarding/payment — Add card via Flutterwave v4.

Handled by capture_payment
Body · CapturePaymentapplication/json
card_number string · min length: 13 · max length: 19
required
expiry_month string · min length: 1 · max length: 2
required
expiry_year string · min length: 2 · max length: 4
required
cvv string · min length: 3 · max length: 4
required
propertyName anything
Responses
200Successful Response
POST /onboarding/payments
1curl -X POST "http://localhost:8000/onboarding/payments" \
2 -H "Content-Type: application/json" \
3 -d '{"card_number":"string","expiry_month":"string","expiry_year":"string","cvv":"string"}'
1fetch("http://localhost:8000/onboarding/payments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "card_number": "string",
6 "expiry_month": "string",
7 "expiry_year": "string",
8 "cvv": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/onboarding/payments",
5 json={"card_number":"string","expiry_month":"string","expiry_year":"string","cvv":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /onboarding/steps undocumented

/onboarding/steps

POST /accounts/onboarding/skip-payment — Skip payment step.

Handled by skip_payment
Responses
200Successful Response
POST /onboarding/steps
1curl -X POST "http://localhost:8000/onboarding/steps"
1fetch("http://localhost:8000/onboarding/steps", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/onboarding/steps")
4print(response.json())
200 Example Response
No Body
POST /onboarding/invitations

Send onboarding invites

POST /accounts/onboarding/invites — Invite collaborators.

Handled by send_invites
Body · SendInvitesapplication/json
emails array
required
propertyName anything
Responses
200Successful Response
POST /onboarding/invitations
1curl -X POST "http://localhost:8000/onboarding/invitations" \
2 -H "Content-Type: application/json" \
3 -d '{"emails":["string"]}'
1fetch("http://localhost:8000/onboarding/invitations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "emails": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/onboarding/invitations",
5 json={"emails":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /onboarding/completions undocumented

/onboarding/completions

POST /accounts/onboarding/complete — Mark workspace as onboarded.

Handled by complete_onboarding
Responses
200Successful Response
POST /onboarding/completions
1curl -X POST "http://localhost:8000/onboarding/completions"
1fetch("http://localhost:8000/onboarding/completions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/onboarding/completions")
4print(response.json())
200 Example Response
No Body
PUT /onboarding/profile

Setup onboarding profile

PUT /accounts/onboarding/profile — Update avatar and workspace theme.

Handled by setup_profile
Body · SetupProfileapplication/json
avatar_url string · max length: 2048
propertyName anything
Responses
200Successful Response
PUT /onboarding/profile
1curl -X PUT "http://localhost:8000/onboarding/profile" \
2 -H "Content-Type: application/json" \
3 -d '{"avatar_url":"string"}'
1fetch("http://localhost:8000/onboarding/profile", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "avatar_url": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/onboarding/profile",
5 json={"avatar_url":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /onboarding/handle

Set workspace handle

PUT /onboarding/handle — Set the workspace handle and display name.

Handled by set_handle
Body · SetHandleapplication/json
handle string · min length: 3 · max length: 30
required
name string · min length: 1 · max length: 200
propertyName anything
Responses
200Successful Response
PUT /onboarding/handle
1curl -X PUT "http://localhost:8000/onboarding/handle" \
2 -H "Content-Type: application/json" \
3 -d '{"handle":"string","name":"string"}'
1fetch("http://localhost:8000/onboarding/handle", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "handle": "string",
6 "name": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/onboarding/handle",
5 json={"handle":"string","name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /onboarding undocumented

/onboarding

Render the onboarding wizard. Redirect to hub if already onboarded.

Handled by onboarding_page
Responses
200Successful Response
GET /onboarding
1curl "http://localhost:8000/onboarding"
1fetch("http://localhost:8000/onboarding")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/onboarding")
4print(response.json())
200 Example Response
No Body
GET /online undocumented

/online

List workspace members who are currently online.

Handled by api_online_members
Responses
200Successful Response
GET /online
1curl "http://localhost:8000/online"
1fetch("http://localhost:8000/online")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/online")
4print(response.json())
200 Example Response
No Body
PATCH /finance/orders/:entry_id

Transition an order

Handled by api_patch_order
Parameters
entry_id string · path
required
Body · UpdateOrderStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/orders/example
1curl -X PATCH "http://localhost:8000/finance/orders/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/orders/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/orders/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/orders

Create an order

Handled by api_create_order
Body · CreateOrderapplication/json
date string · min length: 10
required
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
required
exchange_rate number
memo string · max length: 5000
tags array
sources array
adjustments array
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/orders
1curl -X POST "http://localhost:8000/finance/orders" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"sources":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/orders", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "memo": "string",
30 "tags": [
31 "string"
32 ],
33 "sources": [
34 "string"
35 ],
36 "adjustments": [
37 {
38 "label": "string",
39 "type": null,
40 "value": 1.5,
41 "amount": 1.5,
42 "account_code": "string"
43 }
44 ],
45 "idempotency_key": "string"
46}),
47})
48 .then((res) => res.json())
49 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/orders",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"sources":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/orders/:entry_id/fulfillments

Record a fulfillment

Record a fulfillment — auto-creates a draft invoice with selected lines.

Handled by api_create_fulfillment
Parameters
entry_id string · path
required
Body · CreateFulfillmentapplication/json
date string · min length: 10
required
lines array
required
memo string · max length: 2000
propertyName anything
Responses
200Successful Response
POST /finance/orders/example/fulfillments
1curl -X POST "http://localhost:8000/finance/orders/example/fulfillments" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","lines":[{"item_index":1,"quantity":1.5}],"memo":"string"}'
1fetch("http://localhost:8000/finance/orders/example/fulfillments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "lines": [
7 {
8 "item_index": 1,
9 "quantity": 1.5
10 }
11 ],
12 "memo": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/orders/example/fulfillments",
5 json={"date":"string","lines":[{"item_index":1,"quantity":1.5}],"memo":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/orders/:entry_id

Update a draft order

Handled by api_update_order
Parameters
entry_id string · path
required
Body · UpdateOrderapplication/json
date string · min length: 10
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
memo string · max length: 5000
tags array
adjustments array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/orders/example
1curl -X PUT "http://localhost:8000/finance/orders/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null}'
1fetch("http://localhost:8000/finance/orders/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "memo": "string",
30 "tags": [
31 "string"
32 ],
33 "adjustments": [
34 {
35 "label": "string",
36 "type": null,
37 "value": 1.5,
38 "amount": 1.5,
39 "account_code": "string"
40 }
41 ],
42 "dimensions": null
43}),
44})
45 .then((res) => res.json())
46 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/orders/example",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /organisations/:org_id

Update organisation

PUT /accounts/organisation — Update org details.

Handled by api_update_org
Parameters
org_id string · path
required
Body · UpdateOrgapplication/json
name string · min length: 1 · max length: 200
email_domain string
industry string
size string
timezone string · max length: 64
propertyName anything
Responses
200Successful Response
PUT /organisations/example
1curl -X PUT "http://localhost:8000/organisations/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","email_domain":"string","industry":"string","size":"string","timezone":"string"}'
1fetch("http://localhost:8000/organisations/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "email_domain": "string",
7 "industry": "string",
8 "size": "string",
9 "timezone": "string"
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/organisations/example",
5 json={"name":"string","email_domain":"string","industry":"string","size":"string","timezone":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /ptos

Request time off

Handled by api_create_pto
Body · CreatePtoapplication/json
policy_id string · min length: 1
required
start_date string · min length: 1
required
end_date string · min length: 1
required
half_day
reason string · max length: 1000
propertyName anything
Responses
200Successful Response
POST /ptos
1curl -X POST "http://localhost:8000/ptos" \
2 -H "Content-Type: application/json" \
3 -d '{"policy_id":"string","start_date":"string","end_date":"string","half_day":null,"reason":"string"}'
1fetch("http://localhost:8000/ptos", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "policy_id": "string",
6 "start_date": "string",
7 "end_date": "string",
8 "half_day": null,
9 "reason": "string"
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/ptos",
5 json={"policy_id":"string","start_date":"string","end_date":"string","half_day":null,"reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /ptos/:id

Update a pending PTO

Handled by api_update_pto
Parameters
id string · path
required
Body · UpdatePtoapplication/json
start_date string · min length: 1
end_date string · min length: 1
half_day
reason string · max length: 1000
propertyName anything
Responses
200Successful Response
PUT /ptos/example
1curl -X PUT "http://localhost:8000/ptos/example" \
2 -H "Content-Type: application/json" \
3 -d '{"start_date":"string","end_date":"string","half_day":null,"reason":"string"}'
1fetch("http://localhost:8000/ptos/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "start_date": "string",
6 "end_date": "string",
7 "half_day": null,
8 "reason": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/ptos/example",
5 json={"start_date":"string","end_date":"string","half_day":null,"reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /ptos/:id/decision

Approve or deny a PTO

Approve or deny a PTO (manager/admin).

Handled by api_decide_pto
Parameters
id string · path
required
Body · DecidePtoapplication/json
decision
required
note string · max length: 1000
propertyName anything
Responses
200Successful Response
PUT /ptos/example/decision
1curl -X PUT "http://localhost:8000/ptos/example/decision" \
2 -H "Content-Type: application/json" \
3 -d '{"decision":null,"note":"string"}'
1fetch("http://localhost:8000/ptos/example/decision", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "decision": null,
6 "note": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/ptos/example/decision",
5 json={"decision":null,"note":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /papers/trash undocumented

/papers/trash

DELETE /papers/trash — destroy every trashed document the caller manages. Scoped by the same query as the listing, so this can only ever destroy what the caller was already being shown. It never touches a colleague's trash.

Handled by api_empty_trash
Responses
200Successful Response
DELETE /papers/trash
1curl -X DELETE "http://localhost:8000/papers/trash"
1fetch("http://localhost:8000/papers/trash", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/papers/trash")
4print(response.json())
200 Example Response
No Body
DELETE /papers/trash/:document_id undocumented

/papers/trash/:document_id

DELETE /papers/trash/:document_id — destroy a trashed document for good. The purge gate has already confirmed the document is in the trash and that the caller manages it (CLAUDE.md rule 18). Versions, comments and collaborator rows go with it through ON DELETE CASCADE; the grants are not foreign keys, so they are revoked explicitly.

Handled by api_purge_document
Parameters
document_id string · path
required
Responses
200Successful Response
DELETE /papers/trash/example
1curl -X DELETE "http://localhost:8000/papers/trash/example"
1fetch("http://localhost:8000/papers/trash/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/papers/trash/example")
4print(response.json())
200 Example Response
No Body
DELETE /papers/:document_id undocumented

/papers/:document_id

DELETE /papers/:document_id — move a document to the trash. The delete gate has already loaded the document onto ctx.authz.document (CLAUDE.md rule 18). Grants are deliberately LEFT INTACT here. This used to call revoke_all, on the reasoning that the document was gone, which quietly made the trash unimplementable: a restored document came back with no grants at all, not even its owner's, so nobody could open, edit or delete it ever again. Grants are dropped at permanent deletion instead, in api_purge_document.

Handled by api_delete_document
Parameters
document_id string · path
required
Responses
200Successful Response
DELETE /papers/example
1curl -X DELETE "http://localhost:8000/papers/example"
1fetch("http://localhost:8000/papers/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/papers/example")
4print(response.json())
200 Example Response
No Body
DELETE /papers/:document_id/comments/:comment_id undocumented

/papers/:document_id/comments/:comment_id

DELETE /papers/:document_id/comments/:comment_id — delete a comment. The delete gate (authz.can_delete_comment) has already loaded the comment onto ctx.authz.comment and confirmed the caller authored it or manages the document, so there's no re-query here (CLAUDE.md rule 18).

Handled by api_delete_comment
Parameters
document_id string · path
required
comment_id string · path
required
Responses
200Successful Response
DELETE /papers/example/comments/example
1curl -X DELETE "http://localhost:8000/papers/example/comments/example"
1fetch("http://localhost:8000/papers/example/comments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/papers/example/comments/example")
4print(response.json())
200 Example Response
No Body
GET /papers undocumented

/papers

GET /papers — list documents for the workspace.

Handled by api_list_documents
Responses
200Successful Response
GET /papers
1curl "http://localhost:8000/papers"
1fetch("http://localhost:8000/papers")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers")
4print(response.json())
200 Example Response
No Body
GET /papers/web-images undocumented

/papers/web-images

GET /papers/web-images?q=&page= — search openly-licensed web images.

Handled by api_search_web_images
Responses
200Successful Response
GET /papers/web-images
1curl "http://localhost:8000/papers/web-images"
1fetch("http://localhost:8000/papers/web-images")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/web-images")
4print(response.json())
200 Example Response
No Body
GET /papers/trash undocumented

/papers/trash

GET /papers/trash — documents in the trash that the caller can restore.

Handled by api_list_trash
Responses
200Successful Response
GET /papers/trash
1curl "http://localhost:8000/papers/trash"
1fetch("http://localhost:8000/papers/trash")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/trash")
4print(response.json())
200 Example Response
No Body
GET /papers/:document_id undocumented

/papers/:document_id

GET /papers/:document_id — get a single document with content.

Handled by api_get_document
Parameters
document_id string · path
required
Responses
200Successful Response
GET /papers/example
1curl "http://localhost:8000/papers/example"
1fetch("http://localhost:8000/papers/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/example")
4print(response.json())
200 Example Response
No Body
GET /papers/:document_id/exports/:format undocumented

/papers/:document_id/exports/:format

GET /papers/:document_id/exports/:format — download as docx, odt, or pdf. The read gate (authz.can_view_doc) has already loaded the document onto ctx.authz.document, so there's no re-query here (CLAUDE.md rule 18).

Handled by api_export_document
Parameters
document_id string · path
required
format string · path
required
Responses
200Successful Response
GET /papers/example/exports/example
1curl "http://localhost:8000/papers/example/exports/example"
1fetch("http://localhost:8000/papers/example/exports/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/example/exports/example")
4print(response.json())
200 Example Response
No Body
GET /papers/:document_id/versions undocumented

/papers/:document_id/versions

GET /papers/:document_id/versions — list version history.

Handled by api_list_versions
Parameters
document_id string · path
required
Responses
200Successful Response
GET /papers/example/versions
1curl "http://localhost:8000/papers/example/versions"
1fetch("http://localhost:8000/papers/example/versions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/example/versions")
4print(response.json())
200 Example Response
No Body
GET /papers/:document_id/versions/:version_id undocumented

/papers/:document_id/versions/:version_id

GET /papers/:document_id/versions/:version_id — get a single version.

Handled by api_get_version
Parameters
document_id string · path
required
version_id string · path
required
Responses
200Successful Response
GET /papers/example/versions/example
1curl "http://localhost:8000/papers/example/versions/example"
1fetch("http://localhost:8000/papers/example/versions/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/example/versions/example")
4print(response.json())
200 Example Response
No Body
GET /papers/:document_id/comments undocumented

/papers/:document_id/comments

GET /papers/:document_id/comments — list comments for a document.

Handled by api_list_comments
Parameters
document_id string · path
required
Responses
200Successful Response
GET /papers/example/comments
1curl "http://localhost:8000/papers/example/comments"
1fetch("http://localhost:8000/papers/example/comments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/example/comments")
4print(response.json())
200 Example Response
No Body
GET /papers/:document_id/presence undocumented

/papers/:document_id/presence

GET /papers/:document_id/presence — get active collaborators.

Handled by api_get_presence
Parameters
document_id string · path
required
Responses
200Successful Response
GET /papers/example/presence
1curl "http://localhost:8000/papers/example/presence"
1fetch("http://localhost:8000/papers/example/presence")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/papers/example/presence")
4print(response.json())
200 Example Response
No Body
PATCH /papers/:document_id

Update a document

PATCH /papers/:document_id — update a document, or restore it from trash. The update gate (authz.can_update_doc) has already loaded the document onto ctx.authz.document and decided what this caller may do with it, including the trashed case, so there's no re-query here (CLAUDE.md rule 18).

Handled by api_update_document
Parameters
document_id string · path
required
Body · UpdateDocumentapplication/json
title string · min length: 1 · max length: 500
icon string · max length: 100
icon_type
content string
is_starred
page_mode
visibility
page_setup object
deleted
propertyName anything
Responses
200Successful Response
PATCH /papers/example
1curl -X PATCH "http://localhost:8000/papers/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","icon":"string","icon_type":null,"content":"string","is_starred":null,"page_mode":null,"visibility":null,"page_setup":{"size":null,"orientation":null,"margins":null,"margin_x":1,"margin_y":1,"header_text":"string","footer_text":"string","show_page_numbers":null,"watermark_text":"string"},"deleted":null}'
1fetch("http://localhost:8000/papers/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "icon": "string",
7 "icon_type": null,
8 "content": "string",
9 "is_starred": null,
10 "page_mode": null,
11 "visibility": null,
12 "page_setup": {
13 "size": null,
14 "orientation": null,
15 "margins": null,
16 "margin_x": 1,
17 "margin_y": 1,
18 "header_text": "string",
19 "footer_text": "string",
20 "show_page_numbers": null,
21 "watermark_text": "string"
22 },
23 "deleted": null
24}),
25})
26 .then((res) => res.json())
27 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/papers/example",
5 json={"title":"string","icon":"string","icon_type":null,"content":"string","is_starred":null,"page_mode":null,"visibility":null,"page_setup":{"size":null,"orientation":null,"margins":null,"margin_x":1,"margin_y":1,"header_text":"string","footer_text":"string","show_page_numbers":null,"watermark_text":"string"},"deleted":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /papers/:document_id/versions/:version_id

Name or rename a version

PATCH /papers/:document_id/versions/:version_id — name or rename a version.

Handled by api_update_version
Parameters
document_id string · path
required
version_id string · path
required
Body · UpdateVersionapplication/json
name string · max length: 120
required
propertyName anything
Responses
200Successful Response
PATCH /papers/example/versions/example
1curl -X PATCH "http://localhost:8000/papers/example/versions/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string"}'
1fetch("http://localhost:8000/papers/example/versions/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/papers/example/versions/example",
5 json={"name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /papers/:document_id/comments/:comment_id

Resolve/unresolve comment

PATCH /papers/:document_id/comments/:comment_id — resolve or unresolve.

Handled by api_resolve_comment
Parameters
document_id string · path
required
comment_id string · path
required
Body · ResolveCommentapplication/json
resolved
required
propertyName anything
Responses
200Successful Response
PATCH /papers/example/comments/example
1curl -X PATCH "http://localhost:8000/papers/example/comments/example" \
2 -H "Content-Type: application/json" \
3 -d '{"resolved":null}'
1fetch("http://localhost:8000/papers/example/comments/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "resolved": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/papers/example/comments/example",
5 json={"resolved":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /papers

Create a document

POST /papers — create a new document.

Handled by api_create_document
Body · CreateDocumentapplication/json
title string · min length: 1 · max length: 500
required
icon string · max length: 100
icon_type
content string
propertyName anything
Responses
200Successful Response
POST /papers
1curl -X POST "http://localhost:8000/papers" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","icon":"string","icon_type":null,"content":"string"}'
1fetch("http://localhost:8000/papers", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "icon": "string",
7 "icon_type": null,
8 "content": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/papers",
5 json={"title":"string","icon":"string","icon_type":null,"content":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /papers/imports undocumented

/papers/imports

POST /papers/imports — create a new document from an uploaded .docx/.odt.

Handled by api_import_document
Responses
200Successful Response
POST /papers/imports
1curl -X POST "http://localhost:8000/papers/imports"
1fetch("http://localhost:8000/papers/imports", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/papers/imports")
4print(response.json())
200 Example Response
No Body
POST /papers/images undocumented

/papers/images

POST /papers/images — upload image bytes (From Computer / From Camera).

Handled by api_upload_image
Responses
200Successful Response
POST /papers/images
1curl -X POST "http://localhost:8000/papers/images"
1fetch("http://localhost:8000/papers/images", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/papers/images")
4print(response.json())
200 Example Response
No Body
POST /papers/image-imports

Re-host a remote image

POST /papers/image-imports — re-host a remote image by URL (From URL Link, a Search Web pick, or a Files App pick) into the public bucket.

Handled by api_import_image
Body · ImportImageapplication/json
url string · min length: 1 · max length: 2000
required
propertyName anything
Responses
200Successful Response
POST /papers/image-imports
1curl -X POST "http://localhost:8000/papers/image-imports" \
2 -H "Content-Type: application/json" \
3 -d '{"url":"string"}'
1fetch("http://localhost:8000/papers/image-imports", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "url": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/papers/image-imports",
5 json={"url":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /papers/:document_id/versions

Snapshot a named version

POST /papers/:document_id/versions — snapshot the current state as a named version. The edit gate (authz.can_edit_doc) has already loaded the document onto ctx.authz.document, so there's no re-query here (CLAUDE.md rule 18).

Handled by api_create_version
Parameters
document_id string · path
required
Body · CreateVersionapplication/json
name string · min length: 1 · max length: 120
required
propertyName anything
Responses
200Successful Response
POST /papers/example/versions
1curl -X POST "http://localhost:8000/papers/example/versions" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string"}'
1fetch("http://localhost:8000/papers/example/versions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/papers/example/versions",
5 json={"name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /papers/:document_id/comments

Add a comment

POST /papers/:document_id/comments — add a comment.

Handled by api_create_comment
Parameters
document_id string · path
required
Body · CreateCommentapplication/json
body string · min length: 1 · max length: 4000
required
object_id string · max length: 64
parent_id string · max length: 64
nx number
ny number
propertyName anything
Responses
200Successful Response
POST /papers/example/comments
1curl -X POST "http://localhost:8000/papers/example/comments" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string","object_id":"string","parent_id":"string","nx":1.5,"ny":1.5}'
1fetch("http://localhost:8000/papers/example/comments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string",
6 "object_id": "string",
7 "parent_id": "string",
8 "nx": 1.5,
9 "ny": 1.5
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/papers/example/comments",
5 json={"body":"string","object_id":"string","parent_id":"string","nx":1.5,"ny":1.5},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /papers/:document_id/presence undocumented

/papers/:document_id/presence

PUT /papers/:document_id/presence — update cursor position.

Handled by api_update_presence
Parameters
document_id string · path
required
Responses
200Successful Response
PUT /papers/example/presence
1curl -X PUT "http://localhost:8000/papers/example/presence"
1fetch("http://localhost:8000/papers/example/presence", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/papers/example/presence")
4print(response.json())
200 Example Response
No Body
GET /partials/workspaces undocumented

/partials/workspaces

GET /partials/workspaces — workspace list partial for dashboard tab.

Handled by workspaces_partial
Responses
200Successful Response
GET /partials/workspaces
1curl "http://localhost:8000/partials/workspaces"
1fetch("http://localhost:8000/partials/workspaces")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/workspaces")
4print(response.json())
200 Example Response
No Body
GET /partials/invoices undocumented

/partials/invoices

GET /partials/invoices — global invoice list partial.

Handled by invoices_partial
Responses
200Successful Response
GET /partials/invoices
1curl "http://localhost:8000/partials/invoices"
1fetch("http://localhost:8000/partials/invoices")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/invoices")
4print(response.json())
200 Example Response
No Body
GET /partials/threads undocumented

/partials/threads

GET /partials/threads — support threads list partial.

Handled by threads_partial
Responses
200Successful Response
GET /partials/threads
1curl "http://localhost:8000/partials/threads"
1fetch("http://localhost:8000/partials/threads")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/threads")
4print(response.json())
200 Example Response
No Body
GET /partials/audit undocumented

/partials/audit

GET /partials/audit — audit log partial.

Handled by audit_partial
Responses
200Successful Response
GET /partials/audit
1curl "http://localhost:8000/partials/audit"
1fetch("http://localhost:8000/partials/audit")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/audit")
4print(response.json())
200 Example Response
No Body
GET /partials/microns undocumented

/partials/microns

GET /partials/microns — microns list partial (MicroTable fetches the data).

Handled by microns_partial
Responses
200Successful Response
GET /partials/microns
1curl "http://localhost:8000/partials/microns"
1fetch("http://localhost:8000/partials/microns")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/microns")
4print(response.json())
200 Example Response
No Body
GET /partials/coupons undocumented

/partials/coupons

GET /partials/coupons — coupon list partial (admin).

Handled by coupons_partial
Responses
200Successful Response
GET /partials/coupons
1curl "http://localhost:8000/partials/coupons"
1fetch("http://localhost:8000/partials/coupons")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/coupons")
4print(response.json())
200 Example Response
No Body
GET /partials/demos undocumented

/partials/demos

GET /partials/demos — "Book a demo" request list partial (admin).

Handled by demos_partial
Responses
200Successful Response
GET /partials/demos
1curl "http://localhost:8000/partials/demos"
1fetch("http://localhost:8000/partials/demos")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/demos")
4print(response.json())
200 Example Response
No Body
GET /partials/preview-apps undocumented

/partials/preview-apps

GET /partials/preview-apps — preview apps + their early-adopter allowlists.

Handled by preview_apps_partial
Responses
200Successful Response
GET /partials/preview-apps
1curl "http://localhost:8000/partials/preview-apps"
1fetch("http://localhost:8000/partials/preview-apps")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/preview-apps")
4print(response.json())
200 Example Response
No Body
GET /partials/releases undocumented

/partials/releases

GET /partials/releases — version history master-detail for dashboard tab.

Handled by releases_partial
Responses
200Successful Response
GET /partials/releases
1curl "http://localhost:8000/partials/releases"
1fetch("http://localhost:8000/partials/releases")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/releases")
4print(response.json())
200 Example Response
No Body
GET /partials/settings/forms/new-api-key undocumented

/partials/settings/forms/new-api-key

Form drawer for creating an API key (shared #form-panel).

Handled by new_api_key_form
Responses
200Successful Response
GET /partials/settings/forms/new-api-key
1curl "http://localhost:8000/partials/settings/forms/new-api-key"
1fetch("http://localhost:8000/partials/settings/forms/new-api-key")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/settings/forms/new-api-key")
4print(response.json())
200 Example Response
No Body
GET /partials/settings/apps undocumented

/partials/settings/apps

Handled by apps_partial
Responses
200Successful Response
GET /partials/settings/apps
1curl "http://localhost:8000/partials/settings/apps"
1fetch("http://localhost:8000/partials/settings/apps")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/settings/apps")
4print(response.json())
200 Example Response
No Body
GET /partials/settings/account undocumented

/partials/settings/account

Profile settings — edit own name, job title, password, preferences.

Handled by settings_partial
Responses
200Successful Response
GET /partials/settings/account
1curl "http://localhost:8000/partials/settings/account"
1fetch("http://localhost:8000/partials/settings/account")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/settings/account")
4print(response.json())
200 Example Response
No Body
GET /partials/settings/account/:section undocumented

/partials/settings/account/:section

Profile settings — edit own name, job title, password, preferences.

Handled by settings_partial
Parameters
section string · path
required
Responses
200Successful Response
GET /partials/settings/account/example
1curl "http://localhost:8000/partials/settings/account/example"
1fetch("http://localhost:8000/partials/settings/account/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/settings/account/example")
4print(response.json())
200 Example Response
No Body
GET /partials/settings/store undocumented

/partials/settings/store

HTMX partial — app store catalog grid.

Handled by store_partial
Responses
200Successful Response
GET /partials/settings/store
1curl "http://localhost:8000/partials/settings/store"
1fetch("http://localhost:8000/partials/settings/store")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/settings/store")
4print(response.json())
200 Example Response
No Body
GET /partials/settings/store/:slug undocumented

/partials/settings/store/:slug

HTMX partial — single app detail view with events, deps, pricing.

Handled by store_detail_partial
Parameters
slug string · path
required
Responses
200Successful Response
GET /partials/settings/store/example
1curl "http://localhost:8000/partials/settings/store/example"
1fetch("http://localhost:8000/partials/settings/store/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/partials/settings/store/example")
4print(response.json())
200 Example Response
No Body
PATCH /calls/:id/participants/:member_mrn

Update participant role

Handled by api_update_participant
Parameters
id string · path
required
member_mrn string · path
required
Body · UpdateParticipantapplication/json
role
status
can_speak
propertyName anything
Responses
200Successful Response
PATCH /calls/example/participants/example
1curl -X PATCH "http://localhost:8000/calls/example/participants/example" \
2 -H "Content-Type: application/json" \
3 -d '{"role":null,"status":null,"can_speak":null}'
1fetch("http://localhost:8000/calls/example/participants/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "role": null,
6 "status": null,
7 "can_speak": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/calls/example/participants/example",
5 json={"role":null,"status":null,"can_speak":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /chats/:id/participants/:member_mrn

Update participant role

PATCH /chats/:id/participants/:member_mrn — change a participant's role.

Handled by api_update_participant
Parameters
id string · path
required
member_mrn string · path
required
Body · UpdateParticipantapplication/json
role
status
can_speak
propertyName anything
Responses
200Successful Response
PATCH /chats/example/participants/example
1curl -X PATCH "http://localhost:8000/chats/example/participants/example" \
2 -H "Content-Type: application/json" \
3 -d '{"role":null,"status":null,"can_speak":null}'
1fetch("http://localhost:8000/chats/example/participants/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "role": null,
6 "status": null,
7 "can_speak": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/chats/example/participants/example",
5 json={"role":null,"status":null,"can_speak":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /calls/:id/participants

Invite participants

Handled by api_invite_participants
Parameters
id string · path
required
Body · InviteParticipantsapplication/json
members array
required
propertyName anything
Responses
200Successful Response
POST /calls/example/participants
1curl -X POST "http://localhost:8000/calls/example/participants" \
2 -H "Content-Type: application/json" \
3 -d '{"members":["string"]}'
1fetch("http://localhost:8000/calls/example/participants", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "members": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/calls/example/participants",
5 json={"members":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /chats/:id/participants

Add participants

POST /chats/:id/participants — add participants to a group.

Handled by api_add_participants
Parameters
id string · path
required
Body · AddParticipantsapplication/json
members array
required
history
history_days integer · min: 1 · max: 3650
share_history
propertyName anything
Responses
200Successful Response
POST /chats/example/participants
1curl -X POST "http://localhost:8000/chats/example/participants" \
2 -H "Content-Type: application/json" \
3 -d '{"members":["string"],"history":null,"history_days":1,"share_history":null}'
1fetch("http://localhost:8000/chats/example/participants", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "members": [
6 "string"
7 ],
8 "history": null,
9 "history_days": 1,
10 "share_history": null
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/chats/example/participants",
5 json={"members":["string"],"history":null,"history_days":1,"share_history":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /payment-methods/:pm_id undocumented

/payment-methods/:pm_id

DELETE /payment-methods/:pm_id — Remove a payment method.

Handled by api_remove_payment_method
Parameters
pm_id string · path
required
Responses
200Successful Response
DELETE /payment-methods/example
1curl -X DELETE "http://localhost:8000/payment-methods/example"
1fetch("http://localhost:8000/payment-methods/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/payment-methods/example")
4print(response.json())
200 Example Response
No Body
PUT /payment-methods/:pm_id undocumented

/payment-methods/:pm_id

PUT /payment-methods/:pm_id — Set default payment method.

Handled by api_set_default_method
Parameters
pm_id string · path
required
Responses
200Successful Response
PUT /payment-methods/example
1curl -X PUT "http://localhost:8000/payment-methods/example"
1fetch("http://localhost:8000/payment-methods/example", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/payment-methods/example")
4print(response.json())
200 Example Response
No Body
PATCH /finance/payments/:payment_id

Apply allocations

Apply new allocations to an unallocated (or partially-allocated) payment.

Handled by api_patch_payment
Parameters
payment_id string · path
required
Body · ApplyAllocationsapplication/json
allocations array
required
propertyName anything
Responses
200Successful Response
PATCH /finance/payments/example
1curl -X PATCH "http://localhost:8000/finance/payments/example" \
2 -H "Content-Type: application/json" \
3 -d '{"allocations":[{"entry_id":"string","amount":1.5,"entry_amount":1.5}]}'
1fetch("http://localhost:8000/finance/payments/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "allocations": [
6 {
7 "entry_id": "string",
8 "amount": 1.5,
9 "entry_amount": 1.5
10 }
11 ]
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/payments/example",
5 json={"allocations":[{"entry_id":"string","amount":1.5,"entry_amount":1.5}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/payments

Record a payment

Handled by api_create_payment
Body · CreatePaymentapplication/json
direction
required
amount number
required
method
required
paid_at string · min length: 10
required
bank_account_id string
allocations array
allocate_entry_id string
allow_overpayment
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
reference string · max length: 200
memo string · max length: 2000
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/payments
1curl -X POST "http://localhost:8000/finance/payments" \
2 -H "Content-Type: application/json" \
3 -d '{"direction":null,"amount":1.5,"method":null,"paid_at":"string","bank_account_id":"string","allocations":[{"entry_id":"string","amount":1.5,"entry_amount":1.5}],"allocate_entry_id":"string","allow_overpayment":null,"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"reference":"string","memo":"string","idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/payments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "direction": null,
6 "amount": 1.5,
7 "method": null,
8 "paid_at": "string",
9 "bank_account_id": "string",
10 "allocations": [
11 {
12 "entry_id": "string",
13 "amount": 1.5,
14 "entry_amount": 1.5
15 }
16 ],
17 "allocate_entry_id": "string",
18 "allow_overpayment": null,
19 "contact_mrn": "string",
20 "company_mrn": "string",
21 "currency": "string",
22 "exchange_rate": 1.5,
23 "reference": "string",
24 "memo": "string",
25 "idempotency_key": "string"
26}),
27})
28 .then((res) => res.json())
29 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/payments",
5 json={"direction":null,"amount":1.5,"method":null,"paid_at":"string","bank_account_id":"string","allocations":[{"entry_id":"string","amount":1.5,"entry_amount":1.5}],"allocate_entry_id":"string","allow_overpayment":null,"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"reference":"string","memo":"string","idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/payments/:payment_id/reversals

Reverse a payment

Handled by api_reverse_payment
Parameters
payment_id string · path
required
Body · CreateReversalapplication/json
reason string · min length: 1 · max length: 500
required
propertyName anything
Responses
200Successful Response
POST /finance/payments/example/reversals
1curl -X POST "http://localhost:8000/finance/payments/example/reversals" \
2 -H "Content-Type: application/json" \
3 -d '{"reason":"string"}'
1fetch("http://localhost:8000/finance/payments/example/reversals", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "reason": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/payments/example/reversals",
5 json={"reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/fiscal-periods/:period_id

Update/close a period

Handled by api_patch_fiscal_period
Parameters
period_id string · path
required
Body · UpdateFiscalPeriodapplication/json
name string · min length: 1 · max length: 50
start string · min length: 10
end string · min length: 10
status
propertyName anything
Responses
200Successful Response
PATCH /finance/fiscal-periods/example
1curl -X PATCH "http://localhost:8000/finance/fiscal-periods/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","start":"string","end":"string","status":null}'
1fetch("http://localhost:8000/finance/fiscal-periods/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "start": "string",
7 "end": "string",
8 "status": null
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/fiscal-periods/example",
5 json={"name":"string","start":"string","end":"string","status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/fiscal-periods

Create a fiscal period

Handled by api_create_fiscal_period
Body · FiscalPeriodapplication/json
name string · min length: 1 · max length: 50
required
start string · min length: 10
required
end string · min length: 10
required
status
propertyName anything
Responses
200Successful Response
POST /finance/fiscal-periods
1curl -X POST "http://localhost:8000/finance/fiscal-periods" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","start":"string","end":"string","status":null}'
1fetch("http://localhost:8000/finance/fiscal-periods", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "start": "string",
7 "end": "string",
8 "status": null
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/fiscal-periods",
5 json={"name":"string","start":"string","end":"string","status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/fiscal-periods/:period_id/revaluations

Run period-end FX revaluation

POST /finance/fiscal-periods/:period_id/revaluations Runs one revaluation for the period at the given ``as_of``, applying the supplied closing rates to every open foreign-currency monetary position. Posts a journal entry (``type=journal``, ``status=posted``) and schedules the reversing entry for the first day of the next period.

Handled by api_create_revaluation
Parameters
period_id string · path
required
Body · CreateRevaluationapplication/json
as_of string · min length: 10
required
rates
required
propertyName anything
Responses
200Successful Response
POST /finance/fiscal-periods/example/revaluations
1curl -X POST "http://localhost:8000/finance/fiscal-periods/example/revaluations" \
2 -H "Content-Type: application/json" \
3 -d '{"as_of":"string","rates":null}'
1fetch("http://localhost:8000/finance/fiscal-periods/example/revaluations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "as_of": "string",
6 "rates": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/fiscal-periods/example/revaluations",
5 json={"as_of":"string","rates":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /folders/:folder_id/permissions

Update folder permission

Handled by api_update_folder_permission
Parameters
folder_id string · path
required
Body · UpdateFolderPermissionapplication/json
member_mrn string · min length: 1
required
role
required
propertyName anything
Responses
200Successful Response
PATCH /folders/example/permissions
1curl -X PATCH "http://localhost:8000/folders/example/permissions" \
2 -H "Content-Type: application/json" \
3 -d '{"member_mrn":"string","role":null}'
1fetch("http://localhost:8000/folders/example/permissions", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "member_mrn": "string",
6 "role": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/folders/example/permissions",
5 json={"member_mrn":"string","role":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /files/:file_id/permissions

Update file permission

Handled by api_update_file_permission
Parameters
file_id string · path
required
Body · UpdateFilePermissionapplication/json
member_mrn string · min length: 1
required
role
required
propertyName anything
Responses
200Successful Response
PATCH /files/example/permissions
1curl -X PATCH "http://localhost:8000/files/example/permissions" \
2 -H "Content-Type: application/json" \
3 -d '{"member_mrn":"string","role":null}'
1fetch("http://localhost:8000/files/example/permissions", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "member_mrn": "string",
6 "role": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/files/example/permissions",
5 json={"member_mrn":"string","role":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /folders/:folder_id/permissions

Grant folder permissions

Handled by api_grant_folder_permissions
Parameters
folder_id string · path
required
Body · GrantFolderPermissionsapplication/json
members array
required
propertyName anything
Responses
200Successful Response
POST /folders/example/permissions
1curl -X POST "http://localhost:8000/folders/example/permissions" \
2 -H "Content-Type: application/json" \
3 -d '{"members":[{"mrn":"string","role":null}]}'
1fetch("http://localhost:8000/folders/example/permissions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "members": [
6 {
7 "mrn": "string",
8 "role": null
9 }
10 ]
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/folders/example/permissions",
5 json={"members":[{"mrn":"string","role":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /files/:file_id/permissions

Grant file permissions

Handled by api_grant_file_permissions
Parameters
file_id string · path
required
Body · GrantFilePermissionsapplication/json
members array
required
propertyName anything
Responses
200Successful Response
POST /files/example/permissions
1curl -X POST "http://localhost:8000/files/example/permissions" \
2 -H "Content-Type: application/json" \
3 -d '{"members":[{"mrn":"string","role":null}]}'
1fetch("http://localhost:8000/files/example/permissions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "members": [
6 {
7 "mrn": "string",
8 "role": null
9 }
10 ]
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/files/example/permissions",
5 json={"members":[{"mrn":"string","role":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /pipelines/:pipeline_id undocumented

/pipelines/:pipeline_id

Handled by api_delete_pipeline
Parameters
pipeline_id string · path
required
Responses
200Successful Response
DELETE /pipelines/example
1curl -X DELETE "http://localhost:8000/pipelines/example"
1fetch("http://localhost:8000/pipelines/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/pipelines/example")
4print(response.json())
200 Example Response
No Body
DELETE /pipelines/:pipeline_id/stages/:stage_id undocumented

/pipelines/:pipeline_id/stages/:stage_id

Handled by api_delete_stage
Parameters
pipeline_id string · path
required
stage_id string · path
required
Responses
200Successful Response
DELETE /pipelines/example/stages/example
1curl -X DELETE "http://localhost:8000/pipelines/example/stages/example"
1fetch("http://localhost:8000/pipelines/example/stages/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/pipelines/example/stages/example")
4print(response.json())
200 Example Response
No Body
GET /pipelines undocumented

/pipelines

Handled by api_list_pipelines
Responses
200Successful Response
GET /pipelines
1curl "http://localhost:8000/pipelines"
1fetch("http://localhost:8000/pipelines")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/pipelines")
4print(response.json())
200 Example Response
No Body
GET /pipelines/:pipeline_id undocumented

/pipelines/:pipeline_id

Handled by api_get_pipeline
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /pipelines/example
1curl "http://localhost:8000/pipelines/example"
1fetch("http://localhost:8000/pipelines/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/pipelines/example")
4print(response.json())
200 Example Response
No Body
GET /pipelines/:pipeline_id/stages undocumented

/pipelines/:pipeline_id/stages

Handled by api_list_stages
Parameters
pipeline_id string · path
required
Responses
200Successful Response
GET /pipelines/example/stages
1curl "http://localhost:8000/pipelines/example/stages"
1fetch("http://localhost:8000/pipelines/example/stages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/pipelines/example/stages")
4print(response.json())
200 Example Response
No Body
POST /pipelines

Create a pipeline

Handled by api_create_pipeline
Body · CreatePipelineapplication/json
name string · min length: 1 · max length: 200
required
description string · max length: 2000
stages array
is_default
propertyName anything
Responses
200Successful Response
POST /pipelines
1curl -X POST "http://localhost:8000/pipelines" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","stages":[{"key":"string","name":"string","order":1,"probability":1,"checklist":[{"key":"string","label":"string"}],"playbook":"string","is_closed":null,"is_won":null}],"is_default":null}'
1fetch("http://localhost:8000/pipelines", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "stages": [
8 {
9 "key": "string",
10 "name": "string",
11 "order": 1,
12 "probability": 1,
13 "checklist": [
14 {
15 "key": "string",
16 "label": "string"
17 }
18 ],
19 "playbook": "string",
20 "is_closed": null,
21 "is_won": null
22 }
23 ],
24 "is_default": null
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/pipelines",
5 json={"name":"string","description":"string","stages":[{"key":"string","name":"string","order":1,"probability":1,"checklist":[{"key":"string","label":"string"}],"playbook":"string","is_closed":null,"is_won":null}],"is_default":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /pipelines/:pipeline_id/stages

Add a stage to a pipeline

Handled by api_create_stage
Parameters
pipeline_id string · path
required
Body · CreateStageapplication/json
name string · min length: 1 · max length: 100
required
key string · min length: 1 · max length: 50
position integer
probability integer · min: 0 · max: 100
is_closed
is_won
playbook string · max length: 5000
checklist_template array
propertyName anything
Responses
200Successful Response
POST /pipelines/example/stages
1curl -X POST "http://localhost:8000/pipelines/example/stages" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","key":"string","position":1,"probability":1,"is_closed":null,"is_won":null,"playbook":"string","checklist_template":[{"key":"string","label":"string"}]}'
1fetch("http://localhost:8000/pipelines/example/stages", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "key": "string",
7 "position": 1,
8 "probability": 1,
9 "is_closed": null,
10 "is_won": null,
11 "playbook": "string",
12 "checklist_template": [
13 {
14 "key": "string",
15 "label": "string"
16 }
17 ]
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/pipelines/example/stages",
5 json={"name":"string","key":"string","position":1,"probability":1,"is_closed":null,"is_won":null,"playbook":"string","checklist_template":[{"key":"string","label":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /pipelines/:pipeline_id

Update a pipeline

Handled by api_update_pipeline
Parameters
pipeline_id string · path
required
Body · UpdatePipelineapplication/json
name string · min length: 1 · max length: 200
description string · max length: 2000
is_default
propertyName anything
Responses
200Successful Response
PUT /pipelines/example
1curl -X PUT "http://localhost:8000/pipelines/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","is_default":null}'
1fetch("http://localhost:8000/pipelines/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "is_default": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/pipelines/example",
5 json={"name":"string","description":"string","is_default":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /pipelines/:pipeline_id/stages/:stage_id

Update a stage

Handled by api_update_stage
Parameters
pipeline_id string · path
required
stage_id string · path
required
Body · UpdateStageapplication/json
name string · min length: 1 · max length: 100
position integer
probability integer · min: 0 · max: 100
is_closed
is_won
playbook string · max length: 5000
checklist_template array
propertyName anything
Responses
200Successful Response
PUT /pipelines/example/stages/example
1curl -X PUT "http://localhost:8000/pipelines/example/stages/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","position":1,"probability":1,"is_closed":null,"is_won":null,"playbook":"string","checklist_template":[{"key":"string","label":"string"}]}'
1fetch("http://localhost:8000/pipelines/example/stages/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "position": 1,
7 "probability": 1,
8 "is_closed": null,
9 "is_won": null,
10 "playbook": "string",
11 "checklist_template": [
12 {
13 "key": "string",
14 "label": "string"
15 }
16 ]
17}),
18})
19 .then((res) => res.json())
20 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/pipelines/example/stages/example",
5 json={"name":"string","position":1,"probability":1,"is_closed":null,"is_won":null,"playbook":"string","checklist_template":[{"key":"string","label":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /plan undocumented

/plan

GET /plan — Current plan, selected apps, region, and billing interval.

Handled by api_get_plan
Responses
200Successful Response
GET /plan
1curl "http://localhost:8000/plan"
1fetch("http://localhost:8000/plan")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/plan")
4print(response.json())
200 Example Response
No Body
POST /finance/quotes/:entry_id/links

Share a quote with a customer

Handled by api_create_quote_link
Parameters
entry_id string · path
required
Body · CreatePortalLinkapplication/json
recipient_email string · max length: 320
propertyName anything
Responses
200Successful Response
POST /finance/quotes/example/links
1curl -X POST "http://localhost:8000/finance/quotes/example/links" \
2 -H "Content-Type: application/json" \
3 -d '{"recipient_email":"string"}'
1fetch("http://localhost:8000/finance/quotes/example/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "recipient_email": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/quotes/example/links",
5 json={"recipient_email":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/invoices/:entry_id/links

Share an invoice with a customer

Handled by api_create_invoice_link
Parameters
entry_id string · path
required
Body · CreatePortalLinkapplication/json
recipient_email string · max length: 320
propertyName anything
Responses
200Successful Response
POST /finance/invoices/example/links
1curl -X POST "http://localhost:8000/finance/invoices/example/links" \
2 -H "Content-Type: application/json" \
3 -d '{"recipient_email":"string"}'
1fetch("http://localhost:8000/finance/invoices/example/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "recipient_email": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/invoices/example/links",
5 json={"recipient_email":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/credit-notes/:entry_id/links

Share a credit note with a customer

Handled by api_create_credit_note_link
Parameters
entry_id string · path
required
Body · CreatePortalLinkapplication/json
recipient_email string · max length: 320
propertyName anything
Responses
200Successful Response
POST /finance/credit-notes/example/links
1curl -X POST "http://localhost:8000/finance/credit-notes/example/links" \
2 -H "Content-Type: application/json" \
3 -d '{"recipient_email":"string"}'
1fetch("http://localhost:8000/finance/credit-notes/example/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "recipient_email": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/credit-notes/example/links",
5 json={"recipient_email":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/payment-credentials/:provider

Store workspace payment keys

Store a workspace's own provider keys, encrypted at rest. The raw key is write-only: responses only ever carry the mask.

Handled by api_put_payment_credentials
Parameters
provider string · path
required
Body · UpdatePaymentCredentialsapplication/json
secret_key string · min length: 8 · max length: 200
required
public_key string · max length: 200
enabled
propertyName anything
Responses
200Successful Response
PUT /finance/payment-credentials/example
1curl -X PUT "http://localhost:8000/finance/payment-credentials/example" \
2 -H "Content-Type: application/json" \
3 -d '{"secret_key":"string","public_key":"string","enabled":null}'
1fetch("http://localhost:8000/finance/payment-credentials/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "secret_key": "string",
6 "public_key": "string",
7 "enabled": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/payment-credentials/example",
5 json={"secret_key":"string","public_key":"string","enabled":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /preferences undocumented

/preferences

Handled by get_preferences
Responses
200Successful Response
GET /preferences
1curl "http://localhost:8000/preferences"
1fetch("http://localhost:8000/preferences")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/preferences")
4print(response.json())
200 Example Response
No Body
PUT /preferences undocumented

/preferences

Handled by update_preferences
Responses
200Successful Response
PUT /preferences
1curl -X PUT "http://localhost:8000/preferences"
1fetch("http://localhost:8000/preferences", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/preferences")
4print(response.json())
200 Example Response
No Body
DELETE /presignations/:id undocumented

/presignations/:id

DELETE /presignations/:id — abandon a multipart upload so no orphaned parts linger (R2 bills incomplete parts until aborted).

Handled by abort_multipart
Parameters
id string · path
required
Responses
200Successful Response
DELETE /presignations/example
1curl -X DELETE "http://localhost:8000/presignations/example"
1fetch("http://localhost:8000/presignations/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/presignations/example")
4print(response.json())
200 Example Response
No Body
POST /presignations undocumented

/presignations

POST /presignations — generate a presigned R2 PUT URL. Body: {app, filename, content_type, size_bytes, context: {...}}

Handled by presign
Responses
200Successful Response
POST /presignations
1curl -X POST "http://localhost:8000/presignations"
1fetch("http://localhost:8000/presignations", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/presignations")
4print(response.json())
200 Example Response
No Body
POST /presignations/:id/confirmations undocumented

/presignations/:id/confirmations

POST /presignations/:id/confirmations — confirm upload completed. Emits ``system.{app}.upload.confirmed`` with the upload metadata + app context so the originating app can do its bookkeeping. The client-supplied fields are treated as claims, not facts: the storage key must live inside the caller's own workspace namespace, and when R2 is configured the object is HEAD-verified so the size the apps record (and quota checks trust) is what R2 actually holds, not what the client typed.

Handled by confirm
Parameters
id string · path
required
Responses
200Successful Response
POST /presignations/example/confirmations
1curl -X POST "http://localhost:8000/presignations/example/confirmations"
1fetch("http://localhost:8000/presignations/example/confirmations", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/presignations/example/confirmations")
4print(response.json())
200 Example Response
No Body
POST /presignations/:id/completions undocumented

/presignations/:id/completions

POST /presignations/:id/completions — stitch uploaded parts together. Body: {app, storage_key, r2_upload_id, parts: [{part_number, etag}]}. The client still calls the confirmation endpoint afterwards; that is where the HEAD verification and app bookkeeping happen.

Handled by complete_multipart
Parameters
id string · path
required
Responses
200Successful Response
POST /presignations/example/completions
1curl -X POST "http://localhost:8000/presignations/example/completions"
1fetch("http://localhost:8000/presignations/example/completions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/presignations/example/completions")
4print(response.json())
200 Example Response
No Body
GET /pricing undocumented

/pricing

Handled by pricing
Responses
200Successful Response
GET /pricing
1curl "http://localhost:8000/pricing"
1fetch("http://localhost:8000/pricing")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/pricing")
4print(response.json())
200 Example Response
No Body
GET /privacy undocumented

/privacy

Handled by privacy
Responses
200Successful Response
GET /privacy
1curl "http://localhost:8000/privacy"
1fetch("http://localhost:8000/privacy")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/privacy")
4print(response.json())
200 Example Response
No Body
PUT /me/locale

Set your UI language

PUT /me/locale — save the UI language this person picked. Written to profiles, not members: the preference belongs to the individual, so it follows them into every workspace they belong to and onto every device they sign in from. A workspace never overrides it. Three places are updated together, and all three matter: * profiles.locale — the durable record, read at sign-in on a new device * the session blob — what the locale middleware reads per request * the cookie — so signing out does not drop the login page back to English, and so the marketing site agrees with the app The caller reloads afterwards. Every surface is server-rendered, so there is nothing to re-translate in place.

Handled by set_my_locale
Body · SetLocaleapplication/json
locale
required
propertyName anything
Responses
200Successful Response
PUT /me/locale
1curl -X PUT "http://localhost:8000/me/locale" \
2 -H "Content-Type: application/json" \
3 -d '{"locale":null}'
1fetch("http://localhost:8000/me/locale", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "locale": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/me/locale",
5 json={"locale":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /profiles/:member_id

Update profile

Update own profile (name, job title).

Handled by update_profile
Parameters
member_id string · path
required
Body · UpdateProfileapplication/json
full_name string · min length: 1 · max length: 200
job_title string · max length: 200
propertyName anything
Responses
200Successful Response
PUT /profiles/example
1curl -X PUT "http://localhost:8000/profiles/example" \
2 -H "Content-Type: application/json" \
3 -d '{"full_name":"string","job_title":"string"}'
1fetch("http://localhost:8000/profiles/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "full_name": "string",
6 "job_title": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/profiles/example",
5 json={"full_name":"string","job_title":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /profiles/:member_id/contact

Update contact info

PUT /profiles/:member_id/contact — update phone number and address. Writes the CURRENT WORKSPACE's copy, not the shared profile. Before migration 080 these six fields lived only on profiles, so two workspaces inviting the same email shared one row: handing your mobile to one employer published it to every other workspace you belonged to. Same reason migration 035 moved name, title and avatar.

Handled by update_contact
Parameters
member_id string · path
required
Body · UpdateContactapplication/json
phone_number string · max length: 50
street string · max length: 300
city string · max length: 100
state string · max length: 100
postal_code string · max length: 20
country string · max length: 100
propertyName anything
Responses
200Successful Response
PUT /profiles/example/contact
1curl -X PUT "http://localhost:8000/profiles/example/contact" \
2 -H "Content-Type: application/json" \
3 -d '{"phone_number":"string","street":"string","city":"string","state":"string","postal_code":"string","country":"string"}'
1fetch("http://localhost:8000/profiles/example/contact", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "phone_number": "string",
6 "street": "string",
7 "city": "string",
8 "state": "string",
9 "postal_code": "string",
10 "country": "string"
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/profiles/example/contact",
5 json={"phone_number":"string","street":"string","city":"string","state":"string","postal_code":"string","country":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /passwords/:member_id

Set or change password

Set or change your own password. This is also the only way to SET one, because there is no forgot-password flow: if you cannot remember it, you sign in with a mailed link and come here. So the current password is required only when one exists. Somebody who joined by link and has never had a password proves nothing beyond the live session they are already holding, and demanding a password they do not have would strand them with no way to ever get one.

Handled by change_password
Parameters
member_id string · path
required
Body · ChangePasswordapplication/json
new_password string · min length: 8
required
current_password string · min length: 1
propertyName anything
Responses
200Successful Response
PUT /passwords/example
1curl -X PUT "http://localhost:8000/passwords/example" \
2 -H "Content-Type: application/json" \
3 -d '{"new_password":"string","current_password":"string"}'
1fetch("http://localhost:8000/passwords/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "new_password": "string",
6 "current_password": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/passwords/example",
5 json={"new_password":"string","current_password":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /workers/:worker_id/fields

Update a worker's custom field values

PATCH custom field values: {values: [{field_id, value}]}. A null/empty value clears the field. Values are validated against the definition type.

Handled by api_update_worker_fields
Parameters
worker_id string · path
required
Body · UpdateWorkerCustomFieldsapplication/json
values array
required
propertyName anything
Responses
200Successful Response
PATCH /workers/example/fields
1curl -X PATCH "http://localhost:8000/workers/example/fields" \
2 -H "Content-Type: application/json" \
3 -d '{"values":[{"field_id":"string","value":null}]}'
1fetch("http://localhost:8000/workers/example/fields", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "values": [
6 {
7 "field_id": "string",
8 "value": null
9 }
10 ]
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/workers/example/fields",
5 json={"values":[{"field_id":"string","value":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workers/fields

Create a custom profile field

Handled by api_create_field_definition
Body · CreateFieldDefinitionapplication/json
label string · min length: 1 · max length: 100
required
type
required
section string · max length: 100
options array
required
sensitive
help_text string · max length: 300
position integer · min: 0 · max: 10000
propertyName anything
Responses
200Successful Response
POST /workers/fields
1curl -X POST "http://localhost:8000/workers/fields" \
2 -H "Content-Type: application/json" \
3 -d '{"label":"string","type":null,"section":"string","options":["string"],"required":null,"sensitive":null,"help_text":"string","position":1}'
1fetch("http://localhost:8000/workers/fields", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "label": "string",
6 "type": null,
7 "section": "string",
8 "options": [
9 "string"
10 ],
11 "required": null,
12 "sensitive": null,
13 "help_text": "string",
14 "position": 1
15}),
16})
17 .then((res) => res.json())
18 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/fields",
5 json={"label":"string","type":null,"section":"string","options":["string"],"required":null,"sensitive":null,"help_text":"string","position":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /workers/fields/:field_id

Update a custom profile field

Handled by api_update_field_definition
Parameters
field_id string · path
required
Body · UpdateFieldDefinitionapplication/json
label string · min length: 1 · max length: 100
section string · max length: 100
options array
required
sensitive
help_text string · max length: 300
position integer · min: 0 · max: 10000
propertyName anything
Responses
200Successful Response
PUT /workers/fields/example
1curl -X PUT "http://localhost:8000/workers/fields/example" \
2 -H "Content-Type: application/json" \
3 -d '{"label":"string","section":"string","options":["string"],"required":null,"sensitive":null,"help_text":"string","position":1}'
1fetch("http://localhost:8000/workers/fields/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "label": "string",
6 "section": "string",
7 "options": [
8 "string"
9 ],
10 "required": null,
11 "sensitive": null,
12 "help_text": "string",
13 "position": 1
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/workers/fields/example",
5 json={"label":"string","section":"string","options":["string"],"required":null,"sensitive":null,"help_text":"string","position":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /ptos/:id undocumented

/ptos/:id

Cancel a PTO (worker) or revoke (manager).

Handled by api_delete_pto
Parameters
id string · path
required
Responses
200Successful Response
DELETE /ptos/example
1curl -X DELETE "http://localhost:8000/ptos/example"
1fetch("http://localhost:8000/ptos/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/ptos/example")
4print(response.json())
200 Example Response
No Body
GET /ptos undocumented

/ptos

Handled by api_list_ptos
Responses
200Successful Response
GET /ptos
1curl "http://localhost:8000/ptos"
1fetch("http://localhost:8000/ptos")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/ptos")
4print(response.json())
200 Example Response
No Body
GET /ptos/pending undocumented

/ptos/pending

List pending PTOs the current user can approve. A user approves their direct reports (workers whose manager is them). The projection stores ``manager_id`` as a *worker* id, so we resolve the viewer's own worker id and match against it — never against the member id. Owners and admins additionally approve workers who have no manager at all (the no-manager fallback). A user never approves their own request.

Handled by api_list_pending_ptos
Responses
200Successful Response
GET /ptos/pending
1curl "http://localhost:8000/ptos/pending"
1fetch("http://localhost:8000/ptos/pending")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/ptos/pending")
4print(response.json())
200 Example Response
No Body
GET /ptos/:id undocumented

/ptos/:id

Handled by api_get_pto
Parameters
id string · path
required
Responses
200Successful Response
GET /ptos/example
1curl "http://localhost:8000/ptos/example"
1fetch("http://localhost:8000/ptos/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/ptos/example")
4print(response.json())
200 Example Response
No Body
GET /public/* undocumented

/public/*

Handled by serve_assets
Responses
200Successful Response
GET /public/*
1curl "http://localhost:8000/public/*"
1fetch("http://localhost:8000/public/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/calls/* undocumented

/public/apps/calls/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/calls/*
1curl "http://localhost:8000/public/apps/calls/*"
1fetch("http://localhost:8000/public/apps/calls/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/calls/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/canvas/* undocumented

/public/apps/canvas/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/canvas/*
1curl "http://localhost:8000/public/apps/canvas/*"
1fetch("http://localhost:8000/public/apps/canvas/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/canvas/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/chat/* undocumented

/public/apps/chat/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/chat/*
1curl "http://localhost:8000/public/apps/chat/*"
1fetch("http://localhost:8000/public/apps/chat/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/chat/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/contacts/* undocumented

/public/apps/contacts/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/contacts/*
1curl "http://localhost:8000/public/apps/contacts/*"
1fetch("http://localhost:8000/public/apps/contacts/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/contacts/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/crm/* undocumented

/public/apps/crm/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/crm/*
1curl "http://localhost:8000/public/apps/crm/*"
1fetch("http://localhost:8000/public/apps/crm/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/crm/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/feeds/* undocumented

/public/apps/feeds/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/feeds/*
1curl "http://localhost:8000/public/apps/feeds/*"
1fetch("http://localhost:8000/public/apps/feeds/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/feeds/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/files/* undocumented

/public/apps/files/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/files/*
1curl "http://localhost:8000/public/apps/files/*"
1fetch("http://localhost:8000/public/apps/files/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/files/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/finance/* undocumented

/public/apps/finance/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/finance/*
1curl "http://localhost:8000/public/apps/finance/*"
1fetch("http://localhost:8000/public/apps/finance/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/finance/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/growth/* undocumented

/public/apps/growth/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/growth/*
1curl "http://localhost:8000/public/apps/growth/*"
1fetch("http://localhost:8000/public/apps/growth/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/growth/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/leaves/* undocumented

/public/apps/leaves/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/leaves/*
1curl "http://localhost:8000/public/apps/leaves/*"
1fetch("http://localhost:8000/public/apps/leaves/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/leaves/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/papers/* undocumented

/public/apps/papers/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/papers/*
1curl "http://localhost:8000/public/apps/papers/*"
1fetch("http://localhost:8000/public/apps/papers/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/papers/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/settings/* undocumented

/public/apps/settings/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/settings/*
1curl "http://localhost:8000/public/apps/settings/*"
1fetch("http://localhost:8000/public/apps/settings/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/settings/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/sign/* undocumented

/public/apps/sign/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/sign/*
1curl "http://localhost:8000/public/apps/sign/*"
1fetch("http://localhost:8000/public/apps/sign/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/sign/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/slides/* undocumented

/public/apps/slides/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/slides/*
1curl "http://localhost:8000/public/apps/slides/*"
1fetch("http://localhost:8000/public/apps/slides/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/slides/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/tables/* undocumented

/public/apps/tables/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/tables/*
1curl "http://localhost:8000/public/apps/tables/*"
1fetch("http://localhost:8000/public/apps/tables/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/tables/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/tasks/* undocumented

/public/apps/tasks/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/tasks/*
1curl "http://localhost:8000/public/apps/tasks/*"
1fetch("http://localhost:8000/public/apps/tasks/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/tasks/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/wands/* undocumented

/public/apps/wands/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/wands/*
1curl "http://localhost:8000/public/apps/wands/*"
1fetch("http://localhost:8000/public/apps/wands/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/wands/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/wiki/* undocumented

/public/apps/wiki/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/wiki/*
1curl "http://localhost:8000/public/apps/wiki/*"
1fetch("http://localhost:8000/public/apps/wiki/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/wiki/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/workers/* undocumented

/public/apps/workers/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/workers/*
1curl "http://localhost:8000/public/apps/workers/*"
1fetch("http://localhost:8000/public/apps/workers/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/workers/*")
4print(response.json())
200 Example Response
No Body
GET /public/* undocumented

/public/*

Handled by serve_assets
Responses
200Successful Response
GET /public/*
1curl "http://localhost:8000/public/*"
1fetch("http://localhost:8000/public/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/*")
4print(response.json())
200 Example Response
No Body
GET /public/* undocumented

/public/*

Handled by serve_assets
Responses
200Successful Response
GET /public/*
1curl "http://localhost:8000/public/*"
1fetch("http://localhost:8000/public/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/*")
4print(response.json())
200 Example Response
No Body
GET /public/* undocumented

/public/*

Handled by serve_assets
Responses
200Successful Response
GET /public/*
1curl "http://localhost:8000/public/*"
1fetch("http://localhost:8000/public/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/calls/* undocumented

/public/apps/calls/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/calls/*
1curl "http://localhost:8000/public/apps/calls/*"
1fetch("http://localhost:8000/public/apps/calls/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/calls/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/canvas/* undocumented

/public/apps/canvas/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/canvas/*
1curl "http://localhost:8000/public/apps/canvas/*"
1fetch("http://localhost:8000/public/apps/canvas/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/canvas/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/chat/* undocumented

/public/apps/chat/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/chat/*
1curl "http://localhost:8000/public/apps/chat/*"
1fetch("http://localhost:8000/public/apps/chat/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/chat/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/contacts/* undocumented

/public/apps/contacts/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/contacts/*
1curl "http://localhost:8000/public/apps/contacts/*"
1fetch("http://localhost:8000/public/apps/contacts/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/contacts/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/crm/* undocumented

/public/apps/crm/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/crm/*
1curl "http://localhost:8000/public/apps/crm/*"
1fetch("http://localhost:8000/public/apps/crm/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/crm/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/feeds/* undocumented

/public/apps/feeds/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/feeds/*
1curl "http://localhost:8000/public/apps/feeds/*"
1fetch("http://localhost:8000/public/apps/feeds/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/feeds/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/files/* undocumented

/public/apps/files/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/files/*
1curl "http://localhost:8000/public/apps/files/*"
1fetch("http://localhost:8000/public/apps/files/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/files/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/finance/* undocumented

/public/apps/finance/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/finance/*
1curl "http://localhost:8000/public/apps/finance/*"
1fetch("http://localhost:8000/public/apps/finance/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/finance/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/growth/* undocumented

/public/apps/growth/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/growth/*
1curl "http://localhost:8000/public/apps/growth/*"
1fetch("http://localhost:8000/public/apps/growth/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/growth/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/leaves/* undocumented

/public/apps/leaves/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/leaves/*
1curl "http://localhost:8000/public/apps/leaves/*"
1fetch("http://localhost:8000/public/apps/leaves/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/leaves/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/papers/* undocumented

/public/apps/papers/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/papers/*
1curl "http://localhost:8000/public/apps/papers/*"
1fetch("http://localhost:8000/public/apps/papers/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/papers/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/settings/* undocumented

/public/apps/settings/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/settings/*
1curl "http://localhost:8000/public/apps/settings/*"
1fetch("http://localhost:8000/public/apps/settings/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/settings/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/sign/* undocumented

/public/apps/sign/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/sign/*
1curl "http://localhost:8000/public/apps/sign/*"
1fetch("http://localhost:8000/public/apps/sign/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/sign/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/slides/* undocumented

/public/apps/slides/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/slides/*
1curl "http://localhost:8000/public/apps/slides/*"
1fetch("http://localhost:8000/public/apps/slides/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/slides/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/tables/* undocumented

/public/apps/tables/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/tables/*
1curl "http://localhost:8000/public/apps/tables/*"
1fetch("http://localhost:8000/public/apps/tables/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/tables/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/tasks/* undocumented

/public/apps/tasks/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/tasks/*
1curl "http://localhost:8000/public/apps/tasks/*"
1fetch("http://localhost:8000/public/apps/tasks/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/tasks/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/wands/* undocumented

/public/apps/wands/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/wands/*
1curl "http://localhost:8000/public/apps/wands/*"
1fetch("http://localhost:8000/public/apps/wands/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/wands/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/wiki/* undocumented

/public/apps/wiki/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/wiki/*
1curl "http://localhost:8000/public/apps/wiki/*"
1fetch("http://localhost:8000/public/apps/wiki/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/wiki/*")
4print(response.json())
200 Example Response
No Body
GET /public/apps/workers/* undocumented

/public/apps/workers/*

Handled by serve_assets
Responses
200Successful Response
GET /public/apps/workers/*
1curl "http://localhost:8000/public/apps/workers/*"
1fetch("http://localhost:8000/public/apps/workers/*")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/public/apps/workers/*")
4print(response.json())
200 Example Response
No Body
PATCH /finance/purchase-credit-notes/:entry_id

Issue/void purchase credit note

Handled by api_patch_purchase_credit_note
Parameters
entry_id string · path
required
Body · UpdatePurchaseCreditNoteStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/purchase-credit-notes/example
1curl -X PATCH "http://localhost:8000/finance/purchase-credit-notes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/purchase-credit-notes/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/purchase-credit-notes/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/purchase-credit-notes

Record a supplier credit note

Handled by api_create_purchase_credit_note
Body · CreatePurchaseCreditNoteapplication/json
date string · min length: 10
required
items array
source_entry_id string · min length: 1
required
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
memo string · max length: 5000
adjustments array
dimensions
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/purchase-credit-notes
1curl -X POST "http://localhost:8000/finance/purchase-credit-notes" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"source_entry_id":"string","contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/purchase-credit-notes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "source_entry_id": "string",
26 "contact_mrn": "string",
27 "company_mrn": "string",
28 "currency": "string",
29 "exchange_rate": 1.5,
30 "memo": "string",
31 "adjustments": [
32 {
33 "label": "string",
34 "type": null,
35 "value": 1.5,
36 "amount": 1.5,
37 "account_code": "string"
38 }
39 ],
40 "dimensions": null,
41 "idempotency_key": "string"
42}),
43})
44 .then((res) => res.json())
45 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/purchase-credit-notes",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"source_entry_id":"string","contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null,"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/purchase-credit-notes/:entry_id/allocations

Set supplier credit against a bill

Handled by api_create_purchase_credit_note_allocation
Parameters
entry_id string · path
required
Body · CreatePurchaseCreditNoteAllocationapplication/json
entry_id string · min length: 1
required
amount number
required
entry_amount number
propertyName anything
Responses
200Successful Response
POST /finance/purchase-credit-notes/example/allocations
1curl -X POST "http://localhost:8000/finance/purchase-credit-notes/example/allocations" \
2 -H "Content-Type: application/json" \
3 -d '{"entry_id":"string","amount":1.5,"entry_amount":1.5}'
1fetch("http://localhost:8000/finance/purchase-credit-notes/example/allocations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "entry_id": "string",
6 "amount": 1.5,
7 "entry_amount": 1.5
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/purchase-credit-notes/example/allocations",
5 json={"entry_id":"string","amount":1.5,"entry_amount":1.5},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/purchase-credit-notes/:entry_id

Update a draft purchase credit note

Handled by api_update_purchase_credit_note
Parameters
entry_id string · path
required
Body · UpdatePurchaseCreditNoteapplication/json
date string · min length: 10
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
memo string · max length: 5000
adjustments array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/purchase-credit-notes/example
1curl -X PUT "http://localhost:8000/finance/purchase-credit-notes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null}'
1fetch("http://localhost:8000/finance/purchase-credit-notes/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "memo": "string",
30 "adjustments": [
31 {
32 "label": "string",
33 "type": null,
34 "value": 1.5,
35 "amount": 1.5,
36 "account_code": "string"
37 }
38 ],
39 "dimensions": null
40}),
41})
42 .then((res) => res.json())
43 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/purchase-credit-notes/example",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/purchase-orders/:entry_id

Transition a PO

Handled by api_patch_purchase_order
Parameters
entry_id string · path
required
Body · UpdatePurchaseOrderStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/purchase-orders/example
1curl -X PATCH "http://localhost:8000/finance/purchase-orders/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/purchase-orders/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/purchase-orders/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/purchase-orders

Create a purchase order

Handled by api_create_purchase_order
Body · CreatePurchaseOrderapplication/json
date string · min length: 10
required
items array
company_mrn string
contact_mrn string
currency string · min length: 3 · max length: 3
required
exchange_rate number
memo string · max length: 5000
tags array
adjustments array
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/purchase-orders
1curl -X POST "http://localhost:8000/finance/purchase-orders" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/purchase-orders", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "company_mrn": "string",
26 "contact_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "memo": "string",
30 "tags": [
31 "string"
32 ],
33 "adjustments": [
34 {
35 "label": "string",
36 "type": null,
37 "value": 1.5,
38 "amount": 1.5,
39 "account_code": "string"
40 }
41 ],
42 "idempotency_key": "string"
43}),
44})
45 .then((res) => res.json())
46 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/purchase-orders",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/purchase-orders/:entry_id/receipts

Record a receipt

Record a receipt against a PO — auto-creates a draft bill with the selected lines.

Handled by api_create_receipt
Parameters
entry_id string · path
required
Body · CreateReceiptapplication/json
date string · min length: 10
required
lines array
required
memo string · max length: 2000
propertyName anything
Responses
200Successful Response
POST /finance/purchase-orders/example/receipts
1curl -X POST "http://localhost:8000/finance/purchase-orders/example/receipts" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","lines":[{"item_index":1,"quantity":1.5}],"memo":"string"}'
1fetch("http://localhost:8000/finance/purchase-orders/example/receipts", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "lines": [
7 {
8 "item_index": 1,
9 "quantity": 1.5
10 }
11 ],
12 "memo": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/purchase-orders/example/receipts",
5 json={"date":"string","lines":[{"item_index":1,"quantity":1.5}],"memo":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/purchase-orders/:entry_id

Update a draft PO

Handled by api_update_purchase_order
Parameters
entry_id string · path
required
Body · UpdatePurchaseOrderapplication/json
date string · min length: 10
items array
company_mrn string
contact_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
memo string · max length: 5000
tags array
adjustments array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/purchase-orders/example
1curl -X PUT "http://localhost:8000/finance/purchase-orders/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null}'
1fetch("http://localhost:8000/finance/purchase-orders/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "company_mrn": "string",
26 "contact_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "memo": "string",
30 "tags": [
31 "string"
32 ],
33 "adjustments": [
34 {
35 "label": "string",
36 "type": null,
37 "value": 1.5,
38 "amount": 1.5,
39 "account_code": "string"
40 }
41 ],
42 "dimensions": null
43}),
44})
45 .then((res) => res.json())
46 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/purchase-orders/example",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"company_mrn":"string","contact_mrn":"string","currency":"string","exchange_rate":1.5,"memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/quotes/:entry_id

Transition a quote

Handled by api_patch_quote
Parameters
entry_id string · path
required
Body · UpdateQuoteStatusapplication/json
status
required
propertyName anything
Responses
200Successful Response
PATCH /finance/quotes/example
1curl -X PATCH "http://localhost:8000/finance/quotes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null}'
1fetch("http://localhost:8000/finance/quotes/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/quotes/example",
5 json={"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/quotes

Create a quote

Handled by api_create_quote
Body · CreateQuoteapplication/json
date string · min length: 10
required
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
required
exchange_rate number
valid_until string · min length: 10
memo string · max length: 5000
tags array
adjustments array
idempotency_key string · max length: 100
propertyName anything
Responses
200Successful Response
POST /finance/quotes
1curl -X POST "http://localhost:8000/finance/quotes" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"valid_until":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"idempotency_key":"string"}'
1fetch("http://localhost:8000/finance/quotes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "valid_until": "string",
30 "memo": "string",
31 "tags": [
32 "string"
33 ],
34 "adjustments": [
35 {
36 "label": "string",
37 "type": null,
38 "value": 1.5,
39 "amount": 1.5,
40 "account_code": "string"
41 }
42 ],
43 "idempotency_key": "string"
44}),
45})
46 .then((res) => res.json())
47 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/quotes",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"valid_until":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"idempotency_key":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/quotes/:entry_id/sends

Email a quote

Handled by api_send_quote
Parameters
entry_id string · path
required
Body · SendQuoteapplication/json
to string · min length: 1 · max length: 500
required
cc string · max length: 500
subject string · max length: 300
message string · max length: 5000
propertyName anything
Responses
200Successful Response
POST /finance/quotes/example/sends
1curl -X POST "http://localhost:8000/finance/quotes/example/sends" \
2 -H "Content-Type: application/json" \
3 -d '{"to":"string","cc":"string","subject":"string","message":"string"}'
1fetch("http://localhost:8000/finance/quotes/example/sends", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to": "string",
6 "cc": "string",
7 "subject": "string",
8 "message": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/quotes/example/sends",
5 json={"to":"string","cc":"string","subject":"string","message":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/quotes/:entry_id/revisions

Revise a sent quote

Revise a sent/rejected quote: supersede the original and create a new draft revision carrying the edits. With ``resend`` (and a known recipient) the revision is emailed and marked sent in one step.

Handled by api_create_quote_revision
Parameters
entry_id string · path
required
Body · ReviseQuoteapplication/json
date string · min length: 10
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
valid_until string · min length: 10
memo string · max length: 5000
tags array
resend
to string · max length: 500
propertyName anything
Responses
200Successful Response
POST /finance/quotes/example/revisions
1curl -X POST "http://localhost:8000/finance/quotes/example/revisions" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"valid_until":"string","memo":"string","tags":["string"],"resend":null,"to":"string"}'
1fetch("http://localhost:8000/finance/quotes/example/revisions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "valid_until": "string",
30 "memo": "string",
31 "tags": [
32 "string"
33 ],
34 "resend": null,
35 "to": "string"
36}),
37})
38 .then((res) => res.json())
39 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/quotes/example/revisions",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"valid_until":"string","memo":"string","tags":["string"],"resend":null,"to":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/quotes/:entry_id

Update a draft quote

Handled by api_update_quote
Parameters
entry_id string · path
required
Body · UpdateQuoteapplication/json
date string · min length: 10
items array
contact_mrn string
company_mrn string
currency string · min length: 3 · max length: 3
exchange_rate number
valid_until string · min length: 10
memo string · max length: 5000
tags array
adjustments array
dimensions
propertyName anything
Responses
200Successful Response
PUT /finance/quotes/example
1curl -X PUT "http://localhost:8000/finance/quotes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"valid_until":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null}'
1fetch("http://localhost:8000/finance/quotes/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date": "string",
6 "items": [
7 {
8 "description": "string",
9 "quantity": 1.5,
10 "unit_price": 1.5,
11 "discount": 1.5,
12 "amount": 1.5,
13 "account_code": "string",
14 "product_mrn": "string",
15 "taxes": [
16 {
17 "name": "string",
18 "rate": 1.5,
19 "amount": 1.5,
20 "reverse_charge": null
21 }
22 ]
23 }
24 ],
25 "contact_mrn": "string",
26 "company_mrn": "string",
27 "currency": "string",
28 "exchange_rate": 1.5,
29 "valid_until": "string",
30 "memo": "string",
31 "tags": [
32 "string"
33 ],
34 "adjustments": [
35 {
36 "label": "string",
37 "type": null,
38 "value": 1.5,
39 "amount": 1.5,
40 "account_code": "string"
41 }
42 ],
43 "dimensions": null
44}),
45})
46 .then((res) => res.json())
47 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/quotes/example",
5 json={"date":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"contact_mrn":"string","company_mrn":"string","currency":"string","exchange_rate":1.5,"valid_until":"string","memo":"string","tags":["string"],"adjustments":[{"label":"string","type":null,"value":1.5,"amount":1.5,"account_code":"string"}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /chats/:id/messages/:msg_id/reactions

Add a reaction

POST /chats/:id/messages/:msg_id/reactions — add an emoji reaction.

Handled by api_add_reaction
Parameters
id string · path
required
msg_id string · path
required
Body · AddReactionapplication/json
emoji string · min length: 1 · max length: 32
required
propertyName anything
Responses
200Successful Response
POST /chats/example/messages/example/reactions
1curl -X POST "http://localhost:8000/chats/example/messages/example/reactions" \
2 -H "Content-Type: application/json" \
3 -d '{"emoji":"string"}'
1fetch("http://localhost:8000/chats/example/messages/example/reactions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "emoji": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/chats/example/messages/example/reactions",
5 json={"emoji":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /sign/envelopes/:envelope_id/recipients/:recipient_id

Edit a recipient

PATCH /sign/envelopes/:envelope_id/recipients/:recipient_id — edit a recipient (before send).

Handled by api_update_recipient
Parameters
envelope_id string · path
required
recipient_id string · path
required
Body · UpdateRecipientapplication/json
name string · min length: 1 · max length: 200
email string · email
role string · min length: 1 · max length: 100
recipient_type
signer_mrn string
signing_order integer
access_code string · min length: 4 · max length: 64
propertyName anything
Responses
200Successful Response
PATCH /sign/envelopes/example/recipients/example
1curl -X PATCH "http://localhost:8000/sign/envelopes/example/recipients/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","email":"user@example.com","role":"string","recipient_type":null,"signer_mrn":"string","signing_order":1,"access_code":"string"}'
1fetch("http://localhost:8000/sign/envelopes/example/recipients/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "email": "user@example.com",
7 "role": "string",
8 "recipient_type": null,
9 "signer_mrn": "string",
10 "signing_order": 1,
11 "access_code": "string"
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/sign/envelopes/example/recipients/example",
5 json={"name":"string","email":"user@example.com","role":"string","recipient_type":null,"signer_mrn":"string","signing_order":1,"access_code":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sign/envelopes/:envelope_id/recipients

Add a recipient

POST /sign/envelopes/:envelope_id/recipients — add a recipient (member or external guest).

Handled by api_create_recipient
Parameters
envelope_id string · path
required
Body · CreateRecipientapplication/json
name string · min length: 1 · max length: 200
required
email string · email
required
role string · min length: 1 · max length: 100
required
recipient_type
signer_mrn string
signing_order integer
access_code string · min length: 4 · max length: 64
propertyName anything
Responses
200Successful Response
POST /sign/envelopes/example/recipients
1curl -X POST "http://localhost:8000/sign/envelopes/example/recipients" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","email":"user@example.com","role":"string","recipient_type":null,"signer_mrn":"string","signing_order":1,"access_code":"string"}'
1fetch("http://localhost:8000/sign/envelopes/example/recipients", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "email": "user@example.com",
7 "role": "string",
8 "recipient_type": null,
9 "signer_mrn": "string",
10 "signing_order": 1,
11 "access_code": "string"
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sign/envelopes/example/recipients",
5 json={"name":"string","email":"user@example.com","role":"string","recipient_type":null,"signer_mrn":"string","signing_order":1,"access_code":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/bank-rules/:rule_id

Update a bank rule

Handled by handler
Parameters
rule_id string · path
required
Body · BankRuleapplication/json
name string · min length: 1 · max length: 100
required
match object
required
action object
required
propertyName anything
Responses
200Successful Response
PATCH /finance/bank-rules/example
1curl -X PATCH "http://localhost:8000/finance/bank-rules/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","match":{"description_contains":"string","direction":null,"amount_min":1.5,"amount_max":1.5},"action":{"account_code":"string","description":"string","entry_type":null}}'
1fetch("http://localhost:8000/finance/bank-rules/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "match": {
7 "description_contains": "string",
8 "direction": null,
9 "amount_min": 1.5,
10 "amount_max": 1.5
11 },
12 "action": {
13 "account_code": "string",
14 "description": "string",
15 "entry_type": null
16 }
17}),
18})
19 .then((res) => res.json())
20 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/bank-rules/example",
5 json={"name":"string","match":{"description_contains":"string","direction":null,"amount_min":1.5,"amount_max":1.5},"action":{"account_code":"string","description":"string","entry_type":null}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/bank-imports

Import a bank feed

Handled by api_create_bank_import
Body · ImportBankFeedapplication/json
bank_account_id string · min length: 1
required
rows array
required
propertyName anything
Responses
200Successful Response
POST /finance/bank-imports
1curl -X POST "http://localhost:8000/finance/bank-imports" \
2 -H "Content-Type: application/json" \
3 -d '{"bank_account_id":"string","rows":[{"date":"string","description":"string","amount":1.5,"reference":"string"}]}'
1fetch("http://localhost:8000/finance/bank-imports", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "bank_account_id": "string",
6 "rows": [
7 {
8 "date": "string",
9 "description": "string",
10 "amount": 1.5,
11 "reference": "string"
12 }
13 ]
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/bank-imports",
5 json={"bank_account_id":"string","rows":[{"date":"string","description":"string","amount":1.5,"reference":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/bank-imports/:import_id/entries

Create an entry from a bank import

Create a bill/invoice for an unmatched bank import and reconcile the import against it in one step. The category comes from the request body or from the first matching bank rule.

Handled by api_create_entry_from_import
Parameters
import_id string · path
required
Body · CreateEntryFromImportapplication/json
account_code string · max length: 20
description string · max length: 500
entry_type
propertyName anything
Responses
200Successful Response
POST /finance/bank-imports/example/entries
1curl -X POST "http://localhost:8000/finance/bank-imports/example/entries" \
2 -H "Content-Type: application/json" \
3 -d '{"account_code":"string","description":"string","entry_type":null}'
1fetch("http://localhost:8000/finance/bank-imports/example/entries", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "account_code": "string",
6 "description": "string",
7 "entry_type": null
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/bank-imports/example/entries",
5 json={"account_code":"string","description":"string","entry_type":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/bank-connections

Connect a bank account

Handled by api_create_bank_connection
Body · ConnectBankAccountapplication/json
code string · min length: 1 · max length: 200
required
propertyName anything
Responses
200Successful Response
POST /finance/bank-connections
1curl -X POST "http://localhost:8000/finance/bank-connections" \
2 -H "Content-Type: application/json" \
3 -d '{"code":"string"}'
1fetch("http://localhost:8000/finance/bank-connections", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "code": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/bank-connections",
5 json={"code":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/reconciliations

Finalise a reconciliation

Handled by api_complete_reconciliation
Body · CompleteReconciliationapplication/json
bank_account_id string · min length: 1
required
period_start string · min length: 10
required
period_end string · min length: 10
required
statement_balance number
required
propertyName anything
Responses
200Successful Response
POST /finance/reconciliations
1curl -X POST "http://localhost:8000/finance/reconciliations" \
2 -H "Content-Type: application/json" \
3 -d '{"bank_account_id":"string","period_start":"string","period_end":"string","statement_balance":1.5}'
1fetch("http://localhost:8000/finance/reconciliations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "bank_account_id": "string",
6 "period_start": "string",
7 "period_end": "string",
8 "statement_balance": 1.5
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/reconciliations",
5 json={"bank_account_id":"string","period_start":"string","period_end":"string","statement_balance":1.5},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/bank-rules

Create a bank rule

Handled by handler
Body · BankRuleapplication/json
name string · min length: 1 · max length: 100
required
match object
required
action object
required
propertyName anything
Responses
200Successful Response
POST /finance/bank-rules
1curl -X POST "http://localhost:8000/finance/bank-rules" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","match":{"description_contains":"string","direction":null,"amount_min":1.5,"amount_max":1.5},"action":{"account_code":"string","description":"string","entry_type":null}}'
1fetch("http://localhost:8000/finance/bank-rules", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "match": {
7 "description_contains": "string",
8 "direction": null,
9 "amount_min": 1.5,
10 "amount_max": 1.5
11 },
12 "action": {
13 "account_code": "string",
14 "description": "string",
15 "entry_type": null
16 }
17}),
18})
19 .then((res) => res.json())
20 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/bank-rules",
5 json={"name":"string","match":{"description_contains":"string","direction":null,"amount_min":1.5,"amount_max":1.5},"action":{"account_code":"string","description":"string","entry_type":null}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /calls/:id/recordings/:recording_id

Abort a recording

Abandon a recording: abort the R2 multipart upload and mark it failed. Host-only.

Handled by api_abort_recording
Parameters
id string · path
required
recording_id string · path
required
Body · AbortRecordingapplication/json
status
required
upload_id string · min length: 1 · max length: 512
propertyName anything
Responses
200Successful Response
PATCH /calls/example/recordings/example
1curl -X PATCH "http://localhost:8000/calls/example/recordings/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null,"upload_id":"string"}'
1fetch("http://localhost:8000/calls/example/recordings/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null,
6 "upload_id": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/calls/example/recordings/example",
5 json={"status":null,"upload_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /calls/:id/recordings

Start a recording

Handled by api_start_recording
Parameters
id string · path
required
Body · StartRecordingapplication/json
content_type string · max length: 100
propertyName anything
Responses
200Successful Response
POST /calls/example/recordings
1curl -X POST "http://localhost:8000/calls/example/recordings" \
2 -H "Content-Type: application/json" \
3 -d '{"content_type":"string"}'
1fetch("http://localhost:8000/calls/example/recordings", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "content_type": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/calls/example/recordings",
5 json={"content_type":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /calls/:id/recordings/:recording_id

Complete a recording

Finalize a recording: assemble the uploaded parts in R2 and mark it ready. Host-only.

Handled by api_complete_recording
Parameters
id string · path
required
recording_id string · path
required
Body · CompleteRecordingapplication/json
upload_id string · min length: 1 · max length: 512
required
parts array
required
size_bytes integer · min: 0
duration_seconds integer · min: 0
propertyName anything
Responses
200Successful Response
PUT /calls/example/recordings/example
1curl -X PUT "http://localhost:8000/calls/example/recordings/example" \
2 -H "Content-Type: application/json" \
3 -d '{"upload_id":"string","parts":[{"part_number":1,"etag":"string"}],"size_bytes":1,"duration_seconds":1}'
1fetch("http://localhost:8000/calls/example/recordings/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "upload_id": "string",
6 "parts": [
7 {
8 "part_number": 1,
9 "etag": "string"
10 }
11 ],
12 "size_bytes": 1,
13 "duration_seconds": 1
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/calls/example/recordings/example",
5 json={"upload_id":"string","parts":[{"part_number":1,"etag":"string"}],"size_bytes":1,"duration_seconds":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /recovery-codes undocumented

/recovery-codes

Handled by list_recovery_codes
Responses
200Successful Response
GET /recovery-codes
1curl "http://localhost:8000/recovery-codes"
1fetch("http://localhost:8000/recovery-codes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/recovery-codes")
4print(response.json())
200 Example Response
No Body
POST /recovery-codes undocumented

/recovery-codes

Handled by regenerate_recovery_codes
Responses
200Successful Response
POST /recovery-codes
1curl -X POST "http://localhost:8000/recovery-codes"
1fetch("http://localhost:8000/recovery-codes", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/recovery-codes")
4print(response.json())
200 Example Response
No Body
PATCH /finance/recurring-entries/:recurring_id

Update recurring entry

Handled by api_patch_recurring
Parameters
recurring_id string · path
required
Body · RecurringEntryDefapplication/json
name string · min length: 1 · max length: 200
required
type
required
frequency
required
next_date string · min length: 10
required
company_mrn string
contact_mrn string
items array
auto_approve
propertyName anything
Responses
200Successful Response
PATCH /finance/recurring-entries/example
1curl -X PATCH "http://localhost:8000/finance/recurring-entries/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","type":null,"frequency":null,"next_date":"string","company_mrn":"string","contact_mrn":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"auto_approve":null}'
1fetch("http://localhost:8000/finance/recurring-entries/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "type": null,
7 "frequency": null,
8 "next_date": "string",
9 "company_mrn": "string",
10 "contact_mrn": "string",
11 "items": [
12 {
13 "description": "string",
14 "quantity": 1.5,
15 "unit_price": 1.5,
16 "discount": 1.5,
17 "amount": 1.5,
18 "account_code": "string",
19 "product_mrn": "string",
20 "taxes": [
21 {
22 "name": "string",
23 "rate": 1.5,
24 "amount": 1.5,
25 "reverse_charge": null
26 }
27 ]
28 }
29 ],
30 "auto_approve": null
31}),
32})
33 .then((res) => res.json())
34 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/recurring-entries/example",
5 json={"name":"string","type":null,"frequency":null,"next_date":"string","company_mrn":"string","contact_mrn":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"auto_approve":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/recurring-entries

Create recurring entry

Handled by api_create_recurring
Body · RecurringEntryDefapplication/json
name string · min length: 1 · max length: 200
required
type
required
frequency
required
next_date string · min length: 10
required
company_mrn string
contact_mrn string
items array
auto_approve
propertyName anything
Responses
200Successful Response
POST /finance/recurring-entries
1curl -X POST "http://localhost:8000/finance/recurring-entries" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","type":null,"frequency":null,"next_date":"string","company_mrn":"string","contact_mrn":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"auto_approve":null}'
1fetch("http://localhost:8000/finance/recurring-entries", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "type": null,
7 "frequency": null,
8 "next_date": "string",
9 "company_mrn": "string",
10 "contact_mrn": "string",
11 "items": [
12 {
13 "description": "string",
14 "quantity": 1.5,
15 "unit_price": 1.5,
16 "discount": 1.5,
17 "amount": 1.5,
18 "account_code": "string",
19 "product_mrn": "string",
20 "taxes": [
21 {
22 "name": "string",
23 "rate": 1.5,
24 "amount": 1.5,
25 "reverse_charge": null
26 }
27 ]
28 }
29 ],
30 "auto_approve": null
31}),
32})
33 .then((res) => res.json())
34 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/recurring-entries",
5 json={"name":"string","type":null,"frequency":null,"next_date":"string","company_mrn":"string","contact_mrn":"string","items":[{"description":"string","quantity":1.5,"unit_price":1.5,"discount":1.5,"amount":1.5,"account_code":"string","product_mrn":"string","taxes":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}],"auto_approve":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /reports/burndown undocumented

/reports/burndown

Return burndown + burnup chart data for a schedule (or board-wide).

Handled by api_report_burndown
Responses
200Successful Response
GET /reports/burndown
1curl "http://localhost:8000/reports/burndown"
1fetch("http://localhost:8000/reports/burndown")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/reports/burndown")
4print(response.json())
200 Example Response
No Body
PATCH /finance/requests/:request_id

Approve or decline a request

PATCH /finance/requests/:id — approve (books the artifact) or decline.

Handled by api_decide_request
Parameters
request_id string · path
required
Body · DecideFinanceRequestapplication/json
status
required
reason string · max length: 1000
propertyName anything
Responses
200Successful Response
PATCH /finance/requests/example
1curl -X PATCH "http://localhost:8000/finance/requests/example" \
2 -H "Content-Type: application/json" \
3 -d '{"status":null,"reason":"string"}'
1fetch("http://localhost:8000/finance/requests/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "status": null,
6 "reason": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/requests/example",
5 json={"status":null,"reason":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/requests

File an expense claim, advance, or purchase request

POST /finance/requests — any portal member files their own request.

Handled by api_create_request
Body · CreateFinanceRequestapplication/json
kind
required
amount number
required
date string · min length: 10
required
description string · min length: 1 · max length: 2000
required
currency string · min length: 3 · max length: 3
category_code string · max length: 20
vendor string · max length: 200
needed_by string · min length: 10
receipts array
dimensions
propertyName anything
Responses
200Successful Response
POST /finance/requests
1curl -X POST "http://localhost:8000/finance/requests" \
2 -H "Content-Type: application/json" \
3 -d '{"kind":null,"amount":1.5,"date":"string","description":"string","currency":"string","category_code":"string","vendor":"string","needed_by":"string","receipts":[{"key":"string","filename":"string","url":"string","content_type":"string","size":1}],"dimensions":null}'
1fetch("http://localhost:8000/finance/requests", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "kind": null,
6 "amount": 1.5,
7 "date": "string",
8 "description": "string",
9 "currency": "string",
10 "category_code": "string",
11 "vendor": "string",
12 "needed_by": "string",
13 "receipts": [
14 {
15 "key": "string",
16 "filename": "string",
17 "url": "string",
18 "content_type": "string",
19 "size": 1
20 }
21 ],
22 "dimensions": null
23}),
24})
25 .then((res) => res.json())
26 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/requests",
5 json={"kind":null,"amount":1.5,"date":"string","description":"string","currency":"string","category_code":"string","vendor":"string","needed_by":"string","receipts":[{"key":"string","filename":"string","url":"string","content_type":"string","size":1}],"dimensions":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/requests/:request_id/payments

Pay out an approved request

POST /finance/requests/:id/payments — pay out an approved request. Expenses settle the bill the approval created (outbound payment, AP → cash). Advances post a journal (Employee Advances ← cash). Purchases are paid through their PO chain, never directly.

Handled by api_pay_request
Parameters
request_id string · path
required
Body · PayFinanceRequestapplication/json
bank_account_id string
propertyName anything
Responses
200Successful Response
POST /finance/requests/example/payments
1curl -X POST "http://localhost:8000/finance/requests/example/payments" \
2 -H "Content-Type: application/json" \
3 -d '{"bank_account_id":"string"}'
1fetch("http://localhost:8000/finance/requests/example/payments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "bank_account_id": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/requests/example/payments",
5 json={"bank_account_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/requests/:request_id/messages

Message on a request thread

POST /finance/requests/:id/messages — the claimant or a reviewer leaves a message on the request's thread. Visibility follows the request itself (scope deposited by the authz chain).

Handled by api_post_request_message
Parameters
request_id string · path
required
Body · PostRequestMessageapplication/json
body string · min length: 1 · max length: 2000
required
propertyName anything
Responses
200Successful Response
POST /finance/requests/example/messages
1curl -X POST "http://localhost:8000/finance/requests/example/messages" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string"}'
1fetch("http://localhost:8000/finance/requests/example/messages", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/requests/example/messages",
5 json={"body":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /requests/:update_id undocumented

/requests/:update_id

PUT /requests/:update_id — Approve or deny an install request via status field.

Handled by api_approve_or_deny_request
Parameters
update_id string · path
required
Responses
200Successful Response
PUT /requests/example
1curl -X PUT "http://localhost:8000/requests/example"
1fetch("http://localhost:8000/requests/example", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/requests/example")
4print(response.json())
200 Example Response
No Body
GET /robots.txt undocumented

/robots.txt

Handled by robots_txt
Responses
200Successful Response
GET /robots.txt
1curl "http://localhost:8000/robots.txt"
1fetch("http://localhost:8000/robots.txt")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/robots.txt")
4print(response.json())
200 Example Response
No Body
DELETE /roles/:role_id undocumented

/roles/:role_id

DELETE /accounts/organisation/roles/:role_id — Delete a role.

Handled by api_delete_role
Parameters
role_id string · path
required
Responses
200Successful Response
DELETE /roles/example
1curl -X DELETE "http://localhost:8000/roles/example"
1fetch("http://localhost:8000/roles/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/roles/example")
4print(response.json())
200 Example Response
No Body
DELETE /roles/:role_id/members/:member_id undocumented

/roles/:role_id/members/:member_id

DELETE /accounts/organisation/roles/:role_id/members/:member_id — Remove member from role.

Handled by api_remove_role_member
Parameters
role_id string · path
required
member_id string · path
required
Responses
200Successful Response
DELETE /roles/example/members/example
1curl -X DELETE "http://localhost:8000/roles/example/members/example"
1fetch("http://localhost:8000/roles/example/members/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/roles/example/members/example")
4print(response.json())
200 Example Response
No Body
GET /roles undocumented

/roles

GET /roles — List custom roles for the workspace (admin view).

Handled by api_list_roles
Responses
200Successful Response
GET /roles
1curl "http://localhost:8000/roles"
1fetch("http://localhost:8000/roles")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/roles")
4print(response.json())
200 Example Response
No Body
POST /roles

Create role

POST /accounts/organisation/roles — Create a role.

Handled by api_create_role
Body · CreateRoleapplication/json
name string · min length: 1 · max length: 100
required
description string · max length: 500
propertyName anything
Responses
200Successful Response
POST /roles
1curl -X POST "http://localhost:8000/roles" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string"}'
1fetch("http://localhost:8000/roles", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/roles",
5 json={"name":"string","description":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /roles/:role_id/members

Assign member to role

POST /accounts/organisation/roles/:role_id/members — Assign member to role.

Handled by api_assign_role_member
Parameters
role_id string · path
required
Body · AssignRoleMemberapplication/json
member_id string · min length: 1
required
propertyName anything
Responses
200Successful Response
POST /roles/example/members
1curl -X POST "http://localhost:8000/roles/example/members" \
2 -H "Content-Type: application/json" \
3 -d '{"member_id":"string"}'
1fetch("http://localhost:8000/roles/example/members", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "member_id": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/roles/example/members",
5 json={"member_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /roles/:role_id undocumented

/roles/:role_id

PUT /accounts/organisation/roles/:role_id — Update role + permissions.

Handled by api_update_role
Parameters
role_id string · path
required
Responses
200Successful Response
PUT /roles/example
1curl -X PUT "http://localhost:8000/roles/example"
1fetch("http://localhost:8000/roles/example", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/roles/example")
4print(response.json())
200 Example Response
No Body
PUT /roles/:role_id/default

Set role as default

Toggle whether a role is auto-assigned to new members. Body: {is_default: bool}

Handled by api_set_role_default
Parameters
role_id string · path
required
Body · UpdateRoleDefaultapplication/json
is_default
required
propertyName anything
Responses
200Successful Response
PUT /roles/example/default
1curl -X PUT "http://localhost:8000/roles/example/default" \
2 -H "Content-Type: application/json" \
3 -d '{"is_default":null}'
1fetch("http://localhost:8000/roles/example/default", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "is_default": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/roles/example/default",
5 json={"is_default":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /rooms/:id undocumented

/rooms/:id

Permanently delete a room. Kicks all connected participants, then removes the room row (live_room_members rows cascade via FK).

Handled by api_delete_room
Parameters
id string · path
required
Responses
200Successful Response
DELETE /rooms/example
1curl -X DELETE "http://localhost:8000/rooms/example"
1fetch("http://localhost:8000/rooms/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/rooms/example")
4print(response.json())
200 Example Response
No Body
DELETE /rooms/:id/members/:member_mrn undocumented

/rooms/:id/members/:member_mrn

Remove member from room.

Handled by api_remove_room_member
Parameters
id string · path
required
member_mrn string · path
required
Responses
200Successful Response
DELETE /rooms/example/members/example
1curl -X DELETE "http://localhost:8000/rooms/example/members/example"
1fetch("http://localhost:8000/rooms/example/members/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/rooms/example/members/example")
4print(response.json())
200 Example Response
No Body
DELETE /rooms/:id/sessions undocumented

/rooms/:id/sessions

Leave a room. Sets is_connected = FALSE.

Handled by api_leave_room
Parameters
id string · path
required
Responses
200Successful Response
DELETE /rooms/example/sessions
1curl -X DELETE "http://localhost:8000/rooms/example/sessions"
1fetch("http://localhost:8000/rooms/example/sessions", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/rooms/example/sessions")
4print(response.json())
200 Example Response
No Body
GET /rooms undocumented

/rooms

List rooms visible to the current member. Supports ?q= search and pagination.

Handled by api_list_rooms
Responses
200Successful Response
GET /rooms
1curl "http://localhost:8000/rooms"
1fetch("http://localhost:8000/rooms")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/rooms")
4print(response.json())
200 Example Response
No Body
GET /rooms/:id undocumented

/rooms/:id

Get room details + full member list with connection status.

Handled by api_get_room
Parameters
id string · path
required
Responses
200Successful Response
GET /rooms/example
1curl "http://localhost:8000/rooms/example"
1fetch("http://localhost:8000/rooms/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/rooms/example")
4print(response.json())
200 Example Response
No Body
GET /rooms/:id/members undocumented

/rooms/:id/members

List room members with connection/mute state.

Handled by api_list_room_members
Parameters
id string · path
required
Responses
200Successful Response
GET /rooms/example/members
1curl "http://localhost:8000/rooms/example/members"
1fetch("http://localhost:8000/rooms/example/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/rooms/example/members")
4print(response.json())
200 Example Response
No Body
PATCH /rooms/:id

Update a room

Update room name, description, settings, type.

Handled by api_update_room
Parameters
id string · path
required
Body · UpdateRoomapplication/json
name string · min length: 1 · max length: 50
description string · max length: 200
type
max_participants integer · min: 2 · max: 100
settings object
propertyName anything
Responses
200Successful Response
PATCH /rooms/example
1curl -X PATCH "http://localhost:8000/rooms/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","type":null,"max_participants":1,"settings":{"mute_on_join":null}}'
1fetch("http://localhost:8000/rooms/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "type": null,
8 "max_participants": 1,
9 "settings": {
10 "mute_on_join": null
11 }
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/rooms/example",
5 json={"name":"string","description":"string","type":null,"max_participants":1,"settings":{"mute_on_join":null}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /rooms/:id/members/:member_mrn

Update room member role

Update member role (promote/demote admin).

Handled by api_update_room_member
Parameters
id string · path
required
member_mrn string · path
required
Body · UpdateMemberapplication/json
role
required
propertyName anything
Responses
200Successful Response
PATCH /rooms/example/members/example
1curl -X PATCH "http://localhost:8000/rooms/example/members/example" \
2 -H "Content-Type: application/json" \
3 -d '{"role":null}'
1fetch("http://localhost:8000/rooms/example/members/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "role": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/rooms/example/members/example",
5 json={"role":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /rooms

Create a room

Create a new room. Creator becomes room admin.

Handled by api_create_room
Body · CreateRoomapplication/json
name string · min length: 1 · max length: 50
required
description string · max length: 200
type
max_participants integer · min: 2 · max: 100
settings object
propertyName anything
Responses
200Successful Response
POST /rooms
1curl -X POST "http://localhost:8000/rooms" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","type":null,"max_participants":1,"settings":{"mute_on_join":null}}'
1fetch("http://localhost:8000/rooms", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "type": null,
8 "max_participants": 1,
9 "settings": {
10 "mute_on_join": null
11 }
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/rooms",
5 json={"name":"string","description":"string","type":null,"max_participants":1,"settings":{"mute_on_join":null}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /rooms/:id/members

Add room members

Add member(s) to a room.

Handled by api_add_room_members
Parameters
id string · path
required
Body · AddMembersapplication/json
members array
required
propertyName anything
Responses
200Successful Response
POST /rooms/example/members
1curl -X POST "http://localhost:8000/rooms/example/members" \
2 -H "Content-Type: application/json" \
3 -d '{"members":["string"]}'
1fetch("http://localhost:8000/rooms/example/members", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "members": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/rooms/example/members",
5 json={"members":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /rooms/:id/sessions undocumented

/rooms/:id/sessions

Join a room. Generates a LiveKit access token. Sets is_connected = TRUE.

Handled by api_join_room
Parameters
id string · path
required
Responses
200Successful Response
POST /rooms/example/sessions
1curl -X POST "http://localhost:8000/rooms/example/sessions"
1fetch("http://localhost:8000/rooms/example/sessions", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/rooms/example/sessions")
4print(response.json())
200 Example Response
No Body
POST /rooms/:id/token undocumented

/rooms/:id/token

Mint a fresh LiveKit token for a room the member is already connected to. Unlike POST /rooms/:id/sessions (which runs the full join lifecycle — kicks stale participants, updates is_connected, emits events), this endpoint is a pure token refresh. Used by the client's proactive refresh timer before the current token's `exp` claim kicks in.

Handled by api_refresh_room_token
Parameters
id string · path
required
Responses
200Successful Response
POST /rooms/example/token
1curl -X POST "http://localhost:8000/rooms/example/token"
1fetch("http://localhost:8000/rooms/example/token", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/rooms/example/token")
4print(response.json())
200 Example Response
No Body
POST /rooms/:id/members/:member_mrn/mute undocumented

/rooms/:id/members/:member_mrn/mute

Mute a participant (room admin only). Signals via platform WS.

Handled by api_force_mute_member
Parameters
id string · path
required
member_mrn string · path
required
Responses
200Successful Response
POST /rooms/example/members/example/mute
1curl -X POST "http://localhost:8000/rooms/example/members/example/mute"
1fetch("http://localhost:8000/rooms/example/members/example/mute", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/rooms/example/members/example/mute")
4print(response.json())
200 Example Response
No Body
PUT /rooms/session-state undocumented

/rooms/session-state

PUT /rooms/session-state — Sync client-side mute state into session for restore on refresh.

Handled by api_update_session_state
Responses
200Successful Response
PUT /rooms/session-state
1curl -X PUT "http://localhost:8000/rooms/session-state"
1fetch("http://localhost:8000/rooms/session-state", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/rooms/session-state")
4print(response.json())
200 Example Response
No Body
DELETE /schedules/:schedule_id undocumented

/schedules/:schedule_id

Delete a schedule. Its tasks and deliverables are kept — the schedule link is cleared via the ON DELETE SET NULL foreign key, so they fall back to having no schedule rather than being deleted.

Handled by api_delete_schedule
Parameters
schedule_id string · path
required
Responses
200Successful Response
DELETE /schedules/example
1curl -X DELETE "http://localhost:8000/schedules/example"
1fetch("http://localhost:8000/schedules/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/schedules/example")
4print(response.json())
200 Example Response
No Body
GET /schedules undocumented

/schedules

GET /schedules?board_id=...&q=... — list schedules for a board, optionally filtered by name.

Handled by api_list_schedules
Responses
200Successful Response
GET /schedules
1curl "http://localhost:8000/schedules"
1fetch("http://localhost:8000/schedules")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/schedules")
4print(response.json())
200 Example Response
No Body
POST /schedules

Create a schedule

Handled by api_create_schedule
Body · CreateScheduleapplication/json
board_id string
required
name string · min length: 1 · max length: 200
required
start_date string · min length: 1
required
end_date string · min length: 1
required
goal string · max length: 500
description string · max length: 5000
status
propertyName anything
Responses
200Successful Response
POST /schedules
1curl -X POST "http://localhost:8000/schedules" \
2 -H "Content-Type: application/json" \
3 -d '{"board_id":"string","name":"string","start_date":"string","end_date":"string","goal":"string","description":"string","status":null}'
1fetch("http://localhost:8000/schedules", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "board_id": "string",
6 "name": "string",
7 "start_date": "string",
8 "end_date": "string",
9 "goal": "string",
10 "description": "string",
11 "status": null
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/schedules",
5 json={"board_id":"string","name":"string","start_date":"string","end_date":"string","goal":"string","description":"string","status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /schedules/:schedule_id

Update a schedule

Update a schedule's mutable fields.

Handled by api_update_schedule
Parameters
schedule_id string · path
required
Body · UpdateScheduleapplication/json
name string · min length: 1 · max length: 200
goal string · max length: 500
description string · max length: 5000
status
start_date string
end_date string
propertyName anything
Responses
200Successful Response
PUT /schedules/example
1curl -X PUT "http://localhost:8000/schedules/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","goal":"string","description":"string","status":null,"start_date":"string","end_date":"string"}'
1fetch("http://localhost:8000/schedules/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "goal": "string",
7 "description": "string",
8 "status": null,
9 "start_date": "string",
10 "end_date": "string"
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/schedules/example",
5 json={"name":"string","goal":"string","description":"string","status":null,"start_date":"string","end_date":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /scoring/rules/:rule_id undocumented

/scoring/rules/:rule_id

Handled by api_delete_scoring_rule
Parameters
rule_id string · path
required
Responses
200Successful Response
DELETE /scoring/rules/example
1curl -X DELETE "http://localhost:8000/scoring/rules/example"
1fetch("http://localhost:8000/scoring/rules/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/scoring/rules/example")
4print(response.json())
200 Example Response
No Body
GET /scoring/rules undocumented

/scoring/rules

Handled by api_list_scoring_rules
Responses
200Successful Response
GET /scoring/rules
1curl "http://localhost:8000/scoring/rules"
1fetch("http://localhost:8000/scoring/rules")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/scoring/rules")
4print(response.json())
200 Example Response
No Body
GET /scoring/rules/:rule_id undocumented

/scoring/rules/:rule_id

Handled by api_get_scoring_rule
Parameters
rule_id string · path
required
Responses
200Successful Response
GET /scoring/rules/example
1curl "http://localhost:8000/scoring/rules/example"
1fetch("http://localhost:8000/scoring/rules/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/scoring/rules/example")
4print(response.json())
200 Example Response
No Body
GET /scoring/:entity_type/:entity_id undocumented

/scoring/:entity_type/:entity_id

Compute a score on demand. Deal scores persist on the deal and threshold events fire only on crossings (comparing against the stored score). Contact scores are computed read-only here; the daily sweep in events.py owns persistence and threshold events for contacts, because apis.py must never write the crm_party_index projection.

Handled by api_compute_score
Parameters
entity_type string · path
required
entity_id string · path
required
Responses
200Successful Response
GET /scoring/example/example
1curl "http://localhost:8000/scoring/example/example"
1fetch("http://localhost:8000/scoring/example/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/scoring/example/example")
4print(response.json())
200 Example Response
No Body
POST /scoring/rules

Create a scoring rule

Handled by api_create_scoring_rule
Body · CreateScoringRuleapplication/json
name string · min length: 1 · max length: 200
required
entity_type
required
rules array
required
thresholds array
enabled
propertyName anything
Responses
200Successful Response
POST /scoring/rules
1curl -X POST "http://localhost:8000/scoring/rules" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","entity_type":null,"rules":[{"signal":"string","op":null,"value":"string","points":1,"label":"string"}],"thresholds":[{"score_gte":1,"score_lte":1,"action":"string","label":"string"}],"enabled":null}'
1fetch("http://localhost:8000/scoring/rules", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "entity_type": null,
7 "rules": [
8 {
9 "signal": "string",
10 "op": null,
11 "value": "string",
12 "points": 1,
13 "label": "string"
14 }
15 ],
16 "thresholds": [
17 {
18 "score_gte": 1,
19 "score_lte": 1,
20 "action": "string",
21 "label": "string"
22 }
23 ],
24 "enabled": null
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/scoring/rules",
5 json={"name":"string","entity_type":null,"rules":[{"signal":"string","op":null,"value":"string","points":1,"label":"string"}],"thresholds":[{"score_gte":1,"score_lte":1,"action":"string","label":"string"}],"enabled":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /scoring/rules/:rule_id

Update a scoring rule

Handled by api_update_scoring_rule
Parameters
rule_id string · path
required
Body · UpdateScoringRuleapplication/json
name string · min length: 1 · max length: 200
rules array
thresholds array
enabled
propertyName anything
Responses
200Successful Response
PUT /scoring/rules/example
1curl -X PUT "http://localhost:8000/scoring/rules/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","rules":[{"signal":"string","op":null,"value":"string","points":1,"label":"string"}],"thresholds":[{"score_gte":1,"score_lte":1,"action":"string","label":"string"}],"enabled":null}'
1fetch("http://localhost:8000/scoring/rules/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "rules": [
7 {
8 "signal": "string",
9 "op": null,
10 "value": "string",
11 "points": 1,
12 "label": "string"
13 }
14 ],
15 "thresholds": [
16 {
17 "score_gte": 1,
18 "score_lte": 1,
19 "action": "string",
20 "label": "string"
21 }
22 ],
23 "enabled": null
24}),
25})
26 .then((res) => res.json())
27 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/scoring/rules/example",
5 json={"name":"string","rules":[{"signal":"string","op":null,"value":"string","points":1,"label":"string"}],"thresholds":[{"score_gte":1,"score_lte":1,"action":"string","label":"string"}],"enabled":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /search undocumented

/search

GET /search?app=chat&q=hello&types=message — central search dispatcher.

Handled by search
Responses
200Successful Response
GET /search
1curl "http://localhost:8000/search"
1fetch("http://localhost:8000/search")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/search")
4print(response.json())
200 Example Response
No Body
DELETE /segments/:segment_id undocumented

/segments/:segment_id

DELETE /segments/:segment_id — delete a segment.

Handled by api_delete_segment
Parameters
segment_id string · path
required
Responses
200Successful Response
DELETE /segments/example
1curl -X DELETE "http://localhost:8000/segments/example"
1fetch("http://localhost:8000/segments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/segments/example")
4print(response.json())
200 Example Response
No Body
DELETE /segments/:segment_id/members/:member_id undocumented

/segments/:segment_id/members/:member_id

DELETE /segments/:segment_id/members/:member_id — remove from a static segment.

Handled by api_remove_segment_member
Parameters
segment_id string · path
required
member_id string · path
required
Responses
200Successful Response
DELETE /segments/example/members/example
1curl -X DELETE "http://localhost:8000/segments/example/members/example"
1fetch("http://localhost:8000/segments/example/members/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/segments/example/members/example")
4print(response.json())
200 Example Response
No Body
GET /segments undocumented

/segments

GET /segments — list segments.

Handled by api_list_segments
Responses
200Successful Response
GET /segments
1curl "http://localhost:8000/segments"
1fetch("http://localhost:8000/segments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/segments")
4print(response.json())
200 Example Response
No Body
GET /segments/:segment_id undocumented

/segments/:segment_id

GET /segments/:segment_id — get segment with resolved members.

Handled by api_get_segment
Parameters
segment_id string · path
required
Responses
200Successful Response
GET /segments/example
1curl "http://localhost:8000/segments/example"
1fetch("http://localhost:8000/segments/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/segments/example")
4print(response.json())
200 Example Response
No Body
POST /segments

Create a segment

POST /segments — create a segment (static or dynamic).

Handled by api_create_segment
Body · CreateSegmentapplication/json
name string · min length: 1 · max length: 100
required
description string · max length: 500
type
entity_type
filter object
members array
propertyName anything
Responses
200Successful Response
POST /segments
1curl -X POST "http://localhost:8000/segments" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","type":null,"entity_type":null,"filter":{"entity_type":null,"tags":["string"],"domain":"string","industry":"string","size":["string"],"source":"string","owner_mrn":"string","state":null,"has_open_conversation":null,"csat_below":1,"last_order_within_days":1,"total_paid_orders_gte":1},"members":[{"type":null,"id":"string"}]}'
1fetch("http://localhost:8000/segments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "type": null,
8 "entity_type": null,
9 "filter": {
10 "entity_type": null,
11 "tags": [
12 "string"
13 ],
14 "domain": "string",
15 "industry": "string",
16 "size": [
17 "string"
18 ],
19 "source": "string",
20 "owner_mrn": "string",
21 "state": null,
22 "has_open_conversation": null,
23 "csat_below": 1,
24 "last_order_within_days": 1,
25 "total_paid_orders_gte": 1
26 },
27 "members": [
28 {
29 "type": null,
30 "id": "string"
31 }
32 ]
33}),
34})
35 .then((res) => res.json())
36 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/segments",
5 json={"name":"string","description":"string","type":null,"entity_type":null,"filter":{"entity_type":null,"tags":["string"],"domain":"string","industry":"string","size":["string"],"source":"string","owner_mrn":"string","state":null,"has_open_conversation":null,"csat_below":1,"last_order_within_days":1,"total_paid_orders_gte":1},"members":[{"type":null,"id":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /segments/:segment_id/members

Add member to segment

POST /segments/:segment_id/members — add a contact/company to a static segment.

Handled by api_add_segment_member
Parameters
segment_id string · path
required
Body · AddSegmentMemberapplication/json
type
required
id string · min length: 1
required
propertyName anything
Responses
200Successful Response
POST /segments/example/members
1curl -X POST "http://localhost:8000/segments/example/members" \
2 -H "Content-Type: application/json" \
3 -d '{"type":null,"id":"string"}'
1fetch("http://localhost:8000/segments/example/members", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "type": null,
6 "id": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/segments/example/members",
5 json={"type":null,"id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /segments/:segment_id

Update a segment

PUT /segments/:segment_id — update a segment (name, description, or rules).

Handled by api_update_segment
Parameters
segment_id string · path
required
Body · UpdateSegmentapplication/json
name string · min length: 1 · max length: 100
description string · max length: 500
filter object
propertyName anything
Responses
200Successful Response
PUT /segments/example
1curl -X PUT "http://localhost:8000/segments/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","filter":{"entity_type":null,"tags":["string"],"domain":"string","industry":"string","size":["string"],"source":"string","owner_mrn":"string","state":null,"has_open_conversation":null,"csat_below":1,"last_order_within_days":1,"total_paid_orders_gte":1}}'
1fetch("http://localhost:8000/segments/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "filter": {
8 "entity_type": null,
9 "tags": [
10 "string"
11 ],
12 "domain": "string",
13 "industry": "string",
14 "size": [
15 "string"
16 ],
17 "source": "string",
18 "owner_mrn": "string",
19 "state": null,
20 "has_open_conversation": null,
21 "csat_below": 1,
22 "last_order_within_days": 1,
23 "total_paid_orders_gte": 1
24 }
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/segments/example",
5 json={"name":"string","description":"string","filter":{"entity_type":null,"tags":["string"],"domain":"string","industry":"string","size":["string"],"source":"string","owner_mrn":"string","state":null,"has_open_conversation":null,"csat_below":1,"last_order_within_days":1,"total_paid_orders_gte":1}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /chats/:id/settings

Update chat settings

PATCH /chats/:id/settings — per-chat settings for the caller (mute).

Handled by api_update_settings
Parameters
id string · path
required
Body · UpdateChatSettingsapplication/json
muted_until string
propertyName anything
Responses
200Successful Response
PATCH /chats/example/settings
1curl -X PATCH "http://localhost:8000/chats/example/settings" \
2 -H "Content-Type: application/json" \
3 -d '{"muted_until":"string"}'
1fetch("http://localhost:8000/chats/example/settings", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "muted_until": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/chats/example/settings",
5 json={"muted_until":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/tax-rates/:tax_id

Update tax preset

Handled by handler
Parameters
tax_id string · path
required
Body · TaxRatePresetapplication/json
name string · min length: 1 · max length: 100
required
rates array
required
propertyName anything
Responses
200Successful Response
PATCH /finance/tax-rates/example
1curl -X PATCH "http://localhost:8000/finance/tax-rates/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","rates":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}'
1fetch("http://localhost:8000/finance/tax-rates/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "rates": [
7 {
8 "name": "string",
9 "rate": 1.5,
10 "amount": 1.5,
11 "reverse_charge": null
12 }
13 ]
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/tax-rates/example",
5 json={"name":"string","rates":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /finance/payment-terms/:term_id

Update payment term

Handled by handler
Parameters
term_id string · path
required
Body · PaymentTermPresetapplication/json
name string · min length: 1 · max length: 100
required
days integer · min: 0
required
early_discount_rate number
early_discount_days integer
propertyName anything
Responses
200Successful Response
PATCH /finance/payment-terms/example
1curl -X PATCH "http://localhost:8000/finance/payment-terms/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","days":1,"early_discount_rate":1.5,"early_discount_days":1}'
1fetch("http://localhost:8000/finance/payment-terms/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "days": 1,
7 "early_discount_rate": 1.5,
8 "early_discount_days": 1
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/finance/payment-terms/example",
5 json={"name":"string","days":1,"early_discount_rate":1.5,"early_discount_days":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/tax-rates

Create tax preset

Handled by handler
Body · TaxRatePresetapplication/json
name string · min length: 1 · max length: 100
required
rates array
required
propertyName anything
Responses
200Successful Response
POST /finance/tax-rates
1curl -X POST "http://localhost:8000/finance/tax-rates" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","rates":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]}'
1fetch("http://localhost:8000/finance/tax-rates", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "rates": [
7 {
8 "name": "string",
9 "rate": 1.5,
10 "amount": 1.5,
11 "reverse_charge": null
12 }
13 ]
14}),
15})
16 .then((res) => res.json())
17 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/tax-rates",
5 json={"name":"string","rates":[{"name":"string","rate":1.5,"amount":1.5,"reverse_charge":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /finance/payment-terms

Create payment term

Handled by handler
Body · PaymentTermPresetapplication/json
name string · min length: 1 · max length: 100
required
days integer · min: 0
required
early_discount_rate number
early_discount_days integer
propertyName anything
Responses
200Successful Response
POST /finance/payment-terms
1curl -X POST "http://localhost:8000/finance/payment-terms" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","days":1,"early_discount_rate":1.5,"early_discount_days":1}'
1fetch("http://localhost:8000/finance/payment-terms", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "days": 1,
7 "early_discount_rate": 1.5,
8 "early_discount_days": 1
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/finance/payment-terms",
5 json={"name":"string","days":1,"early_discount_rate":1.5,"early_discount_days":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /finance/settings

Update core settings

Handled by api_update_settings
Body · UpdateSettingsapplication/json
base_currency string · min length: 3 · max length: 3
fiscal_year_start integer · min: 1 · max: 12
accounting_enabled
number_prefixes object
sequential_numbers
default_accounts object
invoice_template object
propertyName anything
Responses
200Successful Response
PUT /finance/settings
1curl -X PUT "http://localhost:8000/finance/settings" \
2 -H "Content-Type: application/json" \
3 -d '{"base_currency":"string","fiscal_year_start":1,"accounting_enabled":null,"number_prefixes":{"quote":"string","purchase_order":"string","order":"string","invoice":"string","bill":"string","credit_note":"string","journal":"string"},"sequential_numbers":null,"default_accounts":{"accounts_receivable":"string","accounts_payable":"string","cash":"string","tax_payable":"string","accrued_expenses":"string","customer_deposits":"string","employee_advances":"string","withholding_tax_receivable":"string","withholding_tax_payable":"string","fx_gains":"string","fx_losses":"string","unrealized_fx_asset":"string","unrealized_fx_liability":"string","sales_discounts":"string","retained_earnings":"string","cogs":"string","inventory":"string","inventory_adjustments":"string"},"invoice_template":{"logo_url":"string","logo_key":"string","company_name":"string","company_address":"string","accent_color":"string","footer_text":"string","bank_details":"string"}}'
1fetch("http://localhost:8000/finance/settings", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "base_currency": "string",
6 "fiscal_year_start": 1,
7 "accounting_enabled": null,
8 "number_prefixes": {
9 "quote": "string",
10 "purchase_order": "string",
11 "order": "string",
12 "invoice": "string",
13 "bill": "string",
14 "credit_note": "string",
15 "journal": "string"
16 },
17 "sequential_numbers": null,
18 "default_accounts": {
19 "accounts_receivable": "string",
20 "accounts_payable": "string",
21 "cash": "string",
22 "tax_payable": "string",
23 "accrued_expenses": "string",
24 "customer_deposits": "string",
25 "employee_advances": "string",
26 "withholding_tax_receivable": "string",
27 "withholding_tax_payable": "string",
28 "fx_gains": "string",
29 "fx_losses": "string",
30 "unrealized_fx_asset": "string",
31 "unrealized_fx_liability": "string",
32 "sales_discounts": "string",
33 "retained_earnings": "string",
34 "cogs": "string",
35 "inventory": "string",
36 "inventory_adjustments": "string"
37 },
38 "invoice_template": {
39 "logo_url": "string",
40 "logo_key": "string",
41 "company_name": "string",
42 "company_address": "string",
43 "accent_color": "string",
44 "footer_text": "string",
45 "bank_details": "string"
46 }
47}),
48})
49 .then((res) => res.json())
50 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/finance/settings",
5 json={"base_currency":"string","fiscal_year_start":1,"accounting_enabled":null,"number_prefixes":{"quote":"string","purchase_order":"string","order":"string","invoice":"string","bill":"string","credit_note":"string","journal":"string"},"sequential_numbers":null,"default_accounts":{"accounts_receivable":"string","accounts_payable":"string","cash":"string","tax_payable":"string","accrued_expenses":"string","customer_deposits":"string","employee_advances":"string","withholding_tax_receivable":"string","withholding_tax_payable":"string","fx_gains":"string","fx_losses":"string","unrealized_fx_asset":"string","unrealized_fx_liability":"string","sales_discounts":"string","retained_earnings":"string","cogs":"string","inventory":"string","inventory_adjustments":"string"},"invoice_template":{"logo_url":"string","logo_key":"string","company_name":"string","company_address":"string","accent_color":"string","footer_text":"string","bank_details":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /shared undocumented

/shared

Handled by api_list_shared_with_me
Responses
200Successful Response
GET /shared
1curl "http://localhost:8000/shared"
1fetch("http://localhost:8000/shared")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/shared")
4print(response.json())
200 Example Response
No Body
DELETE /shares/:share_id undocumented

/shares/:share_id

Handled by api_delete_share
Parameters
share_id string · path
required
Responses
200Successful Response
DELETE /shares/example
1curl -X DELETE "http://localhost:8000/shares/example"
1fetch("http://localhost:8000/shares/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/shares/example")
4print(response.json())
200 Example Response
No Body
GET /shares undocumented

/shares

Handled by api_list_shares
Responses
200Successful Response
GET /shares
1curl "http://localhost:8000/shares"
1fetch("http://localhost:8000/shares")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/shares")
4print(response.json())
200 Example Response
No Body
GET /shares/:share_id undocumented

/shares/:share_id

Handled by api_get_share
Parameters
share_id string · path
required
Responses
200Successful Response
GET /shares/example
1curl "http://localhost:8000/shares/example"
1fetch("http://localhost:8000/shares/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/shares/example")
4print(response.json())
200 Example Response
No Body
PATCH /shares/:share_id

Update a share link

Handled by api_update_share
Parameters
share_id string · path
required
Body · UpdateShareapplication/json
password string · min length: 4 · max length: 128
expires_at string
max_downloads integer
is_active
propertyName anything
Responses
200Successful Response
PATCH /shares/example
1curl -X PATCH "http://localhost:8000/shares/example" \
2 -H "Content-Type: application/json" \
3 -d '{"password":"string","expires_at":"string","max_downloads":1,"is_active":null}'
1fetch("http://localhost:8000/shares/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "password": "string",
6 "expires_at": "string",
7 "max_downloads": 1,
8 "is_active": null
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/shares/example",
5 json={"password":"string","expires_at":"string","max_downloads":1,"is_active":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /shares

Create a share link

Handled by api_create_share
Body · CreateShareapplication/json
resource_type
required
resource_id string · min length: 1
required
password string · min length: 4 · max length: 128
expires_at string
max_downloads integer
propertyName anything
Responses
200Successful Response
POST /shares
1curl -X POST "http://localhost:8000/shares" \
2 -H "Content-Type: application/json" \
3 -d '{"resource_type":null,"resource_id":"string","password":"string","expires_at":"string","max_downloads":1}'
1fetch("http://localhost:8000/shares", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "resource_type": null,
6 "resource_id": "string",
7 "password": "string",
8 "expires_at": "string",
9 "max_downloads": 1
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/shares",
5 json={"resource_type":null,"resource_id":"string","password":"string","expires_at":"string","max_downloads":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /sign/envelopes/:envelope_id/documents/:document_id undocumented

/sign/envelopes/:envelope_id/documents/:document_id

DELETE /sign/envelopes/:envelope_id/documents/:document_id — remove one part. Fields sitting on the removed part's (global) pages are deleted; fields on later pages shift back by the removed page span so they stay on the pages they were placed on.

Handled by api_delete_document
Parameters
envelope_id string · path
required
document_id string · path
required
Responses
200Successful Response
DELETE /sign/envelopes/example/documents/example
1curl -X DELETE "http://localhost:8000/sign/envelopes/example/documents/example"
1fetch("http://localhost:8000/sign/envelopes/example/documents/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/sign/envelopes/example/documents/example")
4print(response.json())
200 Example Response
No Body
DELETE /sign/envelopes/:envelope_id undocumented

/sign/envelopes/:envelope_id

DELETE /sign/envelopes/:envelope_id — delete a draft/template (sent envelopes are voided, not deleted).

Handled by api_delete_envelope
Parameters
envelope_id string · path
required
Responses
200Successful Response
DELETE /sign/envelopes/example
1curl -X DELETE "http://localhost:8000/sign/envelopes/example"
1fetch("http://localhost:8000/sign/envelopes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/sign/envelopes/example")
4print(response.json())
200 Example Response
No Body
DELETE /sign/templates/:envelope_id/links/:link_id undocumented

/sign/templates/:envelope_id/links/:link_id

DELETE /sign/templates/:envelope_id/links/:link_id — close a link. Soft (revoked_at): the row keeps its submission history.

Handled by api_revoke_public_link
Parameters
envelope_id string · path
required
link_id string · path
required
Responses
200Successful Response
DELETE /sign/templates/example/links/example
1curl -X DELETE "http://localhost:8000/sign/templates/example/links/example"
1fetch("http://localhost:8000/sign/templates/example/links/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/sign/templates/example/links/example")
4print(response.json())
200 Example Response
No Body
DELETE /sign/envelopes/:envelope_id/exports/:target undocumented

/sign/envelopes/:envelope_id/exports/:target

DELETE /sign/envelopes/:envelope_id/exports/:target — take the saved copy back out of Files. Files itself refuses to delete anything Sign owns, so this is the only way to undo a Save to Files. It has to live here: a completed envelope can never be deleted (sealed documents are voided, not removed), so without this the copy would be permanent and an accidental save unfixable.

Handled by api_delete_export
Parameters
envelope_id string · path
required
target string · path
required
Responses
200Successful Response
DELETE /sign/envelopes/example/exports/example
1curl -X DELETE "http://localhost:8000/sign/envelopes/example/exports/example"
1fetch("http://localhost:8000/sign/envelopes/example/exports/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/sign/envelopes/example/exports/example")
4print(response.json())
200 Example Response
No Body
DELETE /sign/envelopes/:envelope_id/fields/:field_id undocumented

/sign/envelopes/:envelope_id/fields/:field_id

DELETE /sign/envelopes/:envelope_id/fields/:field_id — remove a field.

Handled by api_delete_field
Parameters
envelope_id string · path
required
field_id string · path
required
Responses
200Successful Response
DELETE /sign/envelopes/example/fields/example
1curl -X DELETE "http://localhost:8000/sign/envelopes/example/fields/example"
1fetch("http://localhost:8000/sign/envelopes/example/fields/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/sign/envelopes/example/fields/example")
4print(response.json())
200 Example Response
No Body
DELETE /sign/envelopes/:envelope_id/recipients/:recipient_id undocumented

/sign/envelopes/:envelope_id/recipients/:recipient_id

DELETE /sign/envelopes/:envelope_id/recipients/:recipient_id — remove a recipient (before send).

Handled by api_delete_recipient
Parameters
envelope_id string · path
required
recipient_id string · path
required
Responses
200Successful Response
DELETE /sign/envelopes/example/recipients/example
1curl -X DELETE "http://localhost:8000/sign/envelopes/example/recipients/example"
1fetch("http://localhost:8000/sign/envelopes/example/recipients/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/sign/envelopes/example/recipients/example")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes undocumented

/sign/envelopes

GET /sign/envelopes — list documents (non-templates by default; ?is_template=true, ?status=).

Handled by api_list_envelopes
Responses
200Successful Response
GET /sign/envelopes
1curl "http://localhost:8000/sign/envelopes"
1fetch("http://localhost:8000/sign/envelopes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id undocumented

/sign/envelopes/:envelope_id

GET /sign/envelopes/:envelope_id — envelope + its fields + recipients.

Handled by api_get_envelope
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example
1curl "http://localhost:8000/sign/envelopes/example"
1fetch("http://localhost:8000/sign/envelopes/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/source undocumented

/sign/envelopes/:envelope_id/source

GET /sign/envelopes/:envelope_id/source — presigned GET URLs for the source PDFs. The builder loads these into PDF.js to render pages for field placement. `documents` lists every part in signing order (a legacy single-PDF envelope synthesizes one entry); `url`/`page_count` keep the pre-multi-document shape (first part / total pages).

Handled by api_get_source
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/source
1curl "http://localhost:8000/sign/envelopes/example/source"
1fetch("http://localhost:8000/sign/envelopes/example/source")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/source")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/documents undocumented

/sign/envelopes/:envelope_id/documents

GET /sign/envelopes/:envelope_id/documents — the envelope's source PDFs in order.

Handled by api_list_documents
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/documents
1curl "http://localhost:8000/sign/envelopes/example/documents"
1fetch("http://localhost:8000/sign/envelopes/example/documents")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/documents")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/audit undocumented

/sign/envelopes/:envelope_id/audit

GET /sign/envelopes/:envelope_id/audit — the envelope's chronological audit trail.

Handled by api_get_audit
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/audit
1curl "http://localhost:8000/sign/envelopes/example/audit"
1fetch("http://localhost:8000/sign/envelopes/example/audit")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/audit")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/values undocumented

/sign/envelopes/:envelope_id/values

GET /sign/envelopes/:envelope_id/values — what each recipient actually entered. Text/date/name/email come back as `value`; signature/initials come back as a short- lived presigned `signature_url` for the drawn PNG. The builder overlays these on a sent/completed document so the owner sees the real content, not the placeholders.

Handled by api_get_values
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/values
1curl "http://localhost:8000/sign/envelopes/example/values"
1fetch("http://localhost:8000/sign/envelopes/example/values")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/values")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/document undocumented

/sign/envelopes/:envelope_id/document

GET /sign/envelopes/:envelope_id/document — presigned URL for the sealed PDF.

Handled by api_get_document
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/document
1curl "http://localhost:8000/sign/envelopes/example/document"
1fetch("http://localhost:8000/sign/envelopes/example/document")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/document")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/certificate undocumented

/sign/envelopes/:envelope_id/certificate

GET /sign/envelopes/:envelope_id/certificate — presigned URL for the Certificate of Completion.

Handled by api_get_certificate
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/certificate
1curl "http://localhost:8000/sign/envelopes/example/certificate"
1fetch("http://localhost:8000/sign/envelopes/example/certificate")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/certificate")
4print(response.json())
200 Example Response
No Body
GET /sign/templates undocumented

/sign/templates

GET /sign/templates — list reusable templates (sugar for ?is_template=true).

Handled by api_list_templates
Responses
200Successful Response
GET /sign/templates
1curl "http://localhost:8000/sign/templates"
1fetch("http://localhost:8000/sign/templates")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/templates")
4print(response.json())
200 Example Response
No Body
GET /sign/templates/:envelope_id/usages undocumented

/sign/templates/:envelope_id/usages

GET /sign/templates/:envelope_id/usages: every document created from this template (one-off clones and broadcast sends), newest first, with sender and recipients attached. Visible to anyone holding a read grant on the template.

Handled by api_list_template_usages
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/templates/example/usages
1curl "http://localhost:8000/sign/templates/example/usages"
1fetch("http://localhost:8000/sign/templates/example/usages")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/templates/example/usages")
4print(response.json())
200 Example Response
No Body
GET /sign/templates/:envelope_id/links undocumented

/sign/templates/:envelope_id/links

GET /sign/templates/:envelope_id/links — this template's self-serve links.

Handled by api_list_public_links
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/templates/example/links
1curl "http://localhost:8000/sign/templates/example/links"
1fetch("http://localhost:8000/sign/templates/example/links")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/templates/example/links")
4print(response.json())
200 Example Response
No Body
GET /sign/signatories undocumented

/sign/signatories

GET /sign/signatories?q= : everyone ever added to a document the caller can see, aggregated by email: document count, signed/declined counts, and last activity.

Handled by api_list_signatories
Responses
200Successful Response
GET /sign/signatories
1curl "http://localhost:8000/sign/signatories"
1fetch("http://localhost:8000/sign/signatories")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/signatories")
4print(response.json())
200 Example Response
No Body
GET /sign/signatories/:email undocumented

/sign/signatories/:email

GET /sign/signatories/:email — one signatory's profile (see _signatory_profile).

Handled by api_get_signatory
Parameters
email string · path
required
Responses
200Successful Response
GET /sign/signatories/example
1curl "http://localhost:8000/sign/signatories/example"
1fetch("http://localhost:8000/sign/signatories/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/signatories/example")
4print(response.json())
200 Example Response
No Body
GET /sign/statistics undocumented

/sign/statistics

GET /sign/statistics: dashboard aggregates over the documents the caller can see (same visibility as the lists: grants, widened for auditors): status counts, monthly sent/completed volume, completion rate, median time-to-complete, pending-signature aging, top templates by usage, and recent activity.

Handled by api_get_statistics
Responses
200Successful Response
GET /sign/statistics
1curl "http://localhost:8000/sign/statistics"
1fetch("http://localhost:8000/sign/statistics")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/statistics")
4print(response.json())
200 Example Response
No Body
GET /sign/jurisdictions undocumented

/sign/jurisdictions

GET /sign/jurisdictions — picker options + carve-out warnings (static config).

Handled by api_get_jurisdictions
Responses
200Successful Response
GET /sign/jurisdictions
1curl "http://localhost:8000/sign/jurisdictions"
1fetch("http://localhost:8000/sign/jurisdictions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/jurisdictions")
4print(response.json())
200 Example Response
No Body
GET /sign/settings undocumented

/sign/settings

GET /sign/settings: Sign's workspace configuration. Today that is one choice: which template a cross-app signature request is raised from. Readable by anyone who can see documents, so the Templates list can mark the chosen one even for members who may not change it.

Handled by api_get_settings
Responses
200Successful Response
GET /sign/settings
1curl "http://localhost:8000/sign/settings"
1fetch("http://localhost:8000/sign/settings")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/settings")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/fields undocumented

/sign/envelopes/:envelope_id/fields

GET /sign/envelopes/:envelope_id/fields — list field placements.

Handled by api_list_fields
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/fields
1curl "http://localhost:8000/sign/envelopes/example/fields"
1fetch("http://localhost:8000/sign/envelopes/example/fields")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/fields")
4print(response.json())
200 Example Response
No Body
GET /sign/envelopes/:envelope_id/recipients undocumented

/sign/envelopes/:envelope_id/recipients

GET /sign/envelopes/:envelope_id/recipients — list recipients + their status.

Handled by api_list_recipients
Parameters
envelope_id string · path
required
Responses
200Successful Response
GET /sign/envelopes/example/recipients
1curl "http://localhost:8000/sign/envelopes/example/recipients"
1fetch("http://localhost:8000/sign/envelopes/example/recipients")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign/envelopes/example/recipients")
4print(response.json())
200 Example Response
No Body
POST /sign/envelopes/:envelope_id/reminders undocumented

/sign/envelopes/:envelope_id/reminders

POST /sign/envelopes/:envelope_id/reminders — remind recipients who haven't signed.

Handled by api_send_reminders
Parameters
envelope_id string · path
required
Responses
200Successful Response
POST /sign/envelopes/example/reminders
1curl -X POST "http://localhost:8000/sign/envelopes/example/reminders"
1fetch("http://localhost:8000/sign/envelopes/example/reminders", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/sign/envelopes/example/reminders")
4print(response.json())
200 Example Response
No Body
POST /sign/templates/:envelope_id/broadcasts undocumented

/sign/templates/:envelope_id/broadcasts

POST /sign/templates/:envelope_id/broadcasts {rows:[{recipients:[{role,name,email}]}]} Send-to-many: clone the template once per row, bind each role to its recipient, and send every envelope. Gated by sign.envelopes.send (it IS sending). A row is used only if it has a distinct email for every role in the template; incomplete rows are skipped.

Handled by api_broadcast_template
Parameters
envelope_id string · path
required
Responses
200Successful Response
POST /sign/templates/example/broadcasts
1curl -X POST "http://localhost:8000/sign/templates/example/broadcasts"
1fetch("http://localhost:8000/sign/templates/example/broadcasts", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/sign/templates/example/broadcasts")
4print(response.json())
200 Example Response
No Body
GET /sign-in/:token undocumented

/sign-in/:token

GET /sign-in/:token — the landing page for a mailed link. This RENDERS ONLY. It deliberately does not redeem the token, because every mail security product worth the name (Safe Links, Proofpoint, Mimecast) fetches every URL in an inbound message before the recipient sees it. A link that signed you in on GET would be spent, or followed, by the scanner. The button below POSTs, which is what actually redeems.

Handled by sign_in_confirm_page
Parameters
token string · path
required
Responses
200Successful Response
GET /sign-in/example
1curl "http://localhost:8000/sign-in/example"
1fetch("http://localhost:8000/sign-in/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sign-in/example")
4print(response.json())
200 Example Response
No Body
GET /signup undocumented

/signup

Handled by signup_page
Responses
200Successful Response
GET /signup
1curl "http://localhost:8000/signup"
1fetch("http://localhost:8000/signup")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/signup")
4print(response.json())
200 Example Response
No Body
GET /sitemap.xml undocumented

/sitemap.xml

Handled by sitemap_xml
Responses
200Successful Response
GET /sitemap.xml
1curl "http://localhost:8000/sitemap.xml"
1fetch("http://localhost:8000/sitemap.xml")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/sitemap.xml")
4print(response.json())
200 Example Response
No Body
PATCH /decks/:id

Update a deck

PATCH /decks/:id. Title, content, thumbnail, or restore from trash.

Handled by api_update_deck
Parameters
id string · path
required
Body · UpdateDeckapplication/json
title string · min length: 1 · max length: 200
deck_json object
slide_count integer · min: 0 · max: 500
thumbnail_key string · max length: 512
deleted
propertyName anything
Responses
200Successful Response
PATCH /decks/example
1curl -X PATCH "http://localhost:8000/decks/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","deck_json":{"v":1,"size":{"w":1,"h":1},"theme":null,"slides":[null]},"slide_count":1,"thumbnail_key":"string","deleted":null}'
1fetch("http://localhost:8000/decks/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "deck_json": {
7 "v": 1,
8 "size": {
9 "w": 1,
10 "h": 1
11 },
12 "theme": null,
13 "slides": [
14 null
15 ]
16 },
17 "slide_count": 1,
18 "thumbnail_key": "string",
19 "deleted": null
20}),
21})
22 .then((res) => res.json())
23 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/decks/example",
5 json={"title":"string","deck_json":{"v":1,"size":{"w":1,"h":1},"theme":null,"slides":[null]},"slide_count":1,"thumbnail_key":"string","deleted":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /decks

Create a deck

POST /decks. Create a blank deck.

Handled by api_create_deck
Body · CreateDeckapplication/json
title string · min length: 1 · max length: 200
propertyName anything
Responses
200Successful Response
POST /decks
1curl -X POST "http://localhost:8000/decks" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string"}'
1fetch("http://localhost:8000/decks", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/decks",
5 json={"title":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /decks/:id/assets

Register a deck image

POST /decks/:id/assets. Register an uploaded image. Gate loaded ctx.authz.deck.

Handled by api_create_asset
Parameters
id string · path
required
Body · CreateAssetapplication/json
asset_id string · min length: 6 · max length: 64
required
storage_key string · min length: 1 · max length: 512
required
filename string · min length: 1 · max length: 255
required
content_type string · min length: 1 · max length: 100
required
size_bytes integer · min: 0
required
width integer · min: 0
height integer · min: 0
propertyName anything
Responses
200Successful Response
POST /decks/example/assets
1curl -X POST "http://localhost:8000/decks/example/assets" \
2 -H "Content-Type: application/json" \
3 -d '{"asset_id":"string","storage_key":"string","filename":"string","content_type":"string","size_bytes":1,"width":1,"height":1}'
1fetch("http://localhost:8000/decks/example/assets", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "asset_id": "string",
6 "storage_key": "string",
7 "filename": "string",
8 "content_type": "string",
9 "size_bytes": 1,
10 "width": 1,
11 "height": 1
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/decks/example/assets",
5 json={"asset_id":"string","storage_key":"string","filename":"string","content_type":"string","size_bytes":1,"width":1,"height":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /spellschemas

Introspect a platform API schema

Introspect a platform API endpoint's pytastic schema. POST /spellschemas with {route: "/tasks", method: "POST"} Returns UI-ready field definitions extracted from the TypedDict at runtime.

Handled by api_create_spellschema
Body · CreateSpellSchemaapplication/json
route string · min length: 1
required
method string
propertyName anything
Responses
200Successful Response
POST /spellschemas
1curl -X POST "http://localhost:8000/spellschemas" \
2 -H "Content-Type: application/json" \
3 -d '{"route":"string","method":"string"}'
1fetch("http://localhost:8000/spellschemas", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "route": "string",
6 "method": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/spellschemas",
5 json={"route":"string","method":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /spell-runs/:run_id undocumented

/spell-runs/:run_id

Handled by api_get_run
Parameters
run_id string · path
required
Responses
200Successful Response
GET /spell-runs/example
1curl "http://localhost:8000/spell-runs/example"
1fetch("http://localhost:8000/spell-runs/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/spell-runs/example")
4print(response.json())
200 Example Response
No Body
DELETE /spells/:spell_id undocumented

/spells/:spell_id

Handled by api_delete_spell
Parameters
spell_id string · path
required
Responses
200Successful Response
DELETE /spells/example
1curl -X DELETE "http://localhost:8000/spells/example"
1fetch("http://localhost:8000/spells/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/spells/example")
4print(response.json())
200 Example Response
No Body
GET /spells undocumented

/spells

Handled by api_list_spells
Responses
200Successful Response
GET /spells
1curl "http://localhost:8000/spells"
1fetch("http://localhost:8000/spells")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/spells")
4print(response.json())
200 Example Response
No Body
GET /spells/:spell_id undocumented

/spells/:spell_id

Handled by api_get_spell
Parameters
spell_id string · path
required
Responses
200Successful Response
GET /spells/example
1curl "http://localhost:8000/spells/example"
1fetch("http://localhost:8000/spells/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/spells/example")
4print(response.json())
200 Example Response
No Body
GET /spells/:spell_id/runs undocumented

/spells/:spell_id/runs

Handled by api_list_runs
Parameters
spell_id string · path
required
Responses
200Successful Response
GET /spells/example/runs
1curl "http://localhost:8000/spells/example/runs"
1fetch("http://localhost:8000/spells/example/runs")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/spells/example/runs")
4print(response.json())
200 Example Response
No Body
POST /spells

Create a spell

Handled by api_create_spell
Body · CreateSpellapplication/json
name string · min length: 1 · max length: 200
description string · max length: 2000
trigger object
chain array
enabled
format
source string · max length: 100000
propertyName anything
Responses
200Successful Response
POST /spells
1curl -X POST "http://localhost:8000/spells" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","trigger":{"events":["string"],"schedule":null,"where":null},"chain":[{"macro":"string","args":null,"output_as":"string","note":"string"}],"enabled":null,"format":null,"source":"string"}'
1fetch("http://localhost:8000/spells", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "trigger": {
8 "events": [
9 "string"
10 ],
11 "schedule": null,
12 "where": null
13 },
14 "chain": [
15 {
16 "macro": "string",
17 "args": null,
18 "output_as": "string",
19 "note": "string"
20 }
21 ],
22 "enabled": null,
23 "format": null,
24 "source": "string"
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/spells",
5 json={"name":"string","description":"string","trigger":{"events":["string"],"schedule":null,"where":null},"chain":[{"macro":"string","args":null,"output_as":"string","note":"string"}],"enabled":null,"format":null,"source":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /spells/:spell_id/test

Test a spell (dry run)

Dry-run a spell with a sample event payload.

Handled by api_test_spell
Parameters
spell_id string · path
required
Body · TestSpellapplication/json
payload
required
event_name string
propertyName anything
Responses
200Successful Response
POST /spells/example/test
1curl -X POST "http://localhost:8000/spells/example/test" \
2 -H "Content-Type: application/json" \
3 -d '{"payload":null,"event_name":"string"}'
1fetch("http://localhost:8000/spells/example/test", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "payload": null,
6 "event_name": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/spells/example/test",
5 json={"payload":null,"event_name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /wands/spellbook

Transform YAML <-> spell

Stateless YAML <-> spell transformer (no persistence). POST /wands/spellbook with {"source": "<yaml>"} -> {"spell": {...}} POST /wands/spellbook with {"spell": {...}} -> {"yaml": "..."} Lets the editor swap between the visual builder and the YAML view without saving. The engine still runs on stored JSON; this only reshapes in flight.

Handled by api_spellbook_transform
Body · SpellbookTransformapplication/json
source string · max length: 100000
spell
propertyName anything
Responses
200Successful Response
POST /wands/spellbook
1curl -X POST "http://localhost:8000/wands/spellbook" \
2 -H "Content-Type: application/json" \
3 -d '{"source":"string","spell":null}'
1fetch("http://localhost:8000/wands/spellbook", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "source": "string",
6 "spell": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/wands/spellbook",
5 json={"source":"string","spell":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /wands/schedule-previews

Check a schedule and preview its next runs

Validate a schedule and return the next few times it would fire. Always answers 200 with {valid: bool}: an author typing into the field gets a friendly message, not a stream of 422s.

Handled by api_create_schedule_preview
Body · SchedulePreviewapplication/json
text string · min length: 1 · max length: 200
required
timezone string · max length: 64
propertyName anything
Responses
200Successful Response
POST /wands/schedule-previews
1curl -X POST "http://localhost:8000/wands/schedule-previews" \
2 -H "Content-Type: application/json" \
3 -d '{"text":"string","timezone":"string"}'
1fetch("http://localhost:8000/wands/schedule-previews", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "text": "string",
6 "timezone": "string"
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/wands/schedule-previews",
5 json={"text":"string","timezone":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /spells/:spell_id

Update a spell

Handled by api_update_spell
Parameters
spell_id string · path
required
Body · UpdateSpellapplication/json
name string · min length: 1 · max length: 200
description string · max length: 2000
trigger object
chain array
enabled
format
source string · max length: 100000
propertyName anything
Responses
200Successful Response
PUT /spells/example
1curl -X PUT "http://localhost:8000/spells/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","description":"string","trigger":{"events":["string"],"schedule":null,"where":null},"chain":[{"macro":"string","args":null,"output_as":"string","note":"string"}],"enabled":null,"format":null,"source":"string"}'
1fetch("http://localhost:8000/spells/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "description": "string",
7 "trigger": {
8 "events": [
9 "string"
10 ],
11 "schedule": null,
12 "where": null
13 },
14 "chain": [
15 {
16 "macro": "string",
17 "args": null,
18 "output_as": "string",
19 "note": "string"
20 }
21 ],
22 "enabled": null,
23 "format": null,
24 "source": "string"
25}),
26})
27 .then((res) => res.json())
28 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/spells/example",
5 json={"name":"string","description":"string","trigger":{"events":["string"],"schedule":null,"where":null},"chain":[{"macro":"string","args":null,"output_as":"string","note":"string"}],"enabled":null,"format":null,"source":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /suspended undocumented

/suspended

Render the subscription suspended recovery page. Shows payment methods, unpaid invoices, retry option, and delete workspace. Only accessible when subscription.status == 'suspended'.

Handled by suspended_page
Responses
200Successful Response
GET /suspended
1curl "http://localhost:8000/suspended"
1fetch("http://localhost:8000/suspended")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/suspended")
4print(response.json())
200 Example Response
No Body
DELETE /tables/:table_id undocumented

/tables/:table_id

DELETE /tables/:table_id — soft-delete a table.

Handled by api_delete_table
Parameters
table_id string · path
required
Responses
200Successful Response
DELETE /tables/example
1curl -X DELETE "http://localhost:8000/tables/example"
1fetch("http://localhost:8000/tables/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/tables/example")
4print(response.json())
200 Example Response
No Body
DELETE /tables/:table_id/sheets/:sheet_id undocumented

/tables/:table_id/sheets/:sheet_id

DELETE /tables/:table_id/sheets/:sheet_id — remove one sheet.

Handled by api_delete_sheet
Parameters
table_id string · path
required
sheet_id string · path
required
Responses
200Successful Response
DELETE /tables/example/sheets/example
1curl -X DELETE "http://localhost:8000/tables/example/sheets/example"
1fetch("http://localhost:8000/tables/example/sheets/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/tables/example/sheets/example")
4print(response.json())
200 Example Response
No Body
GET /tables undocumented

/tables

GET /tables — list tables for the workspace.

Handled by api_list_tables
Responses
200Successful Response
GET /tables
1curl "http://localhost:8000/tables"
1fetch("http://localhost:8000/tables")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/tables")
4print(response.json())
200 Example Response
No Body
GET /tables/:table_id undocumented

/tables/:table_id

GET /tables/:table_id — get a single table with data.

Handled by api_get_table
Parameters
table_id string · path
required
Responses
200Successful Response
GET /tables/example
1curl "http://localhost:8000/tables/example"
1fetch("http://localhost:8000/tables/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/tables/example")
4print(response.json())
200 Example Response
No Body
GET /tables/:table_id/versions undocumented

/tables/:table_id/versions

GET /tables/:table_id/versions — list version history.

Handled by api_list_versions
Parameters
table_id string · path
required
Responses
200Successful Response
GET /tables/example/versions
1curl "http://localhost:8000/tables/example/versions"
1fetch("http://localhost:8000/tables/example/versions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/tables/example/versions")
4print(response.json())
200 Example Response
No Body
GET /tables/:table_id/presence undocumented

/tables/:table_id/presence

GET /tables/:table_id/presence — get active collaborators.

Handled by api_get_presence
Parameters
table_id string · path
required
Responses
200Successful Response
GET /tables/example/presence
1curl "http://localhost:8000/tables/example/presence"
1fetch("http://localhost:8000/tables/example/presence")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/tables/example/presence")
4print(response.json())
200 Example Response
No Body
PATCH /tables/:table_id

Update a table

PATCH /tables/:table_id — update table title, icon, or data.

Handled by api_update_table
Parameters
table_id string · path
required
Body · UpdateTableapplication/json
title string · min length: 1 · max length: 500
icon string · max length: 100
icon_type
data string
visibility
propertyName anything
Responses
200Successful Response
PATCH /tables/example
1curl -X PATCH "http://localhost:8000/tables/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","icon":"string","icon_type":null,"data":"string","visibility":null}'
1fetch("http://localhost:8000/tables/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "icon": "string",
7 "icon_type": null,
8 "data": "string",
9 "visibility": null
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/tables/example",
5 json={"title":"string","icon":"string","icon_type":null,"data":"string","visibility":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /tables

Create a table

POST /tables — create a new table.

Handled by api_create_table
Body · CreateTableapplication/json
title string · min length: 1 · max length: 500
icon string · max length: 100
icon_type
data string
propertyName anything
Responses
200Successful Response
POST /tables
1curl -X POST "http://localhost:8000/tables" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","icon":"string","icon_type":null,"data":"string"}'
1fetch("http://localhost:8000/tables", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "icon": "string",
7 "icon_type": null,
8 "data": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/tables",
5 json={"title":"string","icon":"string","icon_type":null,"data":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /tables/:table_id/sheets/:sheet_id

Create or update a sheet

PUT /tables/:table_id/sheets/:sheet_id — create or update one sheet. The editor's debounced save PUTs only the sheets that actually changed, instead of PATCHing the whole workbook on every edit.

Handled by api_upsert_sheet
Parameters
table_id string · path
required
sheet_id string · path
required
Body · UpsertSheetapplication/json
name string · min length: 1 · max length: 200
position integer · min: 0 · max: 500
doc string
propertyName anything
Responses
200Successful Response
PUT /tables/example/sheets/example
1curl -X PUT "http://localhost:8000/tables/example/sheets/example" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string","position":1,"doc":"string"}'
1fetch("http://localhost:8000/tables/example/sheets/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string",
6 "position": 1,
7 "doc": "string"
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/tables/example/sheets/example",
5 json={"name":"string","position":1,"doc":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /tables/:table_id/presence undocumented

/tables/:table_id/presence

PUT /tables/:table_id/presence — update cursor position.

Handled by api_update_presence
Parameters
table_id string · path
required
Responses
200Successful Response
PUT /tables/example/presence
1curl -X PUT "http://localhost:8000/tables/example/presence"
1fetch("http://localhost:8000/tables/example/presence", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/tables/example/presence")
4print(response.json())
200 Example Response
No Body
DELETE /targets/:target_id undocumented

/targets/:target_id

Handled by api_delete_target
Parameters
target_id string · path
required
Responses
200Successful Response
DELETE /targets/example
1curl -X DELETE "http://localhost:8000/targets/example"
1fetch("http://localhost:8000/targets/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/targets/example")
4print(response.json())
200 Example Response
No Body
GET /targets undocumented

/targets

Handled by api_list_targets
Responses
200Successful Response
GET /targets
1curl "http://localhost:8000/targets"
1fetch("http://localhost:8000/targets")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/targets")
4print(response.json())
200 Example Response
No Body
GET /targets/leaderboard undocumented

/targets/leaderboard

Handled by api_leaderboard
Responses
200Successful Response
GET /targets/leaderboard
1curl "http://localhost:8000/targets/leaderboard"
1fetch("http://localhost:8000/targets/leaderboard")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/targets/leaderboard")
4print(response.json())
200 Example Response
No Body
GET /targets/:target_id undocumented

/targets/:target_id

Handled by api_get_target
Parameters
target_id string · path
required
Responses
200Successful Response
GET /targets/example
1curl "http://localhost:8000/targets/example"
1fetch("http://localhost:8000/targets/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/targets/example")
4print(response.json())
200 Example Response
No Body
POST /targets

Create a target

Handled by api_create_target
Body · CreateTargetapplication/json
type
required
owner_mrn string
required
pipeline_id string
period
required
period_start string
required
period_end string
required
target_value number
required
currency string
propertyName anything
Responses
200Successful Response
POST /targets
1curl -X POST "http://localhost:8000/targets" \
2 -H "Content-Type: application/json" \
3 -d '{"type":null,"owner_mrn":"string","pipeline_id":"string","period":null,"period_start":"string","period_end":"string","target_value":1.5,"currency":"string"}'
1fetch("http://localhost:8000/targets", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "type": null,
6 "owner_mrn": "string",
7 "pipeline_id": "string",
8 "period": null,
9 "period_start": "string",
10 "period_end": "string",
11 "target_value": 1.5,
12 "currency": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/targets",
5 json={"type":null,"owner_mrn":"string","pipeline_id":"string","period":null,"period_start":"string","period_end":"string","target_value":1.5,"currency":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /targets/:target_id

Update a target

Handled by api_update_target
Parameters
target_id string · path
required
Body · UpdateTargetapplication/json
type
owner_mrn string
period
period_start string
period_end string
target_value number
status
propertyName anything
Responses
200Successful Response
PUT /targets/example
1curl -X PUT "http://localhost:8000/targets/example" \
2 -H "Content-Type: application/json" \
3 -d '{"type":null,"owner_mrn":"string","period":null,"period_start":"string","period_end":"string","target_value":1.5,"status":null}'
1fetch("http://localhost:8000/targets/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "type": null,
6 "owner_mrn": "string",
7 "period": null,
8 "period_start": "string",
9 "period_end": "string",
10 "target_value": 1.5,
11 "status": null
12}),
13})
14 .then((res) => res.json())
15 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/targets/example",
5 json={"type":null,"owner_mrn":"string","period":null,"period_start":"string","period_end":"string","target_value":1.5,"status":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /tasks/:task_id undocumented

/tasks/:task_id

Handled by api_delete_task
Parameters
task_id string · path
required
Responses
200Successful Response
DELETE /tasks/example
1curl -X DELETE "http://localhost:8000/tasks/example"
1fetch("http://localhost:8000/tasks/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/tasks/example")
4print(response.json())
200 Example Response
No Body
DELETE /tasks

Delete tasks in bulk

Delete multiple tasks by ID.

Handled by api_bulk_delete_tasks
Body · BulkDeleteTasksapplication/json
task_ids array
required
propertyName anything
Responses
200Successful Response
DELETE /tasks
1curl -X DELETE "http://localhost:8000/tasks" \
2 -H "Content-Type: application/json" \
3 -d '{"task_ids":["string"]}'
1fetch("http://localhost:8000/tasks", {
2 method: "DELETE",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "task_ids": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.delete(
4 "http://localhost:8000/tasks",
5 json={"task_ids":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /tasks/:task_id/links/:link_id undocumented

/tasks/:task_id/links/:link_id

Handled by api_delete_task_link
Parameters
task_id string · path
required
link_id string · path
required
Responses
200Successful Response
DELETE /tasks/example/links/example
1curl -X DELETE "http://localhost:8000/tasks/example/links/example"
1fetch("http://localhost:8000/tasks/example/links/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/tasks/example/links/example")
4print(response.json())
200 Example Response
No Body
GET /tasks undocumented

/tasks

Handled by api_list_tasks
Responses
200Successful Response
GET /tasks
1curl "http://localhost:8000/tasks"
1fetch("http://localhost:8000/tasks")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/tasks")
4print(response.json())
200 Example Response
No Body
POST /tasks

Create a task

Handled by api_create_task
Body · CreateTaskapplication/json
title string · min length: 1 · max length: 200
required
board_id string
required
column_name string · min length: 1
parent_id string
on_board
priority
description string · max length: 10000
topic string
labels array
attachments array
assignee_mrn string
schedule_id string
due_date string
size integer · min: 1
source_mrn string
propertyName anything
Responses
200Successful Response
POST /tasks
1curl -X POST "http://localhost:8000/tasks" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","board_id":"string","column_name":"string","parent_id":"string","on_board":null,"priority":null,"description":"string","topic":"string","labels":["string"],"attachments":[{"key":"string","url":"string","filename":"string","content_type":"string","size":1}],"assignee_mrn":"string","schedule_id":"string","due_date":"string","size":1,"source_mrn":"string"}'
1fetch("http://localhost:8000/tasks", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "board_id": "string",
7 "column_name": "string",
8 "parent_id": "string",
9 "on_board": null,
10 "priority": null,
11 "description": "string",
12 "topic": "string",
13 "labels": [
14 "string"
15 ],
16 "attachments": [
17 {
18 "key": "string",
19 "url": "string",
20 "filename": "string",
21 "content_type": "string",
22 "size": 1
23 }
24 ],
25 "assignee_mrn": "string",
26 "schedule_id": "string",
27 "due_date": "string",
28 "size": 1,
29 "source_mrn": "string"
30}),
31})
32 .then((res) => res.json())
33 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/tasks",
5 json={"title":"string","board_id":"string","column_name":"string","parent_id":"string","on_board":null,"priority":null,"description":"string","topic":"string","labels":["string"],"attachments":[{"key":"string","url":"string","filename":"string","content_type":"string","size":1}],"assignee_mrn":"string","schedule_id":"string","due_date":"string","size":1,"source_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /tasks/completions

Mark tasks as completed

Mark multiple tasks as completed by moving them to a done column.

Handled by api_bulk_complete_tasks
Body · BulkCompleteTasksapplication/json
task_ids array
required
propertyName anything
Responses
200Successful Response
POST /tasks/completions
1curl -X POST "http://localhost:8000/tasks/completions" \
2 -H "Content-Type: application/json" \
3 -d '{"task_ids":["string"]}'
1fetch("http://localhost:8000/tasks/completions", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "task_ids": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/tasks/completions",
5 json={"task_ids":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /tasks/:task_id/links

Link two tasks

POST /tasks/:task_id/links — relate this task to another (blocks/relates/duplicates).

Handled by api_create_task_link
Parameters
task_id string · path
required
Body · CreateTaskLinkapplication/json
to_task_id string · min length: 1
required
kind
required
propertyName anything
Responses
200Successful Response
POST /tasks/example/links
1curl -X POST "http://localhost:8000/tasks/example/links" \
2 -H "Content-Type: application/json" \
3 -d '{"to_task_id":"string","kind":null}'
1fetch("http://localhost:8000/tasks/example/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "to_task_id": "string",
6 "kind": null
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/tasks/example/links",
5 json={"to_task_id":"string","kind":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /tasks/:task_id

Update a task

Handled by api_update_task
Parameters
task_id string · path
required
Body · UpdateTaskapplication/json
title string · min length: 1 · max length: 200
description string · max length: 50000
column_name string · min length: 1
assignee_mrn string
reporter_mrn string
reviewer_mrn string
priority
topic string
due_date string
start_date string
estimate_hours
logged_hours
wiki string · max length: 200000
blocked_by string
position
schedule_id string
deliverable_id string
parent_id string
size integer · min: 1
on_board
completed
labels array
attachments array
watchers array
add_comment object
propertyName anything
Responses
200Successful Response
PUT /tasks/example
1curl -X PUT "http://localhost:8000/tasks/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","description":"string","column_name":"string","assignee_mrn":"string","reporter_mrn":"string","reviewer_mrn":"string","priority":null,"topic":"string","due_date":"string","start_date":"string","estimate_hours":null,"logged_hours":null,"wiki":"string","blocked_by":"string","position":null,"schedule_id":"string","deliverable_id":"string","parent_id":"string","size":1,"on_board":null,"completed":null,"labels":["string"],"attachments":[{"key":"string","url":"string","filename":"string","content_type":"string","size":1}],"watchers":["string"],"add_comment":{"text":"string"}}'
1fetch("http://localhost:8000/tasks/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "description": "string",
7 "column_name": "string",
8 "assignee_mrn": "string",
9 "reporter_mrn": "string",
10 "reviewer_mrn": "string",
11 "priority": null,
12 "topic": "string",
13 "due_date": "string",
14 "start_date": "string",
15 "estimate_hours": null,
16 "logged_hours": null,
17 "wiki": "string",
18 "blocked_by": "string",
19 "position": null,
20 "schedule_id": "string",
21 "deliverable_id": "string",
22 "parent_id": "string",
23 "size": 1,
24 "on_board": null,
25 "completed": null,
26 "labels": [
27 "string"
28 ],
29 "attachments": [
30 {
31 "key": "string",
32 "url": "string",
33 "filename": "string",
34 "content_type": "string",
35 "size": 1
36 }
37 ],
38 "watchers": [
39 "string"
40 ],
41 "add_comment": {
42 "text": "string"
43 }
44}),
45})
46 .then((res) => res.json())
47 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/tasks/example",
5 json={"title":"string","description":"string","column_name":"string","assignee_mrn":"string","reporter_mrn":"string","reviewer_mrn":"string","priority":null,"topic":"string","due_date":"string","start_date":"string","estimate_hours":null,"logged_hours":null,"wiki":"string","blocked_by":"string","position":null,"schedule_id":"string","deliverable_id":"string","parent_id":"string","size":1,"on_board":null,"completed":null,"labels":["string"],"attachments":[{"key":"string","url":"string","filename":"string","content_type":"string","size":1}],"watchers":["string"],"add_comment":{"text":"string"}},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sign/templates

Create a reusable template

POST /sign/templates — create a reusable template.

Handled by api_create_template
Body · CreateEnvelopeapplication/json
title string · min length: 1 · max length: 300
required
subject string · max length: 300
message string · max length: 2000
template_id string
signing_order_mode
jurisdiction string · max length: 10
is_template
source_mrn string · max length: 200
propertyName anything
Responses
200Successful Response
POST /sign/templates
1curl -X POST "http://localhost:8000/sign/templates" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","subject":"string","message":"string","template_id":"string","signing_order_mode":null,"jurisdiction":"string","is_template":null,"source_mrn":"string"}'
1fetch("http://localhost:8000/sign/templates", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "subject": "string",
7 "message": "string",
8 "template_id": "string",
9 "signing_order_mode": null,
10 "jurisdiction": "string",
11 "is_template": null,
12 "source_mrn": "string"
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sign/templates",
5 json={"title":"string","subject":"string","message":"string","template_id":"string","signing_order_mode":null,"jurisdiction":"string","is_template":null,"source_mrn":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /sign/templates/:envelope_id/links

Publish the template as a self-serve link

POST /sign/templates/:envelope_id/links {expires_at?, max_submissions?} — publish the template as a URL anyone can open. Single-role templates only: the visitor fills that one role; multi-party agreements go through send.

Handled by api_create_public_link
Parameters
envelope_id string · path
required
Body · CreatePublicLinkapplication/json
expires_at string
max_submissions integer
propertyName anything
Responses
200Successful Response
POST /sign/templates/example/links
1curl -X POST "http://localhost:8000/sign/templates/example/links" \
2 -H "Content-Type: application/json" \
3 -d '{"expires_at":"string","max_submissions":1}'
1fetch("http://localhost:8000/sign/templates/example/links", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "expires_at": "string",
6 "max_submissions": 1
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/sign/templates/example/links",
5 json={"expires_at":"string","max_submissions":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /terms undocumented

/terms

Handled by terms
Responses
200Successful Response
GET /terms
1curl "http://localhost:8000/terms"
1fetch("http://localhost:8000/terms")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/terms")
4print(response.json())
200 Example Response
No Body
GET /totps/status undocumented

/totps/status

Handled by totp_status
Responses
200Successful Response
GET /totps/status
1curl "http://localhost:8000/totps/status"
1fetch("http://localhost:8000/totps/status")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/totps/status")
4print(response.json())
200 Example Response
No Body
POST /totps undocumented

/totps

Handled by create_totp
Responses
200Successful Response
POST /totps
1curl -X POST "http://localhost:8000/totps"
1fetch("http://localhost:8000/totps", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/totps")
4print(response.json())
200 Example Response
No Body
DELETE /trash undocumented

/trash

Handled by api_empty_trash
Responses
200Successful Response
DELETE /trash
1curl -X DELETE "http://localhost:8000/trash"
1fetch("http://localhost:8000/trash", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/trash")
4print(response.json())
200 Example Response
No Body
GET /trash undocumented

/trash

Handled by api_list_trash
Responses
200Successful Response
GET /trash
1curl "http://localhost:8000/trash"
1fetch("http://localhost:8000/trash")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/trash")
4print(response.json())
200 Example Response
No Body
POST /trash/restorations

Restore from trash

Handled by api_restore_trash
Body · TrashRestoreapplication/json
ids array
required
propertyName anything
Responses
200Successful Response
POST /trash/restorations
1curl -X POST "http://localhost:8000/trash/restorations" \
2 -H "Content-Type: application/json" \
3 -d '{"ids":["string"]}'
1fetch("http://localhost:8000/trash/restorations", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "ids": [
6 "string"
7 ]
8}),
9})
10 .then((res) => res.json())
11 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/trash/restorations",
5 json={"ids":["string"]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /v/admin/versions/:version/notes/:note_id undocumented

/v/admin/versions/:version/notes/:note_id

DELETE /v/admin/versions/:version/notes/:note_id — remove an internal note.

Handled by api_remove_version_note
Parameters
version string · path
required
note_id string · path
required
Responses
200Successful Response
DELETE /v/admin/versions/example/notes/example
1curl -X DELETE "http://localhost:8000/v/admin/versions/example/notes/example"
1fetch("http://localhost:8000/v/admin/versions/example/notes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/v/admin/versions/example/notes/example")
4print(response.json())
200 Example Response
No Body
DELETE /v/admin/coupon-redemptions/:id undocumented

/v/admin/coupon-redemptions/:id

DELETE /v/admin/coupon-redemptions/:id — unapply a redemption and subtract days.

Handled by api_remove_redemption
Parameters
id string · path
required
Responses
200Successful Response
DELETE /v/admin/coupon-redemptions/example
1curl -X DELETE "http://localhost:8000/v/admin/coupon-redemptions/example"
1fetch("http://localhost:8000/v/admin/coupon-redemptions/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/v/admin/coupon-redemptions/example")
4print(response.json())
200 Example Response
No Body
DELETE /v/admin/preview-apps/:slug/adopters/:workspace_id undocumented

/v/admin/preview-apps/:slug/adopters/:workspace_id

DELETE /v/admin/preview-apps/:slug/adopters/:workspace_id — remove from the allowlist.

Handled by api_remove_early_adopter
Parameters
slug string · path
required
workspace_id string · path
required
Responses
200Successful Response
DELETE /v/admin/preview-apps/example/adopters/example
1curl -X DELETE "http://localhost:8000/v/admin/preview-apps/example/adopters/example"
1fetch("http://localhost:8000/v/admin/preview-apps/example/adopters/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/v/admin/preview-apps/example/adopters/example")
4print(response.json())
200 Example Response
No Body
GET /v/admin/stats undocumented

/v/admin/stats

GET /v/admin/stats — summary stats for the admin dashboard.

Handled by api_dashboard_stats
Responses
200Successful Response
GET /v/admin/stats
1curl "http://localhost:8000/v/admin/stats"
1fetch("http://localhost:8000/v/admin/stats")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/stats")
4print(response.json())
200 Example Response
No Body
GET /v/admin/workspaces undocumented

/v/admin/workspaces

GET /v/admin/workspaces — list all workspaces (paginated, filterable).

Handled by api_list_workspaces
Responses
200Successful Response
GET /v/admin/workspaces
1curl "http://localhost:8000/v/admin/workspaces"
1fetch("http://localhost:8000/v/admin/workspaces")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/workspaces")
4print(response.json())
200 Example Response
No Body
GET /v/admin/workspaces/:id undocumented

/v/admin/workspaces/:id

GET /v/admin/workspaces/:id — workspace detail.

Handled by api_get_workspace
Parameters
id string · path
required
Responses
200Successful Response
GET /v/admin/workspaces/example
1curl "http://localhost:8000/v/admin/workspaces/example"
1fetch("http://localhost:8000/v/admin/workspaces/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/workspaces/example")
4print(response.json())
200 Example Response
No Body
GET /v/admin/workspaces/:id/members undocumented

/v/admin/workspaces/:id/members

GET /v/admin/workspaces/:id/members — members of a workspace.

Handled by api_workspace_members
Parameters
id string · path
required
Responses
200Successful Response
GET /v/admin/workspaces/example/members
1curl "http://localhost:8000/v/admin/workspaces/example/members"
1fetch("http://localhost:8000/v/admin/workspaces/example/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/workspaces/example/members")
4print(response.json())
200 Example Response
No Body
GET /v/admin/workspaces/:id/apps undocumented

/v/admin/workspaces/:id/apps

GET /v/admin/workspaces/:id/apps — installed apps for a workspace.

Handled by api_workspace_apps
Parameters
id string · path
required
Responses
200Successful Response
GET /v/admin/workspaces/example/apps
1curl "http://localhost:8000/v/admin/workspaces/example/apps"
1fetch("http://localhost:8000/v/admin/workspaces/example/apps")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/workspaces/example/apps")
4print(response.json())
200 Example Response
No Body
GET /v/admin/workspaces/:id/invoices undocumented

/v/admin/workspaces/:id/invoices

GET /v/admin/workspaces/:id/invoices — invoices for a workspace.

Handled by api_workspace_invoices
Parameters
id string · path
required
Responses
200Successful Response
GET /v/admin/workspaces/example/invoices
1curl "http://localhost:8000/v/admin/workspaces/example/invoices"
1fetch("http://localhost:8000/v/admin/workspaces/example/invoices")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/workspaces/example/invoices")
4print(response.json())
200 Example Response
No Body
GET /v/admin/workspaces/:id/usage undocumented

/v/admin/workspaces/:id/usage

GET /v/admin/workspaces/:id/usage — current period usage meters.

Handled by api_workspace_usage
Parameters
id string · path
required
Responses
200Successful Response
GET /v/admin/workspaces/example/usage
1curl "http://localhost:8000/v/admin/workspaces/example/usage"
1fetch("http://localhost:8000/v/admin/workspaces/example/usage")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/workspaces/example/usage")
4print(response.json())
200 Example Response
No Body
GET /v/admin/settings/billing-alerts undocumented

/v/admin/settings/billing-alerts

GET /v/admin/settings/billing-alerts — operator alert recipients.

Handled by api_get_billing_alerts
Responses
200Successful Response
GET /v/admin/settings/billing-alerts
1curl "http://localhost:8000/v/admin/settings/billing-alerts"
1fetch("http://localhost:8000/v/admin/settings/billing-alerts")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/settings/billing-alerts")
4print(response.json())
200 Example Response
No Body
GET /v/admin/invoices undocumented

/v/admin/invoices

GET /v/admin/invoices — global invoice list (paginated, filterable).

Handled by api_list_invoices
Responses
200Successful Response
GET /v/admin/invoices
1curl "http://localhost:8000/v/admin/invoices"
1fetch("http://localhost:8000/v/admin/invoices")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/invoices")
4print(response.json())
200 Example Response
No Body
GET /v/admin/threads undocumented

/v/admin/threads

GET /v/admin/threads — list all support threads.

Handled by api_list_threads
Responses
200Successful Response
GET /v/admin/threads
1curl "http://localhost:8000/v/admin/threads"
1fetch("http://localhost:8000/v/admin/threads")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/threads")
4print(response.json())
200 Example Response
No Body
GET /v/admin/threads/:id undocumented

/v/admin/threads/:id

GET /v/admin/threads/:id — thread detail + messages.

Handled by api_get_thread
Parameters
id string · path
required
Responses
200Successful Response
GET /v/admin/threads/example
1curl "http://localhost:8000/v/admin/threads/example"
1fetch("http://localhost:8000/v/admin/threads/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/threads/example")
4print(response.json())
200 Example Response
No Body
GET /v/admin/audit undocumented

/v/admin/audit

GET /v/admin/audit — audit log (paginated, filterable).

Handled by api_list_audit_log
Responses
200Successful Response
GET /v/admin/audit
1curl "http://localhost:8000/v/admin/audit"
1fetch("http://localhost:8000/v/admin/audit")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/audit")
4print(response.json())
200 Example Response
No Body
GET /v/admin/profiles undocumented

/v/admin/profiles

GET /v/admin/profiles?q=... — search profiles for micron invite.

Handled by api_search_profiles
Responses
200Successful Response
GET /v/admin/profiles
1curl "http://localhost:8000/v/admin/profiles"
1fetch("http://localhost:8000/v/admin/profiles")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/profiles")
4print(response.json())
200 Example Response
No Body
GET /v/admin/microns undocumented

/v/admin/microns

GET /v/admin/microns — list all microns (paginated, searchable).

Handled by api_list_microns
Responses
200Successful Response
GET /v/admin/microns
1curl "http://localhost:8000/v/admin/microns"
1fetch("http://localhost:8000/v/admin/microns")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/microns")
4print(response.json())
200 Example Response
No Body
GET /v/admin/coupons undocumented

/v/admin/coupons

GET /v/admin/coupons — list coupons with optional search.

Handled by api_list_coupons
Responses
200Successful Response
GET /v/admin/coupons
1curl "http://localhost:8000/v/admin/coupons"
1fetch("http://localhost:8000/v/admin/coupons")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/coupons")
4print(response.json())
200 Example Response
No Body
GET /v/admin/coupons/:code undocumented

/v/admin/coupons/:code

GET /v/admin/coupons/:code — coupon detail + redemption history.

Handled by api_get_coupon
Parameters
code string · path
required
Responses
200Successful Response
GET /v/admin/coupons/example
1curl "http://localhost:8000/v/admin/coupons/example"
1fetch("http://localhost:8000/v/admin/coupons/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/coupons/example")
4print(response.json())
200 Example Response
No Body
GET /v/admin/demo-requests undocumented

/v/admin/demo-requests

GET /v/admin/demo-requests — list demo requests (paginated, filterable).

Handled by api_list_demos
Responses
200Successful Response
GET /v/admin/demo-requests
1curl "http://localhost:8000/v/admin/demo-requests"
1fetch("http://localhost:8000/v/admin/demo-requests")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/demo-requests")
4print(response.json())
200 Example Response
No Body
GET /v/admin/preview-apps undocumented

/v/admin/preview-apps

GET /v/admin/preview-apps — preview apps with their early-adopter allowlists.

Handled by api_list_preview_apps
Responses
200Successful Response
GET /v/admin/preview-apps
1curl "http://localhost:8000/v/admin/preview-apps"
1fetch("http://localhost:8000/v/admin/preview-apps")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/preview-apps")
4print(response.json())
200 Example Response
No Body
GET /v/admin/preview-apps/workspace-search undocumented

/v/admin/preview-apps/workspace-search

GET /v/admin/preview-apps/workspace-search?q= — find workspaces to add.

Handled by api_preview_workspace_search
Responses
200Successful Response
GET /v/admin/preview-apps/workspace-search
1curl "http://localhost:8000/v/admin/preview-apps/workspace-search"
1fetch("http://localhost:8000/v/admin/preview-apps/workspace-search")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/v/admin/preview-apps/workspace-search")
4print(response.json())
200 Example Response
No Body
PATCH /v/admin/workspaces/:id/billing undocumented

/v/admin/workspaces/:id/billing

PATCH /v/admin/workspaces/:id/billing — adjust billing controls. Region is operator-controlled: it derives from the signup country and only the Micron console may correct it (self-service switching allowed customers to pick the cheaper rate).

Handled by api_update_workspace_billing
Parameters
id string · path
required
Responses
200Successful Response
PATCH /v/admin/workspaces/example/billing
1curl -X PATCH "http://localhost:8000/v/admin/workspaces/example/billing"
1fetch("http://localhost:8000/v/admin/workspaces/example/billing", { method: "PATCH" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.patch("http://localhost:8000/v/admin/workspaces/example/billing")
4print(response.json())
200 Example Response
No Body
PATCH /v/admin/coupons/:code undocumented

/v/admin/coupons/:code

PATCH /v/admin/coupons/:code — flip is_active (admin revoke/restore).

Handled by api_update_coupon
Parameters
code string · path
required
Responses
200Successful Response
PATCH /v/admin/coupons/example
1curl -X PATCH "http://localhost:8000/v/admin/coupons/example"
1fetch("http://localhost:8000/v/admin/coupons/example", { method: "PATCH" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.patch("http://localhost:8000/v/admin/coupons/example")
4print(response.json())
200 Example Response
No Body
PATCH /v/admin/demo-requests/:id undocumented

/v/admin/demo-requests/:id

PATCH /v/admin/demo-requests/:id — update a demo request's status.

Handled by api_update_demo
Parameters
id string · path
required
Responses
200Successful Response
PATCH /v/admin/demo-requests/example
1curl -X PATCH "http://localhost:8000/v/admin/demo-requests/example"
1fetch("http://localhost:8000/v/admin/demo-requests/example", { method: "PATCH" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.patch("http://localhost:8000/v/admin/demo-requests/example")
4print(response.json())
200 Example Response
No Body
POST /v/admin/workspaces/:id/winback-emails undocumented

/v/admin/workspaces/:id/winback-emails

POST /v/admin/workspaces/:id/winback-emails — invite a suspended workspace back. Manual, per-workspace, from the console: emails every owner/admin the win-back note with the current entry price for their region.

Handled by api_send_winback
Parameters
id string · path
required
Responses
200Successful Response
POST /v/admin/workspaces/example/winback-emails
1curl -X POST "http://localhost:8000/v/admin/workspaces/example/winback-emails"
1fetch("http://localhost:8000/v/admin/workspaces/example/winback-emails", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/workspaces/example/winback-emails")
4print(response.json())
200 Example Response
No Body
POST /v/admin/invoices/:id/refunds undocumented

/v/admin/invoices/:id/refunds

POST /v/admin/invoices/:id/refunds {amount?, reason} — refund a paid invoice. Full refunds (no amount) mark the invoice 'refunded'; partial refunds keep it 'paid' with the action recorded in the audit log either way.

Handled by api_refund_invoice
Parameters
id string · path
required
Responses
200Successful Response
POST /v/admin/invoices/example/refunds
1curl -X POST "http://localhost:8000/v/admin/invoices/example/refunds"
1fetch("http://localhost:8000/v/admin/invoices/example/refunds", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/invoices/example/refunds")
4print(response.json())
200 Example Response
No Body
POST /v/admin/invoices/:id/charge undocumented

/v/admin/invoices/:id/charge

POST /v/admin/invoices/:id/charge — retry payment on an invoice.

Handled by api_retry_payment
Parameters
id string · path
required
Responses
200Successful Response
POST /v/admin/invoices/example/charge
1curl -X POST "http://localhost:8000/v/admin/invoices/example/charge"
1fetch("http://localhost:8000/v/admin/invoices/example/charge", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/invoices/example/charge")
4print(response.json())
200 Example Response
No Body
POST /v/admin/threads/:id/messages undocumented

/v/admin/threads/:id/messages

POST /v/admin/threads/:id/messages — micron replies to a thread.

Handled by api_reply_thread
Parameters
id string · path
required
Responses
200Successful Response
POST /v/admin/threads/example/messages
1curl -X POST "http://localhost:8000/v/admin/threads/example/messages"
1fetch("http://localhost:8000/v/admin/threads/example/messages", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/threads/example/messages")
4print(response.json())
200 Example Response
No Body
POST /v/admin/microns undocumented

/v/admin/microns

POST /v/admin/microns — add a profile as micron. Owner can add admin or member. Admin can add member only.

Handled by api_invite_micron
Responses
200Successful Response
POST /v/admin/microns
1curl -X POST "http://localhost:8000/v/admin/microns"
1fetch("http://localhost:8000/v/admin/microns", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/microns")
4print(response.json())
200 Example Response
No Body
POST /v/admin/versions/:version/notes undocumented

/v/admin/versions/:version/notes

POST /v/admin/versions/:version/notes — append an internal note to a release.

Handled by api_add_version_note
Parameters
version string · path
required
Responses
200Successful Response
POST /v/admin/versions/example/notes
1curl -X POST "http://localhost:8000/v/admin/versions/example/notes"
1fetch("http://localhost:8000/v/admin/versions/example/notes", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/versions/example/notes")
4print(response.json())
200 Example Response
No Body
POST /v/admin/coupons undocumented

/v/admin/coupons

POST /v/admin/coupons — create a new coupon. Owner or admin only.

Handled by api_create_coupon
Responses
200Successful Response
POST /v/admin/coupons
1curl -X POST "http://localhost:8000/v/admin/coupons"
1fetch("http://localhost:8000/v/admin/coupons", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/coupons")
4print(response.json())
200 Example Response
No Body
POST /v/admin/preview-apps/:slug/adopters undocumented

/v/admin/preview-apps/:slug/adopters

POST /v/admin/preview-apps/:slug/adopters — add a workspace to the allowlist.

Handled by api_add_early_adopter
Parameters
slug string · path
required
Responses
200Successful Response
POST /v/admin/preview-apps/example/adopters
1curl -X POST "http://localhost:8000/v/admin/preview-apps/example/adopters"
1fetch("http://localhost:8000/v/admin/preview-apps/example/adopters", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/v/admin/preview-apps/example/adopters")
4print(response.json())
200 Example Response
No Body
PUT /v/admin/workspaces/:id/subscription undocumented

/v/admin/workspaces/:id/subscription

PUT /v/admin/workspaces/:id/subscription — lock or unlock a workspace.

Handled by api_update_subscription
Parameters
id string · path
required
Responses
200Successful Response
PUT /v/admin/workspaces/example/subscription
1curl -X PUT "http://localhost:8000/v/admin/workspaces/example/subscription"
1fetch("http://localhost:8000/v/admin/workspaces/example/subscription", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/v/admin/workspaces/example/subscription")
4print(response.json())
200 Example Response
No Body
PUT /v/admin/settings/billing-alerts undocumented

/v/admin/settings/billing-alerts

PUT /v/admin/settings/billing-alerts — set operator alert recipients. These addresses receive an email whenever a customer charge fails or a workspace gets suspended for non-payment. Empty list turns emails off (the console invoice list remains the fallback).

Handled by api_set_billing_alerts
Responses
200Successful Response
PUT /v/admin/settings/billing-alerts
1curl -X PUT "http://localhost:8000/v/admin/settings/billing-alerts"
1fetch("http://localhost:8000/v/admin/settings/billing-alerts", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/v/admin/settings/billing-alerts")
4print(response.json())
200 Example Response
No Body
PUT /v/admin/invoices/:id undocumented

/v/admin/invoices/:id

PUT /v/admin/invoices/:id — void an invoice.

Handled by api_update_invoice
Parameters
id string · path
required
Responses
200Successful Response
PUT /v/admin/invoices/example
1curl -X PUT "http://localhost:8000/v/admin/invoices/example"
1fetch("http://localhost:8000/v/admin/invoices/example", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/v/admin/invoices/example")
4print(response.json())
200 Example Response
No Body
PUT /v/admin/threads/:id undocumented

/v/admin/threads/:id

PUT /v/admin/threads/:id — update thread (assign, priority, status).

Handled by api_update_thread
Parameters
id string · path
required
Responses
200Successful Response
PUT /v/admin/threads/example
1curl -X PUT "http://localhost:8000/v/admin/threads/example"
1fetch("http://localhost:8000/v/admin/threads/example", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/v/admin/threads/example")
4print(response.json())
200 Example Response
No Body
PUT /v/admin/microns/:id undocumented

/v/admin/microns/:id

PUT /v/admin/microns/:id — update a micron's role or revoke access. Owner can change any role. Admin cannot change owners or other admins.

Handled by api_update_micron
Parameters
id string · path
required
Responses
200Successful Response
PUT /v/admin/microns/example
1curl -X PUT "http://localhost:8000/v/admin/microns/example"
1fetch("http://localhost:8000/v/admin/microns/example", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/v/admin/microns/example")
4print(response.json())
200 Example Response
No Body
POST /verifications/resend undocumented

/verifications/resend

Handled by resend_otp
Responses
200Successful Response
POST /verifications/resend
1curl -X POST "http://localhost:8000/verifications/resend"
1fetch("http://localhost:8000/verifications/resend", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/verifications/resend")
4print(response.json())
200 Example Response
No Body
GET /verify undocumented

/verify

Handled by verify_page
Responses
200Successful Response
GET /verify
1curl "http://localhost:8000/verify"
1fetch("http://localhost:8000/verify")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/verify")
4print(response.json())
200 Example Response
No Body
DELETE /views/:view_id undocumented

/views/:view_id

Handled by api_delete_saved_view
Parameters
view_id string · path
required
Responses
200Successful Response
DELETE /views/example
1curl -X DELETE "http://localhost:8000/views/example"
1fetch("http://localhost:8000/views/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/views/example")
4print(response.json())
200 Example Response
No Body
GET /views undocumented

/views

Handled by api_list_saved_views
Responses
200Successful Response
GET /views
1curl "http://localhost:8000/views"
1fetch("http://localhost:8000/views")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/views")
4print(response.json())
200 Example Response
No Body
GET /wands/events undocumented

/wands/events

List all platform events available as flow triggers.

Handled by api_list_events
Responses
200Successful Response
GET /wands/events
1curl "http://localhost:8000/wands/events"
1fetch("http://localhost:8000/wands/events")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/events")
4print(response.json())
200 Example Response
No Body
GET /wands/filters undocumented

/wands/filters

List all registered Jinja2 filters with descriptions.

Handled by api_list_filters
Responses
200Successful Response
GET /wands/filters
1curl "http://localhost:8000/wands/filters"
1fetch("http://localhost:8000/wands/filters")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/filters")
4print(response.json())
200 Example Response
No Body
GET /wands/context/:spell_id/:step_index undocumented

/wands/context/:spell_id/:step_index

Get available context variables for a given step in a spell's chain.

Handled by api_get_step_context
Parameters
spell_id string · path
required
step_index string · path
required
Responses
200Successful Response
GET /wands/context/example/example
1curl "http://localhost:8000/wands/context/example/example"
1fetch("http://localhost:8000/wands/context/example/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/context/example/example")
4print(response.json())
200 Example Response
No Body
GET /wands/macros undocumented

/wands/macros

All macros. ?grouped=true returns them in category order with Spellbook-rendered examples (what the reference page renders).

Handled by api_list_macros
Responses
200Successful Response
GET /wands/macros
1curl "http://localhost:8000/wands/macros"
1fetch("http://localhost:8000/wands/macros")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/macros")
4print(response.json())
200 Example Response
No Body
GET /wands/macros/:macro_name undocumented

/wands/macros/:macro_name

Handled by api_get_macro
Parameters
macro_name string · path
required
Responses
200Successful Response
GET /wands/macros/example
1curl "http://localhost:8000/wands/macros/example"
1fetch("http://localhost:8000/wands/macros/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/macros/example")
4print(response.json())
200 Example Response
No Body
GET /wands/samples undocumented

/wands/samples

Recent REAL payloads captured in this workspace. With ?action=core.crm.deal.won: every stored sample for that event. Without it: the latest sample for each event seen, so the builder and the macro playground can offer a menu of real payloads to try.

Handled by api_list_event_samples
Responses
200Successful Response
GET /wands/samples
1curl "http://localhost:8000/wands/samples"
1fetch("http://localhost:8000/wands/samples")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/samples")
4print(response.json())
200 Example Response
No Body
GET /wands/recipes undocumented

/wands/recipes

Curated recipe gallery, filtered to the workspace's installed apps.

Handled by api_list_recipes
Responses
200Successful Response
GET /wands/recipes
1curl "http://localhost:8000/wands/recipes"
1fetch("http://localhost:8000/wands/recipes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/recipes")
4print(response.json())
200 Example Response
No Body
GET /wands/stats undocumented

/wands/stats

Workspace automation dashboard payload.

Handled by api_wands_stats
Responses
200Successful Response
GET /wands/stats
1curl "http://localhost:8000/wands/stats"
1fetch("http://localhost:8000/wands/stats")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wands/stats")
4print(response.json())
200 Example Response
No Body
POST /webhooks/livekit-rooms undocumented

/webhooks/livekit-rooms

LiveKit sends participant events here. Update is_connected state.

Handled by livekit_webhook
Responses
200Successful Response
POST /webhooks/livekit-rooms
1curl -X POST "http://localhost:8000/webhooks/livekit-rooms"
1fetch("http://localhost:8000/webhooks/livekit-rooms", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/webhooks/livekit-rooms")
4print(response.json())
200 Example Response
No Body
POST /webhooks/livekit undocumented

/webhooks/livekit

Handled by livekit_webhook
Responses
200Successful Response
POST /webhooks/livekit
1curl -X POST "http://localhost:8000/webhooks/livekit"
1fetch("http://localhost:8000/webhooks/livekit", { method: "POST" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.post("http://localhost:8000/webhooks/livekit")
4print(response.json())
200 Example Response
No Body
GET /wiki/share-roles undocumented

/wiki/share-roles

GET /wiki/share-roles — roles a member may add to a page share list.

Handled by api_list_share_roles
Responses
200Successful Response
GET /wiki/share-roles
1curl "http://localhost:8000/wiki/share-roles"
1fetch("http://localhost:8000/wiki/share-roles")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wiki/share-roles")
4print(response.json())
200 Example Response
No Body
PATCH /wikis/:page_id

Update a wiki page

PATCH /wikis/:page_id — update page title, content, icon, etc.

Handled by api_update_page
Parameters
page_id string · path
required
Body · UpdatePageapplication/json
title string · min length: 1 · max length: 500
icon string · max length: 100
icon_type
content string
position integer · min: 0
parent_id string
propertyName anything
Responses
200Successful Response
PATCH /wikis/example
1curl -X PATCH "http://localhost:8000/wikis/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","icon":"string","icon_type":null,"content":"string","position":1,"parent_id":"string"}'
1fetch("http://localhost:8000/wikis/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "icon": "string",
7 "icon_type": null,
8 "content": "string",
9 "position": 1,
10 "parent_id": "string"
11}),
12})
13 .then((res) => res.json())
14 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/wikis/example",
5 json={"title":"string","icon":"string","icon_type":null,"content":"string","position":1,"parent_id":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /wikis/:page_id/comments/:comment_id

Resolve/unresolve comment

PATCH /wikis/:page_id/comments/:comment_id — resolve or unresolve.

Handled by api_resolve_comment
Parameters
page_id string · path
required
comment_id string · path
required
Body · ResolveCommentapplication/json
resolved
required
propertyName anything
Responses
200Successful Response
PATCH /wikis/example/comments/example
1curl -X PATCH "http://localhost:8000/wikis/example/comments/example" \
2 -H "Content-Type: application/json" \
3 -d '{"resolved":null}'
1fetch("http://localhost:8000/wikis/example/comments/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "resolved": null
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/wikis/example/comments/example",
5 json={"resolved":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /wikis

Create a wiki page

POST /wikis — create a new wiki page.

Handled by api_create_page
Body · CreatePageapplication/json
title string · min length: 1 · max length: 500
required
parent_id string
icon string · max length: 100
icon_type
content string
propertyName anything
Responses
200Successful Response
POST /wikis
1curl -X POST "http://localhost:8000/wikis" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","parent_id":"string","icon":"string","icon_type":null,"content":"string"}'
1fetch("http://localhost:8000/wikis", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "parent_id": "string",
7 "icon": "string",
8 "icon_type": null,
9 "content": "string"
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/wikis",
5 json={"title":"string","parent_id":"string","icon":"string","icon_type":null,"content":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /wikis/:page_id/comments

Add a comment

POST /wikis/:page_id/comments — add a comment.

Handled by api_create_comment
Parameters
page_id string · path
required
Body · CreateCommentapplication/json
body string · min length: 1 · max length: 4000
required
object_id string · max length: 64
parent_id string · max length: 64
nx number
ny number
propertyName anything
Responses
200Successful Response
POST /wikis/example/comments
1curl -X POST "http://localhost:8000/wikis/example/comments" \
2 -H "Content-Type: application/json" \
3 -d '{"body":"string","object_id":"string","parent_id":"string","nx":1.5,"ny":1.5}'
1fetch("http://localhost:8000/wikis/example/comments", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "body": "string",
6 "object_id": "string",
7 "parent_id": "string",
8 "nx": 1.5,
9 "ny": 1.5
10}),
11})
12 .then((res) => res.json())
13 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/wikis/example/comments",
5 json={"body":"string","object_id":"string","parent_id":"string","nx":1.5,"ny":1.5},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /wikis/:page_id/position

Move/reorder a page

PUT /wikis/:page_id/position — move a page to a new parent/position.

Handled by api_move_page
Parameters
page_id string · path
required
Body · MovePageapplication/json
parent_id string
position integer · min: 0
required
propertyName anything
Responses
200Successful Response
PUT /wikis/example/position
1curl -X PUT "http://localhost:8000/wikis/example/position" \
2 -H "Content-Type: application/json" \
3 -d '{"parent_id":"string","position":1}'
1fetch("http://localhost:8000/wikis/example/position", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "parent_id": "string",
6 "position": 1
7}),
8})
9 .then((res) => res.json())
10 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/wikis/example/position",
5 json={"parent_id":"string","position":1},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /wikis/:page_id/access

Change page visibility and share list

PUT /wikis/:page_id/access — change visibility and share list. Requires manage-level access (authz: can_manage_page).

Handled by api_update_page_access
Parameters
page_id string · path
required
Body · UpdatePageAccessapplication/json
visibility
required
shares array
required
propertyName anything
Responses
200Successful Response
PUT /wikis/example/access
1curl -X PUT "http://localhost:8000/wikis/example/access" \
2 -H "Content-Type: application/json" \
3 -d '{"visibility":null,"shares":[{"type":null,"id":"string","level":null}]}'
1fetch("http://localhost:8000/wikis/example/access", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "visibility": null,
6 "shares": [
7 {
8 "type": null,
9 "id": "string",
10 "level": null
11 }
12 ]
13}),
14})
15 .then((res) => res.json())
16 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/wikis/example/access",
5 json={"visibility":null,"shares":[{"type":null,"id":"string","level":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /wikis/:page_id undocumented

/wikis/:page_id

DELETE /wikis/:page_id — soft-delete a page and its descendants.

Handled by api_delete_page
Parameters
page_id string · path
required
Responses
200Successful Response
DELETE /wikis/example
1curl -X DELETE "http://localhost:8000/wikis/example"
1fetch("http://localhost:8000/wikis/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/wikis/example")
4print(response.json())
200 Example Response
No Body
DELETE /wikis/:page_id/comments/:comment_id undocumented

/wikis/:page_id/comments/:comment_id

DELETE /wikis/:page_id/comments/:comment_id — delete a comment.

Handled by api_delete_comment
Parameters
page_id string · path
required
comment_id string · path
required
Responses
200Successful Response
DELETE /wikis/example/comments/example
1curl -X DELETE "http://localhost:8000/wikis/example/comments/example"
1fetch("http://localhost:8000/wikis/example/comments/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/wikis/example/comments/example")
4print(response.json())
200 Example Response
No Body
GET /wikis undocumented

/wikis

GET /wikis — list root-level pages. Restricted pages the caller cannot access are filtered out at query time. Owners/admins see everything (platform bypass).

Handled by api_list_pages
Responses
200Successful Response
GET /wikis
1curl "http://localhost:8000/wikis"
1fetch("http://localhost:8000/wikis")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wikis")
4print(response.json())
200 Example Response
No Body
GET /wikis/:page_id undocumented

/wikis/:page_id

GET /wikis/:page_id — get a single page with content.

Handled by api_get_page
Parameters
page_id string · path
required
Responses
200Successful Response
GET /wikis/example
1curl "http://localhost:8000/wikis/example"
1fetch("http://localhost:8000/wikis/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wikis/example")
4print(response.json())
200 Example Response
No Body
GET /wikis/:page_id/children undocumented

/wikis/:page_id/children

GET /wikis/:page_id/children — list child pages. Filters out restricted children the caller cannot access.

Handled by api_list_children
Parameters
page_id string · path
required
Responses
200Successful Response
GET /wikis/example/children
1curl "http://localhost:8000/wikis/example/children"
1fetch("http://localhost:8000/wikis/example/children")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wikis/example/children")
4print(response.json())
200 Example Response
No Body
GET /wikis/:page_id/versions undocumented

/wikis/:page_id/versions

GET /wikis/:page_id/versions — list version history.

Handled by api_list_versions
Parameters
page_id string · path
required
Responses
200Successful Response
GET /wikis/example/versions
1curl "http://localhost:8000/wikis/example/versions"
1fetch("http://localhost:8000/wikis/example/versions")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wikis/example/versions")
4print(response.json())
200 Example Response
No Body
GET /wikis/:page_id/versions/:version_id undocumented

/wikis/:page_id/versions/:version_id

GET /wikis/:page_id/versions/:version_id — get a single version.

Handled by api_get_version
Parameters
page_id string · path
required
version_id string · path
required
Responses
200Successful Response
GET /wikis/example/versions/example
1curl "http://localhost:8000/wikis/example/versions/example"
1fetch("http://localhost:8000/wikis/example/versions/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wikis/example/versions/example")
4print(response.json())
200 Example Response
No Body
GET /wikis/:page_id/comments undocumented

/wikis/:page_id/comments

GET /wikis/:page_id/comments — list comments for a page.

Handled by api_list_comments
Parameters
page_id string · path
required
Responses
200Successful Response
GET /wikis/example/comments
1curl "http://localhost:8000/wikis/example/comments"
1fetch("http://localhost:8000/wikis/example/comments")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wikis/example/comments")
4print(response.json())
200 Example Response
No Body
GET /wikis/:page_id/presence undocumented

/wikis/:page_id/presence

GET /wikis/:page_id/presence — get active collaborators.

Handled by api_get_presence
Parameters
page_id string · path
required
Responses
200Successful Response
GET /wikis/example/presence
1curl "http://localhost:8000/wikis/example/presence"
1fetch("http://localhost:8000/wikis/example/presence")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/wikis/example/presence")
4print(response.json())
200 Example Response
No Body
PUT /wikis/:page_id/presence undocumented

/wikis/:page_id/presence

PUT /wikis/:page_id/presence — update cursor position.

Handled by api_update_presence
Parameters
page_id string · path
required
Responses
200Successful Response
PUT /wikis/example/presence
1curl -X PUT "http://localhost:8000/wikis/example/presence"
1fetch("http://localhost:8000/wikis/example/presence", { method: "PUT" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.put("http://localhost:8000/wikis/example/presence")
4print(response.json())
200 Example Response
No Body
PATCH /workers/:worker_id/documents/:document_id

Move or rename a worker document

Move a document between folders (and to/from root), or rename it.

Handled by api_update_document
Parameters
worker_id string · path
required
document_id string · path
required
Body · UpdateDocumentapplication/json
title string · min length: 1 · max length: 500
icon string · max length: 100
icon_type
content string
is_starred
page_mode
visibility
page_setup object
deleted
propertyName anything
Responses
200Successful Response
PATCH /workers/example/documents/example
1curl -X PATCH "http://localhost:8000/workers/example/documents/example" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","icon":"string","icon_type":null,"content":"string","is_starred":null,"page_mode":null,"visibility":null,"page_setup":{"size":null,"orientation":null,"margins":null,"margin_x":1,"margin_y":1,"header_text":"string","footer_text":"string","show_page_numbers":null,"watermark_text":"string"},"deleted":null}'
1fetch("http://localhost:8000/workers/example/documents/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "icon": "string",
7 "icon_type": null,
8 "content": "string",
9 "is_starred": null,
10 "page_mode": null,
11 "visibility": null,
12 "page_setup": {
13 "size": null,
14 "orientation": null,
15 "margins": null,
16 "margin_x": 1,
17 "margin_y": 1,
18 "header_text": "string",
19 "footer_text": "string",
20 "show_page_numbers": null,
21 "watermark_text": "string"
22 },
23 "deleted": null
24}),
25})
26 .then((res) => res.json())
27 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/workers/example/documents/example",
5 json={"title":"string","icon":"string","icon_type":null,"content":"string","is_starred":null,"page_mode":null,"visibility":null,"page_setup":{"size":null,"orientation":null,"margins":null,"margin_x":1,"margin_y":1,"header_text":"string","footer_text":"string","show_page_numbers":null,"watermark_text":"string"},"deleted":null},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workers/:worker_id/documents/folders

Create a document folder

Handled by api_create_folder
Parameters
worker_id string · path
required
Body · CreateDocumentFolderapplication/json
name string · min length: 1 · max length: 120
required
propertyName anything
Responses
200Successful Response
POST /workers/example/documents/folders
1curl -X POST "http://localhost:8000/workers/example/documents/folders" \
2 -H "Content-Type: application/json" \
3 -d '{"name":"string"}'
1fetch("http://localhost:8000/workers/example/documents/folders", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "name": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/example/documents/folders",
5 json={"name":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workers/:worker_id/documents

Record an uploaded worker document

Record a document the browser already uploaded to R2 (Computer source).

Handled by api_create_document
Parameters
worker_id string · path
required
Body · CreateDocumentapplication/json
title string · min length: 1 · max length: 500
required
icon string · max length: 100
icon_type
content string
propertyName anything
Responses
200Successful Response
POST /workers/example/documents
1curl -X POST "http://localhost:8000/workers/example/documents" \
2 -H "Content-Type: application/json" \
3 -d '{"title":"string","icon":"string","icon_type":null,"content":"string"}'
1fetch("http://localhost:8000/workers/example/documents", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "title": "string",
6 "icon": "string",
7 "icon_type": null,
8 "content": "string"
9}),
10})
11 .then((res) => res.json())
12 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/example/documents",
5 json={"title":"string","icon":"string","icon_type":null,"content":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workers/:worker_id/notes

Add a note to a worker

Handled by api_create_worker_note
Parameters
worker_id string · path
required
Body · CreateWorkerNoteapplication/json
text string · min length: 1 · max length: 5000
required
propertyName anything
Responses
200Successful Response
POST /workers/example/notes
1curl -X POST "http://localhost:8000/workers/example/notes" \
2 -H "Content-Type: application/json" \
3 -d '{"text":"string"}'
1fetch("http://localhost:8000/workers/example/notes", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "text": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/example/notes",
5 json={"text":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /workers/:worker_id/notes/:note_id

Update a worker note

Handled by api_update_worker_note
Parameters
worker_id string · path
required
note_id string · path
required
Body · UpdateWorkerNoteapplication/json
text string · min length: 1 · max length: 5000
required
propertyName anything
Responses
200Successful Response
PUT /workers/example/notes/example
1curl -X PUT "http://localhost:8000/workers/example/notes/example" \
2 -H "Content-Type: application/json" \
3 -d '{"text":"string"}'
1fetch("http://localhost:8000/workers/example/notes/example", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "text": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/workers/example/notes/example",
5 json={"text":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /workers/:worker_id/personal

Update personal details

PATCH personal details — merge provided keys; empty string clears a key.

Handled by api_update_personal
Parameters
worker_id string · path
required
Body · UpdateWorkerPersonalapplication/json
date_of_birth string · max length: 10
gender string · max length: 50
pronouns string · max length: 50
nationality string · max length: 100
marital_status string · max length: 50
personal_email string · max length: 200
personal_phone string · max length: 50
address_line1 string · max length: 200
address_line2 string · max length: 200
city string · max length: 100
state string · max length: 100
postal_code string · max length: 30
country string · max length: 100
propertyName anything
Responses
200Successful Response
PATCH /workers/example/personal
1curl -X PATCH "http://localhost:8000/workers/example/personal" \
2 -H "Content-Type: application/json" \
3 -d '{"date_of_birth":"string","gender":"string","pronouns":"string","nationality":"string","marital_status":"string","personal_email":"string","personal_phone":"string","address_line1":"string","address_line2":"string","city":"string","state":"string","postal_code":"string","country":"string"}'
1fetch("http://localhost:8000/workers/example/personal", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "date_of_birth": "string",
6 "gender": "string",
7 "pronouns": "string",
8 "nationality": "string",
9 "marital_status": "string",
10 "personal_email": "string",
11 "personal_phone": "string",
12 "address_line1": "string",
13 "address_line2": "string",
14 "city": "string",
15 "state": "string",
16 "postal_code": "string",
17 "country": "string"
18}),
19})
20 .then((res) => res.json())
21 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/workers/example/personal",
5 json={"date_of_birth":"string","gender":"string","pronouns":"string","nationality":"string","marital_status":"string","personal_email":"string","personal_phone":"string","address_line1":"string","address_line2":"string","city":"string","state":"string","postal_code":"string","country":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /workers/:worker_id/qualifications

Update qualifications

PATCH qualifications — each provided collection replaces that collection.

Handled by api_update_qualifications
Parameters
worker_id string · path
required
Body · UpdateQualificationsapplication/json
education array
certifications array
skills array
languages array
propertyName anything
Responses
200Successful Response
PATCH /workers/example/qualifications
1curl -X PATCH "http://localhost:8000/workers/example/qualifications" \
2 -H "Content-Type: application/json" \
3 -d '{"education":[{"institution":"string","id":"string","degree":"string","field_of_study":"string","start_year":1,"end_year":1}],"certifications":[{"name":"string","id":"string","issuer":"string","issued_date":"string","expiry_date":"string","credential_id":"string"}],"skills":["string"],"languages":[{"language":"string","id":"string","proficiency":null}]}'
1fetch("http://localhost:8000/workers/example/qualifications", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "education": [
6 {
7 "institution": "string",
8 "id": "string",
9 "degree": "string",
10 "field_of_study": "string",
11 "start_year": 1,
12 "end_year": 1
13 }
14 ],
15 "certifications": [
16 {
17 "name": "string",
18 "id": "string",
19 "issuer": "string",
20 "issued_date": "string",
21 "expiry_date": "string",
22 "credential_id": "string"
23 }
24 ],
25 "skills": [
26 "string"
27 ],
28 "languages": [
29 {
30 "language": "string",
31 "id": "string",
32 "proficiency": null
33 }
34 ]
35}),
36})
37 .then((res) => res.json())
38 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/workers/example/qualifications",
5 json={"education":[{"institution":"string","id":"string","degree":"string","field_of_study":"string","start_year":1,"end_year":1}],"certifications":[{"name":"string","id":"string","issuer":"string","issued_date":"string","expiry_date":"string","credential_id":"string"}],"skills":["string"],"languages":[{"language":"string","id":"string","proficiency":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PATCH /workers/:worker_id/bank-details

Update bank details

PATCH bank details — merge flat fields; identifiers list replaces whole.

Handled by api_update_bank_details
Parameters
worker_id string · path
required
Body · UpdateBankDetailsapplication/json
bank_name string · max length: 150
account_name string · max length: 150
account_number string · max length: 50
branch_code string · max length: 50
iban string · max length: 50
swift_bic string · max length: 20
currency string · max length: 3
notes string · max length: 500
identifiers array
propertyName anything
Responses
200Successful Response
PATCH /workers/example/bank-details
1curl -X PATCH "http://localhost:8000/workers/example/bank-details" \
2 -H "Content-Type: application/json" \
3 -d '{"bank_name":"string","account_name":"string","account_number":"string","branch_code":"string","iban":"string","swift_bic":"string","currency":"string","notes":"string","identifiers":[{"kind":null,"value":"string","id":"string","label":"string"}]}'
1fetch("http://localhost:8000/workers/example/bank-details", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "bank_name": "string",
6 "account_name": "string",
7 "account_number": "string",
8 "branch_code": "string",
9 "iban": "string",
10 "swift_bic": "string",
11 "currency": "string",
12 "notes": "string",
13 "identifiers": [
14 {
15 "kind": null,
16 "value": "string",
17 "id": "string",
18 "label": "string"
19 }
20 ]
21}),
22})
23 .then((res) => res.json())
24 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/workers/example/bank-details",
5 json={"bank_name":"string","account_name":"string","account_number":"string","branch_code":"string","iban":"string","swift_bic":"string","currency":"string","notes":"string","identifiers":[{"kind":null,"value":"string","id":"string","label":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /workers/:worker_id/emergency-contacts

Replace emergency contacts

PUT the full emergency contacts list (replace semantics).

Handled by api_update_emergency_contacts
Parameters
worker_id string · path
required
Body · UpdateEmergencyContactsapplication/json
contacts array
required
propertyName anything
Responses
200Successful Response
PUT /workers/example/emergency-contacts
1curl -X PUT "http://localhost:8000/workers/example/emergency-contacts" \
2 -H "Content-Type: application/json" \
3 -d '{"contacts":[{"name":"string","id":"string","relationship":"string","phone":"string","email":"string","is_primary":null}]}'
1fetch("http://localhost:8000/workers/example/emergency-contacts", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "contacts": [
6 {
7 "name": "string",
8 "id": "string",
9 "relationship": "string",
10 "phone": "string",
11 "email": "string",
12 "is_primary": null
13 }
14 ]
15}),
16})
17 .then((res) => res.json())
18 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/workers/example/emergency-contacts",
5 json={"contacts":[{"name":"string","id":"string","relationship":"string","phone":"string","email":"string","is_primary":null}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
PUT /workers/:worker_id/right-to-work

Replace right-to-work documents

PUT the full right-to-work document list (replace semantics).

Handled by api_update_right_to_work
Parameters
worker_id string · path
required
Body · UpdateRightToWorkapplication/json
records array
required
propertyName anything
Responses
200Successful Response
PUT /workers/example/right-to-work
1curl -X PUT "http://localhost:8000/workers/example/right-to-work" \
2 -H "Content-Type: application/json" \
3 -d '{"records":[{"document_type":null,"id":"string","country":"string","number":"string","issued_date":"string","expiry_date":"string","notes":"string"}]}'
1fetch("http://localhost:8000/workers/example/right-to-work", {
2 method: "PUT",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "records": [
6 {
7 "document_type": null,
8 "id": "string",
9 "country": "string",
10 "number": "string",
11 "issued_date": "string",
12 "expiry_date": "string",
13 "notes": "string"
14 }
15 ]
16}),
17})
18 .then((res) => res.json())
19 .then(console.log);
1import requests
2
3response = requests.put(
4 "http://localhost:8000/workers/example/right-to-work",
5 json={"records":[{"document_type":null,"id":"string","country":"string","number":"string","issued_date":"string","expiry_date":"string","notes":"string"}]},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /workers/:worker_id undocumented

/workers/:worker_id

Handled by api_delete_worker
Parameters
worker_id string · path
required
Responses
200Successful Response
DELETE /workers/example
1curl -X DELETE "http://localhost:8000/workers/example"
1fetch("http://localhost:8000/workers/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/workers/example")
4print(response.json())
200 Example Response
No Body
DELETE /workers/fields/:field_id undocumented

/workers/fields/:field_id

Handled by api_delete_field_definition
Parameters
field_id string · path
required
Responses
200Successful Response
DELETE /workers/fields/example
1curl -X DELETE "http://localhost:8000/workers/fields/example"
1fetch("http://localhost:8000/workers/fields/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/workers/fields/example")
4print(response.json())
200 Example Response
No Body
DELETE /workers/:worker_id/notes/:note_id undocumented

/workers/:worker_id/notes/:note_id

Handled by api_delete_worker_note
Parameters
worker_id string · path
required
note_id string · path
required
Responses
200Successful Response
DELETE /workers/example/notes/example
1curl -X DELETE "http://localhost:8000/workers/example/notes/example"
1fetch("http://localhost:8000/workers/example/notes/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/workers/example/notes/example")
4print(response.json())
200 Example Response
No Body
DELETE /workers/:worker_id/employment/:record_id undocumented

/workers/:worker_id/employment/:record_id

Handled by api_delete_employment
Parameters
worker_id string · path
required
record_id string · path
required
Responses
200Successful Response
DELETE /workers/example/employment/example
1curl -X DELETE "http://localhost:8000/workers/example/employment/example"
1fetch("http://localhost:8000/workers/example/employment/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/workers/example/employment/example")
4print(response.json())
200 Example Response
No Body
DELETE /workers/:worker_id/documents/folders/:folder_id undocumented

/workers/:worker_id/documents/folders/:folder_id

Handled by api_delete_folder
Parameters
worker_id string · path
required
folder_id string · path
required
Responses
200Successful Response
DELETE /workers/example/documents/folders/example
1curl -X DELETE "http://localhost:8000/workers/example/documents/folders/example"
1fetch("http://localhost:8000/workers/example/documents/folders/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/workers/example/documents/folders/example")
4print(response.json())
200 Example Response
No Body
DELETE /workers/:worker_id/documents/:document_id undocumented

/workers/:worker_id/documents/:document_id

Handled by api_delete_document
Parameters
worker_id string · path
required
document_id string · path
required
Responses
200Successful Response
DELETE /workers/example/documents/example
1curl -X DELETE "http://localhost:8000/workers/example/documents/example"
1fetch("http://localhost:8000/workers/example/documents/example", { method: "DELETE" })
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.delete("http://localhost:8000/workers/example/documents/example")
4print(response.json())
200 Example Response
No Body
GET /workers undocumented

/workers

Handled by api_list_workers
Responses
200Successful Response
GET /workers
1curl "http://localhost:8000/workers"
1fetch("http://localhost:8000/workers")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id undocumented

/workers/:worker_id

Handled by api_get_worker
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example
1curl "http://localhost:8000/workers/example"
1fetch("http://localhost:8000/workers/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example")
4print(response.json())
200 Example Response
No Body
GET /workers/locations/:location_id/members undocumented

/workers/locations/:location_id/members

Workers currently assigned to a location — powers the delete dialog count.

Handled by api_list_location_members
Parameters
location_id string · path
required
Responses
200Successful Response
GET /workers/locations/example/members
1curl "http://localhost:8000/workers/locations/example/members"
1fetch("http://localhost:8000/workers/locations/example/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/locations/example/members")
4print(response.json())
200 Example Response
No Body
GET /workers/fields undocumented

/workers/fields

Handled by api_list_field_definitions
Responses
200Successful Response
GET /workers/fields
1curl "http://localhost:8000/workers/fields"
1fetch("http://localhost:8000/workers/fields")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/fields")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/fields undocumented

/workers/:worker_id/fields

Field definitions merged with this worker's values. Sensitive-flagged fields are omitted entirely unless the caller holds workers.sensitive.*.

Handled by api_get_worker_fields
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example/fields
1curl "http://localhost:8000/workers/example/fields"
1fetch("http://localhost:8000/workers/example/fields")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/fields")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/personal undocumented

/workers/:worker_id/personal

Personal profile bundle: personal details, emergency contacts, right to work, qualifications (all gated on workers.personal.*).

Handled by api_get_personal
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example/personal
1curl "http://localhost:8000/workers/example/personal"
1fetch("http://localhost:8000/workers/example/personal")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/personal")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/bank-details undocumented

/workers/:worker_id/bank-details

Bank details + identity numbers (gated on workers.sensitive.*).

Handled by api_get_bank_details
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example/bank-details
1curl "http://localhost:8000/workers/example/bank-details"
1fetch("http://localhost:8000/workers/example/bank-details")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/bank-details")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/notes undocumented

/workers/:worker_id/notes

Handled by api_list_worker_notes
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example/notes
1curl "http://localhost:8000/workers/example/notes"
1fetch("http://localhost:8000/workers/example/notes")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/notes")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/compensation undocumented

/workers/:worker_id/compensation

Handled by api_list_compensation
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example/compensation
1curl "http://localhost:8000/workers/example/compensation"
1fetch("http://localhost:8000/workers/example/compensation")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/compensation")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/employment undocumented

/workers/:worker_id/employment

Handled by api_list_employment
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example/employment
1curl "http://localhost:8000/workers/example/employment"
1fetch("http://localhost:8000/workers/example/employment")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/employment")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/documents undocumented

/workers/:worker_id/documents

Handled by api_list_documents
Parameters
worker_id string · path
required
Responses
200Successful Response
GET /workers/example/documents
1curl "http://localhost:8000/workers/example/documents"
1fetch("http://localhost:8000/workers/example/documents")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/documents")
4print(response.json())
200 Example Response
No Body
GET /workers/:worker_id/documents/:document_id/view undocumented

/workers/:worker_id/documents/:document_id/view

Short-lived presigned GET URL for a worker document.

Handled by api_view_document
Parameters
worker_id string · path
required
document_id string · path
required
Responses
200Successful Response
GET /workers/example/documents/example/view
1curl "http://localhost:8000/workers/example/documents/example/view"
1fetch("http://localhost:8000/workers/example/documents/example/view")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workers/example/documents/example/view")
4print(response.json())
200 Example Response
No Body
PATCH /workers/:worker_id

Update a worker profile

Handled by api_update_worker
Parameters
worker_id string · path
required
Body · UpdateWorkerapplication/json
employee_id string · max length: 50
department_id string
manager_id string
status
location_mrn string · max length: 120
work_location string · max length: 200
work_mode
expected_hours_per_day number
work_email string · max length: 200
work_phone string · max length: 50
notes string · max length: 5000
propertyName anything
Responses
200Successful Response
PATCH /workers/example
1curl -X PATCH "http://localhost:8000/workers/example" \
2 -H "Content-Type: application/json" \
3 -d '{"employee_id":"string","department_id":"string","manager_id":"string","status":null,"location_mrn":"string","work_location":"string","work_mode":null,"expected_hours_per_day":1.5,"work_email":"string","work_phone":"string","notes":"string"}'
1fetch("http://localhost:8000/workers/example", {
2 method: "PATCH",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "employee_id": "string",
6 "department_id": "string",
7 "manager_id": "string",
8 "status": null,
9 "location_mrn": "string",
10 "work_location": "string",
11 "work_mode": null,
12 "expected_hours_per_day": 1.5,
13 "work_email": "string",
14 "work_phone": "string",
15 "notes": "string"
16}),
17})
18 .then((res) => res.json())
19 .then(console.log);
1import requests
2
3response = requests.patch(
4 "http://localhost:8000/workers/example",
5 json={"employee_id":"string","department_id":"string","manager_id":"string","status":null,"location_mrn":"string","work_location":"string","work_mode":null,"expected_hours_per_day":1.5,"work_email":"string","work_phone":"string","notes":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workers

Create a worker profile

Handled by api_create_worker
Body · CreateWorkerapplication/json
member_mrn string · min length: 1
required
job_title string · min length: 1 · max length: 200
required
hire_date string · min length: 1
required
employee_id string · max length: 50
department_id string
manager_id string
employment_type
status
location_mrn string · max length: 120
work_location string · max length: 200
work_mode
expected_hours_per_day number
work_email string · max length: 200
work_phone string · max length: 50
notes string · max length: 5000
propertyName anything
Responses
200Successful Response
POST /workers
1curl -X POST "http://localhost:8000/workers" \
2 -H "Content-Type: application/json" \
3 -d '{"member_mrn":"string","job_title":"string","hire_date":"string","employee_id":"string","department_id":"string","manager_id":"string","employment_type":null,"status":null,"location_mrn":"string","work_location":"string","work_mode":null,"expected_hours_per_day":1.5,"work_email":"string","work_phone":"string","notes":"string"}'
1fetch("http://localhost:8000/workers", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "member_mrn": "string",
6 "job_title": "string",
7 "hire_date": "string",
8 "employee_id": "string",
9 "department_id": "string",
10 "manager_id": "string",
11 "employment_type": null,
12 "status": null,
13 "location_mrn": "string",
14 "work_location": "string",
15 "work_mode": null,
16 "expected_hours_per_day": 1.5,
17 "work_email": "string",
18 "work_phone": "string",
19 "notes": "string"
20}),
21})
22 .then((res) => res.json())
23 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers",
5 json={"member_mrn":"string","job_title":"string","hire_date":"string","employee_id":"string","department_id":"string","manager_id":"string","employment_type":null,"status":null,"location_mrn":"string","work_location":"string","work_mode":null,"expected_hours_per_day":1.5,"work_email":"string","work_phone":"string","notes":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
POST /workers/locations/:location_id/reassignment

Reassign workers off a location

Move every worker assigned to a location to another one (or clear it). Body: {"target": "<location mrn>"} to move, or omit/empty to set to none. Called by the location delete dialog before the location is removed.

Handled by api_reassign_location
Parameters
location_id string · path
required
Body · ReassignLocationapplication/json
target string
propertyName anything
Responses
200Successful Response
POST /workers/locations/example/reassignment
1curl -X POST "http://localhost:8000/workers/locations/example/reassignment" \
2 -H "Content-Type: application/json" \
3 -d '{"target":"string"}'
1fetch("http://localhost:8000/workers/locations/example/reassignment", {
2 method: "POST",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "target": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.post(
4 "http://localhost:8000/workers/locations/example/reassignment",
5 json={"target":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
DELETE /workspaces/:id

Delete workspace

DELETE /workspaces/:id — permanently delete a workspace. Owner only.

Handled by api_delete_workspace
Parameters
id string · path
required
Body · DeleteWorkspaceapplication/json
confirmation string · min length: 1
required
propertyName anything
Responses
200Successful Response
DELETE /workspaces/example
1curl -X DELETE "http://localhost:8000/workspaces/example" \
2 -H "Content-Type: application/json" \
3 -d '{"confirmation":"string"}'
1fetch("http://localhost:8000/workspaces/example", {
2 method: "DELETE",
3 headers: { "Content-Type": "application/json" },
4 body: JSON.stringify({
5 "confirmation": "string"
6}),
7})
8 .then((res) => res.json())
9 .then(console.log);
1import requests
2
3response = requests.delete(
4 "http://localhost:8000/workspaces/example",
5 json={"confirmation":"string"},
6)
7print(response.json())
Editable: Test Request sends exactly what's here
200 Example Response
No Body
GET /workspaces/:id undocumented

/workspaces/:id

GET /workspaces/:id — workspace detail page with tabs.

Handled by workspace_detail
Parameters
id string · path
required
Responses
200Successful Response
GET /workspaces/example
1curl "http://localhost:8000/workspaces/example"
1fetch("http://localhost:8000/workspaces/example")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workspaces/example")
4print(response.json())
200 Example Response
No Body
GET /workspaces/:id/partials/members undocumented

/workspaces/:id/partials/members

GET /workspaces/:id/partials/members — paginated members list partial.

Handled by workspace_members_partial
Parameters
id string · path
required
Responses
200Successful Response
GET /workspaces/example/partials/members
1curl "http://localhost:8000/workspaces/example/partials/members"
1fetch("http://localhost:8000/workspaces/example/partials/members")
2 .then((res) => res.json())
3 .then(console.log);
1import requests
2
3response = requests.get("http://localhost:8000/workspaces/example/partials/members")
4print(response.json())
200 Example Response
No Body
WS/ws

/ws

Platform WebSocket handler — authenticates via session and holds connection open.

Handled by ws_platform
Subdomain api
Connect
1const socket = new WebSocket("ws://localhost:8000/ws");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/app/mail/ws/:draft_id

/app/mail/ws/:draft_id

WS at /app/mail/ws/:draft_id — Yjs body sync (binary) + field/presence relay (JSON).

Handled by ws_draft
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/app/mail/ws/:draft_id");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/app/calls/ws

/app/calls/ws

WebSocket handler for call signaling and state updates.

Handled by ws_calls
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/app/calls/ws");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/o1/calls/:token/ws

/o1/calls/:token/ws

Open WebSocket for in-call guests. Guests have no workspace session, so we resolve the call from the (globally unique) link slug and scope the socket to that one call. Receive-only: chat is sent via the REST endpoint; this just delivers chat/state events the same way members get them over their WS.

Handled by ws_guest_calls
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/o1/calls/:token/ws");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/app/canvas/ws/:board_id

/app/canvas/ws/:board_id

Yjs binary relay + awareness + presence for one board.

Handled by ws_canvas
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/app/canvas/ws/:board_id");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/app/chat/ws

/app/chat/ws

WebSocket handler for real-time chat events.

Handled by ws_chat
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/app/chat/ws");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/app/papers/ws/:document_id

/app/papers/ws/:document_id

WebSocket relay for Yjs collaborative editing on a document. The socket is binary-only: y-websocket clients decode every frame as binary y-protocols messages and crash on text frames, so errors are sent as native permission-denied frames and JSON is never written here.

Handled by ws_papers
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/app/papers/ws/:document_id");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/app/tables/ws/:table_id

/app/tables/ws/:table_id

WebSocket handler for collaborative presence on a table.

Handled by ws_tables
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/app/tables/ws/:table_id");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected
WS/app/wiki/ws/:page_id

/app/wiki/ws/:page_id

WebSocket handler for Yjs collaborative editing on a wiki page. WS routes bypass BEFORE hooks, so auth + access are checked here. Restricted pages require share ≥ edit (same as PATCH).

Handled by ws_wiki
Subdomain *
Connect
1const socket = new WebSocket("ws://localhost:8000/app/wiki/ws/:page_id");
2
3socket.onopen = () => socket.send("hello");
4socket.onmessage = (event) => console.log(event.data);
Connection Log
Not connected