# 任务 API

> 任务的增删改查和排序，以及团队的任务类型、任务状态、工作流和优先级。

原文：https://qunli.co/docs/developers/api/tasks

由群历 REST API 的 OpenAPI 契约（`openapi/qunli-api.yaml`，qunli-api 提交 `f18e40d`）生成。路径都相对于 `https://qunli.co`；认证见[认证](https://qunli.co/docs/developers/authentication)，响应包装、分页和错误格式见[约定](https://qunli.co/docs/developers/conventions)。字段说明是契约里的英文原文。

## 任务

### `GET /api/v1/accounts/{account_id}/tasks`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `content` | 查询 | `full` \| `summary` | 否 | full (default): rows carry their whole body. summary: rows leave out content_html, content_json, content_markdown and content_version and carry only preview_text / excerpt (documents: also preview_html); read one record for its body. Other values → 400 param_invalid. 默认 `full`。 |
| `page` | 查询 | integer | 否 | 1-based page number (meta.page / meta.has_next say where you are). 默认 `1`。 |
| `limit` | 查询 | integer | 否 | Rows per page (default 100); values outside 1–1000 are clamped into that range. 默认 `100`。 |
| `assignee_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks assigned to this user (UUID). Repeat as assignee_id[] for several. |
| `task_type_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks of this task type (UUID). Repeat as task_type_id[] for several. |
| `task_status_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks in this status (UUID). Repeat as task_status_id[] for several. |
| `priority_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks with this priority (UUID). Repeat as priority_id[] for several. |
| `scope` | 查询 | string | 否 | all (default), mine (assigned to me), or members (assigned to any member_ids). Intersects existing filters. |
| `member_ids` | 查询 | string 或 string[] | 否 | Required for scope=members. 1–100 live account member refs (U12) or user UUIDs, comma-separated or array. OR across selected members; intersects project filters and caller access. |
| `project_ids` | 查询 | string | 否 | Comma-separated project refs/UUIDs; intersects accessible projects. |
| `due_from` | 查询 | string | 否 | Keep tasks whose due_date is on or after this date (YYYY-MM-DD, inclusive). Tasks without a due_date are excluded whenever due_from or due_to is given. |
| `due_to` | 查询 | string | 否 | Keep tasks whose due_date is on or before this date (YYYY-MM-DD, inclusive). |
| `assignee` | 查询 | string | 否 | `me` keeps tasks assigned to the caller (the only supported value). |
| `finishing` | 查询 | string | 否 | `not_finished` keeps open tasks; `finished` keeps completed or cancelled ones. |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task list | `data`: `Task`[] |
| `400` | Malformed request or invalid parameter. | `ProblemDetails` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/tasks`

Create a task (account-scoped; project_id in the body)

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `project_id` | string (uuid) | 否 | createAccountTask only — the project to create the task in. |
| `recording` | `RecordingFields` | 否 | The fields every recording type shares, sent under `recording`. `id` is create-only (a client-generated UUID). |
| `recording.id` | string (uuid) | 否 |  |
| `recording.title` | string | 否 |  |
| `recording.status` | string | 否 |  |
| `recording.content_html` | string \| null | 否 | 已弃用。 |
| `recording.content_json` | any | 否 | 已弃用。 |
| `recording.content_markdown` | string \| null | 否 | Canonical body (GFM). When present the server renders and sanitizes content_html from it, ignoring any client-sent content_html/content_json. Preferred over content_html and content_json for new integrations. Hard cap 131072 bytes (128KB, UTF-8 bytes — not characters); a larger body is rejected with 422 validation_error ("正文超出 128KB 上限"): upload long content as an attachment or split it into multiple documents. Pre-existing over-limit rows stay readable and editable as long as the body is untouched. |
| `recording.content_version` | integer \| null | 否 | Update only. The content_version the edit started from (recommended for every body edit). When present and the request changes the body, a stale value is refused with 409 content_conflict and nothing is written; the problem body carries the current content_version. Omit it (or send null) for last-write-wins. Title- or metadata-only updates never conflict. |
| `task` | `TaskFields` | 否 | Task fields (tasks_controller#recordable_params). A task_status_id must be a status of the task's type — on update, of the requested task_type_id, else the current type — or the request fails with 422 validation_error (field task_status_id). On create it defaults to the type's first status; priority_id defaults to the team's first priority. An update that changes task_type_id without a task_status_id keeps the current status when the new type has it, otherwise moves the task to the new type's first status in the same stage, otherwise to its first status (422 when the new type has no statuses); the response carries the resulting task_status_id. A task_type_id of another team is 404. Assigning on create notifies the assignee (assigned/assigned), as assigning later does. |
| `task.id` | string (uuid) | 否 |  |
| `task.task_type_id` | string (uuid) | 否 |  |
| `task.task_status_id` | string (uuid) | 否 |  |
| `task.assignee_id` | string (uuid) \| null | 否 |  |
| `task.priority_id` | string (uuid) | 否 |  |
| `task.due_date` | string (date) \| null | 否 |  |
| `task.story_points` | number \| null | 否 |  |
| `task.version_id` | string (uuid) \| null | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | Created task | `data`: `Task` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/tasks/{id}`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string (ref) | 是 | 引用号，例如 `T1042`，大小写不敏感，可带前导 `#`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task | `data`: `Task` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `PATCH /api/v1/accounts/{account_id}/tasks/{id}`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string (ref) | 是 | 引用号，例如 `T1042`，大小写不敏感，可带前导 `#`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `project_id` | string (uuid) | 否 | createAccountTask only — the project to create the task in. |
| `recording` | `RecordingFields` | 否 | The fields every recording type shares, sent under `recording`. `id` is create-only (a client-generated UUID). |
| `recording.id` | string (uuid) | 否 |  |
| `recording.title` | string | 否 |  |
| `recording.status` | string | 否 |  |
| `recording.content_html` | string \| null | 否 | 已弃用。 |
| `recording.content_json` | any | 否 | 已弃用。 |
| `recording.content_markdown` | string \| null | 否 | Canonical body (GFM). When present the server renders and sanitizes content_html from it, ignoring any client-sent content_html/content_json. Preferred over content_html and content_json for new integrations. Hard cap 131072 bytes (128KB, UTF-8 bytes — not characters); a larger body is rejected with 422 validation_error ("正文超出 128KB 上限"): upload long content as an attachment or split it into multiple documents. Pre-existing over-limit rows stay readable and editable as long as the body is untouched. |
| `recording.content_version` | integer \| null | 否 | Update only. The content_version the edit started from (recommended for every body edit). When present and the request changes the body, a stale value is refused with 409 content_conflict and nothing is written; the problem body carries the current content_version. Omit it (or send null) for last-write-wins. Title- or metadata-only updates never conflict. |
| `task` | `TaskFields` | 否 | Task fields (tasks_controller#recordable_params). A task_status_id must be a status of the task's type — on update, of the requested task_type_id, else the current type — or the request fails with 422 validation_error (field task_status_id). On create it defaults to the type's first status; priority_id defaults to the team's first priority. An update that changes task_type_id without a task_status_id keeps the current status when the new type has it, otherwise moves the task to the new type's first status in the same stage, otherwise to its first status (422 when the new type has no statuses); the response carries the resulting task_status_id. A task_type_id of another team is 404. Assigning on create notifies the assignee (assigned/assigned), as assigning later does. |
| `task.id` | string (uuid) | 否 |  |
| `task.task_type_id` | string (uuid) | 否 |  |
| `task.task_status_id` | string (uuid) | 否 |  |
| `task.assignee_id` | string (uuid) \| null | 否 |  |
| `task.priority_id` | string (uuid) | 否 |  |
| `task.due_date` | string (date) \| null | 否 |  |
| `task.story_points` | number \| null | 否 |  |
| `task.version_id` | string (uuid) \| null | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Updated task | `data`: `Task` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `409` | content_conflict — the body was saved elsewhere since the request's recording.content_version; nothing was written. Rebase the edit onto the returned content_version (or reload) and save again. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `DELETE /api/v1/accounts/{account_id}/tasks/{id}`

Soft-delete a task (returns the trashed recording)

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string (ref) | 是 | 引用号，例如 `T1042`，大小写不敏感，可带前导 `#`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Trashed task | `data`: `Task` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/projects/{project_id}/tasks`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `project_id` | 路径 | string | 是 |  |
| `content` | 查询 | `full` \| `summary` | 否 | full (default): rows carry their whole body. summary: rows leave out content_html, content_json, content_markdown and content_version and carry only preview_text / excerpt (documents: also preview_html); read one record for its body. Other values → 400 param_invalid. 默认 `full`。 |
| `page` | 查询 | integer | 否 | 1-based page number (meta.page / meta.has_next say where you are). 默认 `1`。 |
| `limit` | 查询 | integer | 否 | Rows per page (default 100); values outside 1–1000 are clamped into that range. 默认 `100`。 |
| `assignee_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks assigned to this user (UUID). Repeat as assignee_id[] for several. |
| `task_type_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks of this task type (UUID). Repeat as task_type_id[] for several. |
| `task_status_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks in this status (UUID). Repeat as task_status_id[] for several. |
| `priority_id` | 查询 | string (uuid) 或 string (uuid)[] | 否 | Keep tasks with this priority (UUID). Repeat as priority_id[] for several. |
| `scope` | 查询 | string | 否 | all (default), mine (assigned to me), or members (assigned to any member_ids). Intersects existing filters. |
| `member_ids` | 查询 | string 或 string[] | 否 | Required for scope=members. 1–100 live account member refs (U12) or user UUIDs, comma-separated or array. OR across selected members; intersects project filters and caller access. |
| `project_ids` | 查询 | string | 否 | Comma-separated project refs/UUIDs; intersects accessible projects. |
| `due_from` | 查询 | string | 否 | Keep tasks whose due_date is on or after this date (YYYY-MM-DD, inclusive). Tasks without a due_date are excluded whenever due_from or due_to is given. |
| `due_to` | 查询 | string | 否 | Keep tasks whose due_date is on or before this date (YYYY-MM-DD, inclusive). |
| `assignee` | 查询 | string | 否 | `me` keeps tasks assigned to the caller (the only supported value). |
| `finishing` | 查询 | string | 否 | `not_finished` keeps open tasks; `finished` keeps completed or cancelled ones. |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task list | `data`: `Task`[] |
| `400` | Malformed request or invalid parameter. | `ProblemDetails` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/projects/{project_id}/tasks`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `project_id` | 路径 | string | 是 |  |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `project_id` | string (uuid) | 否 | createAccountTask only — the project to create the task in. |
| `recording` | `RecordingFields` | 否 | The fields every recording type shares, sent under `recording`. `id` is create-only (a client-generated UUID). |
| `recording.id` | string (uuid) | 否 |  |
| `recording.title` | string | 否 |  |
| `recording.status` | string | 否 |  |
| `recording.content_html` | string \| null | 否 | 已弃用。 |
| `recording.content_json` | any | 否 | 已弃用。 |
| `recording.content_markdown` | string \| null | 否 | Canonical body (GFM). When present the server renders and sanitizes content_html from it, ignoring any client-sent content_html/content_json. Preferred over content_html and content_json for new integrations. Hard cap 131072 bytes (128KB, UTF-8 bytes — not characters); a larger body is rejected with 422 validation_error ("正文超出 128KB 上限"): upload long content as an attachment or split it into multiple documents. Pre-existing over-limit rows stay readable and editable as long as the body is untouched. |
| `recording.content_version` | integer \| null | 否 | Update only. The content_version the edit started from (recommended for every body edit). When present and the request changes the body, a stale value is refused with 409 content_conflict and nothing is written; the problem body carries the current content_version. Omit it (or send null) for last-write-wins. Title- or metadata-only updates never conflict. |
| `task` | `TaskFields` | 否 | Task fields (tasks_controller#recordable_params). A task_status_id must be a status of the task's type — on update, of the requested task_type_id, else the current type — or the request fails with 422 validation_error (field task_status_id). On create it defaults to the type's first status; priority_id defaults to the team's first priority. An update that changes task_type_id without a task_status_id keeps the current status when the new type has it, otherwise moves the task to the new type's first status in the same stage, otherwise to its first status (422 when the new type has no statuses); the response carries the resulting task_status_id. A task_type_id of another team is 404. Assigning on create notifies the assignee (assigned/assigned), as assigning later does. |
| `task.id` | string (uuid) | 否 |  |
| `task.task_type_id` | string (uuid) | 否 |  |
| `task.task_status_id` | string (uuid) | 否 |  |
| `task.assignee_id` | string (uuid) \| null | 否 |  |
| `task.priority_id` | string (uuid) | 否 |  |
| `task.due_date` | string (date) \| null | 否 |  |
| `task.story_points` | number \| null | 否 |  |
| `task.version_id` | string (uuid) \| null | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | Created task | `data`: `Task` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/users/{user_id}/tasks`

A member's open tasks, as far as the caller can read them

The same list as GET .../my/tasks for any member (open = backlog, todo or
in-progress stage), limited to projects the caller can read; paginated, default
limit 50, newest first. meta.hidden_count is the number of that member's open
tasks in projects the caller cannot read (shown as "N more in projects you
cannot access", never listed).

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `user_id` | 路径 | string | 是 | User UUID or member ref ("U12"). |
| `content` | 查询 | `full` \| `summary` | 否 | full (default): rows carry their whole body. summary: rows leave out content_html, content_json, content_markdown and content_version and carry only preview_text / excerpt (documents: also preview_html); read one record for its body. Other values → 400 param_invalid. 默认 `full`。 |
| `page` | 查询 | integer | 否 |  |
| `limit` | 查询 | integer | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Open tasks (paginated) with hidden_count | `data`: `Task`[] · `meta`: object |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/my/tasks`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `content` | 查询 | `full` \| `summary` | 否 | full (default): rows carry their whole body. summary: rows leave out content_html, content_json, content_markdown and content_version and carry only preview_text / excerpt (documents: also preview_html); read one record for its body. Other values → 400 param_invalid. 默认 `full`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Assigned, unfinished tasks (paginated) | `data`: `Task`[] · `meta`: `PaginationMeta` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/task_moves`

Reorder / restatus a task (returns the updated task)

The task must be accessible and its neighbors must belong to its
project; an unknown task or neighbor returns 404. task_status_id must
be a status of the task's type, as on PATCH /tasks/{id}: any other
status (another type's, or another team's) fails with 422
validation_error (field task_status_id) and the task is left as it
was. A task_status_id equal to the task's current status is not a
status change and is not checked, and a move without task_status_id
only reorders.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `move` | object | 是 |  |
| `move.task_id` | string (uuid) | 是 |  |
| `move.prev` | string (uuid) \| null | 否 |  |
| `move.next` | string (uuid) \| null | 否 |  |
| `move.task_status_id` | string (uuid) | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Updated task | `data`: `Task` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

## 任务类型

### `GET /api/v1/accounts/{account_id}/task_types`

List task types for the account

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task type list | `data`: `TaskType`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/task_types`

Create a task type

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `task_type` | `TaskTypeInput` | 是 | Writable attributes for create/update (wrapped under `task_type`). |
| `task_type.name` | string | 否 |  |
| `task_type.color` | string | 否 |  |
| `task_type.description` | string \| null | 否 |  |
| `task_type.is_project_default` | boolean | 否 |  |
| `task_type.is_milestone` | boolean | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | Task type created | `data`: `TaskType` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/task_types/{id}`

Fetch a task type

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task type | `data`: `TaskType` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `PATCH /api/v1/accounts/{account_id}/task_types/{id}`

Update a task type

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `task_type` | `TaskTypeInput` | 是 | Writable attributes for create/update (wrapped under `task_type`). |
| `task_type.name` | string | 否 |  |
| `task_type.color` | string | 否 |  |
| `task_type.description` | string \| null | 否 |  |
| `task_type.is_project_default` | boolean | 否 |  |
| `task_type.is_milestone` | boolean | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Updated task type | `data`: `TaskType` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `DELETE /api/v1/accounts/{account_id}/task_types/{id}`

Delete a task type (409 while tasks outside the recycle bin use it; trashed tasks and those of deleted projects move to another type)

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Deleted (no content payload) | `data`: null |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `409` | State conflict. | `ProblemDetails` |

## 任务状态

### `GET /api/v1/accounts/{account_id}/task_statuses`

List task statuses for the account

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task status list | `data`: `TaskStatus`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/task_statuses`

Create a task status

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `task_status` | `TaskStatusInput` | 是 |  |
| `task_status.name` | string | 否 |  |
| `task_status.color` | string \| null | 否 |  |
| `task_status.stage` | string | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | Task status created | `data`: `TaskStatus` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/task_statuses/{id}`

Fetch a task status

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task status | `data`: `TaskStatus` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `PATCH /api/v1/accounts/{account_id}/task_statuses/{id}`

Update a task status

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `task_status` | `TaskStatusInput` | 是 |  |
| `task_status.name` | string | 否 |  |
| `task_status.color` | string \| null | 否 |  |
| `task_status.stage` | string | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Updated task status | `data`: `TaskStatus` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `DELETE /api/v1/accounts/{account_id}/task_statuses/{id}`

Delete a task status (409 while tasks outside the recycle bin have it or a task type uses it; trashed tasks and those of deleted projects move to another status)

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Deleted | `data`: null |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `409` | State conflict. | `ProblemDetails` |

### `PUT /api/v1/accounts/{account_id}/task_statuses/{id}/move`

Reorder a task status (legacy verb path; see api-conventions §9)

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `position` | integer | 是 |  |
| `stage` | string | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Reordered task status | `data`: `TaskStatus` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

## 工作流

### `GET /api/v1/accounts/{account_id}/task_type_statuses`

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Task type status list | `data`: `TaskTypeStatus`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `PUT /api/v1/accounts/{account_id}/task_type_statuses/activate`

Both referenced resources must belong to this account; otherwise returns 404.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `task_type_status` | object | 是 |  |
| `task_type_status.task_type_id` | string (uuid) | 否 |  |
| `task_type_status.task_status_id` | string (uuid) | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Activated link | `data`: `TaskTypeStatus` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `PUT /api/v1/accounts/{account_id}/task_type_statuses/deactivate`

Both referenced resources must belong to this account; otherwise returns 404.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `task_type_status` | object | 是 |  |
| `task_type_status.task_type_id` | string (uuid) | 否 |  |
| `task_type_status.task_status_id` | string (uuid) | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Deactivated (no content payload) | `data`: null |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

## 优先级

### `GET /api/v1/accounts/{account_id}/priorities`

List priorities for the account

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Priority list | `data`: `Priority`[] |
| `401` | Missing or invalid authentication. | `ProblemDetails` |

### `POST /api/v1/accounts/{account_id}/priorities`

Create a priority

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `priority` | `PriorityInput` | 是 |  |
| `priority.name` | string | 否 |  |
| `priority.position` | integer | 否 |  |
| `priority.is_default` | boolean | 否 |  |
| `priority.color` | string \| null | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `201` | Priority created | `data`: `Priority` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `GET /api/v1/accounts/{account_id}/priorities/{id}`

Fetch a priority

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Priority | `data`: `Priority` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |

### `PATCH /api/v1/accounts/{account_id}/priorities/{id}`

Update a priority

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `priority` | `PriorityInput` | 是 |  |
| `priority.name` | string | 否 |  |
| `priority.position` | integer | 否 |  |
| `priority.is_default` | boolean | 否 |  |
| `priority.color` | string \| null | 否 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Updated priority | `data`: `Priority` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

### `DELETE /api/v1/accounts/{account_id}/priorities/{id}`

Delete a priority (409 while tasks outside the recycle bin use it; trashed tasks and those of deleted projects move to the default priority)

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Deleted | `data`: null |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `409` | State conflict. | `ProblemDetails` |

### `PUT /api/v1/accounts/{account_id}/priorities/{id}/move`

Reorder a priority (legacy verb path; see api-conventions §9)

Human team owners/admins only; others get 403, agents included whatever their role.

参数：

| 参数 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| `account_id` | 路径 | string | 是 | 团队的数字 id，和网页地址里的相同，例如 `2025`。 |
| `id` | 路径 | string | 是 |  |

请求体（`application/json`，必填）：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `position` | integer | 是 |  |

响应：

| 状态 | 说明 | 返回 |
| --- | --- | --- |
| `200` | Reordered priority | `data`: `Priority` |
| `401` | Missing or invalid authentication. | `ProblemDetails` |
| `403` | Authenticated but not permitted. | `ProblemDetails` |
| `404` | Resource does not exist or has been trashed. | `ProblemDetails` |
| `422` | Validation failed. | `ProblemDetails` |

## 数据结构

上面的响应用到的对象。字段的类型是另一个对象时，它也列在这里。

### Task

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `public_id` | string \| null | 否 |  |
| `legacy_id` | string \| null | 是 |  |
| `title` | string | 是 |  |
| `content_html` | string \| null | 否 |  |
| `content_json` | object \| null | 否 |  |
| `content_markdown` | string \| null | 否 | Canonical body (GFM). content_html is rendered server-side from it; null on rows not yet migrated from Tiptap JSON. |
| `content_version` | integer | 否 | Body version for compare-and-set saves. Starts at 0 and increases by one each time content_markdown / content_html / content_json actually changes (any write path). Send it back as recording.content_version when saving a body edit. |
| `preview_text` | string | 否 | Lists only. The body as plain text (HTML tags removed, entities left encoded, e.g. "&amp;"), cut to 80 UTF-16 units; "" without a body. |
| `excerpt` | string \| null | 否 | Lists only. Up to 100 characters of the body's text, images and videos shown as [图片] / [视频]; null without a body. |
| `preview_html` | string | 否 | Document lists only. The first 3000 characters of content_html (may end inside a tag), for thumbnails. |
| `comments_count` | integer | 是 |  |
| `type` | string | 是 |  |
| `status` | `draft` \| `active` \| `archived` \| `trashed` | 是 |  |
| `recordable_type` | `Task` | 是 |  |
| `app_url` | string \| null | 是 |  |
| `account_id` | string (uuid) | 是 |  |
| `account_public_id` | string | 是 |  |
| `project_id` | string (uuid) | 是 |  |
| `project_public_id` | string | 是 |  |
| `creator_id` | string (uuid) | 是 |  |
| `parent_id` | string (uuid) \| null | 否 |  |
| `parent_public_id` | string \| null | 否 |  |
| `ancestors` | `FolderCrumb`[] | 否 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 | Last change of the recording or of its body, whichever is later. |
| `reactions` | `Reaction`[] | 是 |  |
| `edited_by` | `UserRef` | 否 | Comments and discussions only: the last member other than the author who edited the title or body (the author's own later edits keep it); null when only the author edited it. |
| `trashed_by` | `UserRef` | 否 | Comments and discussions only: the member other than the author who trashed it; null otherwise (cleared by the author's own trash and on restore). A comment with status "trashed" and a trashed_by is a placeholder in GET .../recordings/:id/comments — its title and content are empty. |
| `due_date` | string (date) \| null | 是 |  |
| `start_date` | string (date) \| null | 是 |  |
| `rank` | string | 是 |  |
| `story_points` | integer \| null | 是 |  |
| `priority_id` | string (uuid) | 是 |  |
| `task_type_id` | string (uuid) | 是 |  |
| `task_status_id` | string (uuid) | 是 |  |
| `version_id` | string (uuid) \| null | 是 |  |
| `assignee_id` | string (uuid) \| null | 是 |  |
| `backlog_at` | string (date-time) \| null | 是 |  |
| `todo_at` | string (date-time) \| null | 是 |  |
| `in_progress_at` | string (date-time) \| null | 是 |  |
| `completed_at` | string (date-time) \| null | 是 |  |
| `cancelled_at` | string (date-time) \| null | 是 |  |
| `project` | `ProjectSummary` | 否 | Cross-project lists only (GET .../my/tasks, GET .../users/{user_id}/tasks): the task's project, so a row can show where it lives without loading the project list. |

### PaginationMeta

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `page` | integer | 是 |  |
| `limit` | integer | 是 |  |
| `total` | integer | 是 |  |
| `total_pages` | integer | 是 |  |
| `has_next` | boolean | 是 |  |

### TaskType

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `name` | string | 是 |  |
| `color` | string | 是 |  |
| `description` | string \| null | 是 |  |
| `tasks_count` | integer | 是 | Tasks of this type, not counting trashed tasks or the tasks of deleted projects. |
| `position` | integer | 是 |  |
| `is_project_default` | boolean | 是 |  |
| `is_milestone` | boolean | 是 |  |
| `account_id` | string (uuid) | 是 |  |
| `account_public_id` | string | 是 |  |
| `task_status_ids` | string (uuid)[] | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |

### TaskStatus

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `name` | string | 是 |  |
| `color` | string \| null | 是 |  |
| `stage` | `backlog` \| `todo` \| `in_progress` \| `completed` \| `cancelled` | 是 |  |
| `position` | integer | 是 |  |
| `tasks_count` | integer | 是 | Tasks in this status, not counting trashed tasks or the tasks of deleted projects. |
| `account_id` | string (uuid) | 是 |  |
| `account_public_id` | string | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |

### TaskTypeStatus

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `task_type_id` | string (uuid) | 是 |  |
| `task_status_id` | string (uuid) | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |

### Priority

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `name` | string | 是 |  |
| `position` | integer | 是 |  |
| `is_default` | boolean | 是 |  |
| `color` | string \| null | 是 |  |
| `account_id` | string (uuid) | 是 |  |
| `account_public_id` | string | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |

### FolderCrumb

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `public_id` | string \| null | 是 |  |
| `title` | string | 是 |  |

### Reaction

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `actor_id` | string (uuid) | 是 |  |
| `reactable_id` | string (uuid) | 是 |  |
| `reactable_type` | string | 是 |  |
| `reaction_type_id` | string (uuid) | 是 |  |
| `reaction_emoji` | string | 是 |  |
| `reaction_name` | string | 是 |  |
| `created_at` | string (date-time) | 是 |  |
| `updated_at` | string (date-time) | 是 |  |

### UserRef

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 | User UUID. |
| `public_id` | string \| null | 是 | Member ref ("U12") in this account. |
| `name` | string \| null | 是 |  |
| `avatar_url` | string \| null | 是 |  |
| `kind` | `human` \| `agent` \| null | 是 | null only for an unknown (deleted) user. |

### ProjectSummary

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | string (uuid) | 是 |  |
| `public_id` | string | 是 |  |
| `name` | string | 是 |  |
| `icon` | string \| null | 是 |  |
