Endpoints

Every route an API token can call, by resource, with the scope it needs; and the few that only the portal can.

Reading this page

A route's scope is its resource, the first part of its path after /v1, and its level: read for a GET, write for anything else. So a route nested under a task is a task route: starting a run, POST /v1/tasks/{id}/runs, needs tasks:write, not runs:write. See Authentication for tokens and scopes, and Conventions for errors, pagination and retries.

Every {id} is an id, never a slug. Apart from the catalogue, every route below answers only for your own enterprise: an id from another enterprise is a 404.

Tasks

A task's definition, its versions and schedule, and the runs, memory and recommendations that belong to it. See Tasks, and Tasks over the API for the task as JSON.

Call Scope What it does
GET /v1/tasks tasks:read Tasks, a page at a time, with search and filters.
POST /v1/tasks tasks:write Create a task, with its first version.
GET /v1/tasks/{id} tasks:read The task, its current version and skill, its version list, its webhook, and its definition warnings.
DELETE /v1/tasks/{id} tasks:write Delete the task and every version of it. Its runs are kept. A 409 while it has a run under way.
POST /v1/tasks/{id}/copy tasks:write Copy it as a new task of your own: send teamId, name and slug, and optionally assigneeRole, which is the original's unless you send one.
GET /v1/tasks/{id}/versions tasks:read Every version, newest first.
GET /v1/tasks/{id}/versions/{versionId} tasks:read One version as it was, with its skill, how many runs used it, and whether it is current.
POST /v1/tasks/{id}/versions tasks:write Publish a new version. Send baseVersionId.
GET /v1/tasks/{id}/workflow tasks:read The current version and its skill, on their own.
PUT /v1/tasks/{id}/schedule tasks:write Set its schedule. See Schedules and webhooks.
DELETE /v1/tasks/{id}/schedule tasks:write Remove its schedule.
POST /v1/tasks/{id}/runs tasks:write Start a run, with the body as its input.
GET /v1/tasks/{id}/memory tasks:read The notes trained on this task, and its training grants.
POST /v1/tasks/{id}/memory tasks:write Train a note on this task: { "text": "…" }.
GET /v1/tasks/{id}/memory/ask tasks:read Ask memory as this task would. See Memory.
POST /v1/tasks/{id}/memory/train tasks:write Train a note, or a correction, at a layer this task may write. A person may train this task's team, or the enterprise, here.
GET /v1/tasks/{id}/recommendations tasks:read Self-improvement recommendations for this task.

A task is given to a role, never to one member. A body that creates, changes, copies or clones a task and still names a member in assigneeMemberId is refused with a 400 (assignee_member_removed).

Runs

One run of one task: its status, events, log and cost. See Runs.

Call Scope What it does
GET /v1/runs runs:read Runs, a page at a time, filtered by task, version or status.
GET /v1/runs/{id} runs:read One run, its events and gates, its task, what came before and after it, and its cost. afterEventId sends only the events since that one.
GET /v1/runs/{id}/log runs:read Its full log, once stored. A 404 (log_not_found) until then.
GET /v1/runs/{id}/os-tool runs:read A short read: its status, task, input and last eight events.
POST /v1/runs/{id}/cancel runs:write Cancel it.
POST /v1/runs/{id}/retry runs:write Retry it as a new run, on the task's current version.
POST /v1/runs/{id}/clear runs:write Take a failed run, or a pipeline that stopped, off Blockers.

Blockers

What cannot move without someone. See Runs.

Call Scope What it does
GET /v1/blockers blockers:read Everything on Blockers, section by section. failedPage and pageSize page the failed runs.
POST /v1/blockers/clear blockers:write Clear every failed run at once: { "section": "failed" }.

Executions

The connected runs of more than one task. See Executions.

Call Scope What it does
GET /v1/executions executions:read Executions, a page at a time. Closed ones only with closed=true.
GET /v1/executions/board executions:read Every lane of the board in one read.
GET /v1/executions/counts executions:read How many executions and runs are running, queued and waiting.
GET /v1/executions/{id} executions:read One execution: its runs, links and task graph. Any of its run ids works.
POST /v1/executions/{id}/cancel executions:write Stop every open run in it.
POST /v1/executions/{id}/close executions:write Take a finished execution off the board.
POST /v1/executions/{id}/reopen executions:write Put a closed execution back.
POST /v1/executions/close-completed executions:write Close every execution in the Complete lane under the given filters.

