Managed Agent API

API documentation

Production HTTP reference for the Managed Agent API: OpenAI Responses–compatible agent runs, durable volumes, workspace management, browser authentication, and API keys. All versioned routes use the /v1 prefix.

Quick start

Create a workspace API key in the console, then call the agent API from your server or SDK.

Set AGENT_API_BASE_URL to your API origin (no /v1 suffix) and AGENT_API_KEY to a workspace key (sk-…).

curl
curl -sS https://api.agentsway.dev/v1/agent \
  -H "Authorization: Bearer $AGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "preset": "pro-search",
    "input": "Summarize the latest agent API trends."
  }'
Python (cloudsway-agent)
from agent_api import AgentAPI

client = AgentAPI()  # AGENT_API_KEY, AGENT_API_BASE_URL
response = client.responses.create(
    preset="pro-search",
    input="What changed in AI this week?",
)
print(response["output_text"])
JavaScript (@agent-api/sdk)
import { AgentAPI } from "@agent-api/sdk";

const client = new AgentAPI();
const response = await client.responses.create({
  preset: "pro-search",
  input: "What changed in AI this week?",
});
console.log(response.output_text);
Use POST /v1/agent as the canonical create path. POST /v1/responses is an alias for OpenAI Responses SDK compatibility. Both accept the same body and return the same shapes. For install steps, streaming, and pagination, see Official SDKs.

Official SDKs

Production client libraries published on npm and PyPI (v1.0.7). They cover agent runs, durable volumes, workspace skills, skill artifact sync helpers, discovery endpoints, retries, streaming, and cursor pagination.

Two packages ship from the same public API contract documented below. Source lives in github.com/scalebox-dev/agent-api under sdk/javascript and sdk/python.

  • JavaScript @agent-api/sdk on npm
  • Python cloudsway-agent on PyPI (import with from agent_api import AgentAPI)

Install

Requires Node.js 18+ (JavaScript) or Python 3.10+ (Python). Pin a version with @1.0.5 or ==1.0.5 when you need reproducible builds.

JavaScript — @agent-api/sdk
npm install @agent-api/sdk
Python — cloudsway-agent
pip install cloudsway-agent

Configuration

Pass apiKey / baseURL (JavaScript) or api_key / base_url (Python), or set AGENT_API_KEY and AGENT_API_BASE_URL in the environment. Default base URL is https://api.agentsway.dev. Python also exposes AsyncAgentAPI for async applications.

JavaScript
const client = new AgentAPI({
  apiKey: process.env.AGENT_API_KEY,
  baseURL: "https://api.agentsway.dev",
  timeout: 600_000,        // 10 min request timeout
  streamTimeout: 3_600_000, // 1 h stream timeout
  maxRetries: 2,           // exponential backoff on 429/5xx
});
Python
client = AgentAPI(
    api_key="sk-...",
    base_url="https://api.agentsway.dev",
    timeout=600.0,
    stream_timeout=3600.0,
    max_retries=2,
)

Resources

JavaScript

ResourceMethods
client.responses / client.agentcreate, list, listPage, listIterator, retrieve, cancel, listChildren, listEvents
client.modelslist
client.presetslist
client.toolslist
client.volumeslist, create, retrieve, update, delete, listEntries, searchEntries, readFile, writeFile, deleteFile, reconcileUsage, createDirectory, deleteDirectory
client.skillslist, create, discover, focus, createDev, updateFile, retrieve, update, archive, diff, acceptDev, discardDev, exportArchive, importArchive, pushDirectory, pullDirectory, listFiles, readFile, writeFile, deleteFile

Python

ResourceMethods
client.responses / client.agentcreate, list, list_page, list_iterator, retrieve, cancel, list_children, list_events
client.modelslist
client.presetslist
client.toolslist
client.volumeslist, create, retrieve, update, delete, list_entries, search_entries, read_file, write_file, delete_path, reconcile_usage, create_directory, download_archive, summarize, read_lines, patch_lines, grep
client.skillslist, create, discover, focus, create_dev, update_file, retrieve, update, archive, diff, accept_dev, discard_dev, export_archive, import_archive, push_directory, pull_directory, list_files, read_file, write_file, delete_file

Streaming

Set stream: true on client.responses.create. The client parses SSE events and yields typed objects — use the patterns in Streaming for event types.

JavaScript
const stream = await client.responses.create({
  preset: "fast-search",
  input: "Summarize today's AI news.",
  stream: true,
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta ?? "");
  }
}
Python
for event in client.responses.create(
    preset="fast-search",
    input="Summarize today's AI news.",
    stream=True,
):
    if event["type"] == "response.output_text.delta":
        print(event.get("delta", ""), end="")

Pagination

List endpoints return cursor pages. Use listPage / list_page for manual paging, or listIterator / list_iterator to walk all pages.

JavaScript
for await (const item of client.responses.listIterator({ limit: 20 })) {
  console.log(item.id, item.status);
}
Python
for item in client.responses.list_iterator(limit=20):
    print(item["id"], item["status"])

Errors and retries

Both SDKs raise typed errors mapped from the API envelope — for example AuthenticationError, RateLimitError, NotFoundError, and BadRequestError. Transient network failures, HTTP 429, and 5xx responses are retried with exponential backoff (default two retries). Respect Retry-After when the API returns it.

SDKs cover agent runs, durable volumes, workspace skills, and discovery endpoints (models, presets, tools) — not console browser auth, workspace administration, or API key management. Use the HTTP endpoints in Endpoint reference when you need those flows from a custom client.

Base URL

