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
| Field | Type | Required | Description |
|---|
| email | string | yes | Email address. |
| first_name | string | yes | First Name |
| password | string | no | Password |
| product | string | no | Product |
| require_end_user_id | bool | no | Strict 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. |
Token
Mint or rotate your API key. Rotating invalidates the previous key immediately.
Get Token
POST /token
| Field | Type | Required | Description |
|---|
| email | string | yes | Email address. |
| password | string | yes | Password |
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
Verify Status
GET /verify/status
Agents
Agents are reusable personas with instructions and tools. Coding: bind repositories under /agents/{id}/repos after connecting GitHub App.
Create Agent
POST /agents
| Field | Type | Required | Description |
|---|
| name | string | no | Defaults to a random name if not provided |
| instructions | string | no | Agent system-prompt instructions. |
| tools | string[] | no | Tool names, e.g. ['gmail', 'slack'] |
| enable_memory | bool | no | Default for the memory tool. Null = platform default (on). |
| enable_history | bool | no | Default for the task-history tool. Null = platform default (on). |
| enable_task_setup_tools | bool | no | Default for the same-scope task-setup tools. Null = platform default (on). |
| enable_feedback | bool | no | Default for the issue-reporting feedback tool. Null = platform default (on). |
| enable_self_improvement | bool | no | When 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. |
| role | string | no | Agent persona role, e.g. 'Customer support specialist'. |
| prompt_profile | string | no | Which 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_tools | string[] | no | Built-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. |
| goals | string | no | Agent goals. Injected into system prompt. |
| user_id | string | no | Your end-user ID for data isolation for this agent. |
| metadata | object | no | Arbitrary key-value data |
| allowed_senders | string[] | no | Email addresses or @domain patterns allowed to email this agent. Overrides default. |
| inbound_imessage_enabled | bool | no | Enable inbound iMessage routing for this agent. |
| imessage_chat_guid | string | no | BlueBubbles chat GUID used for inbound routing and outbound replies. |
| bridge_id | int | no | BlueBubblesBridge to route this agent's iMessage through (account-scoped). |
| allowed_imessage_senders | string[] | no | Sender handles (phone/email) allowed to trigger this agent via iMessage. Required (fail-closed) when iMessage is enabled. |
| inbound_slack_enabled | bool | no | Deprecated 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_slug | string | no | Deprecated. Inbound Slack no longer routes by a typed handle; @m8tes in a bound channel reaches this agent. Kept for read compatibility. |
| slack_channels | any[] | no | Slack 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_senders | string[] | no | Slack 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_inbox | bool | no | Enable email inbox on creation |
| webhook | bool | no | Enable webhook trigger on creation. Returns webhook_url once. |
| default_permission_mode | string | no | Default 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 |
| model | string | no | Model 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. |
| effort | string | no | 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. |
| from_template | string | no | Enable 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_answers | object | no | Wizard 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_slugs | string[] | no | Which 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_slugs | string[] | no | Which template bootstrap_tasks to seed. Null = all of them. Bootstrap tasks run once on enable. Only valid alongside from_template. |
Response 201 Created
List Agents
GET /agents
| Parameter | Type | Description |
|---|
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
| include_archived | bool | Include archived agents (status 'archived') so they can be unarchived. |
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
All list endpoints return a paginated envelope:
Use starting_after with the last item's ID to fetch the next page.
Get Agent
GET /agents/{agent_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Response 200 OK
Update Agent
PATCH /agents/{agent_id}
| Field | Type | Required | Description |
|---|
| name | string | no | Agent name. |
| instructions | string | no | Agent system-prompt instructions. |
| tools | string[] | no | Tool names, e.g. ['gmail', 'slack']. |
| enable_memory | bool | no | Default for the memory tool. |
| enable_history | bool | no | Default for the task-history tool. |
| enable_task_setup_tools | bool | no | Default for the same-scope task-setup tools. |
| enable_feedback | bool | no | Default for the issue-reporting feedback tool. |
| enable_self_improvement | bool | no | Turn the weekly review-and-improve task on/off. When true the agent reads its own runs and improves itself (implies task-setup/history/memory). |
| role | string | no | Agent persona role. |
| prompt_profile | string | no | Switch 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_tools | string[] | no | Built-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. |
| goals | string | no | Agent goals. Injected into the system prompt. |
| metadata | object | no | Arbitrary key-value data. |
| display_order | int | no | Manual 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_senders | string[] | no | Email addresses or @domain patterns allowed to email this agent. |
| inbound_imessage_enabled | bool | no | Enable inbound iMessage routing for this agent. |
| imessage_chat_guid | string | no | BlueBubbles chat GUID used for inbound routing and outbound replies. |
| bridge_id | int | no | BlueBubbles bridge to route this agent's iMessage through (account-scoped). |
| allowed_imessage_senders | string[] | no | Sender handles (phone/email) allowed to trigger this agent via iMessage. |
| inbound_slack_enabled | bool | no | Deprecated toggle. Prefer slack_channels: assigning channels turns Slack on for this agent; clearing them turns it off. |
| slack_slug | string | no | Deprecated. Inbound Slack routes by bound channel, not a typed handle. |
| slack_channels | any[] | no | Replace 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_senders | string[] | no | Slack 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_mode | string | no | Default execution mode; null (or omitting the field) leaves it unchanged. |
| model | string | no | Model 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. |
| effort | string | no | 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. |
Response 200 OK
Delete Agent
Soft-deletes (archives) the agent. Returns 204 No Content.
DELETE /agents/{agent_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Disable Agent
POST /agents/{agent_id}/disable
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Response 200 OK
Enable Email Inbox
POST /agents/{agent_id}/email-inbox
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Enable Agent
POST /agents/{agent_id}/enable
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Response 200 OK
Enable Fetchmail
POST /agents/{agent_id}/fetchmail
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
POST /agents/{agent_id}/repos
| Field | Type | Required | Description |
|---|
| repo_full_name | string | yes | Repo Full Name |
| mode | string | no | Omitted: new bindings default to trusted; reconfigure keeps existing mode |
Reset Agent Overrides
POST /agents/{agent_id}/reset
| Field | Type | Required | Description |
|---|
| fields | string[] | no | Fields to reset. None = reset all overrides. |
Unarchive Agent
POST /agents/{agent_id}/unarchive
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Response 200 OK
List Agent Documents
GET /agents/{agent_id}/documents
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
List Agent Repos
GET /agents/{agent_id}/repos
| Parameter | Type | Description |
|---|
| user_id | string | Must be omitted — this resource is account-scoped, never per end-user. |
Get Agent System Prompt
GET /agents/{agent_id}/system-prompt
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Set Agent Webhook Enabled
PATCH /agents/{agent_id}/webhook
| Field | Type | Required | Description |
|---|
| enabled | bool | yes | True resumes the webhook, False pauses it |
Disable Email Inbox
DELETE /agents/{agent_id}/email-inbox
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Disable Fetchmail
DELETE /agents/{agent_id}/fetchmail
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Read Agent Document
GET /agents/{agent_id}/documents/{name}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Response 200 OK
Remove Agent Repo
DELETE /agents/{agent_id}/repos/{repo_id}
| Parameter | Type | Description |
|---|
| user_id | string | Must be omitted — this resource is account-scoped, never per end-user. |
Approve Agent Repo Commands
POST /agents/{agent_id}/repos/{repo_id}/approve-commands
| Field | Type | Required | Description |
|---|
| commands_digest | string | yes | Commands Digest |
Clear Agent Repo Commands
DELETE /agents/{agent_id}/repos/{repo_id}/commands
| Parameter | Type | Description |
|---|
| user_id | string | Must 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
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
| Parameter | Type | Description |
|---|
| zdr | bool | If set, filter by provider-level ZDR support (zdr_supported). Not the same as ZDR enabled for your concentrate key. |
| author | string | Filter by concentrate author/provider slug (e.g. openai, anthropic). |
| curated | bool | If true, return only the Platform curated short list (not full catalog). |
| limit | int | Max 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
| Field | Type | Required | Description |
|---|
| access_token | string | yes | Access Token |
| refresh_token | string | no | Refresh Token |
| expires_at_ms | int | no | Expires 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}
| Field | Type | Required | Description |
|---|
| code | string | yes | Code |
Poll Model Connection Authorization
GET /model-connections/{provider}/authorizations/{state}
Cancel Model Connection Authorization
DELETE /model-connections/{provider}/authorizations/{state}
Runs
Runs are task executions. They stream Server-Sent Events by default.
Create Run
POST /runs
| Field | Type | Required | Description |
|---|
| permission_mode | string | no | Execution 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_loop | bool | no | Enable 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_id | int | no | ID of the agent to use. |
| message | string | yes | The user message that drives the run. |
| tools | string[] | no | Tool names, e.g. gmail, slack. |
| model | string | no | Per-run model override — any id from GET /api/v2/models. Omit to use the agent's model, then the platform default. |
| effort | string | no | Per-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. |
| stream | bool | no | Return Server-Sent Events when true, a JSON object when false. |
| name | string | no | Agent name (creates new if no teammate_id) |
| instructions | string | no | Agent instructions |
| user_id | string | no | Your 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. |
| metadata | object | no | Arbitrary key-value data. Keys reserved for internal use are ignored (backend run markers such as error_code, auto_retryable, interrupted, and nudged_* delivery stamps). |
| memory | bool | no | Saved memories in agent context. Omit to inherit the agent default. |
| history | bool | no | Previous run results in agent context. Omit to inherit the agent default. |
| task_setup_tools | bool | no | Internal same-scope management tools for agents, tasks, runs, approvals, files, memories, schedules, inboxes, webhooks, and app connections. Omit to inherit the agent default. |
| feedback | bool | no | Internal issue-reporting feedback tool (report_issue). Omit to inherit the agent default. |
| email_inbox | bool | no | Enable email inbox on the created agent (only applies when creating new) |
| output_schema | object | no | JSON 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:
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:
Response 200 OK
List Runs
GET /runs
| Parameter | Type | Description |
|---|
| teammate_id | int | Filter by agent |
| task_id | int | Only runs of this task — the pull-path for a scheduled/webhook task's run history and outputs |
| status | string | Filter by status (running, paused, awaiting_approval, completed, failed, cancelled, closed, archived) |
| exclude_platform_runs | bool | Hide 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. |
| sort | string | created (newest first) or priority — runs needing a human first |
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
| user_id | string | Scope 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.
POST /runs/with-files
Response 200 OK
Check Run Freshness
GET /runs/check
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Get Run
GET /runs/{run_id}
Response 200 OK
Answer Question
POST /runs/{run_id}/answer
| Field | Type | Required | Description |
|---|
| answers | object | yes | Map of question text to selected option label |
| request_id | string | no | Optional 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
| Field | Type | Required | Description |
|---|
| request_id | string | yes | Permission request ID |
| decision | string | yes | allow or deny the pending tool request. |
| remember | bool | no | Remember 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. |
| reason | string | no | Optional 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. |
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
Archive Run
POST /runs/{run_id}/archive
Response 200 OK
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
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
| Field | Type | Required | Description |
|---|
| message | string | yes | The user message that drives the run. |
| stream | bool | no | Return Server-Sent Events when true, a JSON object when false. |
| tools | string[] | no | Override 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_mode | string | no | Execution-mode override for this and later replies. Omitted = inherit the mode persisted on the run (the mode it last ran with). |
| task_setup_tools | bool | no | Override whether the internal same-scope management tools are enabled for this reply. When omitted, inherits the previous run's setting. |
| feedback | bool | no | Override 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_loop | bool | no | Override 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
Retry Run
POST /runs/{run_id}/retry
| Parameter | Type | Description |
|---|
| confirm | bool | Acknowledge that retrying may repeat actions the run already took. Required when the run performed non-read-only work. |
Response 201 Created
Share Run
POST /runs/{run_id}/share
List Run Messages
GET /runs/{run_id}/messages
| Parameter | Type | Description |
|---|
| after_sequence | int | Return only messages with sequence greater than this value |
| limit | int | Max results (1-1000, default 500) |
Get Run Outcome
GET /runs/{run_id}/outcome
Response 200 OK
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
Join Run Stream
GET /runs/{run_id}/stream
Update Permission Mode
PATCH /runs/{run_id}/permission-mode
| Field | Type | Required | Description |
|---|
| permission_mode | string | yes | Execution 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
Audit-Logs
Audit logs provide account-scoped request history for the v2 API.
List Audit Logs
GET /audit-logs
| Parameter | Type | Description |
|---|
| action | string | Filter by action: list, read, create, update, delete |
| resource_type | string | Filter by resource type (for example run or task.trigger) |
| method | string | Filter by HTTP method: GET, POST, PATCH, PUT, DELETE |
| status_code | int | Filter by HTTP status code |
| auth | string | Filter 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. |
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
Tasks
Tasks are reusable job definitions. Create a task, then attach triggers via tasks.triggers.create().
Create Task
POST /tasks
| Field | Type | Required | Description |
|---|
| teammate_id | int | yes | ID of the agent to use. |
| name | string | no | Display name. |
| instructions | string | yes | Instructions |
| tools | string[] | no | Tool names, e.g. gmail, slack. |
| enable_memory | bool | no | Default for the memory tool. |
| enable_history | bool | no | Default for the task-history tool. |
| enable_task_setup_tools | bool | no | Default for the same-scope task-setup tools. |
| enable_feedback | bool | no | Default for the issue-reporting feedback tool. |
| enable_lessons | bool | no | Whether this task's agent accumulates self-improvement lessons across its runs. Task-level only (no agent/run cascade). |
| expected_output | string | no | Description of expected output format. |
| goals | string | no | Task-specific goals. |
| user_id | string | no | Your 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_notifications | bool | no | Send email notification when scheduled run completes |
| webhook | bool | no | Enable webhook trigger on creation. Returns webhook_url once. |
| schedule | string | no | Cron expression, e.g. '0 9 * * 1-5' |
| schedule_timezone | string | no | Timezone for schedule, e.g. 'America/New_York' |
| model | string | no | Model 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. |
| effort | string | no | Reasoning 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
List Tasks
GET /tasks
| Parameter | Type | Description |
|---|
| teammate_id | int | Filter by agent |
| include_archived | bool | Include archived tasks. Off by default so the common case stays clean. |
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Get Task
GET /tasks/{task_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Response 200 OK
Update Task
PATCH /tasks/{task_id}
| Field | Type | Required | Description |
|---|
| name | string | no | Display name. |
| instructions | string | no | Instructions |
| tools | string[] | no | Tool names, e.g. gmail, slack. |
| enable_memory | bool | no | Default for the memory tool. |
| enable_history | bool | no | Default for the task-history tool. |
| enable_task_setup_tools | bool | no | Default for the same-scope task-setup tools. |
| enable_feedback | bool | no | Default for the issue-reporting feedback tool. |
| enable_lessons | bool | no | Whether this task accumulates self-improvement lessons. |
| expected_output | string | no | Description of the expected output format. |
| goals | string | no | Goals |
| email_notifications | bool | no | Email the responsible human when a scheduled run completes. |
| model | string | no | Model 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. |
| effort | string | no | Reasoning 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. |
| status | string | no | Enable 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
Delete Task
DELETE /tasks/{task_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Run Task
POST /tasks/{task_id}/runs
| Field | Type | Required | Description |
|---|
| permission_mode | string | no | Execution 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_loop | bool | no | Enable human-in-the-loop features: clarifying questions, tool approval, and plan approval. If omitted, approval/plan inherit as true and autonomous inherits as false. |
| stream | bool | no | Return Server-Sent Events when true, a JSON object when false. |
| model | string | no | Per-run model override — any id from GET /api/v2/models. Omit to use the agent's model, then the platform default. |
| effort | string | no | Per-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_id | string | no | Your 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. |
| metadata | object | no | Arbitrary 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_schema | object | no | JSON 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. |
| memory | bool | no | Saved memories in agent context. Omit to inherit the agent default. |
| history | bool | no | Previous run results in agent context. Omit to inherit the agent default. |
| task_setup_tools | bool | no | Internal same-scope management tools for agents, tasks, runs, approvals, files, memories, schedules, inboxes, webhooks, and app connections. Omit to inherit the agent default. |
| feedback | bool | no | Internal 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
Create Trigger
POST /tasks/{task_id}/triggers
| Field | Type | Required | Description |
|---|
| type | string | yes | Trigger type, e.g. schedule, webhook, or an app event. |
| cron | string | no | Cron expression (for schedule triggers). |
| interval_seconds | int | no | Interval in seconds (for recurring triggers). |
| run_at | string | no | ISO 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. |
| timezone | string | no | IANA timezone for schedule evaluation. |
| app | string | no | App name, e.g. 'github' |
| trigger_name | string | no | Trigger slug, e.g. 'GITHUB_COMMIT_EVENT' |
| trigger_config | object | no | Trigger-specific config |
| user_id | string | no | End-user whose connected account to use |
| allowed_senders | string[] | no | Allowed Senders |
Response 201 Created
Enable Task Webhook
POST /tasks/{task_id}/webhook
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
List Triggers
GET /tasks/{task_id}/triggers
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Set Task Webhook Enabled
PATCH /tasks/{task_id}/webhook
| Field | Type | Required | Description |
|---|
| enabled | bool | yes | True resumes the webhook, False pauses it |
Disable Task Webhook
DELETE /tasks/{task_id}/webhook
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Update Trigger
PATCH /tasks/{task_id}/triggers/{trigger_id}
| Field | Type | Required | Description |
|---|
| enabled | bool | no | Enabled |
| cron | string | no | Cron expression (for schedule triggers). |
| interval_seconds | int | no | Interval in seconds (for recurring triggers). |
| run_at | string | no | ISO 8601 datetime — reshapes this trigger into a one-time run. |
| timezone | string | no | IANA timezone for schedule evaluation. |
Response 200 OK
Delete Trigger
DELETE /tasks/{task_id}/triggers/{trigger_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope 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
| Parameter | Type | Description |
|---|
| confirm | bool | Required to confirm. Pass ?confirm=true to actually clear. |
Response 200 OK
List Lessons
GET /tasks/{task_id}/lessons
Response 200 OK
Delete Lesson
DELETE /tasks/{task_id}/lessons/{lesson_id}
Response 200 OK
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
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Connect App
POST /apps/{app_name}/connect
| Field | Type | Required | Description |
|---|
| redirect_uri | string | yes | URL 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_id | string | no | End-user ID for multi-tenant connections |
Response 200 OK
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
| Field | Type | Required | Description |
|---|
| user_id | string | no | End-user ID to provision for (omit for account-level) |
Response 200 OK
GET /apps/{app_name}/tools
List App Trigger Types
GET /apps/{app_name}/triggers
Disconnect App
DELETE /apps/{app_name}/connections
| Parameter | Type | Description |
|---|
| user_id | string | Scope 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
| Field | Type | Required | Description |
|---|
| api_key | string | yes | API key for the integration |
| user_id | string | no | End-user ID for multi-tenant connections |
Response 200 OK
Connect App Complete
After the user completes OAuth and is redirected back:
POST /apps/{app_name}/connect/complete
| Field | Type | Required | Description |
|---|
| connection_id | string | no | Connection to complete. Required for end-user connections (user_id set); ignored for account-level ones, where the connection comes from claim_ticket. |
| claim_ticket | string | no | REQUIRED 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_id | string | no | End-user ID for multi-tenant connections |
Response 200 OK
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.
GET /built-in-tools
| Parameter | Type | Description |
|---|
| teammate_id | int | Resolve enabled state for this teammate's config |
| user_id | string | Scope 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
| Field | Type | Required | Description |
|---|
| name | string | yes | Display name. |
| url | string | yes | HTTPS endpoint URL to receive deliveries. |
| kind | string | no | rest_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_type | string | no | Auth Type |
| auth_config | object | no | Auth Config |
| secret | string | no | Secret |
| tool_defs | any[] | no | Tool Defs |
| description | string | no | Description |
| user_id | string | no | User Id |
| auto_approve | bool | no | Auto Approve |
| script_source | string | no | Python 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_allowlist | string[] | no | Extra https origins a kind=script tool may call (max 8). The primary origin is url (canonical https origin, no path). |
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
| Field | Type | Required | Description |
|---|
| name | string | yes | Display name. |
| url | string | yes | HTTPS endpoint URL to receive deliveries. |
| kind | string | no | rest_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_type | string | no | Auth Type |
| auth_config | object | no | Auth Config |
| secret | string | no | Secret |
| tool_defs | any[] | no | Tool Defs |
| description | string | no | Description |
| user_id | string | no | User Id |
| auto_approve | bool | no | Auto Approve |
| script_source | string | no | Python 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_allowlist | string[] | no | Extra https origins a kind=script tool may call (max 8). The primary origin is url (canonical https origin, no path). |
List Mcp Servers
GET /mcp-servers
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
List Mcp Servers
GET /mcp-servers
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Get Mcp Server
GET /mcp-servers/{server_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Update Mcp Server
PATCH /mcp-servers/{server_id}
| Field | Type | Required | Description |
|---|
| name | string | no | Display name. |
| url | string | no | HTTPS endpoint URL to receive deliveries. |
| auth_type | string | no | Auth Type |
| auth_config | object | no | Auth Config |
| secret | string | no | Secret |
| tool_defs | any[] | no | Tool Defs |
| description | string | no | Description |
| status | string | no | Status |
| auto_approve | bool | no | Auto Approve |
| script_source | string | no | Replace the Python source (kind=script only). Write-only. Clears auto_approve. |
| script_allowlist | string[] | no | Replace extra https origins (kind=script only). Clears auto_approve. |
Delete Mcp Server
DELETE /mcp-servers/{server_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Approve Mcp Server
POST /mcp-servers/{server_id}/approve
| Parameter | Type | Description |
|---|
| user_id | string | Scope 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
| Field | Type | Required | Description |
|---|
| name | string | yes | Display name. |
| description | string | yes | Description |
| body | string | yes | Body |
| scope | string | no | Scope |
| teammate_id | int | no | ID of the agent to use. |
| user_id | string | no | User Id |
Create Skill
POST /skills
| Field | Type | Required | Description |
|---|
| name | string | yes | Display name. |
| description | string | yes | Description |
| body | string | yes | Body |
| scope | string | no | Scope |
| teammate_id | int | no | ID of the agent to use. |
| user_id | string | no | User Id |
List Skills
GET /skills
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
List Skills
GET /skills
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Get Skill
GET /skills/{skill_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Update Skill
PATCH /skills/{skill_id}
| Field | Type | Required | Description |
|---|
| name | string | no | Display name. |
| description | string | no | Description |
| body | string | no | Body |
| status | string | no | Status |
Delete Skill
DELETE /skills/{skill_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
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
| Field | Type | Required | Description |
|---|
| name | string | no | Display name. |
| server_url | string | yes | https URL of the BlueBubbles server |
| password | string | yes | BlueBubbles API password (stored encrypted, never returned) |
| owner_handle | string | no | Your own iMessage handle (phone or email). Authorizes you to text the Company Agent (your inbound-default agent) right away, without editing its allowlist. |
List Bridges
GET /bridges
Provision Bridge
POST /bridges/provision
Provision Blooio
POST /bridges/provision-blooio
| Field | Type | Required | Description |
|---|
| number | string | yes | The dedicated Blooio iMessage number (E.164) to route to this account. |
| api_key | string | no | Optional BYO Blooio API key (stored encrypted); omit to use the platform key. |
| user_id | string | no | Optional end-user to bind this dedicated line to (multi-tenant isolation). |
Get Bridge
GET /bridges/{bridge_id}
Update Bridge
PATCH /bridges/{bridge_id}
| Field | Type | Required | Description |
|---|
| name | string | no | Display name. |
| server_url | string | no | Server Url |
| password | string | no | Password |
| status | string | no | Status |
| owner_handle | string | no | Owner Handle |
Delete Bridge
DELETE /bridges/{bridge_id}
Regenerate Bridge Link Code
POST /bridges/{bridge_id}/link-code
Rotate Bridge Secret
POST /bridges/{bridge_id}/rotate-secret
Test Bridge Connection
POST /bridges/{bridge_id}/test
List Bridge Handles
GET /bridges/{bridge_id}/handles
Delete Bridge Handle
DELETE /bridges/{bridge_id}/handles/{handle_id}
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 Install Links
GET /channels/install-links
| Parameter | Type | Description |
|---|
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Upsert Identity
PUT /channels/identities
| Field | Type | Required | Description |
|---|
| channel | string | yes | slack or github. Email custom domains are a later slice. |
| client_id | string | yes | Client Id |
| client_secret | string | yes | Client Secret |
| signing_secret | string | yes | Signing Secret |
| github_app_id | string | no | Required when channel is github. |
| github_app_slug | string | no | Required when channel is github. |
| github_private_key | string | no | Required 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
| Field | Type | Required | Description |
|---|
| ticket | string | yes | Ticket |
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
| Field | Type | Required | Description |
|---|
| user_id | string | no | End-user ID this memory belongs to. Omit for an account-level memory (seen by runs that have no user_id). |
| content | string | yes | The text content to store. |
| audience | string | no | Whether 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
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
| Parameter | Type | Description |
|---|
| query | string | Optional keyword filter — case-insensitive substring match on content. |
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Update Memory
PATCH /memories/{memory_id}
| Field | Type | Required | Description |
|---|
| content | string | no | The text content to store. |
| audience | string | no | Reclassify 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
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}
| Parameter | Type | Description |
|---|
| user_id | string | Scope 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
| Field | Type | Required | Description |
|---|
| user_id | string | no | End-user ID. Omit to target the account-level scope. |
| tool | string | yes | Tool name to allow, e.g. 'gmail' |
Response 201 Created
List Permissions
GET /permissions
| Parameter | Type | Description |
|---|
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Delete Permission
DELETE /permissions/{permission_id}
| Parameter | Type | Description |
|---|
| user_id | string | Scope 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
| Field | Type | Required | Description |
|---|
| user_id | string | yes | Your end-user identifier |
| name | string | no | Display name. |
| email | string | no | Email address. |
| company | string | no | Company name. |
| metadata | object | no | Arbitrary key-value data |
| run_limit | int | no | Override: this end-user's completed-runs cap per billing period (0 = blocked entirely; null = inherit the account-wide default) |
| cost_limit_cents | int | no | Override: this end-user's metered-cost cap in US cents (null = inherit) |
| rate_per_minute | int | no | Override: this end-user's run-starts-per-minute rate limit (null = inherit) |
Response 201 Created
List End Users
GET /users
| Parameter | Type | Description |
|---|
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
Get End User
GET /users/{user_id}
Response 200 OK
Update End User
PATCH /users/{user_id}
| Field | Type | Required | Description |
|---|
| name | string | no | Display name. |
| email | string | no | Email address. |
| company | string | no | Company name. |
| metadata | object | no | Arbitrary key-value data |
| run_limit | int | no | Override: this end-user's completed-runs cap per billing period (0 = blocked entirely; null = inherit the account-wide default) |
| cost_limit_cents | int | no | Override: this end-user's metered-cost cap in US cents (null = inherit) |
| rate_per_minute | int | no | Override: this end-user's run-starts-per-minute rate limit (null = inherit) |
Response 200 OK
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
Update Settings
PATCH /settings
| Field | Type | Required | Description |
|---|
| per_end_user_run_limit | int | no | Cap 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_cents | int | no | Cap 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_minute | int | no | Rate-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_mode | string | no | Data 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_id | bool | no | Strict 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
Keys
Create Named Key
POST /keys
| Field | Type | Required | Description |
|---|
| name | string | yes | A label, e.g. 'production'. |
| expires_in_days | int | no | Optional 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
List End User Usage
GET /usage/end-users
| Parameter | Type | Description |
|---|
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Get Usage Timeseries
GET /usage/timeseries
| Parameter | Type | Description |
|---|
| start_date | string | First UTC day (default: 29 days before end_date) |
| end_date | string | Last UTC day, inclusive (default: today) |
| teammate_id | int | Filter to one teammate |
| surface | string | Filter 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_meter | string | Filter 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_by | string | Add per-model slices to each bucket ("model") |
| user_id | string | Scope to one end-user (maps to end_user_id). Omit for the account view. |
Response 200 OK
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
| Field | Type | Required | Description |
|---|
| amount_cents | int | yes | Amount 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
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
Get Plans
GET /billing/plans
Response 200 OK
List Receipts
GET /billing/receipts
| Parameter | Type | Description |
|---|
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
Update Alert Settings
PATCH /billing/alert-settings
| Field | Type | Required | Description |
|---|
| low_balance_threshold_cents | int | yes | Balance (cents) at which the low-balance warning fires (0 to $100k). |
Update Auto Reload
PATCH /billing/auto-reload
| Field | Type | Required | Description |
|---|
| enabled | bool | yes | Turn auto-reload on or off. |
| threshold_cents | int | no | Reload when the balance falls below this (cents). Required to enable. |
| amount_cents | int | no | Amount 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
| Field | Type | Required | Description |
|---|
| enabled | bool | yes | Turn usage overage on or off. |
| monthly_cap_cents | int | yes | Monthly overage spend ceiling in cents (0 to 1,000,000, i.e. up to $10,000). |
Response 200 OK
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
Change Password
POST /account/password
| Field | Type | Required | Description |
|---|
| current_password | string | yes | The account's current password, to prove possession. |
| new_password | string | yes | The 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
Webhooks
Register URLs to receive signed event notifications when runs change status.
Create Webhook
POST /webhooks
| Field | Type | Required | Description |
|---|
| url | string | yes | HTTPS URL to receive events |
| events | string[] | no | Events: 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
List Webhooks
Secrets are masked in list responses.
GET /webhooks
| Parameter | Type | Description |
|---|
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last item ID |
Get Webhook
GET /webhooks/{webhook_id}
Response 200 OK
Update Webhook
PATCH /webhooks/{webhook_id}
| Field | Type | Required | Description |
|---|
| url | string | no | HTTPS endpoint URL to receive deliveries. |
| events | string[] | no | Event types to subscribe to, e.g. run.completed. |
| active | bool | no | Whether it is enabled. |
| rotate_secret | bool | no | Generate a new signing secret |
Response 200 OK
Delete Webhook
DELETE /webhooks/{webhook_id}
List Deliveries
View delivery attempts for a webhook endpoint.
GET /webhooks/{webhook_id}/deliveries
| Parameter | Type | Description |
|---|
| limit | int | Max results (1-100, default 20) |
| starting_after | int | Cursor: last delivery ID |
Errors
All errors follow a standard format:
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.
| Status | Type | SDK Exception | Description |
|---|
| 400 | invalid_request_error | ValidationError | Invalid request |
| 401 | authentication_error | AuthenticationError | Invalid or missing API key |
| 402 | billing_error | BillingError | Run or cost limit reached, or subscription issue |
| 403 | permission_error | PermissionDeniedError | Insufficient permissions |
| 404 | not_found | NotFoundError | Resource not found |
| 409 | conflict_error | ConflictError | Resource conflict (duplicate, not active) |
| 422 | validation_error | ValidationError | Invalid request parameters |
| 429 | rate_limit_error | RateLimitError | Too many requests (auto-retried by SDK) |
| 500+ | api_error | APIError | Server error (auto-retried by SDK) |