Endpoints

m8tes is the hosted agent platform: agents are API resources with per-user isolation (user_id), memory, scheduling, approvals, and 150+ integrations built in.

Base URL: https://api.m8tes.ai/api/v2

All requests require an API key in the Authorization header:

Authorization: Bearer m8_your_key_here

Signup

Create an account and get an API key. No authentication required. See the Quick Start for the Python equivalent (m8tes.signup()). Runs are prepaid: a new account starts at $0, so top up or connect a model subscription before the first run — an unfunded run fails with TOKEN_BALANCE_DEPLETED and a topup_url.

Signup

POST /signup

FieldTypeRequiredDescription
emailstringyesEmail address.
first_namestringyesFirst Name
passwordstringnoPassword
productstringnoProduct
require_end_user_idboolnoStrict multi-tenant mode (see /settings). Omit for the product default: ON for "api" signups (multi-tenant by default — a forgotten user_id fails loudly), OFF for "platform". Pass false if you are building for yourself (single-tenant) and don't want to scope every request; changeable any time via PATCH /settings.
cURL

Token

Mint or rotate your API key. Rotating invalidates the previous key immediately.

Get Token

POST /token

FieldTypeRequiredDescription
emailstringyesEmail address.
passwordstringyesPassword
cURL

Verify

Email verification. A new account may complete setup and run without verifying immediately. After the preview allowance (25 completed runs by default — once funded via top-up or own-subscription OAuth), further runs fail with EMAIL_VERIFICATION_REQUIRED until the emailed link is clicked. Poll status to learn when that happened.

Resend Verify

POST /verify/resend

cURL

Verify Status

GET /verify/status

cURL

Agents

Agents are reusable personas with instructions and tools. Coding: bind repositories under /agents/{id}/repos after connecting GitHub App.

Create Agent

POST /agents

