介绍
# Todoist
通过托管的 OAuth 身份验证访问 Todoist REST API v2。管理任务、项目、部分、标签和评论。
## Quick Start
```bash # List all tasks python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/todoist/rest/v2/tasks') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
## Base URL
``` https://gateway.maton.ai/todoist/rest/v2/{resource} ```
网关将请求代理到 `api.todoist.com/rest/v2` 并自动注入您的 OAuth 令牌。
## Authentication
所有请求都需要在 Authorization 请求头中提供 Maton API 密钥:
``` Authorization: Bearer $MATON_API_KEY ```
**Environment Variable:** 将您的 API 密钥设置为 `MATON_API_KEY`:
```bash export MATON_API_KEY="YOUR_API_KEY" ```
### Getting Your API Key
1. 在 [maton.ai](https://maton.ai) 登录或创建账户 2. 前往 [maton.ai/settings](https://maton.ai/settings) 3. 复制您的 API 密钥
## Connection Management
在 `https://ctrl.maton.ai` 管理您的 Todoist OAuth 连接。
### List Connections
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=todoist&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Create Connection
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'todoist'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Get Connection
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```json { "connection": { "connection_id": "21fd90f9-5935-43cd-b6c8-bde9d915ca80", "status": "ACTIVE", "creation_time": "2025-12-08T07:20:53.488460Z", "last_updated_time": "2026-01-31T20:03:32.593153Z", "url": "https://connect.maton.ai/?session_token=...", "app": "todoist", "metadata": {} } } ```
在浏览器中打开返回的 `url` 以完成 OAuth 授权。
### Delete Connection
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Specifying Connection
如果您有多个 Todoist 连接,请使用 `Maton-Connection` 请求头指定要使用的连接:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/todoist/rest/v2/tasks') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '21fd90f9-5935-43cd-b6c8-bde9d915ca80') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
如果省略,网关将使用默认(最早)的活动连接。
## API Reference
### Projects
#### List Projects
```bash GET /todoist/rest/v2/projects ```
**Response:** ```json [ { "id": "2366738772", "name": "Inbox", "color": "charcoal", "parent_id": null, "order": 0, "is_shared": false, "is_favorite": false, "is_inbox_project": true, "view_style": "list", "url": "https://app.todoist.com/app/project/..." } ] ```
#### Get Project
```bash GET /todoist/rest/v2/projects/{id} ```
#### Create Project
```bash POST /todoist/rest/v2/projects Content-Type: application/json
{ "name": "My Project", "color": "blue", "is_favorite": true, "view_style": "board" } ```
**Parameters:** - `name` (必需) - 项目名称 - `parent_id` - 用于嵌套的父项目 ID - `color` - 项目颜色 (例如 "red", "blue", "green") - `is_favorite` - 布尔值收藏状态 - `view_style` - "list" 或 "board" (默认: list)
**Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'name': 'My New Project', 'color': 'blue'}).encode() req = urllib.request.Request('https://gateway.maton.ai/todoist/rest/v2/projects', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Update Project
```bash POST /todoist/rest/v2/projects/{id} Content-Type: application/json
{ "name": "Updated Project Name", "color": "red" } ```
#### Delete Project
```bash DELETE /todoist/rest/v2/projects/{id} ```
成功时返回 204 No Content。
#### Get Project Collaborators
```bash GET /todoist/rest/v2/projects/{id}/collaborators ```
### Tasks
#### List Tasks
```bash GET /todoist/rest/v2/tasks ```
**Query Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `project_id` | string | 按项目筛选 | | `section_id` | string | 按部分筛选 | | `label` | string | 按标签名称筛选 | | `filter` | string | Todoist 筛选表达式 | | `ids` | string | 逗号分隔的任务 ID |
**Response:** ```json [ { "id": "9993408170", "content": "Buy groceries", "description": "", "project_id": "2366834771", "section_id": null, "parent_id": null, "order": 1, "priority": 2, "is_completed": false, "labels": [], "due": { "date": "2026-02-07", "string": "tomorrow", "lang": "en", "is_recurring": false }, "url": "https://app.todoist.com/app/task/9993408170", "comment_count": 0, "created_at": "2026-02-06T20:41:08.449320Z" } ] ```
#### Get Task
```bash GET /todoist/rest/v2/tasks/{id} ```
#### Create Task
```bash POST /todoist/rest/v2/tasks Content-Type: application/json
{ "content": "Buy groceries", "project_id": "2366834771", "priority": 2, "due_string": "tomorrow at 10am", "labels": ["shopping", "errands"] } ```
**Required Fields:** - `content` - 任务内容/标题
**Optional Fields:** - `description` - 任务描述 - `project_id` - 要添加任务到的项目 (默认为收件箱) - `section_id` - 项目内的部分 - `parent_id` - 子任务的父任务 ID - `labels` - 标签名称数组 - `priority` - 1 (普通) 到 4 (紧急) - `due_string` - 自然语言截止日期 ("tomorrow", "next Monday 3pm") - `due_date` - ISO 格式 YYYY-MM-DD - `due_datetime` - 带时区的 RFC3339 格式 - `assignee_id` - 被分配任务的用户 ID - `duration` - 任务持续时间 (整数) - `duration_unit` - "minute" 或 "day"
**Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({ 'content': 'Complete project report', 'priority': 4, 'due_string': 'tomorrow at 5pm', 'labels': ['work', 'urgent'] }).encode() req = urllib.request.Request('https://gateway.maton.ai/todoist/rest/v2/tasks', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Update Task
```bash POST /todoist/rest/v2/tasks/{id} Content-Type: application/json
{ "content": "Updated task content", "priority": 3 } ```
#### Close Task (Complete)
```bash POST /todoist/rest/v2/tasks/{id}/close ```
返回 204 No Content。对于循环任务,这会安排下一次的执行。
#### Reopen Task
```bash POST /todoist/rest/v2/tasks/{id}/reopen ```
返回 204 No Content。
#### Delete Task
```bash DELETE /todoist/rest/v2/tasks/{id} ```
返回 204 No Content。
### Sections
#### List Sections
```bash GET /todoist/rest/v2/sections GET /todoist/rest/v2/sections?project_id={project_id} ```
**Response:** ```json [ { "id": "214670251", "project_id": "2366834771", "order": 1, "name": "To Do" } ] ```
#### Get Section
```bash GET /todoist/rest/v2/sections/{id} ```
#### Create Section
```bash POST /todoist/rest/v2/sections Content-Type: application/json
{ "name": "In Progress", "project_id": "2366834771", "order": 2 } ```
**Required Fields:** - `name` - 部分名称 - `project_id` - 父项目 ID
#### Update Section
```bash POST /todoist/rest/v2/sections/{id} Content-Type: application/json
{ "name": "Updated Section Name" } ```
#### Delete Section
```bash DELETE /todoist/rest/v2/sections/{id} ```
返回 204 No Content。
### Labels
#### List Labels
```bash GET /todoist/rest/v2/labels ```
**Response:** ```json [ { "id": "2182980313", "name": "urgent", "color": "red", "order": 1, "is_favorite": false } ] ```
#### Get Label
```bash GET /todoist/rest/v2/labels/{id} ```
#### Create Label
```bash POST /todoist/rest/v2/labels Content-Type: application/json
{ "name": "work", "color": "blue", "is_favorite": true } ```
**Parameters:** - `name` (必需) - 标签名称 - `color` - 标签颜色 - `order` - 排序顺序 - `is_favorite` - 布尔值收藏状态
#### Update Label
```bash POST /todoist/rest/v2/labels/{id} Content-Type: application/json
{ "name": "updated-label", "color": "green" } ```
#### Delete Label
```bash DELETE /todoist/rest/v2/labels/{id} ```
返回 204 No Content。
### Comments
#### List Comments
```bash GET /todoist/rest/v2/comments?task_id={task_id} GET /todoist/rest/v2/comments?project_id={project_id} ```
**Note:** 需要 `task_id` 或 `project_id` 其中之一。
**Response:** ```json [ { "id": "3966541561", "task_id": "9993408170", "project_id": null, "content": "This is a comment", "posted_at": "2026-02-06T20:41:35.734376Z", "posted_by_id": "57402826" } ] ```
#### Get Comment
```bash GET /todoist/rest/v2/comments/{id} ```
#### Create Comment
```bash POST /todoist/rest/v2/comments Content-Type: application/json
{ "task_id": "9993408170", "content": "Don't forget to check the budget" } ```
**Required Fields:** - `content` - 评论文本 - `task_id` 或 `project_id` - 评论附加的位置
#### Update Comment
```bash POST /todoist/rest/v2/comments/{id} Content-Type: application/json
{ "content": "Updated comment text" } ```
#### Delete Comment
```bash DELETE /todoist/rest/v2/comments/{id} ```
返回 204 No Content。
## Priority Values
| Priority | Meaning | |----------|---------| | 1 | 普通 (默认) | | 2 | 中等 | | 3 | 高 | | 4 | 紧急 |
## Due Date Formats
每个请求仅使用以下格式之一:
- `due_string` - 自然语言:"tomorrow", "next Monday at 3pm", "every week" - `due_date` - 仅日期:"2026-02-15" - `due_datetime` - 完整日期时间:"2026-02-15T14:00:00Z"
## Code Examples
### JavaScript
```javascript // Create a task const response = await fetch('https://gateway.maton.ai/todoist/rest/v2/tasks', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ content: 'Review pull request', priority: 3, due_string: 'today at 5pm' }) }); const task = await response.json(); ```
### Python
```python import os import requests
# Create a task response = requests.post( 'https://gateway.maton.ai/todoist/rest/v2/tasks', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, json={ 'content': 'Review pull request', 'priority': 3, 'due_string': 'today at 5pm' } ) task = response.json() ```
## Notes
- 任务 ID 和项目 ID 是字符串,而不是整数 - 优先级 4 最高 (紧急),优先级 1 为普通 - 每个请求仅使用一种截止日期格式 (due_string, due_date 或 due_datetime) - 完成循环任务会安排下一次的执行 - 收件箱项目无法删除 - 重要:当将 curl 输出通过管道传递给 `jq` 或其他命令时,在某些 shell 环境中,`$MATON_API_KEY` 等环境变量可能无法正确展开
## Error Handling
| Status | Meaning | |--------|---------| | 204 | 成功 (无内容) - 针对 close, reopen, delete 操作 | | 400 | 请求无效或缺少 Todoist 连接 | | 401 | Maton API 密钥无效或缺失 | | 404 | 资源未找到 | | 429 | 速率受限 | | 4xx/5xx | 来自 Todoist API 的透传错误 |
### Troubleshooting: API Key Issues
1. 检查是否已设置 `MATON_API_KEY` 环境变量:
```bash echo $MATON_API_KEY ```
2. 通过列出连接来验证 API 密钥是否有效:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Troubleshooting: Invalid App Name
1. 确保您的 URL 路径以 `todoist` 开头。例如:
- 正确: `https://gateway.maton.ai/todoist/rest/v2/tasks` - 错误: `https://gateway.maton.ai/rest/v2/tasks`
## Resources
- [Todoist REST API v2 Documentation](https://developer.todoist.com/rest/v2) - [Todoist API v1 Documentation](https://developer.todoist.com/api/v1) - [Todoist Filter Syntax](https://todoist.com/help/articles/introduction-to-filters) - [Todoist OAuth Documentation](https://developer.todoist.com/guides/#oauth) - [Maton Community](https://discord.com/invite/dBfFAcefs2) - [Maton Support](mailto:[email protected])