Skip to content

API Reference

This page is source-aligned with the Spring MVC controllers under mateclaw-server/src/main/java. The route inventory below was rebuilt from controller annotations; when it conflicts with an older feature page, this page and the source code are the contract.

Want a machine-readable OpenAPI doc (import into Postman / Apifox, online debugging)? See the OpenAPI / Swagger guide — visit /swagger-ui.html on your deployment.

Contract

All application REST endpoints use the /api/v1 prefix unless explicitly noted. Most JSON responses use the project envelope:

json
{
  "code": 200,
  "msg": "success",
  "data": {}
}

Important exceptions:

  • Streaming endpoints (text/event-stream) send SSE frames instead of the JSON envelope.
  • Download endpoints such as /api/v1/files/generated/{id}, chat uploads, and wiki raw downloads return bytes or ResponseEntity bodies.
  • A few conflict/error flows may return a small structured object outside R<T> when the client must branch on the HTTP status.

IDs are Snowflake Long values serialized as JSON strings by the backend. Frontends and third-party clients should keep IDs as strings.

Authentication

POST /api/v1/auth/login returns the JWT. Send protected requests with:

text
Authorization: Bearer <token>

Public routes from SecurityConfig include login, first-run setup, webhook/webchat callbacks, chat stream/stop routes, agent stream route, talk WebSocket, GET /api/v1/settings/language, and /api/v1/files/generated/** one-time generated-file downloads. Role annotations such as @RequireWorkspaceRole and @RequireGlobalAdmin still apply after authentication.

Workspace-scoped APIs usually accept X-Workspace-Id. If omitted, many handlers fall back to workspace 1 for desktop/local compatibility.

Conventions

Structural contracts shared by every endpoint. Read this section first, then the flagship endpoint examples and the full route inventory below will line up.

Response envelope R<T>

Source: vip.mate.common.result.R (R.java). Three fields:

FieldTypeMeaning
codeintStatus code. 200 = success; see "Status codes" below
msgstringMessage. Note: msg, not message
dataTPayload; null on failure

Success example:

json
{ "code": 200, "msg": "success", "data": { "id": "1", "name": "Agent A" } }

Failure example:

json
{ "code": 401, "msg": "Token expired or invalid", "data": null }

HTTP status mirrors code: RHttpStatusAdvice (ResponseBodyAdvice) sets the HTTP status to HttpStatus.resolve(code) whenever code != 200. So business code 401 → HTTP 401, 404 → HTTP 404. Business codes that are not valid HTTP statuses (e.g. 1001, 2001) fall back to HTTP 500.

Status codes

Source: vip.mate.common.result.ResultCode. Two categories:

CodeMeaningMaps to HTTP status directly?
200SuccessYes
400Param errorYes
401UnauthorizedYes
403ForbiddenYes
404Not foundYes
500System errorYes
1001Agent not foundNo (HTTP 500)
1002Agent busyNo (HTTP 500)
2001LLM errorNo (HTTP 500)
3001Tool not foundNo (HTTP 500)
4001Channel errorNo (HTTP 500)

Error model

Errors are handled centrally by GlobalExceptionHandler (@RestControllerAdvice):

HTTPTriggerBody
400@Valid / BindException validation failure{code:400, msg:"field: defaultMessage"} — only the first field error is returned
400MethodArgumentTypeMismatchException (e.g. non-numeric /{id}){code:400, msg:"Invalid value for parameter 'X': expected Long"}
401Unauthenticated / invalid token (SecurityConfig authenticationEntryPoint){code:401, msg:"Token expired or invalid"}
403Insufficient workspace role (WorkspaceAccessInterceptor writes the response directly){code:403, msg:"...", data:null}
404No route match (NoResourceFoundException){code:404, msg:"Resource not found"}
405Method not supported (HttpRequestMethodNotSupportedException){code:405, msg:"Method not allowed"}
409Confirmation required (ConfirmRequiredException)Breaks the envelope: {code, message, boundAgents} (field is message, not msg) — the only non-R response in the API
500Catch-all (Exception){code:500, msg:"Internal server error"} — stack trace is not leaked
503Async timeout (non-SSE){code:503, msg:"Request timeout, please try again"}

SSE endpoints (/chat/stream, etc.) do not emit a JSON envelope on error; they send an SSE error event instead: event: error / data: {"message":"..."}. See the WebChat guide.

Pagination

Paginated endpoints return R<IPage<T>> directly — the MyBatis Plus Page serialization:

json
{
  "code": 200,
  "data": {
    "records": [ /* current page rows */ ],
    "total": 128,
    "size": 20,
    "current": 1,
    "pages": 7
  }
}
FieldMeaning
recordsCurrent page rows (field name is records, not list/items)
totalTotal record count
sizePage size
currentCurrent page number, 1-based
pagesTotal page count

Common query params: page (default 1), size (default 20). Examples: GET /api/v1/audit/events, GET /api/v1/conversations/page.

ID & type conventions

  • Snowflake Long serialized as JSON string: all backend PKs are Long, but Jackson serializes them as strings. Clients (especially JS) should treat IDs as strings end-to-end to avoid Number.MAX_SAFE_INTEGER precision loss.
  • Password is write-only: UserEntity.password is annotated @JsonProperty(access = WRITE_ONLY) — accepted on login/create, never present in any response.

Auth model

JwtAuthFilter supports three token forms, all via the Authorization header:

  1. JWT: Authorization: Bearer <jwt>. Starts with eyJ (base64 header). The token field returned by login is exactly this.
  2. Personal Access Token (PAT): Authorization: Bearer <pat>. Prefixed with mc_, for headless / CI / SDK use. The plaintext is returned only once at POST /api/v1/auth/tokens creation; only the hash is stored afterwards. The filter dispatches by the mc_ prefix to the PAT verification path.
  3. SSE ?token= query param: the native browser EventSource cannot set custom headers, so SSE streaming endpoints additionally accept ?token=<token> (JWT or PAT).

Sliding renewal: when a JWT is near expiry (default < 2h remaining), the response header returns a fresh token — X-New-Token: <newJwt> (with Access-Control-Expose-Headers: X-New-Token). Clients should watch for and replace the locally stored token. JWT TTL defaults to 24h (mateclaw.jwt.expiration=86400000).

