Skip to content

REST API ​

Unless otherwise specified, all endpoints require the tenant API key in the request header:

Authorization: Bearer <租户API Key>

Default address is http://localhost:8787, demo tenant is demo (the apiKey is randomly generated on first startup and printed in the logs). This page is for integration development reference only; ordinary users do not need to care about it.

Starting the Server ​

bash
# 无模型 Key 也能启动(认证/会话/接口都能测,只是对话会报错)
pnpm run server

# 带真实模型(推荐)
OPENAI_API_KEY=sk-... OPENAI_MODEL=gpt-4o-mini pnpm run server

Main environment variables: PORT (default 8787), DATA_DIR (default ./.zqagent_data), APPROVAL_TIMEOUT_SECONDS (timeout for pending approvals/questions, default 900), TENANT_ID / TENANT_API_KEY / MODEL (demo tenant).

Authentication ​

bash
export BASE=http://localhost:8787
export TOKEN=zk_xxxx   # 取启动日志「已创建演示租户」那一行的 apiKey

# 健康检查(公开)
curl -s $BASE/healthz                 # => {"status":"ok"}

# 无 Key → 401
curl -s -o /dev/null -w "%{http_code}\n" $BASE/api/v1/sessions   # => 401

# 正确 Key → 200
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $TOKEN" $BASE/api/v1/sessions

Core Endpoints Quick Reference ​

Sessions ​

MethodPathDescription
GET/healthzHealth check (public)
POST/api/v1/sessionsCreate session
GET/api/v1/sessionsList sessions
GET/api/v1/sessions/{id}Get session
PATCH/api/v1/sessions/{id}Rename session
DELETE/api/v1/sessions/{id}Delete session
GET/api/v1/sessions/{id}/stateSession state (including pending approvals/questions)
PATCH/api/v1/sessions/{id}/modelSwitch session model
PATCH/api/v1/sessions/{id}/modeSwitch permission mode (plan / interactive / auto / discuss)
PATCH/api/v1/sessions/{id}/draftSave input box draft (pass an empty string to clear)
POST/api/v1/sessions/{id}/turnsSubmit task
POST/api/v1/sessions/{id}/steerSteering (supplemental input) while running
POST/api/v1/sessions/{id}/interruptInterrupt the current task
POST/api/v1/sessions/{id}/resumeResume session
GET/api/v1/sessions/{id}/eventsEvent stream (polling or SSE, supports ?since= for incremental)
GET/api/v1/sessions/{id}/approvalsList pending approvals
POST/api/v1/sessions/{id}/approvals/{aid}Answer approval
GET/api/v1/sessions/{id}/questionsList pending questions
POST/api/v1/sessions/{id}/questions/{qid}Answer question

Projects and Nodes ​

MethodPathDescription
GET / POST/api/v1/projectsList / create projects (specify the working directory on creation)
DELETE/api/v1/projects/{id}Delete project
GET/api/v1/modelsList available models
GET / PUT/api/v1/configView / update node config
GET / PUT/api/v1/node/llmView / set node-level default model
GET/api/v1/node/hostNode host info
GET/api/v1/toolsList tools
GET/api/v1/mcpList MCP servers
PUT/api/v1/mcpReplace the entire MCP config (written to the project's .agent/mcp.json; 409 when delivered by the platform)
POST/api/v1/mcp/testTest connection to a single MCP server (not persisted to disk)

Usage and Cost ​

MethodPathDescription
GET/api/v1/usage/summaryUsage summary (by time range / model)
GET/api/v1/usage/recordsDetailed records
GET/api/v1/usage/exportExport CSV
GET / PUT/api/v1/usage/pricingView / update pricing table
POST/api/v1/usage/rebuildRebuild summary
POST/api/v1/usage/verifyVerify ledger

Remote Access and Pairing ​

MethodPathDescription
GET/api/v1/fleet/statusNode enrollment status
POST/api/v1/fleet/enrollEnroll with an enrollment code (called by zqagent link)
POST/api/v1/fleet/unlinkUnlink
GET/api/v1/fleet/pairingGet cloud pairing info (gateway address + namespace/key + nodeId)
GET / POST/api/v1/notificationsView / add notification channels
DELETE/api/v1/notifications/{id}Delete notification channel

Quick Start ​

bash
# 创建会话
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o-mini"}' $BASE/api/v1/sessions
# => {"data":{"sessionId":"e4df66d6...","status":"idle",...}}

export SID=e4df66d6...   # 替换为返回的 sessionId

# 提交任务(立即返回,后台异步执行)
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"input":"你好,请介绍一下自己"}' $BASE/api/v1/sessions/$SID/turns
# => {"data":{"accepted":true,"status":"running"}}

# 轮询事件(since 游标增量拉取)
curl -s "$BASE/api/v1/sessions/$SID/events?since=0"

# 实时订阅(SSE)
curl -N -H "Authorization: Bearer $TOKEN" -H "Accept: text/event-stream" \
  $BASE/api/v1/sessions/$SID/events

If the session is currently executing a task, POST /turns will automatically be converted into steering injected into the current task (returning {"data":{"accepted":true,"status":"steering"}}) instead of returning an error.

Approvals and Questions ​

When the model requests an operation with side effects (writing files, executing commands, etc.), it suspends and waits for approval; when calling tools such as ask_user, it suspends and waits for an answer.

bash
# 查看待审批列表(id 就是工具调用 ID)
curl -s -H "Authorization: Bearer $TOKEN" $BASE/api/v1/sessions/$SID/approvals

# 回答审批:once | always_tool | always_command | deny
#   always_command 仅对 run_shell 有效
export AID=call_xxx
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"decision":"once"}' $BASE/api/v1/sessions/$SID/approvals/$AID

# 回答问题
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"answer":"继续"}' $BASE/api/v1/sessions/$SID/questions/qid_xxx

Multi-Tenant Isolation ​

Each tenant uses its own API key to access its own sessions; using tenant A's key to access tenant B's session returns 404.

Error Code Quick Reference ​

HTTPcodeScenario
401unauthorizedNo key / invalid key
404not_foundSession not found / unknown route / cross-tenant access
409not_runningSession is not running when explicitly steering
409has_pending_interactionPending approvals/questions exist; cannot submit a new task
400bad_requestInvalid JSON body / empty input
400invalid_decisionInvalid decision, or always_command submitted for a non-run_shell