The base URL is the origin only: scheme, host, and optional port. Append paths such as /v1/agent or /healthz.
  • Production API host https://api.agentsway.dev (or api.<your-domain>). Recommended for server-side clients and SDKs.
  • Site / console hosts www, apex, and console subdomains also proxy /v1/* for same-origin browser calls; the dedicated API host remains the stable contract.

Example: GET https://api.agentsway.dev/v1/models. Liveness: GET /healthz at the host root.

Authentication

Protected routes require Authorization: Bearer followed by a workspace API key or a short-lived access JWT from browser auth.

API keys

Create keys under Console → API keys or via POST /v1/api_keys. Keys are shown once at creation; store them securely. Scope keys narrowly when possible (see table below).

Browser sessions

Sign-up and sign-in return an AuthSession with access_token, token_type: bearer, expiry, workspace id/name/role, and scopes. Refresh uses an HTTP-only cookie on POST /v1/auth/refresh — not a Bearer header.

Scopes

ScopeGrants
responses:createPOST /v1/agent, POST /v1/responses
responses:readGET response, list, /children, /events
responses:cancelPOST /v1/responses/{id}/cancel
models:readGET /v1/models
volumes:readList, read, search, and reconcile durable volumes
volumes:writeCreate, update, delete volumes and volume files/directories
skills:readList, discover, focus, and read workspace skill artifacts
skills:writeCreate, update, archive, and review workspace skill artifacts
api_keys:readList and read API key metadata
api_keys:writeCreate, activate, deactivate, delete keys
workspace_members:readWorkspaces, members, invitations, usage
workspace_members:writeCreate or mutate workspaces, members, invitations
notifications:readList notifications and unread count (/v1/me/notifications*)
notifications:writeMark notifications read

Routes without a scope in the gateway still require a valid Bearer. Pass X-Request-ID on support tickets when the gateway returns one.

Agent runs

Create runs with a JSON body (CreateResponseRequest). input is required; provide exactly one of model, models (fallback chain), or preset. Model fields accept vendor/model ids or, when unique, a bare suffix alias.
Minimal create body
{
  "input": "Your question or message",
  "preset": "pro-search",
  "stream": false,
  "tools": [{ "name": "web_search", "type": "search" }],
  "memory": { "enabled": true, "read": true, "write": false }
}

Presets

Presets bundle model defaults, tools, and limits. Built-in values include fast-search, pro-search, deep-research, academic-research, advanced-deep-research, or code-agent for software engineering. Call GET /v1/presets for the live catalog (prompt version, default model, policy). Request fields override preset defaults within platform caps.

Tools and extensions

  • Built-in tools: web_search, smart_web_search, lite_web_search, scholar_search, fetch_url, custom function, and server skill tools.
  • volume_id attaches a durable workspace volume so the agent can read and write files during the run. Manage volumes via /v1/volumes/* or client.volumes in the SDK.
  • skills attaches platform-managed workspace skills to the run. Each item is { skill_id, branch? }, with branch defaulting to main. Use local_skills for SDK-provided local skill descriptors.
  • previous_response_id threads conversation turns. parent_response_id is rejected on create — sub-agents are spawned via run_sub_agent on the parent response.
  • plan_mode_preference / sub_agent_preference off | auto | preferred | required for roadmap and delegation behavior.
  • Multimodal input supports inline images and documents (gateway-enforced size limits; see OpenAPI).
  • language_preference — ISO 639-1 code (e.g. en, zh) when supported.

Skills

Skills are workspace-scoped artifact trees. The public management API lives under /v1/skills; agent runs can attach selected platform skills through skills or SDK-local descriptors through local_skills. The model-facing primitives are exposed as normal HTTP operations too: discover returns summaries, focus progressively loads manifests and file listings, and update_file writes proposed changes to the dev branch.

The stable branch is main. Model-generated changes land in dev so users can inspect them with diff and then call accept_dev or discard_dev. Accepting dev uses file-level sync:patch keeps main-only files, while mirror makes main match dev.

Skill artifacts can also move as ZIP archives through export and import. SDKs wrap those routes as local directory push/pull helpers, while the HTTP API stays skill-scoped instead of exposing arbitrary volume operations.

Retrieval and control

Poll GET /v1/responses/{id} or stream (below). List history with GET /v1/responses. Sub-agent runs appear under GET /v1/responses/{id}/children or in run_sub_agent tool results. Cancel with POST /v1/responses/{id}/cancel when a run is still executing on a replica.

Streaming

Set stream: true on create to receive Server-Sent Events instead of a single JSON body.

The gateway returns Content-Type: text/event-stream. Each event is a JSON object with a type field. Common types include response.output_text.delta, response.tool.invocation.completed, response.plan.updated, response.step.completed, and lifecycle events such as response.completed. Only documented event shapes are returned on the wire and in GET …/events.

SDKs accept stream: true on client.responses.create and iterate events asynchronously.

Errors

Non-2xx responses use a stable JSON envelope.
{
  "error": {
    "type": "api_error",
    "code": "unauthorized",
    "message": "…",
    "request_id": "…"
  }
}

Common code values include invalid_request, unauthorized, forbidden, not_found, and service_unavailable when a platform dependency is temporarily unavailable. Streaming failures may emit an SSE error event before the connection closes.

Endpoint reference

Each endpoint is documented with its auth requirements, request parameters, and response format.

Health

GET/healthzNone

Liveness probe for load balancers and orchestrators.

Request params

None

Response format

GET /healthz
HTTP 200 application/json
{
  "status": "ok"
}

Catalog

GET/v1/modelsBearer · models:read

List models available to the workspace. Each entry id uses vendor/model form (e.g. openai/gpt-5.4).

Request params

None

Response format

GET /v1/models
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "id": "openai/gpt-4.1",
      "object": "model",
      "owned_by": "openai",
      "capabilities": {
        "provider": "openai",
        "supports_streaming": true,
        "supports_tools": true,
        "supports_json_schema": true,
        "supports_reasoning": false,
        "context_window": 128000,
        "pricing": { },
        "metadata": { }
      }
    }
  ]
}

HTTP 503 — service_unavailable
GET/v1/toolsBearer

List built-in and registered tools the agent can invoke.

Request params

None

Response format

GET /v1/tools
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "object": "tool",
      "name": "web_search",
      "type": "search",
      "description": "Search the web for current information.",
      "max_tokens": 4096,
      "max_tokens_per_page": 3000
    }
  ]
}

HTTP 503 — service_unavailable
GET/v1/presetsBearer

List managed presets (model defaults, tool policy, prompt version).

Request params

None

Response format

GET /v1/presets
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "preset": "pro-search",
      "prompt_version": "v1",
      "default_model": "openai/gpt-4.1",
      "model_chain": ["openai/gpt-4.1"],
      "max_output_tokens": 4096,
      "policy": {
        "plan_mode_preference": "auto",
        "sub_agent_preference": "auto",
        "allowed_tools": ["web_search", "fetch_url"],
        "max_steps": 10
      }
    }
  ]
}

HTTP 503 — service_unavailable

Durable volumes

GET/v1/volumesBearer · volumes:read

List durable workspace volumes with usage counters.

Request params

Query parameters

NameTypeRequiredDescription
limitintegernoPage size. Default 50.
page_tokenstringnoOpaque cursor from a prior next_page_token.

Response format

GET /v1/volumes
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "volume_id": "vol_abc",
      "tenant_id": "wrk_xyz",
      "name": "research-notes",
      "oss_prefix": "tenants/wrk_xyz/volumes/vol_abc/",
      "bytes_used": 4096,
      "object_count": 3,
      "created_at_unix": 1710000000,
      "updated_at_unix": 1710003600
    }
  ],
  "next_page_token": null
}

HTTP 503 — service_unavailable
POST/v1/volumesBearer · volumes:write

Create a durable volume for agent file I/O.

Request params

Body parameters

NameTypeRequiredDescription
namestringnoHuman-readable label.

Response format

POST /v1/volumes
HTTP 201 application/json — Volume row (same shape as list item)

HTTP 503 — service_unavailable
GET/v1/volumes/{volume_id}Bearer · volumes:read

Fetch volume metadata and usage.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesVolume id matching vol_*.

Response format

GET /v1/volumes/{volume_id}
HTTP 200 application/json — Volume row
PATCH/v1/volumes/{volume_id}Bearer · volumes:write

Rename a volume.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Body parameters

NameTypeRequiredDescription
namestringyesNew display name.

Response format

PATCH /v1/volumes/{volume_id}
HTTP 200 application/json — updated Volume row
DELETE/v1/volumes/{volume_id}Bearer · volumes:write

Delete a volume and its stored objects.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Response format

DELETE /v1/volumes/{volume_id}
HTTP 204 No Content
POST/v1/volumes/{volume_id}/usage/reconcileBearer · volumes:read

Recompute bytes_used and object_count from object storage.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Response format

POST /v1/volumes/{volume_id}/usage/reconcile
HTTP 200 application/json — Volume row with usage_reconciled_at_unix when set
GET/v1/volumes/{volume_id}/entriesBearer · volumes:read

List files and directories under a path.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Query parameters

NameTypeRequiredDescription
pathstringnoDirectory path (default root).
limitintegernoPage size. Default 200.
page_tokenstringnoPagination cursor.

Response format

GET /v1/volumes/{volume_id}/entries
HTTP 200 application/json
{
  "object": "list",
  "entries": [
    { "path": "notes/summary.md", "is_dir": false, "size": 128, "modified_at_unix": 1710000000 }
  ],
  "next_page_token": null
}
GET/v1/volumes/{volume_id}/files/{path}Bearer · volumes:read

Deliver a file with smart encoding (text, extracted document text, image URL, or base64). Use format=raw for direct binary bytes.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*
pathstringyesFile path within the volume.

Query parameters

NameTypeRequiredDescription
max_bytesintegernoRead cap in bytes (0 = server default).
formatstringnoSet to raw for binary bytes with X-Volume-Size and X-Volume-Truncated headers.

Response format

GET /v1/volumes/{volume_id}/files/{path}
HTTP 200 application/json
{
  "path": "notes/summary.md",
  "encoding": "text",
  "mime_type": "text/markdown",
  "size": 128,
  "truncated": false,
  "content": "# Summary\n"
}

HTTP 200 (format=raw) — raw bytes with Content-Type and X-Volume-* headers
PUT/v1/volumes/{volume_id}/files/{path}Bearer · volumes:write

Write or overwrite a file. Request body is raw file bytes.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*
pathstringyesDestination file path.

Response format

PUT /v1/volumes/{volume_id}/files/{path}
HTTP 200 application/json
{ "path": "notes/summary.md", "size": 128 }
DELETE/v1/volumes/{volume_id}/paths/{path}Bearer · volumes:write

Delete a file or directory tree at path.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*
pathstringyesFile or directory prefix to delete.

Response format

DELETE /v1/volumes/{volume_id}/paths/{path}
HTTP 200 application/json
{ "path": "notes/archive", "recursive": true }
POST/v1/volumes/{volume_id}/summarizeBearer · volumes:read

Scan the volume and return stats plus text previews. Writes .agent-volume/summary.json.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Body parameters

NameTypeRequiredDescription
pathstringnoOptional path prefix to limit the scan.

Response format

POST /v1/volumes/{volume_id}/summarize
HTTP 200 application/json — summary_path, file_count, total_bytes, top_paths_by_size, text_previews
GET/v1/volumes/{volume_id}/grepBearer · volumes:read

Search file contents for a literal substring.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Query parameters

NameTypeRequiredDescription
patternstringyesLiteral substring to find.
pathstringnoDirectory prefix to search under.

Response format

GET /v1/volumes/{volume_id}/grep
HTTP 200 application/json — object=list, matches[{path,line_number,line}], files_scanned, scan_truncated
GET/v1/volumes/{volume_id}/file_lines/{path}Bearer · volumes:read

Read a 1-based inclusive line range from a text file.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*
pathstringyesFile path.

Query parameters

NameTypeRequiredDescription
start_lineintegeryes1-based start line.
end_lineintegernoInclusive end line; 0 = EOF.

Response format

GET /v1/volumes/{volume_id}/file_lines/{path}
HTTP 200 application/json — path, start_line, end_line, total_lines, lines[]
PATCH/v1/volumes/{volume_id}/file_lines/{path}Bearer · volumes:write

Replace an inclusive line range in a text file.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*
pathstringyesFile path.

Body parameters

NameTypeRequiredDescription
start_lineintegeryes1-based start line.
end_lineintegernoInclusive end line; 0 = EOF.
replacementstringnoReplacement text.

Response format

PATCH /v1/volumes/{volume_id}/file_lines/{path}
HTTP 200 application/json — path, start_line, end_line, total_lines, size
GET/v1/volumes/{volume_id}/archiveBearer · volumes:read

Download a directory tree as a ZIP archive.

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Query parameters

NameTypeRequiredDescription
pathstringnoDirectory path to archive (default root).

Response format

GET /v1/volumes/{volume_id}/archive
HTTP 200 application/zip
POST/v1/volumes/{volume_id}/directoriesBearer · volumes:write

Create a directory (and parents as needed).

Request params

Path parameters

NameTypeRequiredDescription
volume_idstringyesvol_*

Body parameters

NameTypeRequiredDescription
pathstringyesDirectory path to create.

Response format

POST /v1/volumes/{volume_id}/directories
HTTP 201 application/json
{ "path": "notes/archive" }

Skills

GET/v1/skillsBearer · skills:read

List workspace-scoped skills. Skills are opaque filesystem artifact trees with main/dev branches.

Request params

Query parameters

NameTypeRequiredDescription
include_archivedbooleannoInclude archived skills.
limitintegernoPage size. Default 50.
page_tokenstringnoOpaque cursor from a prior next_page_token.

Response format

GET /v1/skills
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "object": "skill",
      "skill_id": "skl_abc",
      "name": "research-helper",
      "description": "Research workflow guidance",
      "main_digest": "sha256:...",
      "dev_digest": "sha256:...",
      "has_dev": true,
      "archived": false,
      "created_at": 1710000000,
      "updated_at": 1710003600
    }
  ],
  "next_page_token": null
}
POST/v1/skillsBearer · skills:write

Create a workspace skill metadata record and default SKILL.md on the main branch.

Request params

Body parameters

NameTypeRequiredDescription
namestringnoSkill display name.
descriptionstringnoShort model-facing description.
metadataobjectnoString-keyed metadata.

Response format

POST /v1/skills
HTTP 201 application/json — Skill object
POST/v1/skills/discoverBearer · skills:read

Model-facing discovery primitive. Search workspace skills and optional local descriptors without loading full artifacts.

Request params

Body parameters

NameTypeRequiredDescription
querystringnoSearch text matched against skill metadata and manifests.
branchmain | dev | bothnoBranch view. Defaults to main; dev falls back to main when absent.
include_devbooleannoInclude skills with dev branch state.
limitintegernoMaximum summaries to return.
local_skillsLocalSkillDescriptor[]noClient-side local skill descriptors to include in discovery results. SDKs may include an initial SKILL.md manifest preview.

Response format

POST /v1/skills/discover
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "object": "skill_summary",
      "skill_id": "skl_abc",
      "name": "research-helper",
      "branch": "main",
      "digest": "sha256:...",
      "has_dev": true
    }
  ],
  "next_page_token": null
}
POST/v1/skills/focusBearer · skills:read

Model-facing focus primitive. Load selected skill manifests, file listings, and requested supporting files progressively. Set include_manifest=false on follow-up reads when SKILL.md is already in context.

Request params

Body parameters

NameTypeRequiredDescription
skillsSkillFocusItem[]yesItems with skill_id/branch or local_skill descriptor. Each item may include paths for selected supporting files and include_manifest=false for follow-up reads.
fallback_to_mainbooleannoWhen focusing dev, read main if dev does not exist. Default true.
max_manifest_charsintegernoMaximum SKILL.md characters returned per focused skill.
max_file_charsintegernoMaximum characters returned per requested supporting file.

Response format

POST /v1/skills/focus
HTTP 200 application/json
{
  "object": "skill_focus_result",
  "data": [
    {
      "ok": true,
      "skill_id": "skl_abc",
      "branch": "main",
      "skill": {
        "object": "focused_skill",
        "skill_id": "skl_abc",
        "manifest": "# Research helper\n...",
        "manifest_truncated": false,
        "entries": [{ "path": "SKILL.md", "is_dir": false, "size": 128 }],
        "files": [{ "path": "examples.md", "content": "Example...", "truncated": false, "size": 42 }]
      }
    }
  ]
}
POST/v1/skills/create_devBearer · skills:write

Model-facing create primitive. Create a new skill with initial files on the dev branch for later user review.

Request params

Body parameters

NameTypeRequiredDescription
namestringyesSkill name.
descriptionstringnoShort description.
metadataobjectnoString-keyed metadata.
filesSkillFileMutation[]noInitial files with path plus content or content_base64.

Response format

POST /v1/skills/create_dev
HTTP 201 application/json
{
  "object": "skill_create_result",
  "skill": { "object": "skill", "skill_id": "skl_abc", "name": "research-helper", "has_dev": true },
  "branch": "dev",
  "files": [{ "path": "SKILL.md", "size": 128 }]
}
POST/v1/skills/update_fileBearer · skills:write

Model-facing update primitive. Write one or more files to skill dev branches. The operation cap is enforced by the gateway.

Request params

Body parameters

NameTypeRequiredDescription
updatesSkillFileUpdateMutation[]yesEach update includes skill_id, path, and content or content_base64.

Response format

POST /v1/skills/update_file
HTTP 200 application/json
{
  "object": "skill_update_result",
  "data": [
    { "ok": true, "skill_id": "skl_abc", "path": "SKILL.md", "size": 256 }
  ]
}
GET/v1/skills/{skill_id}Bearer · skills:read

Fetch skill metadata.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesSkill id matching skl_*.

Response format

GET /v1/skills/{skill_id}
HTTP 200 application/json — Skill object
PATCH/v1/skills/{skill_id}Bearer · skills:write

Update skill metadata.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Body parameters

NameTypeRequiredDescription
namestringnoNew display name.
descriptionstringnoNew description.
metadataobjectnoReplacement metadata.

Response format

PATCH /v1/skills/{skill_id}
HTTP 200 application/json — updated Skill object
POST/v1/skills/{skill_id}/archiveBearer · skills:write

Archive a skill. Archived skills are read-only and hidden from normal list/discover results.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Response format

POST /v1/skills/{skill_id}/archive
HTTP 200 application/json — archived Skill object
DELETE/v1/skills/{skill_id}Bearer · skills:write

Permanently delete a skill and its main/dev artifact files.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Response format

DELETE /v1/skills/{skill_id}
HTTP 200 application/json — { "deleted": true }
POST/v1/skills/{skill_id}/accept_devBearer · skills:write

Accept dev changes into main with file-level sync, then clear dev state. Default strategy is patch.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Query parameters

NameTypeRequiredDescription
strategypatch | mirrornoAlso accepted in JSON body. patch keeps main-only files; mirror deletes main-only files so main matches dev.

Response format

POST /v1/skills/{skill_id}/accept_dev
HTTP 200 application/json — Skill object with has_dev=false
POST/v1/skills/{skill_id}/discard_devBearer · skills:write

Discard the dev branch and keep main unchanged.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Response format

POST /v1/skills/{skill_id}/discard_dev
HTTP 200 application/json — Skill object with has_dev=false
GET/v1/skills/{skill_id}/exportBearer · skills:read

Download a ZIP archive for a skill branch or subtree. SDKs use this route for local directory pull helpers.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Query parameters

NameTypeRequiredDescription
pathstringnoDirectory path to export. Default root.
branchmain | devnoBranch to export. Default main.
fallback_to_mainbooleannoWhen branch=dev, fall back to main if dev is absent. Default true.

Response format

GET /v1/skills/{skill_id}/export
HTTP 200 application/zip

HTTP 400 — invalid_request
HTTP 404 — not_found
POST/v1/skills/{skill_id}/importBearer · skills:write

Upload a ZIP archive into a skill branch or subtree. SDKs use this route for local directory push helpers.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Query parameters

NameTypeRequiredDescription
pathstringnoTarget directory path. Default root.
branchmain | devnoDestination branch. Default main.
replacebooleannoDelete the target subtree before importing. Default false.
strip_top_level_dirbooleannoStrip one common top-level folder from uploaded archive entries. Default true.

Body parameters

NameTypeRequiredDescription
archiveapplication/zipyesZIP archive containing skill artifact files.

Response format

POST /v1/skills/{skill_id}/import
HTTP 200 application/json
{
  "object": "skill_import_result",
  "branch": "dev",
  "file_count": 3,
  "byte_count": 4096,
  "skill": { "object": "skill", "skill_id": "skl_abc", "has_dev": true }
}

HTTP 400 — invalid_request
HTTP 404 — not_found
GET/v1/skills/{skill_id}/diffBearer · skills:read

Compare main and dev branches. Returns file-level statuses and unified text diffs for UTF-8 files under the configured cap.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Query parameters

NameTypeRequiredDescription
pathstringnoDirectory path to diff. Default root.
max_file_charsintegernoCharacter cap for generated text diffs.
include_unchangedbooleannoInclude unchanged file rows. Default false.

Response format

GET /v1/skills/{skill_id}/diff
HTTP 200 application/json
{
  "object": "skill_branch_diff",
  "skill_id": "skl_abc",
  "base_branch": "main",
  "compare_branch": "dev",
  "summary": { "added": 1, "modified": 2, "deleted": 0, "unchanged": 4 },
  "files": [{ "path": "SKILL.md", "status": "modified", "text": true, "diff": "--- main/SKILL.md\n+++ dev/SKILL.md\n..." }]
}
GET/v1/skills/{skill_id}/filesBearer · skills:read

List files and directories in a skill branch.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*

Query parameters

NameTypeRequiredDescription
pathstringnoDirectory path. Default root.
branchmain | devnoBranch to read. Default main.
fallback_to_mainbooleannoWhen branch=dev, fall back to main if dev is absent. Default true.
limitintegernoPage size.
page_tokenstringnoPagination cursor.

Response format

GET /v1/skills/{skill_id}/files
HTTP 200 application/json
{
  "object": "list",
  "branch": "main",
  "entries": [{ "path": "SKILL.md", "is_dir": false, "size": 128 }],
  "next_page_token": null
}
GET/v1/skills/{skill_id}/files/{path}Bearer · skills:read

Read a skill file as text content.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*
pathstringyesFile path inside the skill.

Query parameters

NameTypeRequiredDescription
branchmain | devnoBranch to read. Default main.
fallback_to_mainbooleannoWhen branch=dev, fall back to main if dev is absent. Default true.
max_bytesintegernoRead cap in bytes.

Response format

GET /v1/skills/{skill_id}/files/{path}
HTTP 200 application/json
{
  "object": "skill_file",
  "path": "SKILL.md",
  "branch": "main",
  "content": "# Research helper\n...",
  "size": 128,
  "truncated": false
}
PUT/v1/skills/{skill_id}/files/{path}Bearer · skills:write

Write or overwrite a skill file. User calls may target main or dev; model-facing updates should use dev.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*
pathstringyesDestination file path.

Query parameters

NameTypeRequiredDescription
branchmain | devnoDestination branch. Default main.

Response format

PUT /v1/skills/{skill_id}/files/{path}
HTTP 200 application/json
{ "object": "skill_file", "path": "SKILL.md", "branch": "dev", "size": 256 }
DELETE/v1/skills/{skill_id}/files/{path}Bearer · skills:write

Delete a file from a skill branch.

Request params

Path parameters

NameTypeRequiredDescription
skill_idstringyesskl_*
pathstringyesFile path inside the skill.

Query parameters

NameTypeRequiredDescription
branchmain | devnoBranch to mutate. Default main.

Response format

DELETE /v1/skills/{skill_id}/files/{path}
HTTP 200 application/json
{ "object": "skill_file", "path": "notes/example.md", "branch": "dev", "recursive": false }

Agent responses

POST/v1/agentBearer · responses:create

Create an agent run (canonical path). model and models accept vendor/model ids from GET /v1/models or, when unique, a bare suffix alias (e.g. gpt-5.4). Returns a stored Response or an SSE stream when stream is true.

Request params

Body parameters

NameTypeRequiredDescription
inputInputyesUser message or multimodal input array (string, message items with input_text/input_image/input_document, function_call, function_call_output).
modelstringnoModel reference in vendor/model form (e.g. openai/gpt-5.4) or, when unique in the catalog, a bare suffix alias (e.g. gpt-5.4). Canonical ids from GET /v1/models are recommended. Ignored when models is set. Required if neither models, preset, nor model_routing=auto is provided.
modelsstring[]noOrdered model references (vendor/model or unique bare suffix) for chain routing, or an optional candidate pool when model_routing is auto.
model_routingauto | chainnoModel routing mode. auto selects within an optional models pool using openmark; chain uses strict fallback order. Default chain.
routing_strategybalanced | high-quality | cost-effectivenoAuto routing strategy. Only applies when model_routing is auto. Default balanced.
presetstringnoManaged bundle: fast-search | pro-search | deep-research | academic-research | advanced-deep-research | code-agent. Required if neither model, models, nor model_routing=auto is provided.
instructionsstringnoSystem-level instructions prepended to the run.
language_preferencestringnoISO 639-1 code from server allowlist (e.g. en, zh). Two lowercase letters.
streambooleannoWhen true, returns text/event-stream instead of JSON. Default false.
toolsTool[]noTools to expose: web_search, smart_web_search, lite_web_search, scholar_search, fetch_url, function, skill.
tool_choicestring | objectnoTool selection policy: "auto", "none", "required", or a named-tool object.
parallel_tool_callsbooleannoAllow parallel tool calls. Default true.
memoryMemoryOptionsnoLong-term memory opts: { enabled?, read?, write? }. Thread with previous_response_id.
plan_mode_preferenceAgentCapabilityPreferencenoRoadmap/plan steering: off | auto | preferred | required.
sub_agent_preferenceAgentCapabilityPreferencenoDelegation steering for run_sub_agent: off | auto | preferred | required.
max_output_tokensintegernoCap on model output tokens (≥ 1).
max_stepsintegernoAgent loop step limit (1–10).
reasoningReasoningConfignoReasoning effort: { effort: none | minimal | low | medium | high | xhigh }.
response_formatResponseFormatnoStructured output: { type: json_schema, json_schema: { … } }.
previous_response_idstringnoPrior response id for conversation threading (resp_*).
prompt_cache_keystringnoOpenAI-compatible field; currently accepted but ignored by AgentsWay.
metadataobjectnoString-keyed response metadata: up to 16 keys; keys ≤64 chars; values must be string, number, or boolean; string values ≤512 chars.
storebooleannoOpenAI-compatible field; currently accepted but ignored. Responses are persisted for platform operation.
userstringnoOpenAI-compatible field; currently accepted but ignored. Attribution uses the authenticated user id.
volume_idstringnoAttach a durable workspace volume (vol_*) so the agent can read and write files during the run.
skillsSkillReference[]noPlatform-managed workspace skills to make available to the run. Each item is { skill_id, branch? }, where branch defaults to main and may be main or dev.
local_skillsLocalSkillDescriptor[]noSDK/client-provided local skill descriptors. Local artifacts stay with the client; SDKs may include an initial SKILL.md manifest preview for auto-focus, and deeper reads still use the local skill tool bridge.
preferred_sitesstring[]noUp to 3 hostnames to bias web discovery or fetching (e.g. arxiv.org). Requires an allowed tool with type web_search or web_fetch. Search tools receive domain filters when the model omits them; fetch tools get prompt-level URL bias.

Response format

POST /v1/agent
Example request (application/json)
{
  "input": "Summarize recent AI news.",
  "model_routing": "auto",
  "routing_strategy": "high-quality",
  "models": ["openai/gpt-5.4", "google/gemini-3-flash-preview"]
}

HTTP 200 application/json (stream: false)
{
  "id": "resp_abc123",
  "object": "response",
  "created_at": 1710000000,
  "completed_at": 1710000060,
  "status": "completed",
  "model": "openai/gpt-4.1",
  "output": [ … ],
  "output_text": "…",
  "usage": { "input_tokens": 120, "output_tokens": 340, "total_tokens": 460 },
  "tool_results": [
    {
      "id": "tir_abc",
      "tool_call_id": "call_abc",
      "tool_name": "web_search",
      "status": "completed",
      "response_summary": "…"
    }
  ],
  "plan": { },
  "background": false,
  "parent_response_id": null,
  "root_response_id": "resp_abc123",
  "store": true
}

HTTP 200 text/event-stream (stream: true)
data: {"type":"response.output_text.delta","sequence_number":1,"delta":"Hello"}
data: {"type":"response.tool.invocation.completed","sequence_number":2,"tool_result":{…}}
data: {"type":"response.step.completed","sequence_number":3,"step":{…}}

HTTP 200 text/event-stream on error mid-stream
data: {"error":"…"}
POST/v1/responsesBearer · responses:create

OpenAI Responses SDK alias for POST /v1/agent — identical request and response shapes.

Request params

Body parameters

NameTypeRequiredDescription
inputInputyesUser message or multimodal input array (string, message items with input_text/input_image/input_document, function_call, function_call_output).
modelstringnoModel reference in vendor/model form (e.g. openai/gpt-5.4) or, when unique in the catalog, a bare suffix alias (e.g. gpt-5.4). Canonical ids from GET /v1/models are recommended. Ignored when models is set. Required if neither models, preset, nor model_routing=auto is provided.
modelsstring[]noOrdered model references (vendor/model or unique bare suffix) for chain routing, or an optional candidate pool when model_routing is auto.
model_routingauto | chainnoModel routing mode. auto selects within an optional models pool using openmark; chain uses strict fallback order. Default chain.
routing_strategybalanced | high-quality | cost-effectivenoAuto routing strategy. Only applies when model_routing is auto. Default balanced.
presetstringnoManaged bundle: fast-search | pro-search | deep-research | academic-research | advanced-deep-research | code-agent. Required if neither model, models, nor model_routing=auto is provided.
instructionsstringnoSystem-level instructions prepended to the run.
language_preferencestringnoISO 639-1 code from server allowlist (e.g. en, zh). Two lowercase letters.
streambooleannoWhen true, returns text/event-stream instead of JSON. Default false.
toolsTool[]noTools to expose: web_search, smart_web_search, lite_web_search, scholar_search, fetch_url, function, skill.
tool_choicestring | objectnoTool selection policy: "auto", "none", "required", or a named-tool object.
parallel_tool_callsbooleannoAllow parallel tool calls. Default true.
memoryMemoryOptionsnoLong-term memory opts: { enabled?, read?, write? }. Thread with previous_response_id.
plan_mode_preferenceAgentCapabilityPreferencenoRoadmap/plan steering: off | auto | preferred | required.
sub_agent_preferenceAgentCapabilityPreferencenoDelegation steering for run_sub_agent: off | auto | preferred | required.
max_output_tokensintegernoCap on model output tokens (≥ 1).
max_stepsintegernoAgent loop step limit (1–10).
reasoningReasoningConfignoReasoning effort: { effort: none | minimal | low | medium | high | xhigh }.
response_formatResponseFormatnoStructured output: { type: json_schema, json_schema: { … } }.
previous_response_idstringnoPrior response id for conversation threading (resp_*).
prompt_cache_keystringnoOpenAI-compatible field; currently accepted but ignored by AgentsWay.
metadataobjectnoString-keyed response metadata: up to 16 keys; keys ≤64 chars; values must be string, number, or boolean; string values ≤512 chars.
storebooleannoOpenAI-compatible field; currently accepted but ignored. Responses are persisted for platform operation.
userstringnoOpenAI-compatible field; currently accepted but ignored. Attribution uses the authenticated user id.
volume_idstringnoAttach a durable workspace volume (vol_*) so the agent can read and write files during the run.
skillsSkillReference[]noPlatform-managed workspace skills to make available to the run. Each item is { skill_id, branch? }, where branch defaults to main and may be main or dev.
local_skillsLocalSkillDescriptor[]noSDK/client-provided local skill descriptors. Local artifacts stay with the client; SDKs may include an initial SKILL.md manifest preview for auto-focus, and deeper reads still use the local skill tool bridge.
preferred_sitesstring[]noUp to 3 hostnames to bias web discovery or fetching (e.g. arxiv.org). Requires an allowed tool with type web_search or web_fetch. Search tools receive domain filters when the model omits them; fetch tools get prompt-level URL bias.

Response format

POST /v1/responses
Same as POST /v1/agent.
GET/v1/responsesBearer · responses:read

Paginated list of top-level orchestrator runs for the authenticated user. Sub-agent children are excluded.

Request params

Query parameters

NameTypeRequiredDescription
limitintegernoPage size, 1–100. Default 20.
page_tokenstringnoOpaque cursor from a prior response next_page_token.

Response format

GET /v1/responses
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "id": "resp_abc123",
      "status": "completed",
      "created_at": 1710000000,
      "completed_at": 1710000060,
      "model": "openai/gpt-4.1",
      "preset": "pro-search",
      "input_preview": "Summarize…",
      "root_response_id": "resp_abc123",
      "background": false
    }
  ],
  "has_more": false,
  "next_page_token": null
}
GET/v1/responses/{response_id}Bearer · responses:read

Retrieve a stored response including output, usage, and lineage fields.

Request params

Path parameters

NameTypeRequiredDescription
response_idstringyesResponse id matching resp_*.

Response format

GET /v1/responses/{response_id}
HTTP 200 application/json
{
  "id": "resp_abc123",
  "object": "response",
  "status": "completed",
  "model": "openai/gpt-4.1",
  "output": [ … ],
  "output_text": "…",
  "usage": { … },
  "metadata": { },
  "parent_response_id": null,
  "root_response_id": "resp_abc123"
}
POST/v1/responses/{response_id}/cancelBearer · responses:cancel

Abort an in-flight run while it is still executing. Idempotent.

Request params

Path parameters

NameTypeRequiredDescription
response_idstringyesResponse id matching resp_*.

Response format

POST /v1/responses/{response_id}/cancel
HTTP 200 application/json
{
  "interrupted": true
}
GET/v1/responses/{response_id}/childrenBearer · responses:read

List sub-agent runs spawned by run_sub_agent on the parent response.

Request params

Path parameters

NameTypeRequiredDescription
response_idstringyesParent response id matching resp_*.

Response format

GET /v1/responses/{response_id}/children
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "id": "resp_child1",
      "status": "completed",
      "created_at": 1710000010,
      "completed_at": 1710000030,
      "root_response_id": "resp_abc123",
      "model": "openai/gpt-4.1"
    }
  ]
}
GET/v1/responses/{response_id}/volumeBearer · responses:read · volumes:read

Resolve the durable workspace volume for a response thread.

Request params

Path parameters

NameTypeRequiredDescription
response_idstringyesResponse id matching resp_*.

Response format

GET /v1/responses/{response_id}/volume
HTTP 200 application/json — Volume row (volume_id, name, bytes_used, ...)

HTTP 404 — no workspace volume for this response
GET/v1/responses/{response_id}/eventsBearer · responses:read

Replay SSE event shapes for a response.

Request params

Path parameters

NameTypeRequiredDescription
response_idstringyesResponse id matching resp_*.

Query parameters

NameTypeRequiredDescription
after_sequenceintegernoReturn events with sequence_number strictly greater than this value.
viewstringnotimeline (default) or full — full includes tool_result.body on tool events.

Response format

GET /v1/responses/{response_id}/events
HTTP 200 application/json
{
  "data": [
    {
      "type": "response.output_text.delta",
      "sequence_number": 42,
      "delta": "Hello"
    }
  ]
}

With view=full, tool completion events may include tool_result.body.

Browser auth

POST/v1/auth/signupNone

Register a new user. Sends an email verification code when SMTP is configured.

Request params

Body parameters

NameTypeRequiredDescription
emailstringyesValid email address.
passwordstringyes8–32 ASCII chars (A–Z, a–z, 0–9, and !@#$%^&*()-_=+[]{};:,.?/~).
display_namestringnoOptional display name.

Response format

POST /v1/auth/signup
HTTP 201 application/json
{
  "user_id": "usr_abc",
  "email": "you@example.com",
  "verification_required": true,
  "code_expires_at": 1710003600
}
POST/v1/auth/verify_emailNone

Confirm signup with the emailed verification code.

Request params

Body parameters

NameTypeRequiredDescription
emailstringyesAccount email.
codestringyesVerification code from email.

Response format

POST /v1/auth/verify_email
HTTP 200 application/json
Set-Cookie: agent_api_refresh=… (when configured)

{
  "access_token": "eyJ…",
  "token_type": "bearer",
  "access_token_expires_at": 1710003600,
  "user_id": "usr_abc",
  "workspace_id": "wrk_xyz",
  "workspace_name": "My Team",
  "workspace_role": "owner",
  "scopes": ["responses:create", "responses:read", …]
}
POST/v1/auth/signinNone

Sign in with email and password.

Request params

Body parameters

NameTypeRequiredDescription
emailstringyesAccount email.
passwordstringyesAccount password.

Response format

POST /v1/auth/signin
HTTP 200 application/json — AuthSession (same shape as verify_email)
POST/v1/auth/refreshRefresh cookie

Rotate the browser session using the HTTP-only refresh cookie.

Request params

Cookie parameters

NameTypeRequiredDescription
agent_api_refreshstringyesHTTP-only refresh cookie. No Authorization header.

Response format

POST /v1/auth/refresh
HTTP 200 application/json — rotated AuthSession + Set-Cookie
POST/v1/auth/signoutNone

Clear the refresh session server-side.

Request params

None

Response format

POST /v1/auth/signout
HTTP 200 application/json
{
  "status": "ok",
  "message": "signed out"
}
POST/v1/auth/password_reset/requestNone

Request a password reset link. Always returns a generic success message (anti-enumeration).

Request params

Body parameters

NameTypeRequiredDescription
emailstringyesAccount email.

Response format

POST /v1/auth/password_reset/request
HTTP 200 application/json
{
  "status": "ok",
  "message": "If an account exists, a reset link was sent."
}
POST/v1/auth/password_reset/confirmNone

Set a new password using the token from the emailed reset link.

Request params

Body parameters

NameTypeRequiredDescription
tokenstringyesToken from /reset-password?token=…
new_passwordstringyesSame password policy as signup.

Response format

POST /v1/auth/password_reset/confirm
HTTP 200 application/json
{
  "status": "ok",
  "message": "password updated"
}
GET/v1/auth/oauth/{provider}/startNone

Begin OAuth sign-in and return the provider authorization URL.

Request params

Path parameters

NameTypeRequiredDescription
providerstringyesgoogle or github.

Query parameters

NameTypeRequiredDescription
redirect_urlstringnoOverride OAuth callback origin when allowed.

Response format

GET /v1/auth/oauth/{provider}/start
HTTP 200 application/json
{
  "authorization_url": "https://…",
  "state": "…",
  "expires_at": 1710003600
}
GET/v1/auth/oauth/{provider}/callbackNone

Complete OAuth and issue an AuthSession.

Request params

Path parameters

NameTypeRequiredDescription
providerstringyesgoogle or github.

Query parameters

NameTypeRequiredDescription
codestringyesProvider authorization code.
statestringyesState from /start.
redirect_urlstringnoOptional callback override.

Response format

GET /v1/auth/oauth/{provider}/callback
HTTP 200 application/json — AuthSession (browser/API clients)

HTTP 302 Found — browser redirect to the console with Set-Cookie when Accept prefers HTML

Identity

GET/v1/meBearer

Return the authenticated identity and active workspace context.

Request params

None

Response format

GET /v1/me
HTTP 200 application/json
{
  "object": "identity",
  "user_id": "usr_abc",
  "workspace_id": "wrk_xyz",
  "workspace_name": "My Team",
  "workspace_role": "owner",
  "api_key_id": "key_123",
  "scopes": ["responses:create", "responses:read"]
}
GET/v1/me/profileBearer

Profile fields for the user in the active workspace.

Request params

None

Response format

GET /v1/me/profile
HTTP 200 application/json
{
  "object": "user_profile",
  "user_id": "usr_abc",
  "email": "you@example.com",
  "display_name": "Alex",
  "email_verified": true,
  "has_password": true
}
PATCH/v1/me/profileBearer

Update the authenticated user's display name.

Request params

Body parameters

NameTypeRequiredDescription
display_namestringyesNew display name.

Response format

PATCH /v1/me/profile
HTTP 200 application/json — updated user_profile object
POST/v1/me/passwordBearer

Add or rotate the account password while signed in.

Request params

Body parameters

NameTypeRequiredDescription
new_passwordstringyesNew password (signup policy).
current_passwordstringnoRequired when the account already has a password.

Response format

POST /v1/me/password
HTTP 200 application/json
{
  "status": "ok",
  "message": "password updated"
}
GET/v1/me/budgetBearer

Return the signed-in user's budget configuration and current-period usage rollup.

Request params

Query parameters

NameTypeRequiredDescription
periodstringnoOptional period anchor (YYYY-MM-DD). Defaults to the current calendar month.

Response format

GET /v1/me/budget
HTTP 200 application/json — user_budget (limits, enforcement, budget_usage, remaining)
GET/v1/me/budget/statusBearer

Check whether the signed-in user is allowed to run agent services under their budget (hard enforcement).

Request params

None

Response format

GET /v1/me/budget/status
HTTP 200 application/json
{
  "object": "user_budget_status",
  "allowed": true,
  "reason": "",
  "enforcement": "hard"
}

Notifications

GET/v1/me/notificationsBearer

List in-app notifications for the signed-in user (newest first). Workspace invitation alerts are delivered here in addition to email.

Request params

Query parameters

NameTypeRequiredDescription
page_sizeintegernoPage size (default 20).
page_tokenstringnoCursor from a previous response next_page_token.
unread_onlybooleannoWhen true or 1, return only unread notifications.

Response format

GET /v1/me/notifications
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "object": "user_notification",
      "id": "ntf_abc",
      "kind": "workspace.invitation",
      "title": "Workspace invitation",
      "body": "You were invited to join My Team.",
      "action_url": "https://www.example.com/accept-invitation?token=…",
      "payload": { "invitation_token": "…", "workspace_id": "wrk_xyz" },
      "created_at": 1710000000,
      "expires_at": 1710604800
    }
  ],
  "next_page_token": "…"
}
GET/v1/me/notifications/unread_countBearer

Return the unread notification count for the signed-in user.

Request params

None

Response format

GET /v1/me/notifications/unread_count
HTTP 200 application/json
{
  "object": "user_notification_unread_count",
  "unread_count": 2
}
POST/v1/me/notifications/{notification_id}/readBearer

Mark one notification as read.

Request params

Path parameters

NameTypeRequiredDescription
notification_idstringyesNotification id (ntf_*).

Response format

POST /v1/me/notifications/{notification_id}/read
HTTP 200 application/json — user_notification with read_at set
POST/v1/me/notifications/read_allBearer

Mark all notifications for the signed-in user as read.

Request params

None

Response format

POST /v1/me/notifications/read_all
HTTP 200 application/json
{
  "object": "user_notification_read_all",
  "updated_count": 3
}

Workspaces

GET/v1/workspacesBearer · workspace_members:read

List workspaces where the caller is an active member.

Request params

None

Response format

GET /v1/workspaces
HTTP 200 application/json
{
  "object": "list",
  "data": [ { "id": "wrk_xyz", "object": "workspace", "name": "…", "type": "team", "status": "active", "role": "owner" } ]
}
POST/v1/workspacesBearer · workspace_members:write

Create a workspace; the caller becomes owner.

Request params

Body parameters

NameTypeRequiredDescription
namestringyesWorkspace display name.
slugstringnoURL-safe slug.
typestringnopersonal | team | organization.
billing_emailstringnoBilling contact email.

Response format

POST /v1/workspaces
HTTP 201 application/json — Workspace object
GET/v1/workspaces/{workspace_id}Bearer · workspace_members:read

Fetch workspace details including plan and billing hints.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyesWorkspace id matching wrk_*.

Response format

GET /v1/workspaces/{workspace_id}
HTTP 200 application/json — Workspace object
PATCH/v1/workspaces/{workspace_id}Bearer · workspace_members:write

Partially update workspace metadata.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Body parameters

NameTypeRequiredDescription
namestringnoWorkspace display name.
slugstringnoURL-safe slug.
typestringnopersonal | team | organization.
statusstringnoactive | inactive.
billing_account_idstringnoExternal billing account reference.
billing_customer_refstringnoExternal customer reference.
planstringnoPlan identifier.
usage_limit_monthlyintegernoMonthly usage cap.
billing_emailstringnoBilling contact email.

Response format

PATCH /v1/workspaces/{workspace_id}
HTTP 200 application/json — updated Workspace
POST/v1/workspaces/{workspace_id}/switchBearer · workspace_members:read

Issue a new AuthSession scoped to the selected workspace (browser/console clients).

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Response format

POST /v1/workspaces/{workspace_id}/switch
HTTP 200 application/json — AuthSession
GET/v1/workspaces/{workspace_id}/usageBearer · workspace_members:read

Workspace usage summary for the current calendar month (identity-core usage facts).

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Query parameters

NameTypeRequiredDescription
periodstringnoYYYY-MM-DD month start (UTC)

Response format

GET /v1/workspaces/{workspace_id}/usage
HTTP 200 application/json
{
  "object": "workspace_usage",
  "workspace_id": "wrk_xyz",
  "period_start": 1711929600,
  "response_count": 12,
  "input_tokens": 45000,
  "output_tokens": 12000,
  "total_tokens": 57000,
  "tool_calls_total": 8
}
GET/v1/workspaces/{workspace_id}/usage/eventsBearer · workspace_members:read

Paginated usage events for the workspace (one row per recorded agent response). Each event includes input, output, and cache token breakdown when reported by the provider.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Query parameters

NameTypeRequiredDescription
periodstringnoYYYY-MM-DD month start (UTC)
limitintegerno1–100, default 25
page_tokenstringnoCursor from next_page_token

Response format

GET /v1/workspaces/{workspace_id}/usage/events
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "object": "usage_event",
      "response_id": "resp_abc",
      "workspace_id": "wrk_xyz",
      "user_id": "user_xyz",
      "auth_method": "jwt",
      "input_tokens": 1200,
      "output_tokens": 400,
      "total_tokens": 1600,
      "cache_read_input_tokens": 320,
      "cache_creation_input_tokens": 0,
      "tool_calls_total": 1,
      "recorded_at": 1710000000
    }
  ],
  "next_page_token": null
}

Members and invitations

GET/v1/workspaces/{workspace_id}/membersBearer · workspace_members:read

List members of a workspace.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Response format

GET /v1/workspaces/{workspace_id}/members
HTTP 200 application/json
{ "object": "list", "data": [ WorkspaceMember ] }
POST/v1/workspaces/{workspace_id}/membersBearer · workspace_members:write

Add an existing user to a workspace.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Body parameters

NameTypeRequiredDescription
user_idstringyesExisting user id to add.
rolestringnoowner | admin | member.

Response format

POST /v1/workspaces/{workspace_id}/members
HTTP 201 application/json
{
  "workspace_id": "wrk_xyz",
  "user_id": "usr_abc",
  "role": "member",
  "status": "active",
  "created_at": 1710000000
}
PATCH/v1/workspaces/{workspace_id}/members/{user_id}Bearer · workspace_members:write

Update a member's role or active status. Set status to inactive to deactivate (keeps the roster row; reactivate with status active). Does not delete the membership.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*
user_idstringyesMember user id.

Body parameters

NameTypeRequiredDescription
rolestringnoNew role.
statusstringnoactive | inactive.

Response format

PATCH /v1/workspaces/{workspace_id}/members/{user_id}
HTTP 200 application/json — WorkspaceMember
DELETE/v1/workspaces/{workspace_id}/members/{user_id}Bearer · workspace_members:write

Permanently remove a workspace member from the roster. Rejoin requires a new invitation.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*
user_idstringyesMember user id.

Response format

DELETE /v1/workspaces/{workspace_id}/members/{user_id}
HTTP 200 application/json — last known WorkspaceMember snapshot
GET/v1/workspace_membersBearer · workspace_members:read

List members of the caller's active workspace.

Request params

None

Response format

GET /v1/workspace_members
HTTP 200 application/json
{ "object": "list", "data": [ WorkspaceMember ] }
POST/v1/workspace_membersBearer · workspace_members:write

Add a member to the active workspace.

Request params

Body parameters

NameTypeRequiredDescription
user_idstringyesExisting user id.
rolestringnoOptional role.

Response format

POST /v1/workspace_members
HTTP 201 application/json — WorkspaceMember
PATCH/v1/workspace_members/{user_id}Bearer · workspace_members:write

Update a member on the active workspace. Use status active | inactive to activate or deactivate without removing the row.

Request params

Path parameters

NameTypeRequiredDescription
user_idstringyesMember user id.

Body parameters

NameTypeRequiredDescription
rolestringnoOptional role.
statusstringnoOptional status.

Response format

PATCH /v1/workspace_members/{user_id}
HTTP 200 application/json — WorkspaceMember
DELETE/v1/workspace_members/{user_id}Bearer · workspace_members:write

Permanently remove a member from the active workspace. Rejoin requires a new invitation.

Request params

Path parameters

NameTypeRequiredDescription
user_idstringyesMember user id.

Response format

DELETE /v1/workspace_members/{user_id}
HTTP 200 application/json — last known WorkspaceMember snapshot
GET/v1/workspaces/{workspace_id}/invitationsBearer · workspace_members:read

List pending invitations.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Response format

GET /v1/workspaces/{workspace_id}/invitations
HTTP 200 application/json
{ "object": "list", "data": [ WorkspaceInvitation ] }
POST/v1/workspaces/{workspace_id}/invitationsBearer · workspace_members:write

Invite a user by email. The invitation is persisted immediately; invitation email and in-app notification delivery run asynchronously.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*

Body parameters

NameTypeRequiredDescription
emailstringyesInvitee email.
rolestringnoOptional role.
expires_atintegernoUnix expiry.

Response format

POST /v1/workspaces/{workspace_id}/invitations
HTTP 201 application/json
{
  "id": "inv_abc",
  "email": "friend@example.com",
  "invitation_token": "…"
}
DELETE/v1/workspaces/{workspace_id}/invitations/{invitation_id}Bearer · workspace_members:write

Revoke a pending invitation.

Request params

Path parameters

NameTypeRequiredDescription
workspace_idstringyeswrk_*
invitation_idstringyesInvitation id.

Response format

DELETE /v1/workspaces/{workspace_id}/invitations/{invitation_id}
HTTP 200 application/json — revoked WorkspaceInvitation
GET/v1/workspace_invitations/previewNone

Preview invitation details before sign-in (public; requires the invitation token).

Request params

Query parameters

NameTypeRequiredDescription
tokenstringyesInvitation token from the email link or admin copy.

Response format

GET /v1/workspace_invitations/preview
HTTP 200 application/json
{
  "object": "workspace_invitation_preview",
  "email": "friend@example.com",
  "workspace_id": "wrk_xyz",
  "workspace_name": "My Team",
  "role": "member",
  "expires_at": 1710604800
}
POST/v1/workspace_invitations/acceptBearer · workspace_members:write

Accept an invitation and join the workspace.

Request params

Body parameters

NameTypeRequiredDescription
invitation_tokenstringyesToken from the invitation.

Response format

POST /v1/workspace_invitations/accept
HTTP 200 application/json — WorkspaceMember

API keys

GET/v1/api_keysBearer · api_keys:read

List API keys for the workspace (metadata only — no secrets).

Request params

None

Response format

GET /v1/api_keys
HTTP 200 application/json
{
  "object": "list",
  "data": [
    {
      "id": "key_abc",
      "object": "api_key",
      "key_prefix": "sk-abcd",
      "name": "prod",
      "user_id": "usr_abc",
      "creator_display_name": "Alex",
      "creator_email": "alex@example.com",
      "status": "active",
      "scopes": ["responses:create"],
      "created_at": 1710000000
    }
  ]
}
POST/v1/api_keysBearer · api_keys:write

Create a workspace API key. The raw secret is returned once.

Request params

Body parameters

NameTypeRequiredDescription
namestringnoHuman-readable label.
scopesstring[]noOAuth-style scopes.
expires_atintegernoUnix expiry timestamp.

Response format

POST /v1/api_keys
HTTP 201 application/json
Send {} when no optional fields are needed (empty body is rejected).

{
  "id": "key_abc",
  "object": "api_key",
  "api_key": "sk-…",
  "key_prefix": "sk-abcd",
  "workspace_id": "wrk_xyz",
  "user_id": "usr_abc",
  "scopes": ["responses:create"],
  "created_at": 1710000000
}
GET/v1/api_keys/{api_key_id}Bearer · api_keys:read

Fetch API key metadata.

Request params

Path parameters

NameTypeRequiredDescription
api_key_idstringyeskey_*

Response format

GET /v1/api_keys/{api_key_id}
HTTP 200 application/json — APIKeyInfo
POST/v1/api_keys/{api_key_id}/activateBearer · api_keys:write

Re-enable a deactivated key.

Request params

Path parameters

NameTypeRequiredDescription
api_key_idstringyeskey_*

Response format

POST /v1/api_keys/{api_key_id}/activate
HTTP 200 application/json
{ "id": "key_abc", "status": "active", "updated_at": 1710000000 }
POST/v1/api_keys/{api_key_id}/deactivateBearer · api_keys:write

Disable a key without deleting it.

Request params

Path parameters

NameTypeRequiredDescription
api_key_idstringyeskey_*

Response format

POST /v1/api_keys/{api_key_id}/deactivate
HTTP 200 application/json
{ "id": "key_abc", "status": "inactive", "updated_at": 1710000000 }
DELETE/v1/api_keys/{api_key_id}Bearer · api_keys:write

Permanently delete an API key.

Request params

Path parameters

NameTypeRequiredDescription
api_key_idstringyeskey_*

Response format

DELETE /v1/api_keys/{api_key_id}
HTTP 200 application/json
{ "id": "key_abc", "status": "deleted", "updated_at": 1710000000 }
Shared objects: AuthSession (access_token, token_type, workspace_id, workspace_name, workspace_role, scopes), WorkspaceMember (workspace_id, user_id, role, status, created_at), UserNotification (id, kind, title, body, action_url, payload, created_at, read_at, expires_at). Member lifecycle: PATCH with status activates or deactivates; DELETE permanently removes the roster row (rejoin requires a new invitation). Field-level details are listed under each endpoint below.

OpenAPI

Machine-readable request and response schemas for tools, volumes, multimodal input, SSE events, and workspace objects.

The OpenAPI 3.1 spec (api/openapi/agent-api.v1.yaml in the agent-api repository) tracks the same public HTTP contract as this page. Official SDKs are described in Official SDKs (@agent-api/sdk on npm, cloudsway-agent on PyPI). Contact support if you need a hosted copy or early access to schema changes.