Gates

The calls and questions waiting for your decision. See Gates and tool scopes.

Call Scope What it does
GET /v1/gates gates:read Every gate waiting on you.
POST /v1/gates/{id}/decision gates:write Decide one: decision is approve, reject or request_changes, with an optional note, answers for questions, and choice (the key of one of the gate's choices) on a gate that offers its own.
POST /v1/gates/chat/{chatId}/decision gates:write Answer the question a chat is waiting on. Name it with gateId, or the newest is answered.

gates:write decides gates, including merges that go live. Grant it deliberately.

Chats

Talking to a member. See Chat and plans.

Call Scope What it does
GET /v1/chats chats:read Chats, the most recently active first. memberId narrows them to one member. A chat opened for a purpose is not listed.
POST /v1/chats chats:write Start a chat with a member: { "memberId": "…" }. Or open one for a single job, { "purpose": "create_task" }: a new chat with the COO (the member who has held the role longest), or with memberId when you send one, whose greeting is already in it. It closes once the task it proposes is applied or rejected. Refused with unknown_purpose for any other purpose, and no_coo when nobody holds the COO role.
GET /v1/chats/unread chats:read How many replies nobody has read yet, in the chats GET /v1/chats lists.
GET /v1/chats/{id} chats:read One chat and its messages, oldest first. limit (1 to 200) returns only the newest. Reading it marks it read.
POST /v1/chats/{id}/messages chats:write Send a message: { "content": "…" }. The member's reply follows in the chat.
POST /v1/chats/{id}/tool-calls/{callId}/decision chats:write Answer a tool call the member is waiting on: allow, always or deny.
POST /v1/chats/{id}/close chats:write Close the chat.
GET /v1/chats/tool-grants chats:read The "Always allow" answers you have given for one member's tools. Send memberId.
DELETE /v1/chats/tool-grants/{grantId} chats:write Withdraw one.

A token's "Always allow" answers are its own, not a person's, and a person's are not the token's.

Planned

Plans

When a member can propose a change to the company as a plan (Chat and plans), you will read it here and decide it as a gate:

Call Scope What it does
GET /v1/plans plans:read Plans, newest first, filtered by status, kind, chatSessionId or producedByRunId.
GET /v1/plans/{id} plans:read One plan, its items, and the run and gates behind it.

Memory

What the company has learned. See Memory.

Call Scope What it does
GET /v1/memory memory:read The notes, with search and filters, a page at a time.
POST /v1/memory/train memory:write Train a team or enterprise note. No task is required. layer is team or enterprise; a team train sends teamId, and that team must belong to your enterprise.
GET /v1/memory/recall-health memory:read How often memory could be read over the last 24 hours, by runs and by chat messages.
GET /v1/memory/{id} memory:read One note and its evidence.
POST /v1/memory/{id}/tombstone memory:write Exclude a note from every future answer.
POST /v1/memory/{id}/rate memory:write Rate a note up or down, with an optional reason.
GET /v1/memory/review memory:read The review queue: conflicts, and notes rated down.
GET /v1/memory/review/history memory:read Every review decision made.
POST /v1/memory/review/{id}/resolve memory:write Resolve a conflict by applying a correction: correctionId and a reason.
POST /v1/memory/review/{id}/dismiss memory:write Dismiss an item, with a reason.

Recommendations

Self-improvement's proposed changes to a task. See Self-improvement.

Call Scope What it does
GET /v1/recommendations recommendations:read The recommendations waiting for a decision; taskId narrows them. With view=decided, those decided in the last 60 days.
GET /v1/recommendations/{id} recommendations:read One recommendation, in full.
POST /v1/recommendations/{id}/decision recommendations:write approve or decline, with a reason to decline. Takes an idempotencyKey.

Spend

Caps on what runs may cost, and today's spend. See Spend and models.

Call Scope What it does
GET /v1/spend spend:read Today's spend and runs, and every cap.
PATCH /v1/spend/caps spend:write Set the cap on one layer and layerId. Raising a cap queues paused runs again.
PATCH /v1/spend/enabled spend:write Turn spend limits on or off: { "enabled": false }.

Models

Your model connections and the tiers they resolve to. See Spend and models.

Call Scope What it does
GET /v1/llm/connections llm:read Your model connections, without their keys.
PATCH /v1/llm/connections/{id} llm:write Rename a connection, describe it, or set a Claude login's plan.
GET /v1/llm/connections/{id}/usage llm:read A connection's usage.
GET /v1/llm/bindings llm:read Whether a model key is connected, for the enterprise or, with layer=member and layerId, one member.
POST /v1/llm/bindings llm:write Connect a key: apiKey, and provider (openrouter, the default, or claude). layer and layerId connect it for one member.
DELETE /v1/llm/bindings llm:write Remove a key, named by provider, layer and layerId in the query.
POST /v1/llm/claude/oauth/start, …/complete llm:write Connect a Claude login: start returns the address to sign in at, and complete takes the code and state it gives back.
GET /v1/llm/tiers llm:read Which model each tier runs, per provider.
POST /v1/llm/tiers/override llm:write Point a tier at another model the provider offers: provider, tier, model.
GET /v1/llm/models llm:read The models your connections offer, for a task's exact model.

Tools

The systems your members reach, and the connections that let them. See Tools.

Call Scope What it does
GET /v1/tools/bindings tools:read Your tool connections, without their secrets. layer and layerId narrow them.
POST /v1/tools/bindings tools:write Connect a tool: an MCP server's address and token, or for a system a member operates in a browser, its sites and start page.
PATCH /v1/tools/bindings/{id} tools:write Change a connection, or move it to another layer. Only the CEO may change its mustGate list (the tools a task must gate by name).
DELETE /v1/tools/bindings/{id} tools:write Remove it.
GET /v1/tools/bindings/{id}/sign-ins tools:read The sign-ins members have saved on a browser connection's sites.
DELETE /v1/tools/bindings/{id}/sign-ins/{memberId} tools:write Forget a member's saved sign-in, on one site or all of them.
GET /v1/tools/oauth/redirect-uri tools:read The redirect address to register with a provider for OAuth.
POST /v1/tools/oauth/start tools:write Start connecting a tool by OAuth. It finishes in the browser of the person who started it, signed in to the portal, so start it there.

A token connects tools on a team, member, role or task. It cannot connect, change or remove a connection on the enterprise itself (403 ceo_bind_only).

Teams

A charter, a lead, and the members on it. See Teams and charters.

Call Scope What it does
GET /v1/teams teams:read Every team.
POST /v1/teams teams:write Create one: name, and optionally slug, charter, leadMemberId and concurrentRunLimit.
GET /v1/teams/{id} teams:read One team.
PATCH /v1/teams/{id} teams:write Change its name, charter, lead or concurrent-run limit.
DELETE /v1/teams/{id} teams:write Delete it. Your last team cannot be deleted.
POST /v1/teams/{id}/members teams:write Put a member on the team: memberId, and optionally roleId.
DELETE /v1/teams/{id}/members/{memberId} teams:write Take a member off it.

Members

The AI team members, and their inboxes. See Members and inboxes.

Call Scope What it does
GET /v1/members members:read Every member.
POST /v1/members members:write Create one: name, and optionally email and persona.
GET /v1/members/{id} members:read One member.
PATCH /v1/members/{id} members:write Change their name, email or persona.
GET /v1/members/{id}/avatar members:read Their picture, as an image.
PUT /v1/members/{id}/avatar members:write Set it: { "dataUrl": "data:image/png;base64,…" }.
DELETE /v1/members/{id}/avatar members:write Remove it.
POST /v1/members/{id}/roles members:write Give them a role: { "roleId": "…" }.
DELETE /v1/members/{id}/roles/{roleId} members:write Take a role away.
GET /v1/members/{id}/emails members:read Their inbox, a page at a time. unreadOnly=true for unread mail only.
GET /v1/members/{id}/emails/{emailId} members:read One email. Reading it marks it read.
GET /v1/members/{id}/emails/{emailId}/attachments/{attachmentId} members:read An attachment, as the file.

Roles

A job: who holds it, and the tasks it runs. See Roles.

Call Scope What it does
GET /v1/roles roles:read Every role.
POST /v1/roles roles:write Create one: name, and optionally slug and teamId.
GET /v1/roles/{id} roles:read One role, its holders and its tasks.
POST /v1/roles/{id}/members roles:write Give the role to a member: { "memberId": "…" }.
DELETE /v1/roles/{id}/members/{memberId} roles:write Take it from them.
POST /v1/roles/{id}/tasks roles:write Point a task at the role: { "taskId": "…" }. Its runs then go to the role's holders on the task's team. This publishes no new version.
DELETE /v1/roles/{id}/tasks/{taskId} roles:write Stop the role running it.

The org

Everything at once: the shape the portal's map draws. See Enterprise.

Call Scope What it does
GET /v1/orgs orgs:read Your whole organisation as one tree: teams, their members, the roles they hold, and the tasks of each.

Enterprise settings

Settings that belong to the whole enterprise. See Enterprise.

Call Scope What it does
GET /v1/enterprise/webhook-secret enterprise:read Which webhook secret is in use and since when: its last characters, never the secret.
POST /v1/enterprise/webhook-secret/rotate enterprise:write A new webhook secret, in this response only. The old one stops working at once.
PUT /v1/enterprise/avatar enterprise:write Set the enterprise's picture: { "dataUrl": "…" }.
DELETE /v1/enterprise/avatar enterprise:write Remove it.
GET /v1/enterprise/concurrency enterprise:read How many runs may run at once.
PATCH /v1/enterprise/concurrency enterprise:write Change it: { "concurrentRunLimit": 3 }.
GET /v1/enterprise/chat-model-tier enterprise:read The model tier chats run on.
PATCH /v1/enterprise/chat-model-tier enterprise:write Change it: { "chatModelTier": "mid" }.
GET /v1/enterprise/chat-memory-depth enterprise:read How much of memory a chat reply reads, and the depths to choose from.
PATCH /v1/enterprise/chat-memory-depth enterprise:write Change it: { "chatMemoryDepth": "large" }.
GET /v1/enterprise/metrics enterprise:read The company's own metrics, the ones that belong to no single team.
PATCH /v1/enterprise/metrics enterprise:write Set them: { "metrics": ["…"] }.

No token can manage API tokens, whatever enterprise:write would otherwise reach: see Portal only.

Catalogue

The tasks and roles you can take into your enterprise. See Task directory.

Call Scope What it does
GET /v1/catalog/tasks catalog:read The catalogue, a page at a time.
GET /v1/catalog/tasks/{id} catalog:read One task in it.
POST /v1/catalog/tasks/{id}/clone catalog:write Install it, linked to the original: { "teamId": "…" }. It keeps the original's role.
POST /v1/catalog/tasks/{id}/copy catalog:write Copy it as your own task: teamId, name and slug, and optionally assigneeRole, which is the original's unless you send one.
GET /v1/catalog/roles catalog:read The catalogue's public roles, a page at a time, each with the public tasks on it.
GET /v1/catalog/roles/{id} catalog:read One role and the public tasks on it.
POST /v1/catalog/roles/{id}/clone catalog:write Install the role and every task on it, linked to the originals, in one go: { "teamId": "…" }. A role you already have with that slug is reused. Deprecated tasks are skipped. If you already have a task with one of the slugs, nothing is installed and the 409 lists those slugs.

Webhooks

What your enterprise's webhooks received, and replaying it.

Call Scope What it does
GET /v1/webhooks webhooks:read Deliveries, a page at a time.
GET /v1/webhooks/{id} webhooks:read One delivery: its request, response, and what followed.
POST /v1/webhooks/{id}/replay webhooks:write Replay it. Send an idempotencyKey.

Without a token

Call What it does
GET /v1/health Whether the API is up, and the version it runs.
POST /v1/webhooks/{enterprise}/tasks/{task} Start a run of a task, named by its slug. Authenticated by your webhook secret. See Webhooks.
POST /v1/webhooks/{enterprise}/gates/{gateId} Decide a gate. Authenticated by your webhook secret.

Portal only

These belong to a person signed in to the portal, not to a credential. No API token can use them, whatever its scopes:

Routes What they are A token is refused with
/v1/enterprise/api-tokens Creating, rotating, changing and revoking API tokens. 403 api_token_cannot_manage_tokens
/v1/enterprise/connections Apps connected to your enterprise, and revoking them. 403 api_token_cannot_manage_connections
/v1/users The people in your enterprise and what each may reach. Owners only. 403 api_token_scope
/v1/enterprises Creating an enterprise, and the pictures of the enterprises a person belongs to. 403 api_token_scope
/v1/auth/me, /v1/auth/enterprise Who is signed in, and which enterprise their session is in. 403 api_token_scope
/v1/consent/enterprises, …/members, …/approve, …/decline The screen where a person connects an app to an enterprise. 403 api_token_scope

A token with no enterprise scope is refused api_token_scope on the first two, before it gets that far. Signing in and out (the rest of /v1/auth) happens in a browser, with a session a token does not have.