待办接口
通过 Dinox 开放接口搜索、读取、新建、更新、移动和删除笔记中的待办。
待办接口
待办保存在笔记正文中。每条待办用「笔记 ID + 任务 ID」定位。以下接口都使用 POST 和 application/json,并要求 Token 具有可读或可写笔记的权限。
基础域名为 https://aisdk.chatgo.pro,接口前缀为 /api/openapi。请求头使用 Authorization: <你的Token>;写入时可通过 Idempotency-Key 请求头或 clientRequestId 请求字段实现幂等。
每个请求都必须提供 IANA 时区名 timezone,例如 Asia/Shanghai。日期筛选、日期型截止时间和「今天」均按该时区计算。
待办对象
成功响应使用 { "code": "000000", "msg": "success", "data": ... }。待办对象结构如下:
{
"noteId": "00000000-0000-4000-8000-000000000001",
"taskId": "00000000-0000-7000-8000-00000000000a",
"parentTaskId": null,
"depth": 0,
"text": "买牛奶",
"checked": false,
"priority": "high",
"tags": ["购物"],
"startAt": null,
"dueAt": { "iso": "2026-10-30T01:00:00.000Z", "displayFormat": "datetime" },
"schedule": {
"source": "task",
"start": "2026-10-30T01:00:00.000Z",
"end": "2026-10-30T01:00:00.000Z",
"allDay": false
},
"note": {
"title": "采购清单",
"parentNoteId": null,
"tags": ["生活"],
"folders": [{ "id": "00000000-0000-4000-8000-000000000002", "name": "日常" }],
"createdAt": "2026-10-29T08:00:00.000Z",
"version": 12
}
}priority 为 high、medium、low 或 null。startAt、dueAt 是时间点或 null;schedule 按请求时区解析,没有时间信息的待办以笔记创建日期作为日程日期。note.folders 是笔记所在的有效卡片盒,已删除的卡片盒不会返回。
对于批注(子卡)中的待办,note.parentNoteId 指向父笔记;标签和卡片盒按「父笔记 ∪ 批注」合并,标题为空时使用父笔记标题。按标签或卡片盒筛选时也使用合并后的标签和卡片盒。
搜索待办
接口地址
POST /api/openapi/todos/search请求参数(application/json)
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timezone | string | 是 | IANA 时区名,例如 Asia/Shanghai |
| status | string | 否 | all(默认)、open 或 done |
| dateFrom | string | 否 | 起始日期,YYYY-MM-DD,按 timezone 计算 |
| dateTo | string | 否 | 结束日期,YYYY-MM-DD,按 timezone 计算 |
| query | string | 否 | 按待办文字包含匹配 |
| tag | string | 否 | 匹配待办标签或笔记标签,可带或不带 # |
| folderId | string | 否 | 卡片盒 ID;同时匹配其子卡片盒 |
| noteId | string | 否 | 只搜索指定笔记,必须是 UUID |
| limit | integer | 否 | 每页数量,默认 50,范围 1–200 |
| cursor | string | null | 否 | 上一页响应中的 nextCursor,原样传回 |
日期范围与待办日程有交集即命中。结果按笔记创建时间倒序、同一笔记内按正文顺序排列。
请求示例
{
"timezone": "Asia/Shanghai",
"status": "open",
"dateFrom": "2026-10-29",
"dateTo": "2026-11-04",
"query": "牛奶",
"tag": "购物",
"folderId": "00000000-0000-4000-8000-000000000002",
"noteId": "00000000-0000-4000-8000-000000000001",
"limit": 50,
"cursor": null
}响应示例
{
"code": "000000",
"msg": "success",
"data": {
"todos": [{ "noteId": "00000000-0000-4000-8000-000000000001", "taskId": "00000000-0000-7000-8000-00000000000a", "text": "买牛奶", "checked": false }],
"hasMore": false,
"nextCursor": null
}
}每页返回的 todos 中每一项都是上面的完整待办对象。单次最多扫描 1000 篇笔记;达到上限时 hasMore 为 true,此时结果可能少于 limit,请继续使用 nextCursor。
读取待办
接口地址
POST /api/openapi/todos/get请求参数(application/json)
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timezone | string | 是 | IANA 时区名,例如 Asia/Shanghai |
| noteId | string | 是 | 笔记 ID,UUID |
| taskId | string | 是 | 任务 ID,最长 128 个字符 |
请求示例
{
"timezone": "Asia/Shanghai",
"noteId": "00000000-0000-4000-8000-000000000001",
"taskId": "00000000-0000-7000-8000-00000000000a"
}响应示例
{
"code": "000000",
"msg": "success",
"data": {
"todo": { "noteId": "00000000-0000-4000-8000-000000000001", "taskId": "00000000-0000-7000-8000-00000000000a", "text": "买牛奶", "checked": false },
"subtasks": []
}
}todo 是完整待办对象;subtasks 按正文顺序列出它下面所有层级的子任务。
新建待办
接口地址
POST /api/openapi/todos/create请求参数(application/json)
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timezone | string | 是 | IANA 时区名,例如 Asia/Shanghai |
| target | object | 否 | 新建位置,见下方三种类型;省略时为当天待办 |
| target.type | string | 否 | daily(默认)、note 或 task |
| target.date | string | 否 | daily 的目标日期,YYYY-MM-DD;省略时为今天 |
| target.title | string | 否 | 新建每日笔记的标题,非空且最多 500 字符 |
| target.noteId | string | 按类型需要 | note 或 task 时必填,笔记 ID UUID |
| target.taskId | string | 按类型需要 | task 时必填,作为子任务的目标任务 ID |
| items | array | 是 | 待办数组,至少一条有效任务;最多 100 条(包含子任务) |
| items[].text | string | 是 | 待办文字,最多 2000 字符;空白文字会被忽略(有子任务时不可空) |
| items[].checked | boolean | 否 | 是否完成,默认 false |
| items[].priority | string | null | 否 | high、medium、low 或 null |
| items[].due | object | null | 否 | 截止时间 { "date": "YYYY-MM-DD", "time": "HH:mm" };time 省略或为 null 表示全天 |
| items[].subtasks | array | 否 | 子任务,最多嵌套 5 层;字段与任务项相同 |
| cascade | boolean | 否 | 是否联动勾选状态,默认 true;仅对 target.type 为 task 生效 |
| clientRequestId | string | 否 | 幂等键;也可在请求头使用 Idempotency-Key |
target 三种写入位置:
daily:追加到该时区当天已有待办的最新笔记,没有则新建。指定date后,未提供due的任务默认截止日为该日期。为其他日期(例如明天)新建的笔记,之后同一日期的请求会继续追加到这篇笔记。note:追加到指定笔记末尾。笔记末尾已经是任务列表时,新任务并入该列表。task:将新任务作为指定任务的子任务。新增的子任务里有未完成的,目标任务及其已勾选的上级任务会一起取消勾选(与更新待办的勾选联动规则一致);传"cascade": false可关闭。
items[].text 支持行内 Markdown 和 #标签。
请求示例
{
"timezone": "Asia/Shanghai",
"target": { "type": "daily", "date": "2026-10-30", "title": "10 月 30 日待办" },
"clientRequestId": "reminder-20261030-01",
"items": [
{ "text": "买牛奶 #购物", "priority": "medium", "due": { "date": "2026-10-30", "time": "18:00" }, "subtasks": [{ "text": "确认品牌" }] }
]
}响应示例
{
"code": "000000",
"msg": "success",
"data": {
"noteId": "00000000-0000-4000-8000-000000000001",
"noteCreated": true,
"version": 1,
"target": { "type": "daily", "date": "2026-10-30" },
"todos": [{ "noteId": "00000000-0000-4000-8000-000000000001", "taskId": "00000000-0000-7000-8000-00000000000a", "text": "买牛奶", "checked": false }],
"cascaded": []
}
}todos 返回新建的待办完整对象。cascaded 列出因联动被取消勾选的上级任务(更新后的状态)。幂等键最多 256 个字符。使用 Idempotency-Key 请求头或 clientRequestId 时,7 天内相同键和相同请求体会返回相同结果;同一键换用不同请求体会返回冲突。
更新待办
接口地址
POST /api/openapi/todos/update请求参数(application/json)
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timezone | string | 是 | IANA 时区名,例如 Asia/Shanghai |
| cascade | boolean | 否 | 是否联动勾选状态,默认 true;false 只改指定任务本身 |
| updates | array | 是 | 更新列表,1–100 项;单项也可直接放在顶层 |
| updates[].noteId | string | 是 | 笔记 ID,UUID |
| updates[].taskId | string | 是 | 任务 ID,最长 128 个字符 |
| updates[].checked | boolean | 否 | 设置完成状态 |
| updates[].priority | string | null | 否 | high、medium、low 或 null(清除优先级) |
| updates[].due | object | null | 否 | { "date": "YYYY-MM-DD", "time": "HH:mm" };null 清除截止时间 |
| updates[].expectedVersion | integer | 否 | 非负版本号;不匹配时返回冲突 |
每项至少要提供 checked、priority、due 之一。若待办同时有开始和截止时间,更新 due 只修改截止时间。整批更新在一个事务中原子执行:任一项找不到或版本冲突时,全部不生效。
cascade 是请求级参数,默认开启。勾选联动规则如下:
- 勾选父任务时,它下面所有层级的子任务一起勾选。
- 取消勾选某个任务时,已勾选的上级任务一起取消(还有子任务没完成时,父任务不算完成);该任务自己的子任务保持原样。
- 取消勾选父任务时,子任务保持原样。
- 子任务全部勾选后,父任务不会自动完成,需要显式勾选。
请求示例
{
"timezone": "Asia/Shanghai",
"updates": [
{ "noteId": "00000000-0000-4000-8000-000000000001", "taskId": "00000000-0000-7000-8000-00000000000a", "checked": true, "expectedVersion": 12 },
{ "noteId": "00000000-0000-4000-8000-000000000001", "taskId": "00000000-0000-7000-8000-00000000000b", "priority": null, "due": null }
]
}响应示例
{
"code": "000000",
"msg": "success",
"data": {
"todos": [{ "noteId": "00000000-0000-4000-8000-000000000001", "taskId": "00000000-0000-7000-8000-00000000000a", "text": "买牛奶", "checked": true }],
"cascaded": [],
"notes": [{ "noteId": "00000000-0000-4000-8000-000000000001", "version": 13, "written": true }]
}
}todos 是更新后的完整待办对象。cascaded 列出因联动被改动、但不在 updates 里的任务,内容是更新后的状态。notes 返回各笔记版本和是否实际写入。没有实际变化时 written 为 false,且不会写库。
删除待办
接口地址
POST /api/openapi/todos/delete请求参数(application/json)
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timezone | string | 是 | IANA 时区名,例如 Asia/Shanghai |
| noteId | string | 是 | 笔记 ID,UUID |
| taskId | string | 是 | 任务 ID,最长 128 个字符 |
| expectedVersion | integer | 是 | 待办对象 note.version 中的非负版本号 |
| children | string | 否 | delete(默认,连同子任务删除)或 promote(子任务上移) |
删除前请读取最新版本并填写 expectedVersion,版本不匹配时不会删除,返回 HTTP 409。冲突响应的 data 中带有笔记当前版本和该任务的当前状态(见下方「版本冲突」),确认仍要删除时用 currentVersion 重试即可;todo 为 null 表示任务已不存在,不要重试。删除后如果笔记里的任务列表为空,该列表也会移除。
请求示例
{
"timezone": "Asia/Shanghai",
"noteId": "00000000-0000-4000-8000-000000000001",
"taskId": "00000000-0000-7000-8000-00000000000a",
"expectedVersion": 12,
"children": "promote"
}响应示例
{
"code": "000000",
"msg": "success",
"data": {
"noteId": "00000000-0000-4000-8000-000000000001",
"removedTaskIds": ["00000000-0000-7000-8000-00000000000a"],
"version": 13
}
}移动待办
接口地址
POST /api/openapi/todos/move把任务连同它的所有子任务移到新位置,子任务之间的层级关系保持不变。
请求参数(application/json)
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timezone | string | 是 | IANA 时区名,例如 Asia/Shanghai |
| noteId | string | 是 | 源笔记 ID,UUID |
| taskId | string | 是 | 要移动的任务 ID,最长 128 个字符 |
| expectedVersion | integer | 否 | 源笔记的非负版本号;不匹配时返回冲突 |
| cascade | boolean | 否 | 是否联动勾选状态,默认 true |
| to | object | 是 | 目标位置;下面三种写法只能设置一种 |
| to.parentTaskId | string | null | 按位置需要 | 任务 ID:成为该任务的最后一个子任务;null:作为顶层任务放到笔记末尾(末尾已是任务列表时并入该列表,否则新建列表) |
| to.beforeTaskId | string | 按位置需要 | 放到该任务前面,与它同级 |
| to.afterTaskId | string | 按位置需要 | 放到该任务后面,与它同级 |
| to.noteId | string | 否 | 目标笔记 ID;省略时与源笔记相同 |
| to.expectedVersion | integer | 否 | 目标笔记的非负版本号;跨笔记移动时用于校验目标笔记 |
to 必须设置,且 parentTaskId、beforeTaskId、afterTaskId 三者只能有一个。降级(增加缩进)时,把 parentTaskId 设为上一个同级任务。升级时,把 afterTaskId 设为当前父任务。同级排序使用 beforeTaskId 或 afterTaskId。
不能移到自己或自己的子任务旁边或下面,否则返回参数错误。原位置的任务列表移空后会一起删除。同一篇笔记内移动后如果层级和顺序都没有变化,written 为 false,不会写库。跨笔记移动时,只有时间、没有日期的时间节点会改按目标笔记的创建日计算。
勾选联动:移过去的任务或它的子任务里有未完成的,新位置上已勾选的上级任务会一起取消勾选;传 "cascade": false 可关闭。
请求示例
{
"timezone": "Asia/Shanghai",
"noteId": "00000000-0000-4000-8000-000000000001",
"taskId": "00000000-0000-7000-8000-00000000000a",
"expectedVersion": 12,
"to": { "parentTaskId": "00000000-0000-7000-8000-00000000000b" }
}移到笔记末尾的新列表时使用 "to": { "parentTaskId": null }。放到同级任务前面或后面时使用 "to": { "beforeTaskId": "…" } 或 "to": { "afterTaskId": "…" }。跨笔记时在 to 中加上 noteId,需要校验目标笔记版本时再加上 expectedVersion。
响应示例
{
"code": "000000",
"msg": "success",
"data": {
"todo": { "noteId": "00000000-0000-4000-8000-000000000001", "taskId": "00000000-0000-7000-8000-00000000000a", "parentTaskId": "00000000-0000-7000-8000-00000000000b", "text": "买牛奶", "checked": false },
"subtasks": [],
"cascaded": [],
"notes": [{ "noteId": "00000000-0000-4000-8000-000000000001", "version": 13, "written": true }]
}
}todo 和 subtasks 是移动后的位置;subtasks 按正文顺序列出它下面所有层级的子任务。cascaded 列出因联动被取消勾选的上级任务。notes 返回涉及的笔记版本和是否实际写入。
错误码
| 错误码 | 说明 |
|---|---|
| 000001 | Token 缺失或无效 |
| 000006 | 参数错误(HTTP 400),或笔记、待办不存在(HTTP 404) |
| 000009 | 版本冲突或幂等键冲突(HTTP 409) |
版本冲突
笔记的任何改动都会让 note.version 加 1,包括调用方自己的写入和用户在 App 里的编辑。所以不要长期缓存版本号,写入时以最近一次响应里的版本为准。
版本冲突时,响应的 data 带有当前状态,方便直接决定是否重试:
{
"code": "000009",
"msg": "note … was modified since it was read (expectedVersion 4, current version 6); fetch it again before retrying",
"data": {
"noteId": "00000000-0000-4000-8000-000000000001",
"expectedVersion": 4,
"currentVersion": 6,
"todo": { "taskId": "00000000-0000-7000-8000-00000000000a", "text": "买牛奶", "checked": false }
}
}todo 只在删除待办时返回,是任务的完整当前状态;任务已不存在时为 null。
任务 ID 的稳定性
从 App 的下一个版本起,在 App 中编辑时任务 ID 保持不变:打字、勾选、缩进、拖动排序、在任务开头回车,以及把任务转成段落或无序列表后再转回任务,都不会改变任务 ID。复制粘贴和剪切粘贴得到的是新任务、新 ID。
收到某个任务的 404 时,请把它当作「任务已被删除或已改变」,用搜索接口重新同步,不要原样重试。
已知限制
- 暂不支持修改待办文字或管理提醒。
- 没有任务 ID 的旧待办及其子任务不会出现在搜索结果中;通过接口写入该笔记时会自动补齐任务 ID。
- 在手机离线编辑同一篇笔记时,联网后的同步可能覆盖接口写入,具体取决于同步时的冲突处理。