Open API Reference
This chapter summarizes the currently available APIs, grouped by capability into seven categories: Auth, UserProfile, Local Assistant, Cloud Tasks, ACP Channel, Session Artifacts, and Redemption Code Redemption. Developers can first choose the category that matches their business goals, then complete integration based on each API's permission requirements, request parameters, and response structure.
- Auth API: Complete user authorization and exchange for access credentials.
- UserProfile API: Read the total credit quota and amount used for the currently authorized user.
- Local Assistant API: Query PC local assistant status, send messages, and query message history.
- Cloud Task API: Create and query cloud tasks, and obtain ACP connection information for the task.
- ACP Channel: Establish a real-time bidirectional communication channel for cloud tasks and exchange protocol messages.
- Session Artifacts: Query plans, tasks, media, summaries, and other artifacts produced by cloud sessions.
- Redemption Code Redemption API: Issue credits to the currently authorized user via redemption codes or vouchers.
Auth API
Overview
WorkBuddy Open Platform implements third-party application authorization based on the OAuth 2.1 authorization code flow. Developers guide users through authorization via the /authorize endpoint, then exchange the authorization code at the /token endpoint for access credentials (access_token) and refresh credentials (refresh_token). Subsequent Open API calls are authenticated with access_token.
This section includes two core endpoints:
- "Request User Authorization" — Guide the user to complete authorization in the browser
- "Exchange for Access Credentials" — Exchange an authorization code or refresh credential for an access_token
Request User Authorization
Guide the user to open the authorization page in the browser. After the user confirms, the platform callbacks with an Authorization Code.
| Item | Content |
|---|---|
| HTTP URL | GET https://www.workbuddy.cn/openapi/v2/authorize |
| HTTP Method | GET (browser redirect) |
| Permission Requirements | No access_token required; client_id must belong to a registered application |
Query Parameters
| Name | Type | Required | Example | Description |
|---|---|---|---|---|
| response_type | String | Yes | code | Fixed value code, indicating authorization code mode |
| client_id | String | Yes | app_7a3f2b... | Client ID obtained after application registration |
| redirect_uri | String | Yes | https://example.com/callback | Callback URL |
| scope | String | Yes | user.task.readable user.task.invokable | Requested permission scopes; multiple scopes separated by spaces. Must be within the Scope set bound to the application |
| state | String | Recommended | a1b2c3_random_xyz | Random string for CSRF protection and callback state preservation. Returned as-is on callback |
Request Example
GET /openapi/v2/authorize?response_type=code&client_id=app_7a3f2b1c&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&scope=user.task.readable%20user.localassistant.readable&state=a1b2c3_random_xyz HTTP/1.1
Host: www.workbuddy.cn
Accept: text/html
Callback Response
After the user confirms authorization, the platform redirects to redirect_uri with the following parameters:
| Name | Type | Example | Description |
|---|---|---|---|
| code | String | auth_c0d3_xyz789 | Authorization code; single-use; valid for 10 minutes |
| state | String | a1b2c3_random_xyz | Matches the state in the request. The application should validate this value to prevent CSRF attacks |
GET https://example.com/callback?code=auth_c0d3_xyz789&state=a1b2c3_random_xyz
Exchange for Access Token
Exchange the authorization code for an access_token.
| Item | Content |
|---|---|
| HTTP URL | POST https://www.workbuddy.cn/openapi/v2/token |
| HTTP Method | POST |
| Content-Type | application/x-www-form-urlencoded |
| Permission Requirements | None (use client_secret for application authentication) |
Request Body
| Name | Type | Required | Example | Description |
|---|---|---|---|---|
| grant_type | String | Yes | authorization_code | Fixed value authorization_code |
| code | String | Yes | auth_c0d3_xyz789 | Authorization code from the previous step; single-use; valid for 10 minutes |
| client_id | String | Yes | app_7a3f2b1c | Application ID |
| client_secret | String | Yes | sk_live_abc123... | Application secret; must never be exposed in frontend or client code |
| redirect_uri | String | Yes | https://example.com/callback | Must exactly match (byte-for-byte) the callback URL parameter from the authorization code stage |
Request Example
POST /openapi/v2/token HTTP/1.1
Host: www.workbuddy.cn
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=auth_c0d3_xyz789&client_id=app_7a3f2b1c&client_secret=sk_live_abc123...&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
Response Body
| Name | Type | Example | Description |
|---|---|---|---|
| access_token | String | eyJhbGciOiJSUzI1NiIs... | Access token used to call Open API |
| token_type | String | Bearer | Token type; fixed value Bearer |
| expires_in | Number | 604800 | access_token validity period in seconds (7 days) |
| refresh_token | String | def50200a1b2c3d4e... | Refresh token used to obtain a new token after access_token expires. Returned only in authorization_code mode |
| scope | String | user.task.readable user.localassistant.readable | Actually granted permission scopes |
| open_id | String | op_9f8e7d6c5b4a | User's open_id |
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 604800,
"refresh_token": "def50200a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p...",
"scope": "user.task.readable user.localassistant.readable",
"open_id":"op_9f8e7d6c5b4a"
}
Refresh Access Token
Use refresh_token to refresh the access_token.
| Item | Content |
|---|---|
| HTTP URL | POST https://www.workbuddy.cn/openapi/v2/token |
| HTTP Method | POST |
| Content-Type | application/x-www-form-urlencoded |
| Permission Requirements | None |
Request Body
| Name | Type | Required | Example | Description |
|---|---|---|---|---|
| grant_type | String | Yes | refresh_token | Fixed value refresh_token |
| refresh_token | String | Yes | def50200a1b2... | refresh_token from the previous exchange |
| client_id | String | Yes | app_7a3f2b1c | Application ID |
| client_secret | String | Yes | sk_live_abc123... | Application secret; must never be exposed in frontend or client code |
Request Example
POST /openapi/v2/token HTTP/1.1
Host: www.workbuddy.cn
Content-Type: application/x-www-form-urlencoded
Accept: application/json
grant_type=refresh_token&refresh_token=wbjt_xxxxxxxxxxxxx&client_id=cb_xxxxxxxxxxxxx&client_secret=xxxxxxxxxxxxx
Response Body
| Name | Type | Example | Description |
|---|---|---|---|
| access_token | String | eyJhbGciOiJSUzI1NiIs... | Access token used to call Open API |
| token_type | String | Bearer | Token type; fixed value Bearer |
| expires_in | Number | 3600 | access_token validity period, in seconds |
| refresh_token | String | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9… | Refresh token used to obtain a new token after access_token expires. Returned only in authorization_code mode |
| scope | String | user.profile.readable task.write | Actually granted permission scopes |
| open_id | String | op_9f8e7d6c5b4a | User's open_id |
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"scope": "user.profile.readable task.write",
"open_id": "op_9f8e7d6c5b4a"
}
UserProfile API
Overview
The UserProfile API is used to query the total credit quota and amount used for the currently authorized user. The API supports personal users only. It does not distinguish subscription packs, top-up packs, or gift packs, and only counts resource packs whose status is "valid" or "used up".
Read Personal Credits
| Item | Content |
|---|---|
| HTTP URL | GET https://www.workbuddy.cn/openapi/v2/credit |
| HTTP Method | GET |
| Permission Requirements | user.credit.readable |
Request
GET /openapi/v2/credit HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"total_capacity_size": 3609,
"total_capacity_used": 285
}
Response Body
| Field | Type | Required | Description |
|---|---|---|---|
| total_capacity_size | Integer | Yes | Current-period total quota of all valid and used-up resource packs |
| total_capacity_used | Integer | Yes | Current-period amount used of all valid and used-up resource packs |
Local Assistant API
Overview
The Local Assistant API is used for message interaction with the PC local assistant connected to WorkBuddy, including querying online status, sending messages, and querying message history.
Query Local Assistant Online Status
Query whether the current user's PC local assistant is online.
| Item | Content |
|---|---|
| HTTP URL | GET https://www.workbuddy.cn/openapi/v2/localassistant |
| HTTP Method | GET |
| Permission Requirements | user.localassistant.readable |
Request
GET /openapi/v2/localassistant HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 74
{"code":0,"msg":"success","request_id":"a1b2c3d4e5","data":{"online":true}}
Response data
| Field | Type | Meaning |
|---|---|---|
| online | bool | Whether the current user's PC local assistant is online |
Send Message to Local Assistant
Send a message to the PC local assistant to trigger the assistant to execute a task.
| Item | Content |
|---|---|
| HTTP URL | POST https://www.workbuddy.cn/openapi/v2/localassistant/message |
| HTTP Method | POST |
| Permission Requirements | user.localassistant.invokable |
| Content-Type | application/json |
Request
POST /openapi/v2/localassistant/message HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Accept: application/json
Content-Length: 52
{"content":"帮我查一下今天的日程","msg_type":"text"}
Request body
| Field | Type | Required | Meaning |
|---|---|---|---|
| content | string | Yes | Message content, e.g. "帮我查一下今天的日程" |
| msg_type | string | Yes | Message type. Currently only text is allowed; permission_response is explicitly rejected (tool approval remains with the local user) |
Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 87
{"code":0,"msg":"success","request_id":"a1b2c3d4e5","data":{"message_id":"msg-001"}}
Response data
| Field | Type | Meaning |
|---|---|---|
| message_id | string | ID of the newly created message, e.g. msg-001 |
Query Local Assistant Message History
Query the current user's local assistant message history, with support for pagination and incremental queries.
| Item | Content |
|---|---|
| HTTP URL | GET https://www.workbuddy.cn/openapi/v2/localassistant/message |
| HTTP Method | GET |
| Permission Requirements | user.localassistant.readable |
Request (pagination mode)
GET /openapi/v2/localassistant/message?limit=20&offset=0 HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Request (incremental mode)
GET /openapi/v2/localassistant/message?message_id=msg-001 HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Query Parameters
| Parameter | Type | Meaning |
|---|---|---|
| limit | int | Pagination mode: page size; default 20; max 100 |
| offset | int | Pagination mode: offset; default 0 |
| message_id | string | Incremental mode: return only messages produced after this message (for polling assistant replies) |
When message_id is provided, incremental mode is used; otherwise pagination mode is used.
Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 396
{"code":0,"msg":"success","request_id":"a1b2c3d4e5","data":{"messages":[{"message_id":"msg-001","role":"user","content":["帮我查一下今天的日程"],"msg_type":"text","created_at":"2026-07-30T10:00:00Z","attachments":[],"metadata":{"msgType":"text"}},{"message_id":"msg-002","role":"assistant","content":["你今天有3个日程..."],"msg_type":"text","created_at":"2026-07-30T10:00:05Z","attachments":[],"metadata":{"msgType":"text"}}]}}
Response data
| Field | Type | Meaning |
|---|---|---|
| messages | array | Message list |
messages[] single message element
| Field | Type | Meaning |
|---|---|---|
| message_id | string | Message ID |
| role | string | Role: user (user) / assistant (assistant) |
| content | array | Message content; always an array (use [] when empty; do not omit the key) |
| msg_type | string | Message type, extracted from downstream metadata msgType |
| created_at | string | Creation time (ISO8601, e.g. 2026-07-30T10:00:00Z) |
| attachments | array | Attachment list; always an array (use [] when empty) |
| metadata | object | Metadata; always an object (use {} when empty) |
Cloud Task API
Overview
The Cloud Task API is used to create and query cloud tasks, and returns the ACP connection URL and auth token for establishing real-time communication with the cloud session.
Create Cloud Task
Create a cloud task. Supports interconnection with WorkBuddy mobile or mini-program sessions. Returns task_id, ACP link, and token.
| Item | Content |
|---|---|
| HTTP URL | POST https://www.workbuddy.cn/openapi/v2/tasks |
| HTTP Method | POST |
| Permission Requirements | user.task.invokable |
| Content-Type | application/json |
Request
POST /openapi/v2/tasks HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"prompt": "帮我看下明天的天气如何",
"name": "明天天气"
}
Request Body
| Parameter | Type | Required | Meaning |
|---|---|---|---|
| prompt | string | Yes | Initial task instruction, used to create the session, generate the title, and set the initial status |
| name | string | No | Task name; if omitted, the server generates one from prompt |
Response
HTTP/1.1 201 Created
Content-Type: application/json
{
"task_id": "2076261663968759808",
"status": "working",
"name": "明天天气",
"link": "https://acp.workbuddy.cn/sessions/2076261663968759808",
"token": "sk-sandbox-xxxxxxxxxxxxxxxxxxxx",
"expire_at": 1786087200,
"sandboxLink": "https://sandbox.example.com/e2b/abc123",
"sandboxDataLink": "https://sandbox-data.example.com/e2b/abc123"
}
Response Body
| Field | Type | Always Returned | Meaning |
|---|---|---|---|
| task_id | string | Yes | Task ID; actually corresponds to the agentserver conversation ID |
| status | string | Yes | Current task/session status |
| name | string | No | Task or session name |
| link | string | No | ACP connection URL for connecting to the task sandbox |
| token | string | No | ACP gateway authentication credential |
| expire_at | integer | No | token expiration time; Unix timestamp in seconds |
| sandboxLink | string | No | Sandbox control-plane access URL |
| sandboxDataLink | string | No | Sandbox data-plane access URL |
status field enum
| Status | Meaning |
|---|---|
| CREATING | Creating the task and sandbox |
| idle | Idle, waiting to execute |
| planning | Planning in progress |
| working | Executing |
| pending | Paused or waiting for external input |
| completed | Completed |
| failed | Execution failed |
| archived | Archived |
| deleted | Deleted |
Query Cloud Task List
Query the list of cloud tasks created by the current user, with pagination support. Returns basic task information and ACP Link; does not return ACP Token or its expiration time.
| Item | Content |
|---|---|
| HTTP URL | GET https://www.workbuddy.cn/openapi/v2/tasks |
| HTTP Method | GET |
| Permission Requirements | user.task.readable |
Request
GET /openapi/v2/tasks?page=1&size=20 HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Query Parameters
| Parameter | Type | Required | Default | Meaning |
|---|---|---|---|---|
| page | integer | No | 1 | Page number; treated as 1 if not an integer or less than 1 |
| size | integer | No | 20 | Page size; treated as 20 if not an integer or less than 1; max 100; treated as 100 if greater than 100 |
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"tasks": [
{
"task_id": "2076261663968759808",
"status": "working",
"name": "明天天气",
"link": "https://acp.workbuddy.cn/sessions/2076261663968759808",
"created_at": "2026-08-04T10:30:00Z",
"updated_at": "2026-08-04T10:35:00Z"
},
{
"task_id": "2076261663968759809",
"status": "completed",
"name": "日程整理",
"link": "https://acp.workbuddy.cn/sessions/2076261663968759809",
"created_at": "2026-08-03T08:00:00Z",
"updated_at": "2026-08-03T09:00:00Z"
}
],
"total": 2,
"pagination": {
"page": 1,
"size": 20,
"total": 2
}
}
Response Fields
| Field | Type | Always Present | Meaning |
|---|---|---|---|
| tasks | array | Yes | Task list for the current page |
| tasks[].task_id | string | Yes | Task ID; corresponds to the cloud session ID |
| tasks[].status | string | Yes | Current task status |
| tasks[].name | string | No | Task name |
| tasks[].link | string | No | ACP direct connection URL |
| tasks[].created_at | string | No | Creation time in ISO 8601 format |
| tasks[].updated_at | string | No | Last update time in ISO 8601 format |
| total | integer | Yes | Total number of matching tasks |
| pagination | object | Yes | Pagination information |
| pagination.page | integer | Yes | Current page number |
| pagination.size | integer | Yes | Current page size |
| pagination.total | integer | Yes | Total number of matching tasks |
Note: The list API does not return token or expire_at. To obtain a task's ACP Token, call GET /openapi/v2/tasks/{task_id}.
Query Cloud Task
Query task status and obtain a new ACP link/token. Responds with 200 OK. After creating a task, if the response temporarily lacks link or token, poll this API until they are populated.
| Item | Content |
|---|---|
| HTTP URL | GET https://www.workbuddy.cn/openapi/v2/tasks/{task_id} |
| HTTP Method | GET |
| Permission Requirements | user.task.readable |
Request
GET /openapi/v2/tasks/2076261663968759808 HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Path Parameters
| Parameter | Type | Required | Meaning |
|---|---|---|---|
| task_id | string | Yes | task_id returned when creating the task |
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"task_id": "2076261663968759808",
"status": "working",
"name": "明天天气",
"link": "https://acp.workbuddy.cn/sessions/2076261663968759808",
"token": "sk-sandbox-xxxxxxxxxxxxxxxxxxxx",
"expire_at": 1786087200,
"sandboxLink": "https://sandbox.example.com/e2b/abc123",
"sandboxDataLink": "https://sandbox-data.example.com/e2b/abc123"
}
Response Body
| Field | Type | Always Returned | Meaning |
|---|---|---|---|
| task_id | string | Yes | Task ID; actually corresponds to the agentserver conversation ID |
| status | string | Yes | Current task/session status |
| name | string | No | Task or session name |
| link | string | No | ACP connection URL for connecting to the task sandbox |
| token | string | No | ACP gateway authentication credential |
| expire_at | integer | No | token expiration time; Unix timestamp in seconds |
| sandboxLink | string | No | Sandbox control-plane access URL |
| sandboxDataLink | string | No | Sandbox data-plane access URL |
status field enum
| Status | Meaning |
|---|---|
| CREATING | Creating the task and sandbox |
| idle | Idle, waiting to execute |
| planning | Planning in progress |
| working | Executing |
| pending | Paused or waiting for external input |
| completed | Completed |
| failed | Execution failed |
| archived | Archived |
| deleted | Deleted |
ACP Usage Notes
Start a Conversation
Use the ACP channel to start a conversation. After creating or querying a task to obtain link and token, use them to communicate with the cloud session. ACP (Agent Client Protocol) is based on SSE long connections + JSON-RPC 2.0 and uses a dual-channel model: one GET SSE long connection for receiving server pushes (streaming answers, notifications), and POST requests for sending JSON-RPC calls. Both are associated via the same connection identifier.
Connection and Authentication
- Receive channel: GET {link}, with request headers Authorization: Bearer {token} and Accept: text/event-stream, to establish an SSE long connection for receiving server messages. The Acp-Connection-Id in the response headers is the identifier for this connection.
- Send channel: POST {link}, with request headers Authorization: Bearer {token}, Content-Type: application/json, and the Acp-Connection-Id echoed to associate with the SSE connection above; Body is a JSON-RPC request. Call results (including streaming answers) are pushed back asynchronously via the SSE channel.
- token: Used only for ACP channel authentication. Due to differences in the underlying Agent sandbox environment, token validity varies—typically 3 days, but it may also be much shorter. If the caller receives a 401 on an ACP request, use GET /tasks/{task_id} to obtain a new token.
Conversation Flow (JSON-RPC)
- initialize: Negotiate protocol version and client capabilities; call once immediately after connecting.
- session/load: Load the created session; pass the task_id returned when creating the task as params.sessionId.
- session/prompt: Send a question; params.prompt is a ContentBlock array (each element contains type=text and a text field; see example below). For follow-ups, reuse the same sessionId and call again.
Complete call example (send in order after connecting; results and streaming answers are pushed back via the SSE channel):
// 1) initialize — 协商协议版本与客户端能力,建连后先调用一次
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": 1,
"clientCapabilities": {
"fs": { "readTextFile": false, "writeTextFile": false }
}
}
}
// 2) session/load — 加载已创建的会话,sessionId 传创建任务返回的 task_id
{
"jsonrpc": "2.0",
"id": 2,
"method": "session/load",
"params": {
"sessionId": "2076261663968759808",
"cwd": "/workspace",
"mcpServers": []
}
}
// 3) session/prompt — 发送提问,prompt 为 ContentBlock 数组;追问时复用同一 sessionId 再次调用
{
"jsonrpc": "2.0",
"id": 3,
"method": "session/prompt",
"params": {
"sessionId": "2076261663968759808",
"prompt": [{ "type": "text", "text": "帮我看下明天的天气如何" }]
}
}
Receiving Server Messages
The server pushes two types of JSON-RPC messages via the SSE channel:
- Notification (no id): One-way push for streaming answers, status changes, extension events, etc. The client does not need to reply.
- Server-to-Client Request (with id): The client must return a response via the SSE-associated Acp-Connection-Id before timeout. Used for interactions that require user participation (tool permission confirmation, AskUserQuestion, etc.).
| Type | Method | Purpose |
|---|---|---|
| Notification | session/update | Streaming increments: conversation content, tool calls, task planning, session status |
| Request (requires reply) | session/request_permission | Confirmation requiring user interaction: tool execution authorization, AskUserQuestion |
| Response (to session/prompt) | — | Final end marker for one prompt round: stopReason + usage |
Task completion determination: The session/prompt response is the authoritative signal for "this round ended"; result.stopReason indicates the end reason (end_turn / max_tokens / max_turn_requests / refusal / cancelled).
Extension Method Notes
In addition to standard ACP methods, the server also pushes extension JSON-RPC notifications prefixed with _codebuddy.ai/ via the SSE channel to carry session assets not defined by the ACP standard protocol (such as artifacts, breakpoints, commands, etc.). These messages:
- Follow the JSON-RPC 2.0 specification (no id; no reply required)
- Methods unrecognized by the client can be safely ignored without affecting the standard protocol flow
- Are not defined in the official ACP protocol (agentclientprotocol.com); they are WorkBuddy cloud private extensions to ACP
Extension methods that integrators most need to pay attention to:
| Method | Purpose |
|---|---|
| _codebuddy.ai/artifact | Artifact (plan / task list / media / summary) incremental push |
Artifact notification example:
{
"jsonrpc": "2.0",
"method": "_codebuddy.ai/artifact",
"params": {
"sessionId": "2076261663968759808",
"event": "created",
"artifact": {
"type": "media",
"uri": "agent:///artifacts/output.png",
"mimeType": "image/png",
"size": 102400
}
}
}
Three event values:
- created: New artifact added; artifact is the full object.
- updated: Artifact changed; artifact is the full object (full overwrite, not a diff).
- deleted: Artifact removed; artifact guarantees only the type and uri fields.
Clients should use artifact.uri as the primary key for local upsert / delete; receiving a duplicate created should be treated as equivalent to updated.
Artifact List API
The SSE channel pushes incremental events. To fetch all historical artifacts in a session at once (e.g. first-screen rendering, state recovery), use the REST API GET /api/session/artifacts. SSE and REST share the same data source and can be combined (REST for full load on first screen + SSE for subsequent increments).
| Item | Content |
|---|---|
| HTTP URL | GET {sandbox_url}/api/session/artifacts |
| Request Method | GET |
| Authentication | Header: Authorization: Bearer {task_ticket} |
| Content-Type | application/json |
sandbox_url is obtained by removing the trailing /acp path segment from the link field returned by the "Create Cloud Task" / "Query Cloud Task" APIs. For example, if link = "https://65225-xxx.ap-guangzhou.agentos-run.net/acp", then sandbox_url = "https://65225-xxx.ap-guangzhou.agentos-run.net".
The authentication credential task_ticket is the same one shared with the ACP channel. If task_ticket is expired, HTTP 401 is returned; call the "Query Cloud Task" API to obtain a new task_ticket and retry.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| sessionId | string | No | Target session ID. Can be omitted for single-session sandboxes (automatically uses the current active session); required in multi-session scenarios. |
| type | string | No | Filter by artifact type; allowed values: plan / tasks / media / overview. If omitted, all types are returned. |
| startMs | int64 | No | Return only records with updatedAt >= startMs (epoch milliseconds). Omitted or 0 means no lower bound. |
| endMs | int64 | No | Return only records with updatedAt <= endMs (epoch milliseconds). Omitted or 0 means no upper bound. |
| limit | int | No | Page size; range [1, 500]. Omitted or 0 means no pagination; return all at once. |
| offset | int | No | Page offset; >= 0; default 0. |
Request Example
# 拉取当前会话的全部产物
curl -H "Authorization: Bearer {task_ticket}" \
"{sandbox_url}/api/session/artifacts"
# 仅拉取媒体类产物,分页
curl -H "Authorization: Bearer {task_ticket}" \
"{sandbox_url}/api/session/artifacts?type=media&limit=50&offset=0"
# 增量拉取(配合本地记录的 lastUpdatedAt)
curl -H "Authorization: Bearer {task_ticket}" \
"{sandbox_url}/api/session/artifacts?startMs=1730000000000"
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"code": 0,
"msg": "success",
"data": {
"sessionId": "2076261663968759808",
"artifacts": [
{
"sessionId": "2076261663968759808",
"event": "created",
"artifact": { /* Artifact 对象,见下方字段说明 */ },
"md5": "3f2a...",
"url": "https://.../artifacts/output.png"
}
],
"pagination": {
"total": 123,
"returned": 50,
"limit": 50,
"offset": 0,
"hasMore": true
},
"filter": { "type": "media", "startMs": 0, "endMs": 0 }
}
}
Response Fields (top level)
| Field | Type | Description |
|---|---|---|
| code | int | Business status code; 0 means success. |
| msg | string | Business status description. |
| data.sessionId | string | Session ID matched by this query. |
| data.artifacts | array | Artifact record array; elements are Entry. |
| data.pagination | object | Pagination information. |
| data.filter | object | Filter conditions applied for this request (echo). |
Entry Fields (data.artifacts[])
| Field | Type | Description |
|---|---|---|
| sessionId | string | Owning session ID. |
| event | string | Most recent artifact change event; values: created / updated / deleted. |
| artifact | object | Artifact body (structure: Artifact fields below). |
| md5 | string | Artifact content md5 (optional; for deduplication / instant upload). |
| url | string | Direct access URL for media artifacts (optional; returned only when artifact.type = media). |
Artifact Common Fields
| Field | Type | Description |
|---|---|---|
| type | string | Discriminator; values: plan / tasks / media / overview. |
| uri | string | Unique artifact identifier. Cloud form: agent:///artifacts/plan.md; local form: file:///…. Use as primary key across messages. |
| name | string | Resource name (e.g. file name). |
| title | string | Display title. |
| description | string | Description text. |
| mimeType | string | MIME type. |
| createdAt | int64 | Creation time (epoch milliseconds). |
| updatedAt | int64 | Last update time (epoch milliseconds). |
Artifact Type-Specific Fields
type = plan (plan document, Markdown):
| Field | Type | Description |
|---|---|---|
| text | string | Full current Markdown text. |
| version | int | Version number (increments on each update). |
| previousText | string | Previous full text; can be used to display a diff. |
| enableEdit | bool | Whether frontend edit write-back is allowed. |
type = tasks (task list):
| Field | Type | Description |
|---|---|---|
| tasks | array | Task array; elements contain id / content / status (pending / in_progress / completed / cancelled) / order. |
| enableEdit | bool | Whether frontend edit write-back is allowed. |
type = media (media file):
| Field | Type | Description |
|---|---|---|
| mimeType | string | File MIME type, e.g. image/png / video/mp4 / audio/mpeg. |
| size | int64 | File size in bytes. |
| contentType | string | Coarse category: image / video / audio / document, etc. |
| width | int | Image / video width (pixels). |
| height | int | Image / video height (pixels). |
Downloading media files: Prefer the url field at the Entry level; if not provided, replace agent:/// in uri with {sandbox_url}/ and request (reuse the same task_ticket for authentication).
type = overview (task summary, Markdown):
| Field | Type | Description |
|---|---|---|
| text | string | Full summary Markdown text. |
Error Responses
| HTTP | code | Typical Scenario and Description |
|---|---|---|
| 200 | 0 | Success. |
| 400 | 1 | Invalid parameters. Typical messages: sessionId is required (multi-session without specification); invalid type (outside whitelist); startMs / endMs / limit / offset out of range or wrong type. |
| 401 | — | task_ticket missing, invalid, or expired. Call the "Query Cloud Task" API for a new one and retry. |
| 404 | 1 | Session does not exist (session ended or sessionId incorrect). |
Error response body format:
{
"code": 1,
"msg": "invalid type: xxx (allowed: plan|tasks|media|overview)"
}
Usage recommendations
- First-screen rendering: Call the REST API once when entering a session to fetch all artifacts, and build a local index by artifact.uri.
- Incremental updates: Subscribe to SSE _codebuddy.ai/artifact notifications and upsert / delete in the local index by event.
- Session recovery: The REST first-screen + SSE incremental combination is naturally idempotent; no special "recovery branch" is needed—simply overwrite by the same uri.
Redemption Code Redemption API
Overview
Redeem a redemption code or voucher to issue credits to the currently authorized user. The API supports single-code mode and dual-code mode.
Redeem Redemption Code
| Item | Content |
|---|---|
| HTTP URL | POST https://www.workbuddy.cn/openapi/v2/redemptions |
| HTTP Method | POST |
| Permission Requirements | user.credit.exchange |
| Content-Type | application/json |
Request (Scenario A: redemption code)
POST /openapi/v2/redemptions HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Accept: application/json
Content-Length: 78
{"code":"CODE-OPER-8888","request_id":"550e8400-e29b-41d4-a716-446655440000"}
Request (Scenario B: pickup voucher)
POST /openapi/v2/redemptions HTTP/1.1
Host: www.workbuddy.cn
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Accept: application/json
Content-Length: 102
{"gift_key":"GK-000001","gift_code":"CODE-XXX","request_id":"550e8400-e29b-41d4-a716-446655440000"}
Request body
| Field | Type | Required | Meaning |
|---|---|---|---|
| code | string | Required in single-code mode | Operations platform redemption code, e.g. CODE-OPER-8888; 1-64 characters |
| gift_key | string | Required in dual-code mode | Cloud platform card number (card key), e.g. GK-000001; 6-64 characters |
| gift_code | string | Required in dual-code mode | Cloud platform card secret; 8-64 characters |
| request_id | string | Yes | Idempotent / anti-duplicate request ID; length 8-64 (example is a UUID) |
Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 158
{"status":"success","flow_no":"flow-2026072912345","credits":100,"open_id":"pairwise-open-id-xxx"}
Response Fields
| Field | Type | Meaning |
|---|---|---|
| status | string | Redemption result status, e.g. success |
| flow_no | string | Redemption flow number, e.g. flow-2026072912345 |
| credits | int64 | Credits issued by this redemption |
| open_id | string | open_id of the receiving user (pairwise; isolated per application) |
Return codes
| Status Code | Description |
|---|---|
| 200 | Redemption successful |
Return Code Specification
All Open APIs follow a unified return code specification. When an API call fails, use the HTTP status code, business code, and troubleshooting suggestions to locate the issue.
| HTTP Status Code | Business Code | Description | Troubleshooting Suggestions |
|---|---|---|---|
| 200 | success | Request succeeded | None |
| 201 | success | Request succeeded | None |
| 400 | invalid_request | Invalid request parameters (missing params / illegal format / body parse failure / unauthorized parameter combination) | Confirm parameters are valid and required fields are present |
| 400 | unsupported_grant_type | Unsupported grant_type | Use a supported grant_type |
| 400 | unsupported_response_type | response_type is not code | Always use response_type=code |
| 400 | invalid_grant | Authorization code / refresh_token invalid or mismatched; redemption code already used / expired / exhausted | Re-run the authorization flow for a new code; treat redemption as terminal—do not retry |
| 400 | invalid_scope | Application has no bound scope or requested scope exceeds bounds | Bind scopes to the application; constrain requested scopes to the bound set |
| 400 | authorization_pending | Device authorization polling in progress; user has not acted yet | Continue polling normally at the interval |
| 400 | slow_down | Device authorization polling too frequent | Increase polling interval by 5 seconds and retry |
| 400 | expired_token | device_code expired / already consumed | Re-initiate device_auth to obtain a new device_code |
| 401 | invalid_token | Authentication failed (missing Bearer / signature verification failed / missing subject·client) | Confirm the auth triad is valid and the token has not expired |
| 401 | invalid_client | Application credentials invalid or status is not active | Verify client_id/client_secret and application status |
| 401 | unauthorized_client | Application status is not active (device_auth scenario) | Confirm the application is enabled |
| 401 | Unauthorized | paysign missing login state (uid is empty) | Confirm the user is signed in with a valid login state |
| 403 | access_denied | Access to the resource is not allowed (unauthorized / application not active / downstream 403) | Confirm legitimate permissions exist and the user has authorized the application |
| 403 | insufficient_scope | Token scope does not meet endpoint requirements | Supplement scopes as indicated by WWW-Authenticate |
| 403 | forbidden | LocalAssistant identity missing or downstream 401/403 | Check the token; if still 403 after confirmed authorization, report with request_id |
| 403 | PermissionDenied | paysign X-Service-Id is not on the whitelist | Use a registered X-Service-Id or contact the platform to whitelist |
| 404 | not_found / not found | Accessed resource does not exist (application / session / batch / redemption code / message) | Confirm the resource identifier is correct and has not been deleted |
| 409 | invalid_request | Resource state conflict (device user_code already processed; anti-duplication) | This request has already been processed; do not submit again |
| 412 | invalid_request | Precondition not met (scene=client but user has no active authorization) | Complete user authorization for the application before obtaining a code |
| 429 | rate_limited | Request count exceeded limit; on 429 retry with exponential backoff (1s → 2s → 4s) | Request rate too high; reduce call frequency and retry with backoff |
| 500 | server_error / server error / InternalServerError | Internal server error | Server error; contact developers with request_id |
| 502 | server error | LocalAssistant downstream exception (not 401/403/404) | Server/downstream issue; retry and report request_id |
| 503 | server_error / temporarily unavailable / InternalServerError | Service unavailable (dependent client not configured / business temporarily unavailable) | Server configuration missing or temporarily unavailable; contact developers |