How X-Workspace-Id works

  • No ThreadLocal / request-context holder. The workspace id is consumed two ways:
    1. RBAC enforcement: WorkspaceAccessInterceptor reads X-Workspace-Id for methods annotated @RequireWorkspaceRole (roles owner > admin > member > viewer) or @RequireGlobalAdmin, falling back to workspace 1 when absent/unparseable. Insufficient permission writes a 403 JSON response directly.
    2. Business reads: many controllers take it via @RequestHeader(value="X-Workspace-Id", required=false) Long workspaceId for query scoping, also defaulting to 1.
  • So workspace isolation is enforced by "interceptor auth + controller self-read" together; clients should pass X-Workspace-Id explicitly for workspace-scoped calls.

Frequently Used APIs

Login

bash
curl -X POST http://localhost:18088/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123"}'

Chat

bash
curl -N -X POST http://localhost:18088/api/v1/chat/stream \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"agentId":"1","message":"Hello","conversationId":"conv-abc123"}'

Use fetch() with a streaming reader for /chat/stream; browser EventSource cannot send POST bodies.

Tool Approval

There is no POST /api/v1/approvals/{id}/resolve REST endpoint. Web approval and denial go through the chat stream by sending /approve or /deny in the waiting conversation. Read-only hydration remains GET /api/v1/chat/{conversationId}/pending-approvals. Auto-approval policies are managed under /api/v1/approval/grants.

Doctor / Health

