由群历 REST API 的 OpenAPI 契约(openapi/qunli-api.yaml,qunli-api 提交 f18e40d)生成。路径都相对于 https://qunli.co;认证见认证,响应包装、分页和错误格式见约定。字段说明是契约里的英文原文。
记录
GET/api/v1/accounts/{account_id}/recordings
Paginated list of recordings across accessible projects
参数
参数
位置
类型
必填
说明
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
Dereference any recording ref ("T1042", "M15761") to its full typed payload — tasks/goals/forwarded emails carry their recordable fields; uploads (F…) and folders (B…) answer with the DriveItem shape; messages/documents are complete in the base recording shape; schedules (S…) answer with the Schedule shape.
Deletes the recording into its project's recycle bin (回收站, GET /projects/{project_id}/trashed_recordings): restorable for 30 days, then purged for good.
Unarchives, publishes a draft, or restores a deleted recording. For a deleted task, discussion, document, file, folder, schedule, goal or forwarded email this is the recycle bin's restore (see restoreTrashedRecording): it returns to the status it had — which may be archived or draft — under the bin's permission rules.
Revision history (历史版本) of a recording, newest first
Documents and discussions keep their title and body, tasks their description; other types have no history (empty list). Metadata only — read one revision's body with GET .../revisions/{number}. Readable by whoever can read the recording: trashed recordings 404, drafts 404 for everyone but their author.
Restore a revision's body (signed-in members only, not API keys)
Writes the revision's body back as the current body; the title stays as it is. content_version is the body version the restorer saw: stale → 409 content_conflict, nothing written. Adds a "restore" revision and a revision_restored activity (details.revision_number; none for drafts); sends no notifications and registers no mentions. When the revision already is the current body nothing is written and content_version stays the same. Needs project write access, and for a discussion its author (or, for an agent's discussion, its human manager or a team owner/admin). API keys (agents) are refused with 403 — restore is for signed-in members.
参数
参数
位置
类型
必填
说明
account_id
路径
string
是
团队的数字 id,和网页地址里的相同,例如 2025。
recording_id
路径
string (ref)
是
引用号,例如 T1042,大小写不敏感,可带前导 #。
number
路径
integer
是
请求体application/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.
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.
The project's deleted tasks, discussions, documents, files, folders, schedules, goals and forwarded emails, most recently deleted first. Each stays here for 30 days (purge_at) and is then purged for good. A folder's contents and the later meetings of a "cancel following" are not listed: they went in with the folder / first meeting (items_count) and come back or go with it. Everyone who can see the project sees its bin (a deleted draft only its author); can_restore and can_purge say what the caller may do. Comments are not listed: a deleted comment is restored with PUT /recordings/{ref}/status/active by its author.
参数
参数
位置
类型
必填
说明
account_id
路径
string
是
团队的数字 id,和网页地址里的相同,例如 2025。
project_id
路径
string
是
page
查询
integer
否
1-based page number (meta.page / meta.has_next say where you are).默认 1
Permanently deletes the entry with its comments and everything that went into the bin with it (a folder's contents). Cannot be undone. Human project admins and team owners/admins only (403 otherwise).
Brings the entry back where it was, with the same ref, comments and history: to the status it had (restores_to), in the same folder — or the drive root when that folder is gone. A task keeps its type, status and priority (deleting one of those while the task is in the bin reassigns it). What went in with it comes back too; a "restored" activity is recorded. Allowed for project writers who deleted or wrote it, the human 负责人 of the robot that deleted or wrote it, project admins and team owners/admins; a robot only restores what it deleted or wrote itself (403 otherwise). PUT /recordings/{ref}/status/active does the same for these types.
参数
参数
位置
类型
必填
说明
account_id
路径
string
是
团队的数字 id,和网页地址里的相同,例如 2025。
project_id
路径
string
是
id
路径
string (ref)
是
The entry's ref ("T1042")
响应
状态
说明
返回
200
The restored recording, as GET /recordings/{ref} returns it
Deleted projects, most recent first. A deleted project is gone for everyone (its records, notifications, search hits, calendar entries; mail to its forwarding address bounces) and can be restored for 30 days (purge_at), after which it is purged with everything in it. Team owners/admins see every deleted project; a project admin sees the ones they administer. Robots see none.
参数
参数
位置
类型
必填
说明
account_id
路径
string
是
团队的数字 id,和网页地址里的相同,例如 2025。
page
查询
integer
否
1-based page number (meta.page / meta.has_next say where you are).默认 1
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.
comment
CommentFields
否
comment.id
string (uuid)
否
comment.comment_type
general | inline
否
comment.parent_id
string (uuid) | null
否
Reply to a top-level comment (its recording id) on the same recording. Threads are two levels: a reply's parent_id must be a top-level comment, else 422; to answer a reply, use its parent_id.
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.
comment
CommentFields
否
comment.id
string (uuid)
否
comment.comment_type
general | inline
否
comment.parent_id
string (uuid) | null
否
Reply to a top-level comment (its recording id) on the same recording. Threads are two levels: a reply's parent_id must be a top-level comment, else 422; to answer a reply, use its parent_id.
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.
A member's activity in projects the caller can read
Lists the member's activity, newest first, limited to projects the caller can currently read (the same rule as the account activity feed). Activity in other projects is omitted, not masked.
参数
参数
位置
类型
必填
说明
account_id
路径
string
是
团队的数字 id,和网页地址里的相同,例如 2025。
user_id
路径
string
是
User UUID or member ref ("U12"); bare numbers never resolve.
page
查询
integer
否
1-based page number (meta.page / meta.has_next say where you are).默认 1
limit
查询
integer
否
Rows per page (default 100; 50 for my/activities).
The current user's draft recordings (not paginated)
参数
参数
位置
类型
必填
说明
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
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. "&"), 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 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.
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.
PaginationMeta
字段
类型
必填
说明
page
integer
是
limit
integer
是
total
integer
是
total_pages
integer
是
has_next
boolean
是
RecordingRevision
One snapshot of a recording's title and whole body. Events: baseline (the body a recording had before its history began, by its creator), create (created published), edit (saves; one author's saves within 10 minutes update the same edit in place, so updated_at moves), publish (draft published), restore (a revision brought back; restored_from_number names it).
字段
类型
必填
说明
number
integer
是
Per-recording sequence.
event
baseline | create | edit | publish | restore
是
title
string
是
The recording title at the time (a task's own title for its description history).
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.
restored_from_number
integer | null
是
created_at
string (date-time)
是
updated_at
string (date-time)
是
RecordingRevisionDetail
字段
类型
必填
说明
number
integer
是
Per-recording sequence.
event
baseline | create | edit | publish | restore
是
title
string
是
The recording title at the time (a task's own title for its description history).
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.
Task types enabled in this project, in the team's task type order. The first is the default type of a task created without task_type_id.
Comment
字段
类型
必填
说明
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. "&"), 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 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.
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.
The bookmarked recording itself (id == bookmarkable_id); a bookmarked comment is a Comment summary whose title is a placeholder — label it with parent.title. Null when the bookmarkable is not a recording.