# Todoist REST API Cheat Sheet
Quick reference for the Todoist REST API (current: `/api/v1/` prefix). The older `/rest/v1/` and `/rest/v2/` endpoints are deprecated.
**Auth token** is available via 1Password (Item ID `f3y34n2gfcgbn2ngsgxfd2wkde` in `Keys for Service Account`).
## Base URL & Auth
```
https://api.todoist.com/api/v1
Authorization: Bearer <token>
Content-Type: application/json
```
## Filter Syntax (For search & tAsk qUeries)
The `filter` parameter supports Todoist's full filter grammar:
| Syntax | Meaning | Example |
|---|---|---|
| `today` | Due today | `filter=today` |
| `tomorrow` | Due tomorrow | |
| `overdue` | Past due | |
| `no due date` | No deadline | |
| `p1` – `p4` | Priority level | `filter=p1` |
| `search: <text>` | Full-text search | `filter=search%3A+rent` |
| `@label` | Has label | `@errand` |
| `#project` | In project | `#Work` |
| `/section` | In section | |
| `due before: YYYY-MM-DD` | Due date range | |
| `&` | AND | `today & p1` |
| `,` | OR | `@errand, @computer` |
## Tasks
### List / Search Tasks
- `GET /api/v1/tasks`
- Query params: `project_id`, `section_id`, `label`, `filter`, `priority`, `limit`
### Create Task
- `POST /api/v1/tasks`
- Body:
- `content` **(required)** — task name
- `description` — notes
- `project_id` — project UUID
- `section_id` — section UUID
- `parent_id` — subtask parent
- `due_string` — natural language: `"every month on the 10th"`, `"tomorrow"`, `"2026-08-15"`, `"next friday"`
- `priority` — 1 (normal) to 4 (urgent)
- `labels` — array of label strings
- `assignee_id` — user ID
- `duration` / `duration_unit` — task duration (`minute`)
### Get / Update / Close / Reopen / Delete
- `GET /api/v1/tasks/{task_id}`
- `POST /api/v1/tasks/{task_id}` — update (same body as create)
- `POST /api/v1/tasks/{task_id}/close` → 204 No Content
- `POST /api/v1/tasks/{task_id}/reopen` → 204 No Content
- `DELETE /api/v1/tasks/{task_id}` → 204 No Content
To **clear a due date**, pass `due_string: "no due date"` or `"none"`. To **clear labels**, pass `labels: []`.
## Projects
- `GET /api/v1/projects` — list all
- `GET /api/v1/projects/{project_id}` — get one
- `POST /api/v1/projects` — create
- `POST /api/v1/projects/{project_id}` — update
- `DELETE /api/v1/projects/{project_id}` → 204
### Body Fields
| Field | Description |
|---|---|
| `name` **(required for create)** | Project name |
| `parent_id` | Parent project ID (sub-project) |
| `color` | `berry_red`, `red`, `orange`, `yellow`, `olive_green`, `lime_green`, `green`, `mint_green`, `teal`, `sky_blue`, `light_blue`, `blue`, `grape`, `violet`, `lavender`, `magenta`, `salmon`, `charcoal`, `grey`, `taupe` |
| `is_favorite` | `true` / `false` |
| `view_style` | `"list"` or `"board"` |
## Sections
- `GET /api/v1/sections?project_id={project_id}` — list in project
- `GET /api/v1/sections/{section_id}` — get one
- `POST /api/v1/sections` — create → requires `name` + `project_id`
- `POST /api/v1/sections/{section_id}` — update (rename)
- `DELETE /api/v1/sections/{section_id}` → 204
## Reminders
- `GET /api/v1/reminders?task_id={task_id}` — list for task
- `POST /api/v1/reminders` — create
- `POST /api/v1/reminders/{reminder_id}` — update
- `DELETE /api/v1/reminders/{reminder_id}` → 204
### Body Fields
| Field | Description |
|---|---|
| `task_id` **(required for create)** | Task UUID |
| `reminder_type` | `"absolute"` or `"relative"` |
| `due` (absolute) | `{ "string": "every 10th", "lang": "en" }` — natural language; date-only unless time is explicitly needed |
| `minute_offset` (relative) | Negative integer, e.g. `-30` for 30 min before due. Only works with non-recurring, timed due dates |
| `notify_uid` | User ID (defaults to authenticated user) |
**Reminders on recurring tasks:** Use `reminder_type: "absolute"` with a `due.string` that specifies recurrence (e.g. `"every 10th"`). Relative reminders are not supported for recurring tasks.
## Comments
- `GET /api/v1/comments?task_id={task_id}` or `?project_id={project_id}`
- `POST /api/v1/comments` — `content` + `task_id` or `project_id`
- `GET /api/v1/comments/{comment_id}`
- `POST /api/v1/comments/{comment_id}` — update
- `DELETE /api/v1/comments/{comment_id}` → 204
## Labels
- `GET /api/v1/labels` — list all
- `POST /api/v1/labels` — create: `name` **(required)**, `color`, `is_favorite`
- `GET /api/v1/labels/{label_id}`
- `POST /api/v1/labels/{label_id}` — update
- `DELETE /api/v1/labels/{label_id}` → 204
## Pi Extension
All of the above is wrapped in a Pi extension at `~/.pi/agent/extensions/todoist/index.ts`. See the [[../Skills/Todoist Extension|Todoist skill]] for tool-level documentation. Key design notes:
- **Token resolution:** `.token` file → `TODOIST_API_TOKEN` env var → 1Password CLI
- **Cache:** projects/sections cached for 2 min; auto-invalidated on mutations
- **IDs:** all tools accept raw UUIDs or Todoist URLs (auto-extracted)
- **Project/section lookup:** by name, case-insensitive
## Known Project IDs
| Project | ID |
| ------------------------- | ------------------ |
| Inbox | `6CrfrQ2XjMh72FjF` |
| Work | `6CrfrQ2cFH437jH9` |
| Personal | `6CrfrQ2cCGCxw3qX` |
| 💵 Bills | `6CrfrQ2cG7rwRJXG` |
| 🐶 Mishti | `6c7F7qXFj8rRQcm4` |
| 🇨🇦 Canadian Citizenship | `6cw7m48r4XpXMw2J` |
| 🍽️ Dining Buddy | `6fmV54mjXrPw4wGW` |
| 💡 Ideas | `6cwCg2GrCmqVj4jJ` |
| AgileCode Studio | `6Ph7v3H2vXrC9Xvx` |
| JCPF Website | `6fm7r5wcv54Ph5qm` |
Run `todoist_list_projects` in Pi for the complete up-to-date list.
## See Also
- [Personal Todoist API docs](file:///Users/shayon/DevProjects/~meta/docs/apis/todoist/todoist-api.md) — deeper API reference
- [Todoist NLP syntax cheat sheet](file:///Users/shayon/DevProjects/~meta/docs/apis/todoist/todoist-nlp-syntax-cheatsheet.md) — natural-language date parsing
- [Official Todoist API docs](https://developer.todoist.com/)