The current backend health surface is GET /api/v1/system/health. The old /api/v1/doctor/* endpoints are not implemented in the current source tree.

Multimodal Generation

Image, video, music, and 3D generation are agent tools (image_generate, video_generate, music_generate, model3d_generate), not standalone /api/v1/image, /api/v1/video, or /api/v1/music REST controllers. REST surfaces that do exist here are TTS/STT and generated-file download.

Non-REST Endpoint

/api/v1/talk/ws is registered by WebSocketConfig for Talk Mode. It is intentionally listed in SecurityConfig as a public WebSocket route, but it is not counted in the controller route inventory below.

Flagship Endpoint Reference

Full request/response reference for the most-used endpoints. Every field maps 1:1 to the source DTO. The 406-row route inventory further down is the complete index; this section is the human-readable walkthrough for high-traffic endpoints.

Login: POST /api/v1/auth/login

Public endpoint (no auth required). Exchanges credentials for a JWT.

Request body LoginRequest (AuthController.java):

FieldTypeDescription
usernamestringUsername
passwordstringPassword

Response R<LoginResponse>:

json
{
  "code": 200,
  "data": {
    "id": "1",
    "token": "eyJhbGciOi...",
    "username": "admin",
    "nickname": "Admin",
    "role": "admin"
  }
}
FieldTypeDescription
idstringUser ID (Snowflake, as a string)
tokenstringJWT — send as Authorization: Bearer <token> on subsequent requests. There is no separate expiry field; expiry lives in the JWT's exp claim
usernamestringUsername
nicknamestringDisplay name
rolestringadmin or user

Errors: wrong username/password → HTTP 401, {code:401, msg:"..."}.

bash
curl -X POST http://localhost:18088/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123"}'

Streaming chat: POST /api/v1/chat/stream

Public endpoint (SecurityConfig permits /api/v1/chat/stream), but in practice you still need a token to resolve the user and permissions — pass ?token= or the Authorization header.

Returns text/event-stream; not the JSON envelope. The SSE event protocol (meta / content_delta / done / error, etc.) is documented in the WebChat guide.

Request body ChatController.ChatStreamRequest (ChatController.java:1211):

FieldTypeDefaultDescription
agentIdstringRequired, target Agent ID
messagestringThis turn's user message (mutually exclusive with contentParts)
contentPartsarrayMultimodal message parts (text + image); mutually exclusive with message
conversationIdstring"default"Conversation ID; for a new conversation use a client-generated unique string
reconnectbooleantrue = reconnect to an in-flight stream, send no new message
lastEventIdstringOnly meaningful with reconnect=true: skip events with id ≤ this value to avoid duplicate replay
thinkingLevelstringnullReasoning depth: off / low / medium / high / max; null follows the Agent default
modelProviderstringnullPer-conversation provider override (paired with modelName)
modelNamestringnullPer-conversation model-name override
endUserIdstringnullThird-party end-user ID, isolates memory when one MateClaw account fronts many end-users

The native browser EventSource cannot send a POST body — use fetch() with a streaming reader.

bash
curl -N -X POST "http://localhost:18088/api/v1/chat/stream?token=$TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"agentId":"1","message":"Hello","conversationId":"conv-abc123"}'

Related endpoints: POST /api/v1/chat/{conversationId}/stop (stop generation), POST /api/v1/chat/{conversationId}/interrupt (queue a follow-up without interrupting the current stream).

Agent management

Mounted at /api/v1/agents, @Tag("Agent管理"). Every method requires @RequireWorkspaceRole (at least viewer; writes need member).

List GET /api/v1/agents?enabled=true — request header X-Workspace-Id; returns R<List<AgentEntity>>.

Create POST /api/v1/agents — request body is an AgentEntity (key fields below); the backend force-injects workspaceId and creatorUserId. Returns the full created entity.

Key AgentEntity fields (AgentEntity.java):

FieldTypeDescription
idstringAgent ID (ignored on create, assigned by the backend)
namestringName
descriptionstringDescription
agentTypestringreact or plan_execute
systemPromptstringSystem prompt
modelNamestringPer-Agent model override (model name); empty = global default
maxIterationsintMax iterations
enabledbooleanEnabled flag
iconstringIcon (emoji or URL)
tagsstringTags (comma-separated)
defaultThinkingLevelstringDefault reasoning depth
primaryKbIdstringPrimary knowledge base ID
skillsDisabledbooleanExplicitly disable all skills
toolsDisabledbooleanExplicitly disable all non-system tools

Delete DELETE /api/v1/agents/{id} — three-way auth: system admin / workspace admin+ / the creator. Otherwise 403.

bash
# List
curl http://localhost:18088/api/v1/agents?enabled=true \
  -H "Authorization: Bearer $TOKEN" -H "X-Workspace-Id: 1"

# Create
curl -X POST http://localhost:18088/api/v1/agents \
  -H "Authorization: Bearer $TOKEN" -H "X-Workspace-Id: 1" \
  -H "Content-Type: application/json" \
  -d '{"name":"Support Agent","agentType":"react","systemPrompt":"You are a support agent","enabled":true}'

The same tree also has GET /api/v1/agents/{id}/chat/stream (a GET form of SSE, coexisting with the POST /chat/stream above), POST /api/v1/agents/{id}/chat (synchronous chat), and POST /api/v1/agents/{id}/execute (Plan-Execute).

Conversation management

Mounted at /api/v1/conversations, @Tag("会话管理"). Isolated per logged-in user (JWT principal).

List GET /api/v1/conversations — returns R<List<ConversationVO>>. ConversationVO adds display fields on top of the conversation entity:

FieldDescription
conversationIdConversation ID (a string, not a Snowflake)
titleTitle
agentId / agentName / agentIconAssociated Agent
usernameOwning user
messageCountMessage count
lastMessage / lastActiveTimeLast message and time
pinned / archivedPinned / archived (0/1)
modelProvider / modelNamePer-conversation model override
statusactive (active within 24h) / closed
streamStatusidle / running
sourceSource channel: web / feishu / dingtalk / telegram / discord / wecom / qq / weixin / cron

Paginated GET /api/v1/conversations/page?page=1&size=20&keyword=xxx — returns R<IPage<ConversationVO>> (pagination shape in "Conventions").

Message history GET /api/v1/conversations/{conversationId}/messages — supports three modes:

  • No limit: returns all messages (R<List<MessageVO>>, backward compatible).
  • With limit: returns the latest limit messages + a hasMore flag: R<{messages: MessageVO[], hasMore: boolean}>.
  • With beforeId + limit: pull up to load earlier messages.

Key MessageVO fields: id, role, content, toolName, status, metadata (object, contains toolCalls etc.), promptTokens / completionTokens, runtimeModel / runtimeProvider, contentParts, createTime.

Per-conversation ops: PUT .../title (rename), PUT .../pin ({pinned:bool}), PUT .../model (switch model {modelProvider, modelName}), DELETE .../messages (clear messages, keep the conversation), DELETE .../{conversationId} (delete conversation), POST /batch-delete ({conversationIds: [...]}), GET .../status (stream status {streamStatus}).

Every op first checks isConversationOwner(conversationId, username); non-owners get 403.

Model configuration

Mounted at /api/v1/models, @Tag("模型配置管理"). GET / and GET /catalog require @RequireGlobalAdmin (they include sensitive info like API keys); /enabled, /default, /active only need viewer.

  • GET /api/v1/models — enabled provider list (R<List<ProviderInfoDTO>>, includes keys, admin only).
  • GET /api/v1/models/enabled — enabled model list (R<List<ModelConfigEntity>>, no keys).
  • GET /api/v1/models/default — global default model (R<ModelConfigEntity>).
  • GET /api/v1/models/active — current active model {activeLlm: {provider, modelName}}.
  • PUT /api/v1/models/active — set the active model.

Audit events (pagination example)

GET /api/v1/audit/events@RequireWorkspaceRole("admin"), returns R<IPage<AuditEventEntity>>. The canonical example of "pagination + workspace header".

Query paramDefaultDescription
actionAction filter (e.g. CREATE / UPDATE / DELETE)
resourceTypeResource type filter (e.g. AGENT)
startTimeISO 8601 start time
endTimeISO 8601 end time
page1Page number
size20Page size
bash
curl "http://localhost:18088/api/v1/audit/events?page=1&size=20&resourceType=AGENT" \
  -H "Authorization: Bearer $TOKEN" -H "X-Workspace-Id: 1"

Change password: PUT /api/v1/auth/users/{id}/password

Three things to note (they differ from intuition):

  1. Params go via @RequestParam, not a request body: both oldPassword and newPassword are query params.
  2. The {id} in the path is informational only: the user actually operated on is resolved from the JWT principal (auth.getName()); a user can only change their own password.
  3. Requires login (not @RequireGlobalAdmin).
bash
curl -X PUT "http://localhost:18088/api/v1/auth/users/1/password?oldPassword=admin123&newPassword=newPass456" \
  -H "Authorization: Bearer $TOKEN"

Personal Access Token

Mounted at /api/v1/auth/tokens, @Tag("Personal Access Tokens"). For headless / CI / SDK use.

  • GET /api/v1/auth/tokens — list my PATs (metadata only; plaintext is never returned).
  • POST /api/v1/auth/tokens — create a PAT: the plaintext appears only in this response, afterwards only the SHA-256 hash is stored and cannot be recovered. Save it immediately.
  • DELETE /api/v1/auth/tokens/{id} — soft-delete revoke; subsequent auth with this token fails.

A created PAT (mc_ prefix) goes straight into Authorization: Bearer mc_...; JwtAuthFilter dispatches by prefix to the PAT verification path, behaving identically to a JWT.

Tool approval (important clarification)

There is no standalone approval REST endpoint like POST /api/v1/approvals/{id}/resolve. Web-side approve / deny happens by sending /approve or /deny in the waiting conversation, going through the chat-stream replay flow. The read-only "hydration" endpoint after a page refresh is GET /api/v1/chat/{conversationId}/pending-approvals. Auto-approval policies are managed under /api/v1/approval/grants.

Dangerous operations requiring a second confirmation raise ConfirmRequiredException — returning HTTP 409 and breaking the R envelope: {code, message, boundAgents} (the field is message, not msg). Clients should branch on the 409 status and render a confirmation dialog.

Source-Aligned Route Inventory

Total routes extracted: 406.

Authentication

MethodPathPurpose / handler
POST/api/v1/auth/loginLogin
GET/api/v1/auth/tokensList my PATs (metadata only — plaintext is never returned after creation)
POST/api/v1/auth/tokensMint a new PAT — returned plaintext is shown once and cannot be recovered
DELETE/api/v1/auth/tokens/{id}Revoke a PAT — soft-delete; further auth attempts with this token will fail
GET/api/v1/auth/usersList Users
POST/api/v1/auth/usersCreate User
PUT/api/v1/auth/users/{id}/passwordChange Password

Chat

MethodPathPurpose / handler
POST/api/v1/chatChat
GET/api/v1/chat/files/{conversationId}/{storedName:.+}Read Uploaded File
POST/api/v1/chat/streamChat Stream
POST/api/v1/chat/uploadUpload
POST/api/v1/chat/{conversationId}/interruptInterrupt Stream
GET/api/v1/chat/{conversationId}/pending-approvalsGet Pending Approvals
POST/api/v1/chat/{conversationId}/stopStop Stream

Conversations

MethodPathPurpose / handler
GET/api/v1/conversationsList
POST/api/v1/conversations/batch-deleteBatch Delete
GET/api/v1/conversations/pagePage
DELETE/api/v1/conversations/{conversationId}Delete
DELETE/api/v1/conversations/{conversationId}/messagesClear Messages
GET/api/v1/conversations/{conversationId}/messagesList Messages
PUT/api/v1/conversations/{conversationId}/modelSet Model
PUT/api/v1/conversations/{conversationId}/pinSet Pinned
GET/api/v1/conversations/{conversationId}/statusGet Stream Status
PUT/api/v1/conversations/{conversationId}/titleRename

Agents

MethodPathPurpose / handler
GET/api/v1/agentsList
POST/api/v1/agentsCreate
GET/api/v1/agents/{agentId}/provider-preferencesList Provider Preferences
PUT/api/v1/agents/{agentId}/provider-preferencesSet Provider Preferences
GET/api/v1/agents/{agentId}/skillsList Skills
PUT/api/v1/agents/{agentId}/skillsSet Skills
DELETE/api/v1/agents/{agentId}/skills/{skillId}Unbind Skill
POST/api/v1/agents/{agentId}/skills/{skillId}Bind Skill
GET/api/v1/agents/{agentId}/toolsList Tools
PUT/api/v1/agents/{agentId}/toolsSet Tools
GET/api/v1/agents/{agentId}/workspace/filesList Files
DELETE/api/v1/agents/{agentId}/workspace/files/**Delete File
GET/api/v1/agents/{agentId}/workspace/files/**Get File
PUT/api/v1/agents/{agentId}/workspace/files/**Save File
GET/api/v1/agents/{agentId}/workspace/memory/exportExport Memory
POST/api/v1/agents/{agentId}/workspace/memory/importImport Memory
POST/api/v1/agents/{agentId}/workspace/memory/import/previewPreview Import Memory
GET/api/v1/agents/{agentId}/workspace/prompt-filesGet Prompt Files
PUT/api/v1/agents/{agentId}/workspace/prompt-filesSet Prompt Files
DELETE/api/v1/agents/{id}Delete
GET/api/v1/agents/{id}Get
PUT/api/v1/agents/{id}Update
GET/api/v1/agents/{id}/capabilitiesCapabilities
POST/api/v1/agents/{id}/chatChat
GET/api/v1/agents/{id}/chat/streamChat Stream
POST/api/v1/agents/{id}/executeExecute
GET/api/v1/agents/{id}/stateGet State

Agent Templates

MethodPathPurpose / handler
GET/api/v1/templatesList
POST/api/v1/templates/{id}/applyApply

Sub-agents

MethodPathPurpose / handler
GET/api/v1/subagents/activeList active sub-agents in a conversation's delegation tree
POST/api/v1/subagents/spawn-pauseSet sub-agent spawn-pause for a conversation
POST/api/v1/subagents/{subagentId}/interruptInterrupt a running sub-agent

Admin Runtime

MethodPathPurpose / handler
POST/api/v1/admin/agent-runtime/runs/{conversationId}/recycleForce recycle — dispose flux + drop RunState; use after friendly stop ignored
POST/api/v1/admin/agent-runtime/runs/{conversationId}/stopFriendly stop — request the run to wind down at its next checkpoint
GET/api/v1/admin/agent-runtime/snapshotSnapshot of every in-flight agent turn
POST/api/v1/admin/agent-runtime/subagents/{subagentId}/interruptInterrupt one sub-agent (admin override of ownership check)
POST/api/v1/admin/agent-runtime/sweepRecycle every run currently flagged as stuck

Approval Grants

MethodPathPurpose / handler
GET/api/v1/approval/grantsList
POST/api/v1/approval/grantsCreate
GET/api/v1/approval/grants/activeActive Summary
DELETE/api/v1/approval/grants/{id}Revoke
GET/api/v1/approval/resolutionsList Resolutions

Security and Tool Guard

MethodPathPurpose / handler
GET/api/v1/security/approvalsList Approvals
GET/api/v1/security/audit/logsList Audit Logs
GET/api/v1/security/audit/statsGet Audit Stats
GET/api/v1/security/guard/configGet Guard Config
PUT/api/v1/security/guard/configUpdate Guard Config
GET/api/v1/security/guard/config/file-guardGet File Guard Config
PUT/api/v1/security/guard/config/file-guardUpdate File Guard Config
GET/api/v1/security/guard/rulesList Rules
POST/api/v1/security/guard/rulesCreate Rule
GET/api/v1/security/guard/rules/builtinList Builtin Rules
DELETE/api/v1/security/guard/rules/by-id/{id}Delete Rule By Pk
GET/api/v1/security/guard/rules/exportExport Rules
POST/api/v1/security/guard/rules/importImport Rules
DELETE/api/v1/security/guard/rules/{ruleId}Delete Rule
PUT/api/v1/security/guard/rules/{ruleId}Update Rule
PUT/api/v1/security/guard/rules/{ruleId}/toggleToggle Rule

Audit

MethodPathPurpose / handler
GET/api/v1/audit/eventsList Events

Activity

MethodPathPurpose / handler
GET/api/v1/activity/feedUnified activity feed (audit + approval + tool calls)

Notifications

MethodPathPurpose / handler
GET/api/v1/notifications/summaryAggregated counts for the sidebar attention badges

Workspaces

MethodPathPurpose / handler
GET/api/v1/workspacesList
POST/api/v1/workspacesCreate
DELETE/api/v1/workspaces/{id}Delete
GET/api/v1/workspaces/{id}Get
PUT/api/v1/workspaces/{id}Update
GET/api/v1/workspaces/{id}/accessGet Access
GET/api/v1/workspaces/{id}/membersList Members
POST/api/v1/workspaces/{id}/membersAdd Member
DELETE/api/v1/workspaces/{id}/members/{targetUserId}Remove Member
PUT/api/v1/workspaces/{id}/members/{targetUserId}Update Member Role

Settings

MethodPathPurpose / handler
GET/api/v1/settingsGet Settings
PUT/api/v1/settingsSave Settings
GET/api/v1/settings/languageGet Language
PUT/api/v1/settings/languageSave Language
PUT/api/v1/settings/sidecarSave Sidecar

First-run Setup

MethodPathPurpose / handler
POST/api/v1/setup/initInit
GET/api/v1/setup/onboarding-statusGet Onboarding Status
GET/api/v1/setup/statusGet Status

System Health

MethodPathPurpose / handler
GET/api/v1/system/browser-healthBrowser launch diagnostics
GET/api/v1/system/healthSystem health check

Dashboard

MethodPathPurpose / handler
GET/api/v1/dashboard/cron-runsRecent Runs
GET/api/v1/dashboard/cron-runs/{cronJobId}Cron Job Runs
GET/api/v1/dashboard/overviewOverview
GET/api/v1/dashboard/trendTrend

Token Usage

MethodPathPurpose / handler
GET/api/v1/token-usageGet Summary

Models

MethodPathPurpose / handler
GET/api/v1/modelsList
POST/api/v1/modelsCreate
GET/api/v1/models/activeGet Active Model
PUT/api/v1/models/activeSet Active Model
GET/api/v1/models/by-typeList By Type
GET/api/v1/models/catalogCatalog
DELETE/api/v1/models/custom-providersDelete Custom Provider By Query
POST/api/v1/models/custom-providersCreate Custom Provider
DELETE/api/v1/models/custom-providers/{providerId}Delete Custom Provider
GET/api/v1/models/defaultGet Default Model
GET/api/v1/models/embedding/defaultGet Default Embedding
POST/api/v1/models/embedding/defaultSet Default Embedding
POST/api/v1/models/embedding/{modelId}/testTest Embedding
GET/api/v1/models/enabledList Enabled
DELETE/api/v1/models/{id}Delete
GET/api/v1/models/{id}Get
PUT/api/v1/models/{id}Update
POST/api/v1/models/{id}/defaultSet Default
PUT/api/v1/models/{providerId}/configUpdate Provider Config
POST/api/v1/models/{providerId}/disableDisable Provider
POST/api/v1/models/{providerId}/discoverDiscover Models
POST/api/v1/models/{providerId}/discover/applyApply Discovered Models
POST/api/v1/models/{providerId}/enableEnable Provider
DELETE/api/v1/models/{providerId}/modelsRemove Provider Model
POST/api/v1/models/{providerId}/modelsAdd Provider Model
POST/api/v1/models/{providerId}/models/testTest Model
POST/api/v1/models/{providerId}/test-connectionTest Connection

OAuth

MethodPathPurpose / handler
POST/api/v1/oauth/anthropic/reloadForce re-detect credentials and refresh if near expiry
GET/api/v1/oauth/anthropic/statusRead current Claude Code OAuth credential status from local disk
GET/api/v1/oauth/openai/authorizeAuthorize
POST/api/v1/oauth/openai/callback-pasteCallback Paste
POST/api/v1/oauth/openai/device/cancelDevice flow: cancel a pending session
POST/api/v1/oauth/openai/device/pollDevice flow: poll for completion
POST/api/v1/oauth/openai/device/startDevice flow: start — request user_code
POST/api/v1/oauth/openai/refreshRefresh
DELETE/api/v1/oauth/openai/revokeRevoke
GET/api/v1/oauth/openai/statusStatus

LLM Runtime

MethodPathPurpose / handler
GET/api/v1/llm/provider-poolSnapshot
POST/api/v1/llm/provider-pool/{providerId}/reprobeReprobe

Tools

MethodPathPurpose / handler
GET/api/v1/toolsList
POST/api/v1/toolsCreate
GET/api/v1/tools/availableList Available
GET/api/v1/tools/enabledList Enabled
DELETE/api/v1/tools/{id}Delete
GET/api/v1/tools/{id}Get
PUT/api/v1/tools/{id}Update
PUT/api/v1/tools/{id}/disclosure-tierSet Disclosure Tier
PUT/api/v1/tools/{id}/toggleToggle

MCP Servers

MethodPathPurpose / handler
GET/api/v1/mcp/serversList
POST/api/v1/mcp/serversCreate
POST/api/v1/mcp/servers/refreshRefresh
DELETE/api/v1/mcp/servers/{id}Delete
GET/api/v1/mcp/servers/{id}Get
PUT/api/v1/mcp/servers/{id}Update
PUT/api/v1/mcp/servers/{id}/disclosure-tierSet Disclosure Tier
POST/api/v1/mcp/servers/{id}/testTest
PUT/api/v1/mcp/servers/{id}/toggleToggle
GET/api/v1/mcp/servers/{id}/toolsList Tools

ACP Endpoints

MethodPathPurpose / handler
GET/api/v1/acp/endpointsList ACP endpoints
POST/api/v1/acp/endpointsCreate a custom ACP endpoint
DELETE/api/v1/acp/endpoints/{id}Delete an ACP endpoint (builtins are protected)
GET/api/v1/acp/endpoints/{id}Get ACP endpoint by id
PUT/api/v1/acp/endpoints/{id}Update an ACP endpoint
POST/api/v1/acp/endpoints/{id}/testTest ACP endpoint connection (initialize handshake)
PUT/api/v1/acp/endpoints/{id}/toggleEnable / disable an ACP endpoint

Skills

MethodPathPurpose / handler
GET/api/v1/skillsList
POST/api/v1/skillsCreate
GET/api/v1/skills/countsCounts
POST/api/v1/skills/curator/activateCurator Activate
POST/api/v1/skills/curator/dry-runCurator Dry Run
POST/api/v1/skills/curator/pauseCurator Pause
GET/api/v1/skills/curator/reportsCurator Reports
GET/api/v1/skills/curator/reports/{runId}Curator Report
POST/api/v1/skills/curator/resumeCurator Resume
GET/api/v1/skills/curator/statusCurator Status
GET/api/v1/skills/enabledList Enabled
POST/api/v1/skills/install/cancel/{taskId}Cancel
GET/api/v1/skills/install/hub/searchSearch Hub
POST/api/v1/skills/install/startStart Install
GET/api/v1/skills/install/status/{taskId}Get Status
POST/api/v1/skills/install/uploadUpload Zip
DELETE/api/v1/skills/install/{skillName}Uninstall
GET/api/v1/skills/prompt-previewPrompt Preview
GET/api/v1/skills/runtime/activeGet Active Skills
POST/api/v1/skills/runtime/refreshRefresh Runtime
GET/api/v1/skills/runtime/statusGet Runtime Status
GET/api/v1/skills/summarySummary
POST/api/v1/skills/sync-filesRe-sync every skill's bundle files (admin)
POST/api/v1/skills/synthesize-from-conversationSynthesize From Conversation
GET/api/v1/skills/type/{skillType}List By Type
DELETE/api/v1/skills/{id}Delete
GET/api/v1/skills/{id}Get
PUT/api/v1/skills/{id}Update
POST/api/v1/skills/{id}/archiveArchive
GET/api/v1/skills/{id}/employeesList agents that can use this skill
POST/api/v1/skills/{id}/export-workspaceExport To Workspace
GET/api/v1/skills/{id}/lessonsRead per-skill LESSONS.md
POST/api/v1/skills/{id}/lessons/clearClear all lessons for a skill
POST/api/v1/skills/{id}/pinPin
GET/api/v1/skills/{id}/requirementsPre-flight requirement statuses for a skill
POST/api/v1/skills/{id}/rescanRescan
POST/api/v1/skills/{id}/restoreRestore
POST/api/v1/skills/{id}/sync-filesRe-sync this skill's bundle files from DB → local workspace cache
PUT/api/v1/skills/{id}/toggleToggle
GET/api/v1/skills/{id}/workspaceGet Workspace Info
GET/api/v1/skills/{skillId}/secretsList secret keys + masked previews for a skill
POST/api/v1/skills/{skillId}/secretsUpsert a secret value (empty value deletes it)
DELETE/api/v1/skills/{skillId}/secrets/{key}Delete a single secret by key

Skill Templates

MethodPathPurpose / handler
GET/api/v1/skill-templatesList skill templates
GET/api/v1/skill-templates/{id}Get a single skill template
POST/api/v1/skill-templates/{id}/instantiateInstantiate a template into a skill

Plugins

MethodPathPurpose / handler
GET/api/v1/pluginsList all plugins
GET/api/v1/plugins/{name}Get plugin detail
PUT/api/v1/plugins/{name}/configUpdate plugin configuration
POST/api/v1/plugins/{name}/disableDisable a plugin
POST/api/v1/plugins/{name}/enableEnable a plugin

LLM Wiki

MethodPathPurpose / handler
POST/api/v1/wiki/admin/backfill-tokensForce-run the token-count backfill batch now
GET/api/v1/wiki/admin/failuresCross-KB list of materials needing attention (failed/partial/degraded) — admin
POST/api/v1/wiki/admin/kb/{kbId}/rebuild-overviewEnsure overview/log scaffold + rebuild overview stats now
GET/api/v1/wiki/chunks/{chunkId}/pagesPages By Chunk Id
DELETE/api/v1/wiki/hot-cache/{kbId}Soft-delete the hot cache row
GET/api/v1/wiki/hot-cache/{kbId}Get the current hot cache snapshot for a KB
POST/api/v1/wiki/hot-cache/{kbId}/regenerateSchedule a manual rebuild of the hot cache
GET/api/v1/wiki/kb/{kbId}/jobsGet Jobs
GET/api/v1/wiki/kb/{kbId}/pages/{pageId}/citationsPage Citations
GET/api/v1/wiki/kb/{kbId}/pages/{slugA}/relation/{slugB}Explain Relation
POST/api/v1/wiki/kb/{kbId}/pages/{slug}/enrichEnrich Page
GET/api/v1/wiki/kb/{kbId}/pages/{slug}/relatedRelated Pages
POST/api/v1/wiki/kb/{kbId}/pages/{slug}/repairRepair Page
POST/api/v1/wiki/kb/{kbId}/search-previewSearch Preview
GET/api/v1/wiki/kb/{kbId}/statsKb Stats
GET/api/v1/wiki/knowledge-basesList KBs
POST/api/v1/wiki/knowledge-basesCreate KB
GET/api/v1/wiki/knowledge-bases/agent/{agentId}List KBs By Agent
GET/api/v1/wiki/knowledge-bases/bindableList Bindable KBs
DELETE/api/v1/wiki/knowledge-bases/{id}Delete KB
GET/api/v1/wiki/knowledge-bases/{id}Get KB
PUT/api/v1/wiki/knowledge-bases/{id}Update KB
GET/api/v1/wiki/knowledge-bases/{id}/configGet Config
PUT/api/v1/wiki/knowledge-bases/{id}/configUpdate Config
GET/api/v1/wiki/knowledge-bases/{id}/page-type-profileGet Page Type Profile
PUT/api/v1/wiki/knowledge-bases/{id}/page-type-profileSave Page Type Profile
POST/api/v1/wiki/knowledge-bases/{id}/page-type-profile/reset-defaultReset Page Type Profile
POST/api/v1/wiki/knowledge-bases/{id}/page-type-profile/validateValidate Page Type Profile
POST/api/v1/wiki/knowledge-bases/{id}/scanScan Directory
PUT/api/v1/wiki/knowledge-bases/{id}/source-directorySet Source Directory
GET/api/v1/wiki/knowledge-bases/{id}/source-watcherGet Source Watcher
POST/api/v1/wiki/knowledge-bases/{id}/source-watcher/scanTrigger Source Watcher
GET/api/v1/wiki/knowledge-bases/{kbId}/agents/{agentId}/page-type-permissionsList Page Type Permissions
POST/api/v1/wiki/knowledge-bases/{kbId}/agents/{agentId}/page-type-permissionsSave Page Type Permission
DELETE/api/v1/wiki/knowledge-bases/{kbId}/agents/{agentId}/page-type-permissions/{id}Delete Page Type Permission
GET/api/v1/wiki/knowledge-bases/{kbId}/lint/broken-linksGet Broken Links Report
POST/api/v1/wiki/knowledge-bases/{kbId}/lint/broken-linksStart Broken Links Scan
GET/api/v1/wiki/knowledge-bases/{kbId}/lint/broken-links/jobs/{jobId}Get Broken Links Job
GET/api/v1/wiki/knowledge-bases/{kbId}/pagesList Pages
GET/api/v1/wiki/knowledge-bases/{kbId}/pages/archivedList Archived Pages
DELETE/api/v1/wiki/knowledge-bases/{kbId}/pages/batchBatch Delete Pages
GET/api/v1/wiki/knowledge-bases/{kbId}/pages/refsList Page Refs
DELETE/api/v1/wiki/knowledge-bases/{kbId}/pages/{slug}Delete Page
GET/api/v1/wiki/knowledge-bases/{kbId}/pages/{slug}Get Page
PUT/api/v1/wiki/knowledge-bases/{kbId}/pages/{slug}Update Page
POST/api/v1/wiki/knowledge-bases/{kbId}/pages/{slug}/archiveArchive Page
GET/api/v1/wiki/knowledge-bases/{kbId}/pages/{slug}/backlinksGet Backlinks
POST/api/v1/wiki/knowledge-bases/{kbId}/pages/{slug}/renameRename Page
POST/api/v1/wiki/knowledge-bases/{kbId}/pages/{slug}/unarchiveUnarchive Page
GET/api/v1/wiki/knowledge-bases/{kbId}/pipeline-runs/{runId}Get Pipeline Run
GET/api/v1/wiki/knowledge-bases/{kbId}/pipelinesList Pipelines
POST/api/v1/wiki/knowledge-bases/{kbId}/pipelinesSave Pipeline
POST/api/v1/wiki/knowledge-bases/{kbId}/pipelines/validateValidate Pipeline
DELETE/api/v1/wiki/knowledge-bases/{kbId}/pipelines/{id}Delete Pipeline
GET/api/v1/wiki/knowledge-bases/{kbId}/pipelines/{id}/runsList Pipeline Runs
POST/api/v1/wiki/knowledge-bases/{kbId}/processProcess KB
GET/api/v1/wiki/knowledge-bases/{kbId}/processing-statusGet Processing Status
GET/api/v1/wiki/knowledge-bases/{kbId}/progressSubscribe Progress
GET/api/v1/wiki/knowledge-bases/{kbId}/rawList Raw
POST/api/v1/wiki/knowledge-bases/{kbId}/raw/textAdd Raw Text
POST/api/v1/wiki/knowledge-bases/{kbId}/raw/uploadUpload Raw
DELETE/api/v1/wiki/knowledge-bases/{kbId}/raw/{rawId}Delete Raw
POST/api/v1/wiki/knowledge-bases/{kbId}/raw/{rawId}/cancelCancel Raw
GET/api/v1/wiki/knowledge-bases/{kbId}/raw/{rawId}/downloadDownload Raw
POST/api/v1/wiki/knowledge-bases/{kbId}/raw/{rawId}/reprocessReprocess Raw
GET/api/v1/wiki/pages/lookupLookup Pages
GET/api/v1/wiki/raw/{rawId}/pagesPages By Raw Id
POST/api/v1/wiki/research/startStart Research
GET/api/v1/wiki/research/stream/{sessionId}Stream
GET/api/v1/wiki/transformationsList transformations available to a KB
POST/api/v1/wiki/transformationsCreate
GET/api/v1/wiki/transformations/runsList Runs
DELETE/api/v1/wiki/transformations/runs/{runId}Delete Run
GET/api/v1/wiki/transformations/runs/{runId}Get Run
POST/api/v1/wiki/transformations/runs/{runId}/cancelCancel a still-running transformation run
POST/api/v1/wiki/transformations/runs/{runId}/save-as-pageSave a completed run's output as a synthesis wiki page
DELETE/api/v1/wiki/transformations/{id}Delete
GET/api/v1/wiki/transformations/{id}Get
PUT/api/v1/wiki/transformations/{id}Update
POST/api/v1/wiki/transformations/{id}/aggregateAggregate all completed runs of a template into one KB-level synthesis page
POST/api/v1/wiki/transformations/{id}/applyRun a transformation against a raw material or wiki page

Memory

MethodPathPurpose / handler
GET/api/v1/memory/{agentId}/dream/eventsSubscribe to dream events (SSE)
GET/api/v1/memory/{agentId}/dream/morning-cardGet morning card for current user + agent
POST/api/v1/memory/{agentId}/dream/morning-card/seenMark morning card as seen
GET/api/v1/memory/{agentId}/dream/reportsList dream reports (paginated, newest first)
GET/api/v1/memory/{agentId}/dream/reports/{reportId}Get a single dream report by ID
POST/api/v1/memory/{agentId}/dream/reports/{reportId}/entries/{key}/confirmConfirm a memory entry (no-op acknowledgment)
POST/api/v1/memory/{agentId}/dream/reports/{reportId}/entries/{key}/editEdit a memory entry — writes back to the target memory file with user-edited metadata
GET/api/v1/memory/{agentId}/dreaming/candidatesGet Dreaming Candidates
GET/api/v1/memory/{agentId}/dreaming/dreamsGet Dreams
POST/api/v1/memory/{agentId}/dreaming/focusedTrigger Focused Dream
GET/api/v1/memory/{agentId}/dreaming/statusGet Dreaming Status
POST/api/v1/memory/{agentId}/emergenceTrigger Emergence
GET/api/v1/memory/{agentId}/factsList facts for an agent
GET/api/v1/memory/{agentId}/facts/contradictionsList unresolved contradictions
POST/api/v1/memory/{agentId}/facts/contradictions/{contradictionId}/resolveResolve a contradiction (KEEP_A / KEEP_B / MERGE / IGNORE)
POST/api/v1/memory/{agentId}/facts/{factId}/feedbackSubmit feedback on a fact (HELPFUL/UNHELPFUL)
POST/api/v1/memory/{agentId}/facts/{factId}/forgetForget a fact — writes canonical metadata, rebuilds projection
POST/api/v1/memory/{agentId}/summarize/{conversationId}Trigger Summarize

Goals

MethodPathPurpose / handler
GET/api/v1/goalsList goals (optionally filtered by status)
POST/api/v1/goalsCreate a persistent goal for a conversation
GET/api/v1/goals/by-conversation/{conversationId}Get the active goal bound to a conversation (or null)
GET/api/v1/goals/{id}Get goal detail by id
PATCH/api/v1/goals/{id}Sparse update of a non-terminal goal
POST/api/v1/goals/{id}/abandonAbandon a goal (terminal)
POST/api/v1/goals/{id}/criteriaAppend a sub-criterion to an active goal
GET/api/v1/goals/{id}/eventsGet the event timeline for a goal
POST/api/v1/goals/{id}/pausePause an active goal
POST/api/v1/goals/{id}/resumeResume a paused goal

Cron Jobs

MethodPathPurpose / handler
GET/api/v1/cron-jobsList
POST/api/v1/cron-jobsCreate
GET/api/v1/cron-jobs/active-runsActive Runs
DELETE/api/v1/cron-jobs/{id}Delete
GET/api/v1/cron-jobs/{id}Get
PUT/api/v1/cron-jobs/{id}Update
POST/api/v1/cron-jobs/{id}/runRun Now
PUT/api/v1/cron-jobs/{id}/toggleToggle

Triggers

MethodPathPurpose / handler
GET/api/v1/triggersList triggers in the caller's workspace.
POST/api/v1/triggersCreate a trigger; if enabled, registers it with the scheduler.
POST/api/v1/triggers/eventsIngest one event envelope; returns per-trigger fire / drop summary.
DELETE/api/v1/triggers/{id}Delete a trigger and unregister its schedule.
GET/api/v1/triggers/{id}Get a trigger by id, scoped to the caller's workspace.
PUT/api/v1/triggers/{id}Update a trigger; pattern_version bumps when the cron expression changes.

Workflows

MethodPathPurpose / handler
GET/api/v1/workflowsList workflows in the workspace
POST/api/v1/workflowsCreate a workflow row (draft starts empty).
POST/api/v1/workflows/draft/generateGenerate a workflow draft from a natural-language description.
POST/api/v1/workflows/draft/preview-compileCompile arbitrary draft JSON without persisting — used by the template picker / generator preview to surface real ACL + schema diagnostics before a workflow row exists.
GET/api/v1/workflows/draft/templatesList the canonical workflow templates the generator can apply directly.
GET/api/v1/workflows/runs/pausedList paused runs across the workspace so operators can resume them.
GET/api/v1/workflows/runs/{runId}Inspect a single run with its step rows for replay / debugging.
POST/api/v1/workflows/runs/{runId}/resumeResume a paused workflow run with the given outcome.
DELETE/api/v1/workflows/{id}Soft-delete a workflow row.
GET/api/v1/workflows/{id}Get a workflow by id (includes inline draft + latest published graph).
PUT/api/v1/workflows/{id}Update workflow metadata (name / description / enabled).
POST/api/v1/workflows/{id}/compileCompile the draft and surface diagnostics without persisting a revision.
PUT/api/v1/workflows/{id}/draftSave the inline draft graph_json without compiling.
POST/api/v1/workflows/{id}/publishCompile the draft and persist a new revision pointed at by latest_revision_id.
GET/api/v1/workflows/{id}/runsList the most recent runs for a workflow.

Channels

MethodPathPurpose / handler
GET/api/v1/channelsList
POST/api/v1/channelsCreate
GET/api/v1/channels/healthHealth All
POST/api/v1/channels/preflightPre-flight: validate draft channel config without persisting
POST/api/v1/channels/qrcode/{channelType}/beginBegin
GET/api/v1/channels/qrcode/{channelType}/statusStatus
GET/api/v1/channels/statusStatus
GET/api/v1/channels/type/{channelType}List By Type
GET/api/v1/channels/webchat/configGet Config
POST/api/v1/channels/webchat/streamChat Stream
POST/api/v1/channels/webhook/dingtalkDingtalk Webhook
POST/api/v1/channels/webhook/dingtalk/register/beginDingtalk Register Begin
GET/api/v1/channels/webhook/dingtalk/register/statusDingtalk Register Status
POST/api/v1/channels/webhook/discordDiscord Webhook
POST/api/v1/channels/webhook/feishuFeishu Webhook
POST/api/v1/channels/webhook/feishu/register/beginFeishu Register Begin
GET/api/v1/channels/webhook/feishu/register/statusFeishu Register Status
POST/api/v1/channels/webhook/slackSlack Webhook
GET/api/v1/channels/webhook/statusStatus
POST/api/v1/channels/webhook/telegramTelegram Webhook
POST/api/v1/channels/webhook/wecomWecom Webhook
GET/api/v1/channels/webhook/weixin/qrcodeWeixin Qrcode
GET/api/v1/channels/webhook/weixin/qrcode/statusWeixin Qrcode Status
DELETE/api/v1/channels/{id}Delete
GET/api/v1/channels/{id}Get
PUT/api/v1/channels/{id}Update
GET/api/v1/channels/{id}/healthHealth
PUT/api/v1/channels/{id}/toggleToggle

Datasources

MethodPathPurpose / handler
GET/api/v1/datasourcesList
POST/api/v1/datasourcesCreate
DELETE/api/v1/datasources/{id}Delete
GET/api/v1/datasources/{id}Get
PUT/api/v1/datasources/{id}Update
POST/api/v1/datasources/{id}/testTest Connection
PUT/api/v1/datasources/{id}/toggleToggle

Speech to Text

MethodPathPurpose / handler
POST/api/v1/stt/transcribeTranscribe

Text to Speech

MethodPathPurpose / handler
POST/api/v1/tts/synthesizeSynthesize
GET/api/v1/tts/voicesList Voices

Generated Files

MethodPathPurpose / handler
GET/api/v1/files/generated/{id}Download a tool-generated file by its one-time id

Plans

MethodPathPurpose / handler
GET/api/v1/plansList By Agent
GET/api/v1/plans/{id}Get Plan

Feature Flags

MethodPathPurpose / handler
GET/api/v1/feature-flagsList
PUT/api/v1/feature-flags/{flagKey}Update