FieldTypeRequiredDescription
namestringnoDefaults to a random name if not provided
instructionsstringnoAgent system-prompt instructions.
toolsstring[]noTool names, e.g. ['gmail', 'slack']
enable_memoryboolnoDefault for the memory tool. Null = platform default (on).
enable_historyboolnoDefault for the task-history tool. Null = platform default (on).
enable_task_setup_toolsboolnoDefault for the same-scope task-setup tools. Null = platform default (on).
enable_feedbackboolnoDefault for the issue-reporting feedback tool. Null = platform default (on).
enable_self_improvementboolnoWhen true, the agent runs a weekly review-and-improve task: it reads its own recent runs and improves itself — rewriting its instructions, refining/creating its tasks, and recording lessons/memory. Implies the task-setup, history, and memory tools. Null/false = off.
rolestringnoAgent persona role, e.g. 'Customer support specialist'.
prompt_profilestringnoWhich system prompt this agent runs on. "platform" (default) is the full m8tes prompt: the agent knows it runs on m8tes and can guide the owner through the product. "bare" is for embedding the agent in YOUR product — it never names m8tes, never calls itself a Mate, is never told our billing model, and cannot load m8tes' own Agent Skills. It keeps every capability and safety rule; only the branding is removed. Your own skills, tools, and instructions are unaffected. Read the exact prompt an agent will receive with GET /api/v2/agents/{id}/system-prompt.
disabled_builtin_toolsstring[]noBuilt-in tools this agent must NOT be given, by name from GET /api/v2/built-in-tools (e.g. ["feedback", "notify", "computer_use"]). Any built-in can be switched off — useful when embedding an agent in your own product, where our issue-reporting and owner-notify tools have no place. Omit or [] to keep the platform defaults. Unknown names are rejected.
goalsstringnoAgent goals. Injected into system prompt.
user_idstringnoYour end-user ID for data isolation for this agent.
metadataobjectnoArbitrary key-value data
allowed_sendersstring[]noEmail addresses or @domain patterns allowed to email this agent. Overrides default.
inbound_imessage_enabledboolnoEnable inbound iMessage routing for this agent.
imessage_chat_guidstringnoBlueBubbles chat GUID used for inbound routing and outbound replies.
bridge_idintnoBlueBubblesBridge to route this agent's iMessage through (account-scoped).
allowed_imessage_sendersstring[]noSender handles (phone/email) allowed to trigger this agent via iMessage. Required (fail-closed) when iMessage is enabled.
inbound_slack_enabledboolnoDeprecated toggle. Prefer slack_channels: assigning channels turns Slack on for this agent; clearing them turns it off. The Company Agent does not need this — it already answers every unbound channel and every DM.
slack_slugstringnoDeprecated. Inbound Slack no longer routes by a typed handle; @m8tes in a bound channel reaches this agent. Kept for read compatibility.
slack_channelsany[]noSlack channels this agent answers. @m8tes in one of these rooms reaches this agent; every other channel and every DM reaches the Company Agent. One agent per channel. Omit on create to leave unbound.
allowed_slack_sendersstring[]noSlack user IDs allowed to trigger this agent. None/empty = any member of the workspace that installed the app (the installer is always allowed). This list narrows WHO may trigger inside that workspace; it cannot admit someone outside it — a guest in a shared/Slack Connect channel is refused even if listed, because a Slack user ID is scoped to one workspace.
email_inboxboolnoEnable email inbox on creation
webhookboolnoEnable webhook trigger on creation. Returns webhook_url once.
default_permission_modestringnoDefault execution mode for direct runs and the starting mode for new tasks. autonomous=auto-approve all tools, approval=pause and ask before tool use, plan=require plan approval before execution
modelstringnoModel for runs: a short Claude alias (sonnet, opus, fable) or any concentrate catalog id from GET /api/v2/models. Check zdr_supported / zdr_providers on each model (provider capability only — not ZDR on for every route or your account). Omit or null = platform default (the GET /api/v2/models entry flagged default: true — currently grok-4.6 at high reasoning effort). Discover ids, prices, and ZDR via GET /api/v2/models.
effortstringnoReasoning effort for runs: low | medium | high | xhigh | max. Omit or null = platform default (max on Claude models — reason as hard as the model allows; high on all others). Higher effort = deeper reasoning, more tokens, higher cost per run; lower effort = faster and cheaper. xhigh and max are Claude-only tiers — on other models they are clamped down to high, never rejected (each model's ceiling is max_effort on GET /api/v2/models). Per-run effort overrides the task's, which overrides the agent's; resumes and replies inherit the run's effort. Effort currently takes effect on Claude models and the GPT-5.6 family; other models accept the field but may ignore it.
from_templatestringnoEnable a pre-built agent template by slug (e.g. 'ppc-manager'). When set, system_prompt + default tasks + required integrations are applied from the template. The agent stays linked: improvements we ship to the template flow through automatically unless you customize a field (which then takes precedence). Other body fields EXCEPT user_id, metadata, and onboarding/wizard fields may NOT be set alongside from_template — use PATCH to customize after creation. See GET /api/v2/agent-templates for available slugs.
onboarding_answersobjectnoWizard answers keyed by OnboardingQuestion.key. Saved as account-level memories so the agent reads them on every run. Only valid alongside from_template. All keys optional; unknown keys are silently ignored.
enabled_task_slugsstring[]noWhich template default_tasks to seed. Null = all of them. Lets the wizard customer uncheck specific recurring tasks before enabling. Only valid alongside from_template.
enabled_bootstrap_slugsstring[]noWhich template bootstrap_tasks to seed. Null = all of them. Bootstrap tasks run once on enable. Only valid alongside from_template.

Response 201 Created

JSON

List Agents

GET /agents

ParameterTypeDescription
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID
include_archivedboolInclude archived agents (status 'archived') so they can be unarchived.
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

All list endpoints return a paginated envelope:

JSON

Use starting_after with the last item's ID to fetch the next page.

Get Agent

GET /agents/{agent_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Response 200 OK

JSON

Update Agent

PATCH /agents/{agent_id}

FieldTypeRequiredDescription
namestringnoAgent name.
instructionsstringnoAgent system-prompt instructions.
toolsstring[]noTool names, e.g. ['gmail', 'slack'].
enable_memoryboolnoDefault for the memory tool.
enable_historyboolnoDefault for the task-history tool.
enable_task_setup_toolsboolnoDefault for the same-scope task-setup tools.
enable_feedbackboolnoDefault for the issue-reporting feedback tool.
enable_self_improvementboolnoTurn the weekly review-and-improve task on/off. When true the agent reads its own runs and improves itself (implies task-setup/history/memory).
rolestringnoAgent persona role.
prompt_profilestringnoSwitch this agent between the full m8tes prompt ("platform") and the embedding prompt ("bare"). Takes effect on the agent's next run. See the same field on agent create, and GET /api/v2/agents/{id}/system-prompt to read the exact result.
disabled_builtin_toolsstring[]noBuilt-in tools this agent must NOT be given, by name from GET /api/v2/built-in-tools (e.g. ["feedback", "notify", "computer_use"]). Any built-in can be switched off — useful when embedding an agent in your own product, where our issue-reporting and owner-notify tools have no place. Omit or [] to keep the platform defaults. Unknown names are rejected.
goalsstringnoAgent goals. Injected into the system prompt.
metadataobjectnoArbitrary key-value data.
display_orderintnoManual roster position (lower sorts first). Sort agents by COALESCE(display_order, id) ascending: unplaced agents keep creation order and newly created ones append at the bottom. Send null to un-place the agent (back to creation order).
allowed_sendersstring[]noEmail addresses or @domain patterns allowed to email this agent.
inbound_imessage_enabledboolnoEnable inbound iMessage routing for this agent.
imessage_chat_guidstringnoBlueBubbles chat GUID used for inbound routing and outbound replies.
bridge_idintnoBlueBubbles bridge to route this agent's iMessage through (account-scoped).
allowed_imessage_sendersstring[]noSender handles (phone/email) allowed to trigger this agent via iMessage.
inbound_slack_enabledboolnoDeprecated toggle. Prefer slack_channels: assigning channels turns Slack on for this agent; clearing them turns it off.
slack_slugstringnoDeprecated. Inbound Slack routes by bound channel, not a typed handle.
slack_channelsany[]noReplace this agent's Slack channels. @m8tes in one of these rooms reaches this agent; every other channel and every DM reaches the Company Agent. Pass [] to unbind. Omit to leave unchanged. One agent per channel.
allowed_slack_sendersstring[]noSlack user IDs allowed to trigger this agent. None/empty = any member of the INSTALLED workspace. Narrows who may trigger within that workspace; it cannot admit a guest from another workspace.
default_permission_modestringnoDefault execution mode; null (or omitting the field) leaves it unchanged.
modelstringnoModel for runs — any id from GET /api/v2/models (short Claude aliases or concentrate slugs). Check zdr_supported (provider capability only, not 'ZDR always on'). Explicit null resets to the platform default; omitting the field leaves the current model unchanged.
effortstringnoReasoning effort for runs: low | medium | high | xhigh | max. Omit or null = platform default (max on Claude models — reason as hard as the model allows; high on all others). Higher effort = deeper reasoning, more tokens, higher cost per run; lower effort = faster and cheaper. xhigh and max are Claude-only tiers — on other models they are clamped down to high, never rejected (each model's ceiling is max_effort on GET /api/v2/models). Per-run effort overrides the task's, which overrides the agent's; resumes and replies inherit the run's effort. Effort currently takes effect on Claude models and the GPT-5.6 family; other models accept the field but may ignore it.

Response 200 OK

JSON

Delete Agent

Soft-deletes (archives) the agent. Returns 204 No Content.

DELETE /agents/{agent_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Disable Agent

POST /agents/{agent_id}/disable

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Response 200 OK

JSON

Enable Email Inbox

POST /agents/{agent_id}/email-inbox

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Enable Agent

POST /agents/{agent_id}/enable

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Response 200 OK

JSON

Enable Fetchmail

POST /agents/{agent_id}/fetchmail

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Configure Agent Repo

POST /agents/{agent_id}/repos

FieldTypeRequiredDescription
repo_full_namestringyesRepo Full Name
modestringnoOmitted: new bindings default to trusted; reconfigure keeps existing mode

Reset Agent Overrides

POST /agents/{agent_id}/reset

FieldTypeRequiredDescription
fieldsstring[]noFields to reset. None = reset all overrides.

Unarchive Agent

POST /agents/{agent_id}/unarchive

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Response 200 OK

JSON

List Agent Documents

GET /agents/{agent_id}/documents

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

List Agent Repos

GET /agents/{agent_id}/repos

ParameterTypeDescription
user_idstringMust be omitted — this resource is account-scoped, never per end-user.

Get Agent System Prompt

GET /agents/{agent_id}/system-prompt

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Set Agent Webhook Enabled

PATCH /agents/{agent_id}/webhook

FieldTypeRequiredDescription
enabledboolyesTrue resumes the webhook, False pauses it

Disable Email Inbox

DELETE /agents/{agent_id}/email-inbox

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Disable Fetchmail

DELETE /agents/{agent_id}/fetchmail

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Read Agent Document

GET /agents/{agent_id}/documents/{name}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Response 200 OK

JSON

Remove Agent Repo

DELETE /agents/{agent_id}/repos/{repo_id}

ParameterTypeDescription
user_idstringMust be omitted — this resource is account-scoped, never per end-user.

Approve Agent Repo Commands

POST /agents/{agent_id}/repos/{repo_id}/approve-commands

FieldTypeRequiredDescription
commands_digeststringyesCommands Digest

Clear Agent Repo Commands

DELETE /agents/{agent_id}/repos/{repo_id}/commands

ParameterTypeDescription
user_idstringMust be omitted — this resource is account-scoped, never per end-user.

Agent-Templates

Pre-built agent templates (e.g. ppc-manager). Enable one with agents.create(from_template=...); improvements we ship flow through automatically until you customize a field.

List Agent Templates

GET /agent-templates

Response 200 OK

JSON

Models

The model catalog: ids, pricing, ZDR coverage, and reasoning-effort caps for every model an agent or run can use. The default: true flag reflects what your account's runs use when no model is set.

List Models

GET /models

ParameterTypeDescription
zdrboolIf set, filter by provider-level ZDR support (zdr_supported). Not the same as ZDR enabled for your concentrate key.
authorstringFilter by concentrate author/provider slug (e.g. openai, anthropic).
curatedboolIf true, return only the Platform curated short list (not full catalog).
limitintMax results (1-500, default 500)

Model-Connections

List account-level Claude connection status and manage native OpenAI/Codex, Grok/xAI, or Gemini authorization. Provider credentials are captured automatically, encrypted at rest, and never returned.

List Model Connections

GET /model-connections

Disconnect Model Connection

DELETE /model-connections/{provider}

Paste Claude Connection

POST /model-connections/claude/paste

FieldTypeRequiredDescription
access_tokenstringyesAccess Token
refresh_tokenstringnoRefresh Token
expires_at_msintnoExpires At Ms

Apply Model Connection Default

POST /model-connections/{provider}/apply-default

Start Model Connection Authorization

POST /model-connections/{provider}/authorizations

Complete Model Connection Authorization

POST /model-connections/{provider}/authorizations/{state}

FieldTypeRequiredDescription
codestringyesCode

Poll Model Connection Authorization

GET /model-connections/{provider}/authorizations/{state}

Cancel Model Connection Authorization

DELETE /model-connections/{provider}/authorizations/{state}

cURL

Runs

Runs are task executions. They stream Server-Sent Events by default.

Create Run

POST /runs

FieldTypeRequiredDescription
permission_modestringnoExecution mode override. If omitted, inherits from the agent default for direct runs or the saved task mode for task runs. autonomous=auto-approve all tools, approval=pause and ask before tool use, plan=require plan approval before execution
human_in_the_loopboolnoEnable human-in-the-loop features: clarifying questions, tool approval, and plan approval. If omitted, approval/plan inherit as true and autonomous inherits as false.
teammate_idintnoID of the agent to use.
messagestringyesThe user message that drives the run.
toolsstring[]noTool names, e.g. gmail, slack.
modelstringnoPer-run model override — any id from GET /api/v2/models. Omit to use the agent's model, then the platform default.
effortstringnoPer-run reasoning-effort override. Reasoning effort for runs: low | medium | high | xhigh | max. Omit or null = platform default (max on Claude models — reason as hard as the model allows; high on all others). Higher effort = deeper reasoning, more tokens, higher cost per run; lower effort = faster and cheaper. xhigh and max are Claude-only tiers — on other models they are clamped down to high, never rejected (each model's ceiling is max_effort on GET /api/v2/models). Per-run effort overrides the task's, which overrides the agent's; resumes and replies inherit the run's effort. Effort currently takes effect on Claude models and the GPT-5.6 family; other models accept the field but may ignore it.
streamboolnoReturn Server-Sent Events when true, a JSON object when false.
namestringnoAgent name (creates new if no teammate_id)
instructionsstringnoAgent instructions
user_idstringnoYour end-user ID for data isolation. If the targeted agent is already scoped, this must match that scope. When omitted, the run inherits the agent's existing scope.
metadataobjectnoArbitrary key-value data. Keys reserved for internal use are ignored (backend run markers such as error_code, auto_retryable, interrupted, and nudged_* delivery stamps).
memoryboolnoSaved memories in agent context. Omit to inherit the agent default.
historyboolnoPrevious run results in agent context. Omit to inherit the agent default.
task_setup_toolsboolnoInternal same-scope management tools for agents, tasks, runs, approvals, files, memories, schedules, inboxes, webhooks, and app connections. Omit to inherit the agent default.
feedbackboolnoInternal issue-reporting feedback tool (report_issue). Omit to inherit the agent default.
email_inboxboolnoEnable email inbox on the created agent (only applies when creating new)
output_schemaobjectnoJSON Schema the run's final result must match. The structured result comes back on output_data (and on the run.completed webhook). Must be "type": "object"; inline your definitions ($ref/$defs are not supported). output_data is null when the model produced no structured result — always null-check it.

Streaming response: Server-Sent Events — raw flat Claude-native frames (the SDK normalizes these into text-delta, tool-call-start, tool-result-end):

data: {"type": "content_block_delta", "id": "block_1", "delta": {"type": "text_delta", "text": "Hello"}} data: {"type": "tool_use", "id": "tc_1", "name": "gmail_send", "input": {"to": "a@b.com"}} data: {"type": "tool_result", "tool_use_id": "tc_1", "content": "...", "result": "..."} data: {"type": "done", "completion_state": "complete", "stop_reason": "end_turn", "message_count": 2}

Non-streaming response 200 OK:

JSON

Polling: Non-streaming runs return immediately with status: "running". Poll GET /runs/{id} every 2 seconds until status is completed, failed, or cancelled.

Defaults: If permission_mode is omitted, the run inherits the agent's saved default. If human_in_the_loop is omitted, inherited approval and plan runs automatically enable it.

Validation: Explicitly setting human_in_the_loop=false is only valid with permission_mode="autonomous".

Internal tools: task_setup_tools=true by default. Set it to false when you do not want the agent to receive the internal same-scope management tools for agents, tasks, runs, approvals, files, memories, schedules, inboxes, webhooks, and app connections during this run.

End-user scope: when you target an existing scoped agent, the user_id in the request must match that agent's scope. If omitted, the run inherits the agent's existing scope.

Quick start: omit teammate_id and provide name to auto-create an agent:

Python

Response 200 OK

JSON

List Runs

GET /runs

ParameterTypeDescription
teammate_idintFilter by agent
task_idintOnly runs of this task — the pull-path for a scheduled/webhook task's run history and outputs
statusstringFilter by status (running, paused, awaiting_approval, completed, failed, cancelled, closed, archived)
exclude_platform_runsboolHide the platform's own work — the Company Agent's Day-1 onboarding, its twice-daily pulse, and context maintenance. Chat with the Company Agent still counts, because a user talking to it is the user working. Opt-in: used to ask whether the USER has run anything themselves yet.
sortstringcreated (newest first) or priority — runs needing a human first
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Create Run With Files

Multipart form-data: the payload field carries the exact POST /runs JSON body; files carries the attachments.

cURL

POST /runs/with-files

Response 200 OK

JSON

Check Run Freshness

GET /runs/check

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Get Run

GET /runs/{run_id}

Response 200 OK

JSON

Answer Question

POST /runs/{run_id}/answer

FieldTypeRequiredDescription
answersobjectyesMap of question text to selected option label
request_idstringnoOptional permission request_id for this AskUserQuestion. Required when multiple questions are pending so the answer targets the right gate (Platform dogfood / multi-pending). Omit to answer the first unanswered ask.

Use this for AskUserQuestion responses.

  • If the run is running, the answer is stored and picked up by the active run.
  • If the run is awaiting_approval, the answer resumes execution.
  • If the run is terminal (completed/failed/cancelled), the API returns 409.

Plan mode approvals use this endpoint with {"Plan Approval": "Approve"}.

Approve Permission

POST /runs/{run_id}/approve

FieldTypeRequiredDescription
request_idstringyesPermission request ID
decisionstringyesallow or deny the pending tool request.
rememberboolnoRemember this decision for subsequent matching tool requests during the current run, including after the run pauses and resumes. With decision=allow this also stores a cross-run always-allow policy for the tool (the same one /permissions manages); the response's remembered field reports whether that policy actually persisted. Re-sending the same decision can upgrade this to true, but cannot turn it back off: the field defaults to false, so an omitted flag is indistinguishable from an explicit opt-out and never revokes a grant. To stop remembering, deny the next request.
reasonstringnoOptional steering in your own words — e.g. with decision=deny, "use the staging board instead". The agent reads it and adapts rather than silently skipping the action. Delivered on both decisions when the run is paused; a deny's reason also reaches a still-live run.
cURL

Response status: after approval this returns a resolved status (allowed or denied), not pending. The response's resumed and remembered fields report what actually happened — whether a paused run restarted, and whether an always-allow policy persisted.

Remember behavior: remember=true applies to subsequent matching requests during the current run, and with decision=allow it also stores a persistent cross-run always-allow policy (the same one POST /permissions manages — use that endpoint to pre-configure or revoke). Check remembered in the response: the backend refuses to store a policy it would never consult (e.g. force-gated tools).

Response 200 OK

JSON

Archive Run

POST /runs/{run_id}/archive

Response 200 OK

JSON

Cancel Run

Cancel an active run. Returns 409 if the run is already completed, failed, or cancelled.

POST /runs/{run_id}/cancel

Response 200 OK

JSON

Reply To Run

Send a follow-up message on an existing run to continue the conversation.

Behavior note: runs.reply() inherits the run's settings: the permission mode (approval/plan gates keep applying) and whether the agent may ask questions (human_in_the_loop, as persisted at run creation). Pass human_in_the_loop: false on the reply to pin the legacy always-non-interactive behavior. Runs created before this setting existed stay non-interactive.

Internal tools: replies inherit the previous run's task_setup_tools setting unless you override it in the request body. Tools are automatically inherited from the previous run — to use different tools, start a new run.

POST /runs/{run_id}/reply

FieldTypeRequiredDescription
messagestringyesThe user message that drives the run.
streamboolnoReturn Server-Sent Events when true, a JSON object when false.
toolsstring[]noOverride this reply's app toolset (tool names from GET /api/v2/apps). Omitted or [] = inherit the run's current set ([] is NOT 'no tools'). A changed set persists to the run, so later replies inherit it. Custom MCP server slugs are not accepted here (422).
permission_modestringnoExecution-mode override for this and later replies. Omitted = inherit the mode persisted on the run (the mode it last ran with).
task_setup_toolsboolnoOverride whether the internal same-scope management tools are enabled for this reply. When omitted, inherits the previous run's setting.
feedbackboolnoOverride whether the internal issue-reporting feedback tool (report_issue) is enabled for this reply. When omitted, inherits the previous run's setting.
human_in_the_loopboolnoOverride whether the agent may ask questions (AskUserQuestion) during this reply. When omitted, inherits the setting persisted at run creation (runs created before this field existed stay non-interactive). Pass false to pin the legacy always-non-interactive reply behavior.

Response 200 OK

JSON

Retry Run

POST /runs/{run_id}/retry

ParameterTypeDescription
confirmboolAcknowledge that retrying may repeat actions the run already took. Required when the run performed non-read-only work.

Response 201 Created

JSON

Share Run

POST /runs/{run_id}/share

List Run Messages

GET /runs/{run_id}/messages

ParameterTypeDescription
after_sequenceintReturn only messages with sequence greater than this value
limitintMax results (1-1000, default 500)

Get Run Outcome

GET /runs/{run_id}/outcome

Response 200 OK

JSON

List Run Permissions

Returns pending and resolved tool permission requests for runs using approval or plan mode. This list can include tool_name="AskUserQuestion" entries.

GET /runs/{run_id}/permissions

cURL

Join Run Stream

GET /runs/{run_id}/stream

Update Permission Mode

PATCH /runs/{run_id}/permission-mode

FieldTypeRequiredDescription
permission_modestringyesExecution mode: autonomous, approval, or plan.

Mid-run behavior: Call this while the run is running or awaiting_approval.

Autonomous switch: changing to autonomous auto-approves pending tool approval requests and resumes a paused tool approval run.

Questions still wait: AskUserQuestion and plan approvals are not auto-answered. Use POST /runs/{id}/answer for those pauses.

Unshare Run

DELETE /runs/{run_id}/share

Reply To Run With Files

POST /runs/{run_id}/reply/with-files

Response 200 OK

JSON

Audit-Logs

Audit logs provide account-scoped request history for the v2 API.

List Audit Logs

GET /audit-logs

ParameterTypeDescription
actionstringFilter by action: list, read, create, update, delete
resource_typestringFilter by resource type (for example run or task.trigger)
methodstringFilter by HTTP method: GET, POST, PATCH, PUT, DELETE
status_codeintFilter by HTTP status code
authstringFilter by how the request was authenticated: api_key (SDK/API calls made with an m8_ key), dashboard (web app sessions and auth/tool events), or all. Defaults to all so this stays a complete security trail.
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID
cURL

Tasks

Tasks are reusable job definitions. Create a task, then attach triggers via tasks.triggers.create().

Create Task

POST /tasks

FieldTypeRequiredDescription
teammate_idintyesID of the agent to use.
namestringnoDisplay name.
instructionsstringyesInstructions
toolsstring[]noTool names, e.g. gmail, slack.
enable_memoryboolnoDefault for the memory tool.
enable_historyboolnoDefault for the task-history tool.
enable_task_setup_toolsboolnoDefault for the same-scope task-setup tools.
enable_feedbackboolnoDefault for the issue-reporting feedback tool.
enable_lessonsboolnoWhether this task's agent accumulates self-improvement lessons across its runs. Task-level only (no agent/run cascade).
expected_outputstringnoDescription of expected output format.
goalsstringnoTask-specific goals.
user_idstringnoYour end-user ID for data isolation. If the targeted agent is already scoped, this must match that scope. When omitted, the task inherits the agent's existing scope.
email_notificationsboolnoSend email notification when scheduled run completes
webhookboolnoEnable webhook trigger on creation. Returns webhook_url once.
schedulestringnoCron expression, e.g. '0 9 * * 1-5'
schedule_timezonestringnoTimezone for schedule, e.g. 'America/New_York'
modelstringnoModel for this task's runs, overriding the agent's. Same ids as the agent model field. Omit or null = inherit the agent's model (then the platform default). Use it to put one expensive task on a stronger model without moving the agent's other work.
effortstringnoReasoning effort for this task's runs, overriding the agent's. Same tiers as the agent effort field. Omit or null = inherit the agent's effort. A tier above the resolved model's max_effort is clamped down, never rejected.

Response 201 Created

JSON

List Tasks

GET /tasks

ParameterTypeDescription
teammate_idintFilter by agent
include_archivedboolInclude archived tasks. Off by default so the common case stays clean.
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Get Task

GET /tasks/{task_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Response 200 OK

JSON

Update Task

PATCH /tasks/{task_id}

FieldTypeRequiredDescription
namestringnoDisplay name.
instructionsstringnoInstructions
toolsstring[]noTool names, e.g. gmail, slack.
enable_memoryboolnoDefault for the memory tool.
enable_historyboolnoDefault for the task-history tool.
enable_task_setup_toolsboolnoDefault for the same-scope task-setup tools.
enable_feedbackboolnoDefault for the issue-reporting feedback tool.
enable_lessonsboolnoWhether this task accumulates self-improvement lessons.
expected_outputstringnoDescription of the expected output format.
goalsstringnoGoals
email_notificationsboolnoEmail the responsible human when a scheduled run completes.
modelstringnoModel for this task's runs, overriding the agent's. Same ids as the agent model field. Omit or null = inherit the agent's model (then the platform default). Use it to put one expensive task on a stronger model without moving the agent's other work.
effortstringnoReasoning effort for this task's runs, overriding the agent's. Same tiers as the agent effort field. Omit or null = inherit the agent's effort. A tier above the resolved model's max_effort is clamped down, never rejected.
statusstringnoEnable or disable the task. Disabling pauses its schedules and event triggers; re-enabling re-arms the paused schedules, but event triggers stay off until re-enabled explicitly (PATCH the trigger).

Response 200 OK

JSON

Delete Task

DELETE /tasks/{task_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Run Task

POST /tasks/{task_id}/runs

FieldTypeRequiredDescription
permission_modestringnoExecution mode override. If omitted, inherits from the agent default for direct runs or the saved task mode for task runs. autonomous=auto-approve all tools, approval=pause and ask before tool use, plan=require plan approval before execution
human_in_the_loopboolnoEnable human-in-the-loop features: clarifying questions, tool approval, and plan approval. If omitted, approval/plan inherit as true and autonomous inherits as false.
streamboolnoReturn Server-Sent Events when true, a JSON object when false.
modelstringnoPer-run model override — any id from GET /api/v2/models. Omit to use the agent's model, then the platform default.
effortstringnoPer-run reasoning-effort override. Reasoning effort for runs: low | medium | high | xhigh | max. Omit or null = platform default (max on Claude models — reason as hard as the model allows; high on all others). Higher effort = deeper reasoning, more tokens, higher cost per run; lower effort = faster and cheaper. xhigh and max are Claude-only tiers — on other models they are clamped down to high, never rejected (each model's ceiling is max_effort on GET /api/v2/models). Per-run effort overrides the task's, which overrides the agent's; resumes and replies inherit the run's effort. Effort currently takes effect on Claude models and the GPT-5.6 family; other models accept the field but may ignore it.
user_idstringnoYour end-user ID for data isolation. If the saved task is already scoped, this must match that scope. When omitted, the run inherits the task's existing scope.
metadataobjectnoArbitrary key-value data. Keys reserved for internal use are ignored (backend run markers such as error_code, auto_retryable, interrupted, and nudged_* delivery stamps).
output_schemaobjectnoJSON Schema the run's final result must match. The structured result comes back on output_data (and on the run.completed webhook). Must be "type": "object"; inline your definitions ($ref/$defs are not supported). output_data is null when the model produced no structured result — always null-check it. Applies to THIS run only: a scheduled run of the same task does not inherit it.
memoryboolnoSaved memories in agent context. Omit to inherit the agent default.
historyboolnoPrevious run results in agent context. Omit to inherit the agent default.
task_setup_toolsboolnoInternal same-scope management tools for agents, tasks, runs, approvals, files, memories, schedules, inboxes, webhooks, and app connections. Omit to inherit the agent default.
feedbackboolnoInternal issue-reporting feedback tool (report_issue). Omit to inherit the agent default.

Defaults: If permission_mode is omitted, the run inherits the saved task's permission mode. If human_in_the_loop is omitted, inherited approval and plan runs automatically enable it.

Validation: Explicitly setting human_in_the_loop=false is only valid with permission_mode="autonomous".

Internal tools: task_setup_tools=true by default. Set it to false to run a saved task without the internal same-scope management tools.

End-user scope: when the saved task is already scoped, the user_id in the request must match that scope. If omitted, the run inherits the task's existing scope.

Response 200 OK

JSON

Create Trigger

POST /tasks/{task_id}/triggers

FieldTypeRequiredDescription
typestringyesTrigger type, e.g. schedule, webhook, or an app event.
cronstringnoCron expression (for schedule triggers).
interval_secondsintnoInterval in seconds (for recurring triggers).
run_atstringnoISO 8601 datetime for a ONE-TIME run (e.g. '2027-07-20T09:00:00'). Fires once, then retires itself. Naive values are read in timezone.
timezonestringnoIANA timezone for schedule evaluation.
appstringnoApp name, e.g. 'github'
trigger_namestringnoTrigger slug, e.g. 'GITHUB_COMMIT_EVENT'
trigger_configobjectnoTrigger-specific config
user_idstringnoEnd-user whose connected account to use
allowed_sendersstring[]noAllowed Senders

Response 201 Created

JSON

Enable Task Webhook

POST /tasks/{task_id}/webhook

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

List Triggers

GET /tasks/{task_id}/triggers

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Set Task Webhook Enabled

PATCH /tasks/{task_id}/webhook

FieldTypeRequiredDescription
enabledboolyesTrue resumes the webhook, False pauses it

Disable Task Webhook

DELETE /tasks/{task_id}/webhook

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Update Trigger

PATCH /tasks/{task_id}/triggers/{trigger_id}

FieldTypeRequiredDescription
enabledboolnoEnabled
cronstringnoCron expression (for schedule triggers).
interval_secondsintnoInterval in seconds (for recurring triggers).
run_atstringnoISO 8601 datetime — reshapes this trigger into a one-time run.
timezonestringnoIANA timezone for schedule evaluation.

Response 200 OK

JSON

Delete Trigger

DELETE /tasks/{task_id}/triggers/{trigger_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Lessons

Self-improvement lessons a task's agent writes for itself across runs. The agent authors them during runs; via the API you can list or clear them per task.

Clear Lessons

POST /tasks/{task_id}/lessons:clear

ParameterTypeDescription
confirmboolRequired to confirm. Pass ?confirm=true to actually clear.
cURL

Response 200 OK

JSON

List Lessons

GET /tasks/{task_id}/lessons

cURL

Response 200 OK

JSON

Delete Lesson

DELETE /tasks/{task_id}/lessons/{lesson_id}

cURL

Response 200 OK

JSON

Apps

List available tools, connect integrations via OAuth, and manage end-user connections.

List Apps

Pass user_id to check connection status for a specific end-user.

GET /apps

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Connect App

POST /apps/{app_name}/connect

FieldTypeRequiredDescription
redirect_uristringyesURL to redirect after OAuth. For end-user connections (user_id set) this is your own callback. For ACCOUNT-level connections it must be a m8tes URL (https://www.m8tes.ai/apps): the claim ticket that authorizes completion is delivered here, so it has to reach the browser that authorized rather than the caller that created the link. That means an account-level connect finishes in the browser, not in your backend — read composio_claim off the URL you land on and pass it to connect/complete. To connect on behalf of one of your own users from your own app, pass user_id: that keeps your callback and needs no ticket.
user_idstringnoEnd-user ID for multi-tenant connections

Response 200 OK

JSON

Provision App

For apps with auth_type: "platform_provisioned" (e.g. twilio), the platform allocates a dedicated resource — a phone number — rather than you supplying credentials. Pass user_id to provision a per-end-user resource (strictly isolated at run time); omit it for an account-level resource. Release it with DELETE /apps/{app_name}/connections (client.apps.release(...)).

POST /apps/{app_name}/provision

FieldTypeRequiredDescription
user_idstringnoEnd-user ID to provision for (omit for account-level)

Response 200 OK

JSON

List App Tools

GET /apps/{app_name}/tools

List App Trigger Types

GET /apps/{app_name}/triggers

Disconnect App

DELETE /apps/{app_name}/connections

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Connect App Api Key

POST /apps/{app_name}/connect/api-key

FieldTypeRequiredDescription
api_keystringyesAPI key for the integration
user_idstringnoEnd-user ID for multi-tenant connections

Response 200 OK

JSON

Connect App Complete

After the user completes OAuth and is redirected back:

POST /apps/{app_name}/connect/complete

FieldTypeRequiredDescription
connection_idstringnoConnection to complete. Required for end-user connections (user_id set); ignored for account-level ones, where the connection comes from claim_ticket.
claim_ticketstringnoREQUIRED for account-level connections. Appended to your redirect_uri as composio_claim when the OAuth flow returns, so it reaches the browser that authorized. It is what proves the caller is the account that started the flow — without it a connect link could be forwarded and the recipient's provider account bound to whoever sent it. Not used for end-user connections, which the developer hands to their own end user by design.
user_idstringnoEnd-user ID for multi-tenant connections

Response 200 OK

JSON

Built-In-Tools

Discover the platform's built-in tools (memory, task history, task setup, feedback, and more). These are not passed in the tools array; the four configurable ones are toggled via the enable_* fields on agents, tasks, and runs.

List Built In Tools

GET /built-in-tools

ParameterTypeDescription
teammate_idintResolve enabled state for this teammate's config
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Mcp-Servers

Register your own REST, remote MCP, or Python script tools. kind=script takes script_source (write-only; reads return script_sha256) and cannot take user_id; strict API accounts can still create one. See the Custom tools guide.

Create Mcp Server

kind is rest_api (default; typed tool_defs with method/path), mcp_http/mcp_sse (remote MCP; empty tool_defs), or script (Python script_source; tool_defs are name-only; user_id is forbidden). script_source is write-only — the response carries script_sha256.

POST /mcp-servers

FieldTypeRequiredDescription
namestringyesDisplay name.
urlstringyesHTTPS endpoint URL to receive deliveries.
kindstringnorest_api (typed endpoints in tool_defs), mcp_http/mcp_sse (remote MCP; empty tool_defs), or script (Python; script_source required, user_id forbidden).
auth_typestringnoAuth Type
auth_configobjectnoAuth Config
secretstringnoSecret
tool_defsany[]noTool Defs
descriptionstringnoDescription
user_idstringnoUser Id
auto_approveboolnoAuto Approve
script_sourcestringnoPython source for kind=script. Write-only — never returned. Must define def <tool_name>(**args) for each tool_def name. Injected names: http, json only.
script_allowliststring[]noExtra https origins a kind=script tool may call (max 8). The primary origin is url (canonical https origin, no path).
cURL

Create Mcp Server

kind is rest_api (default; typed tool_defs with method/path), mcp_http/mcp_sse (remote MCP; empty tool_defs), or script (Python script_source; tool_defs are name-only; user_id is forbidden). script_source is write-only — the response carries script_sha256.

POST /mcp-servers

FieldTypeRequiredDescription
namestringyesDisplay name.
urlstringyesHTTPS endpoint URL to receive deliveries.
kindstringnorest_api (typed endpoints in tool_defs), mcp_http/mcp_sse (remote MCP; empty tool_defs), or script (Python; script_source required, user_id forbidden).
auth_typestringnoAuth Type
auth_configobjectnoAuth Config
secretstringnoSecret
tool_defsany[]noTool Defs
descriptionstringnoDescription
user_idstringnoUser Id
auto_approveboolnoAuto Approve
script_sourcestringnoPython source for kind=script. Write-only — never returned. Must define def <tool_name>(**args) for each tool_def name. Injected names: http, json only.
script_allowliststring[]noExtra https origins a kind=script tool may call (max 8). The primary origin is url (canonical https origin, no path).
cURL

List Mcp Servers

GET /mcp-servers

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

List Mcp Servers

GET /mcp-servers

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Get Mcp Server

GET /mcp-servers/{server_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Update Mcp Server

PATCH /mcp-servers/{server_id}

FieldTypeRequiredDescription
namestringnoDisplay name.
urlstringnoHTTPS endpoint URL to receive deliveries.
auth_typestringnoAuth Type
auth_configobjectnoAuth Config
secretstringnoSecret
tool_defsany[]noTool Defs
descriptionstringnoDescription
statusstringnoStatus
auto_approveboolnoAuto Approve
script_sourcestringnoReplace the Python source (kind=script only). Write-only. Clears auto_approve.
script_allowliststring[]noReplace extra https origins (kind=script only). Clears auto_approve.
cURL

Delete Mcp Server

DELETE /mcp-servers/{server_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Approve Mcp Server

POST /mcp-servers/{server_id}/approve

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Skills

Reusable SKILL.md playbooks agents load on demand. Create account- or agent-scoped skills; see the Custom Skills guide.

Create Skill

POST /skills

FieldTypeRequiredDescription
namestringyesDisplay name.
descriptionstringyesDescription
bodystringyesBody
scopestringnoScope
teammate_idintnoID of the agent to use.
user_idstringnoUser Id
cURL

Create Skill

POST /skills

FieldTypeRequiredDescription
namestringyesDisplay name.
descriptionstringyesDescription
bodystringyesBody
scopestringnoScope
teammate_idintnoID of the agent to use.
user_idstringnoUser Id
cURL

List Skills

GET /skills

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

List Skills

GET /skills

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Get Skill

GET /skills/{skill_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Update Skill

PATCH /skills/{skill_id}

FieldTypeRequiredDescription
namestringnoDisplay name.
descriptionstringnoDescription
bodystringnoBody
statusstringnoStatus
cURL

Delete Skill

DELETE /skills/{skill_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.
cURL

Bridges

Per-account BlueBubbles bridges that connect an agent to iMessage. Register a bridge, then enable inbound iMessage on an agent with bridge_id.

Create Bridge

POST /bridges

FieldTypeRequiredDescription
namestringnoDisplay name.
server_urlstringyeshttps URL of the BlueBubbles server
passwordstringyesBlueBubbles API password (stored encrypted, never returned)
owner_handlestringnoYour own iMessage handle (phone or email). Authorizes you to text the Company Agent (your inbound-default agent) right away, without editing its allowlist.
cURL

List Bridges

GET /bridges

cURL

Provision Bridge

POST /bridges/provision

cURL

Provision Blooio

POST /bridges/provision-blooio

FieldTypeRequiredDescription
numberstringyesThe dedicated Blooio iMessage number (E.164) to route to this account.
api_keystringnoOptional BYO Blooio API key (stored encrypted); omit to use the platform key.
user_idstringnoOptional end-user to bind this dedicated line to (multi-tenant isolation).
cURL

Get Bridge

GET /bridges/{bridge_id}

cURL

Update Bridge

PATCH /bridges/{bridge_id}

FieldTypeRequiredDescription
namestringnoDisplay name.
server_urlstringnoServer Url
passwordstringnoPassword
statusstringnoStatus
owner_handlestringnoOwner Handle
cURL

Delete Bridge

DELETE /bridges/{bridge_id}

cURL

POST /bridges/{bridge_id}/link-code

cURL

Rotate Bridge Secret

POST /bridges/{bridge_id}/rotate-secret

cURL

Test Bridge Connection

POST /bridges/{bridge_id}/test

cURL

List Bridge Handles

GET /bridges/{bridge_id}/handles

cURL

Delete Bridge Handle

DELETE /bridges/{bridge_id}/handles/{handle_id}

cURL

Channels

Slack and GitHub channel identity for this account. With no identity the shared @m8tes Slack app / m8tes Code GitHub App is used; upsert_identity stores your own Slack app or GitHub App credentials (bot/App name and avatar stay in Slack/GitHub dashboards). channel=github requires github_app_id, github_app_slug, and github_private_key. install_links mints Add-to-Slack and GitHub App install URLs; it 503s if Slack is unavailable even when GitHub is configured.

List Channels

GET /channels

GET /channels/install-links

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Upsert Identity

PUT /channels/identities

FieldTypeRequiredDescription
channelstringyesslack or github. Email custom domains are a later slice.
client_idstringyesClient Id
client_secretstringyesClient Secret
signing_secretstringyesSigning Secret
github_app_idstringnoRequired when channel is github.
github_app_slugstringnoRequired when channel is github.
github_private_keystringnoRequired when channel is github. Never returned.

Github-App

m8tes Code — account GitHub App install for coding agents (clone, test, push, PR). Account-scoped (not per user_id). Open install_url in a browser; bind a claim ticket when needed. Per-agent repo bindings live under Agents (/agents/{id}/repos). See Coding Agents.

Github App Disconnect

DELETE /github-app

Github App Claim

POST /github-app/claim

FieldTypeRequiredDescription
ticketstringyesTicket

Github App Install Url

GET /github-app/install-url

Github App Repos

GET /github-app/repos

Github App Status

GET /github-app/status


Memories

Pre-populate or manage end-user memories. Memories are injected into the agent's context during execution to personalize responses.

Create Memory

POST /memories

FieldTypeRequiredDescription
user_idstringnoEnd-user ID this memory belongs to. Omit for an account-level memory (seen by runs that have no user_id).
contentstringyesThe text content to store.
audiencestringnoWhether this memory is about the end-user themselves or about their business. Optional; omit when you cannot tell. Both are read by every agent today — this records the distinction for future visibility rules rather than changing what is injected now.

Response 201 Created

JSON

List Memories

Pass user_id to list one end-user's memories; omit it for account-level memories. The two scopes never mix.

GET /memories

ParameterTypeDescription
querystringOptional keyword filter — case-insensitive substring match on content.
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Update Memory

PATCH /memories/{memory_id}

FieldTypeRequiredDescription
contentstringnoThe text content to store.
audiencestringnoReclassify this memory as personal or company. Omitted leaves the existing classification alone — send it explicitly to correct one. Classification is one-way: you can change personal to company or vice versa, but not back to unclassified, which means 'never classified' rather than 'we decided we cannot tell'. Delete and re-create if you truly need that. Ignored for teammate-scoped memories, whose audience is the teammate.

Response 200 OK

JSON

Delete Memory

Matches exactly the scope you pass: an end-user memory is only reachable with its user_id, an account-level memory only without one.

DELETE /memories/{memory_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Permissions

Pre-configure tool allow-lists for your end-users. Tools added here are auto-approved when runs use approval mode.

Create Permission

Idempotent: re-creating the same permission returns the existing record.

POST /permissions

FieldTypeRequiredDescription
user_idstringnoEnd-user ID. Omit to target the account-level scope.
toolstringyesTool name to allow, e.g. 'gmail'

Response 201 Created

JSON

List Permissions

GET /permissions

ParameterTypeDescription
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Delete Permission

DELETE /permissions/{permission_id}

ParameterTypeDescription
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Users

Manage end-user profiles. Profiles are auto-created when user_id is passed to any endpoint, or created explicitly with profile data.

Create End User

POST /users

FieldTypeRequiredDescription
user_idstringyesYour end-user identifier
namestringnoDisplay name.
emailstringnoEmail address.
companystringnoCompany name.
metadataobjectnoArbitrary key-value data
run_limitintnoOverride: this end-user's completed-runs cap per billing period (0 = blocked entirely; null = inherit the account-wide default)
cost_limit_centsintnoOverride: this end-user's metered-cost cap in US cents (null = inherit)
rate_per_minuteintnoOverride: this end-user's run-starts-per-minute rate limit (null = inherit)

Response 201 Created

JSON

List End Users

GET /users

ParameterTypeDescription
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID

Get End User

GET /users/{user_id}

Response 200 OK

JSON

Update End User

PATCH /users/{user_id}

FieldTypeRequiredDescription
namestringnoDisplay name.
emailstringnoEmail address.
companystringnoCompany name.
metadataobjectnoArbitrary key-value data
run_limitintnoOverride: this end-user's completed-runs cap per billing period (0 = blocked entirely; null = inherit the account-wide default)
cost_limit_centsintnoOverride: this end-user's metered-cost cap in US cents (null = inherit)
rate_per_minuteintnoOverride: this end-user's run-starts-per-minute rate limit (null = inherit)

Response 200 OK

JSON

Delete End User

DELETE /users/{user_id}


Settings

Account-level configuration: data retention and per-end-user sub-caps.

Get Settings

GET /settings

Response 200 OK

JSON

Update Settings

PATCH /settings

FieldTypeRequiredDescription
per_end_user_run_limitintnoCap each end-user's (user_id) completed runs per billing period so one end-user can't drain the account budget. Send null to remove the cap; omit to leave unchanged.
per_end_user_cost_limit_centsintnoCap each end-user's metered run cost (US cents) per billing period. Send null to remove the cap; omit to leave unchanged.
per_end_user_rate_per_minuteintnoRate-limit each end-user to this many agent turns per minute — run starts AND replies (429 END_USER_RATE_LIMITED past it). Send null to turn off; omit to leave unchanged.
retention_modestringnoData retention. 'standard' stores conversation content; 'metadata_only' (zero data retention) never persists message content, tool I/O, or generated reports — only metadata (token/cost metrics, tool names). Omit to leave unchanged.
require_end_user_idboolnoStrict multi-tenant mode: reject requests that would land data in the account-level scope because user_id was omitted (422) instead of silently assuming the global account scope. Enforced on agent, task, run, skill, and custom-MCP-server creation; on every memory operation; and on LISTING agents, tasks, runs, skills, custom MCP servers, memories and permissions — an unscoped list is how a forgotten user_id returns one end-user another's rows. Catalogue reads (apps, built-in tools), app connections, and replies/retries of pre-existing unscoped runs are exempt. Recommended for multi-tenant integrations. Omit to leave unchanged.

Response 200 OK

JSON

Keys

Create Named Key

POST /keys

FieldTypeRequiredDescription
namestringyesA label, e.g. 'production'.
expires_in_daysintnoOptional expiry in days; omit for no expiry.

Get Key Info

GET /keys

Revoke Key

DELETE /keys

Rotate Key

POST /keys/rotate

List Named Keys

GET /keys/all

Revoke Named Key

DELETE /keys/{key_id}

Rotate Named Key

POST /keys/{key_id}/rotate


Usage

Inspect the current account plan, run usage, cost usage, and billing period.

Get Usage

GET /usage

client.billing.usage() is an alias for client.auth.get_usage().

Response 200 OK

JSON

List End User Usage

GET /usage/end-users

ParameterTypeDescription
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Get Usage Timeseries

GET /usage/timeseries

ParameterTypeDescription
start_datestringFirst UTC day (default: 29 days before end_date)
end_datestringLast UTC day, inclusive (default: today)
teammate_idintFilter to one teammate
surfacestringFilter by the run's stamped billing surface: "api" (end-user-scoped / embedding work) or "platform" (first-party work). This is the surface a run was CREATED on, not the meter it finally settled on — a run's settlement can differ (own-subscription turns, plan finalisation). Omit for every surface.
settled_meterstringFilter by where the run actually settled: wallet (prepaid ledger), plan (subscription), released (non-billable), or own_sub (user's own model subscription). This is Run.settled_meter, not billing_surface. The API billing page passes wallet so the chart cannot show spend the prepaid ledger never saw. Cost is still the usage estimate, not SUM(ledger debits). Omit for every settlement.
group_bystringAdd per-model slices to each bucket ("model")
user_idstringScope to one end-user (maps to end_user_id). Omit for the account view.

Response 200 OK

JSON

Billing

Inspect the public paid-plan catalog, manage opt-in usage overage (per-run charges past your plan's included runs, capped at a monthly ceiling you set), and top up or read a prepaid token balance (a micro-USD balance plus its ledger).

Create Topup

POST /billing/topup

FieldTypeRequiredDescription
amount_centsintyesAmount to add to the token balance, in cents ($5 min, $1M max).

The call returns a Stripe Checkout URL; the balance is credited asynchronously after payment, so balance() won't reflect it until checkout completes.

Response 200 OK

JSON

Get Balance

GET /billing/balance

Amounts are in micro-USD (1 micro-USD = 1e-6 USD); balance_usd is a rounded display string. Each transaction type is one of topup, debit, refund, or adjustment.

Response 200 OK

JSON

Get Plans

GET /billing/plans

Response 200 OK

JSON

List Receipts

GET /billing/receipts

ParameterTypeDescription
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID

Update Alert Settings

PATCH /billing/alert-settings

FieldTypeRequiredDescription
low_balance_threshold_centsintyesBalance (cents) at which the low-balance warning fires (0 to $100k).

Update Auto Reload

PATCH /billing/auto-reload

FieldTypeRequiredDescription
enabledboolyesTurn auto-reload on or off.
threshold_centsintnoReload when the balance falls below this (cents). Required to enable.
amount_centsintnoAmount charged per reload, in cents ($5 min, $10k max). Required to enable.

Update Overage Settings

Opt in/out of usage overage and set the monthly spend cap (cents, max $10,000). The response echoes the full usage payload — the same shape as GET /usage.

PATCH /billing/overage

FieldTypeRequiredDescription
enabledboolyesTurn usage overage on or off.
monthly_cap_centsintyesMonthly overage spend ceiling in cents (0 to 1,000,000, i.e. up to $10,000).

Response 200 OK

JSON

Account

Account-level data controls: export all of your account's data, or delete the account and its data (GDPR/CCPA).

Delete Account

DELETE /account

cURL

Change Password

POST /account/password

FieldTypeRequiredDescription
current_passwordstringyesThe account's current password, to prove possession.
new_passwordstringyesThe replacement password, at least 8 characters. Revokes every session (a fresh pair is returned, or an MFA challenge when 2FA is on) but deliberately leaves API keys and webhook tokens working — only a password RESET, which cannot prove you knew the old password, revokes those.

Export Account

GET /account/export

cURL

Webhooks

Register URLs to receive signed event notifications when runs change status.

Create Webhook

POST /webhooks

FieldTypeRequiredDescription
urlstringyesHTTPS URL to receive events
eventsstring[]noEvents: run.started, run.completed, run.failed, run.cancelled, run.awaiting_input

Note: The secret is only returned on creation. Store it securely.

Response 201 Created

JSON

List Webhooks

Secrets are masked in list responses.

GET /webhooks

ParameterTypeDescription
limitintMax results (1-100, default 20)
starting_afterintCursor: last item ID

Get Webhook

GET /webhooks/{webhook_id}

Response 200 OK

JSON

Update Webhook

PATCH /webhooks/{webhook_id}

FieldTypeRequiredDescription
urlstringnoHTTPS endpoint URL to receive deliveries.
eventsstring[]noEvent types to subscribe to, e.g. run.completed.
activeboolnoWhether it is enabled.
rotate_secretboolnoGenerate a new signing secret

Response 200 OK

JSON

Delete Webhook

DELETE /webhooks/{webhook_id}

List Deliveries

View delivery attempts for a webhook endpoint.

GET /webhooks/{webhook_id}/deliveries

ParameterTypeDescription
limitintMax results (1-100, default 20)
starting_afterintCursor: last delivery ID

Errors

All errors follow a standard format:

JSON

doc_url links to the docs page for that error type. Include request_id when you contact support.

code is always the HTTP status. When a semantic app code exists (e.g. RUN_LIMIT_REACHED, TOKEN_BALANCE_DEPLETED, unknown_query_parameter) it is on error.error_code — branch on that, never on the message text. error.details.error_code carries the same value for backward compatibility, alongside any extra context fields.

StatusTypeSDK ExceptionDescription
400invalid_request_errorValidationErrorInvalid request
401authentication_errorAuthenticationErrorInvalid or missing API key
402billing_errorBillingErrorRun or cost limit reached, or subscription issue
403permission_errorPermissionDeniedErrorInsufficient permissions
404not_foundNotFoundErrorResource not found
409conflict_errorConflictErrorResource conflict (duplicate, not active)
422validation_errorValidationErrorInvalid request parameters
429rate_limit_errorRateLimitErrorToo many requests (auto-retried by SDK)
500+api_errorAPIErrorServer error (auto-retried by SDK)
Was this page helpful?