# 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/)