home / skills / intellectronica / agent-skills / todoist-api
This skill guides you to read, create, update, or delete Todoist data via REST v2 using curl and jq with safe confirmations.
npx playbooks add skill intellectronica/agent-skills --skill todoist-apiReview the files below or copy the command above to add this skill to your agents.
---
name: todoist-api
description: This skill provides instructions for interacting with the Todoist REST API v2 using curl and jq. It covers authentication, CRUD operations for tasks/projects/sections/labels/comments, pagination handling, and requires confirmation before destructive actions. Use this skill when the user wants to read, create, update, or delete Todoist data via the API.
---
# Todoist API Skill
This skill provides procedural guidance for working with the Todoist REST API v2 via curl and jq.
## Authentication
### Token Resolution
Resolve the API token in this order:
1. Check environment variable `TODOIST_API_TOKEN`
2. Check if the user has provided a token in the conversation context
3. If neither is available, use AskUserQuestion (or similar tool) to request the token from the user
To verify a token exists in the environment:
```bash
[ -n "$TODOIST_API_TOKEN" ] && echo "Token available" || echo "Token not set"
```
### Making Authenticated Requests
All requests require the Authorization header with Bearer token:
```bash
curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/ENDPOINT"
```
For POST requests with JSON body, include Content-Type:
```bash
curl -s -X POST \
-H "Authorization: Bearer $TODOIST_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"key": "value"}' \
"https://api.todoist.com/rest/v2/ENDPOINT"
```
## Base URL
All REST API v2 endpoints use: `https://api.todoist.com/rest/v2/`
## Confirmation Requirement
**Before executing any destructive action (DELETE, close, update, archive), always ask the user for confirmation using AskUserQuestion or similar tool.** A single confirmation suffices for a logical group of related actions.
Destructive actions include:
- Deleting tasks, projects, sections, labels, or comments
- Closing (completing) tasks
- Updating existing resources
- Archiving projects
Read-only operations (GET requests) do not require confirmation.
## Endpoints Reference
### Tasks
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List active tasks | GET | `/tasks` |
| Get task | GET | `/tasks/{id}` |
| Create task | POST | `/tasks` |
| Update task | POST | `/tasks/{id}` |
| Close task | POST | `/tasks/{id}/close` |
| Reopen task | POST | `/tasks/{id}/reopen` |
| Delete task | DELETE | `/tasks/{id}` |
**Task filters** (query params for GET /tasks):
- `project_id` - Filter by project
- `section_id` - Filter by section
- `label` - Filter by label name
- `filter` - Todoist filter query (e.g., "today", "overdue")
**Task creation/update fields:**
- `content` (required for creation) - Task text
- `description` - Additional details
- `project_id`, `section_id`, `parent_id` - Organisation
- `priority` - 1 (normal) to 4 (urgent)
- `due_string` - Natural language ("tomorrow", "every monday")
- `due_date` - YYYY-MM-DD format
- `due_datetime` - RFC3339 format
- `labels` - Array of label names
- `assignee_id` - For shared projects
- `duration`, `duration_unit` - Estimated time
### Projects
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List projects | GET | `/projects` |
| Get project | GET | `/projects/{id}` |
| Create project | POST | `/projects` |
| Update project | POST | `/projects/{id}` |
| Archive project | POST | `/projects/{id}/archive` |
| Unarchive project | POST | `/projects/{id}/unarchive` |
| Delete project | DELETE | `/projects/{id}` |
| List collaborators | GET | `/projects/{id}/collaborators` |
**Project fields:**
- `name` (required for creation)
- `parent_id` - For nested projects
- `color` - Colour name (e.g., "berry_red", "blue")
- `is_favorite` - Boolean
- `view_style` - "list" or "board"
### Sections
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List sections | GET | `/sections` |
| Get section | GET | `/sections/{id}` |
| Create section | POST | `/sections` |
| Update section | POST | `/sections/{id}` |
| Delete section | DELETE | `/sections/{id}` |
**Section filters** (query params for GET):
- `project_id` - Filter by project (recommended)
**Section fields:**
- `name` (required)
- `project_id` (required for creation)
- `order` - Position within project
### Labels
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List personal labels | GET | `/labels` |
| Get label | GET | `/labels/{id}` |
| Create label | POST | `/labels` |
| Update label | POST | `/labels/{id}` |
| Delete label | DELETE | `/labels/{id}` |
| List shared labels | GET | `/shared_labels` |
| Rename shared label | POST | `/shared_labels/{name}/rename` |
| Remove shared label | DELETE | `/shared_labels/{name}` |
**Label fields:**
- `name` (required)
- `color` - Colour name
- `order` - Display order
- `is_favorite` - Boolean
### Comments
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List comments | GET | `/comments` |
| Get comment | GET | `/comments/{id}` |
| Create comment | POST | `/comments` |
| Update comment | POST | `/comments/{id}` |
| Delete comment | DELETE | `/comments/{id}` |
**Comment filters** (query params for GET):
- `task_id` - Comments on a task (required if no project_id)
- `project_id` - Comments on a project (required if no task_id)
**Comment fields:**
- `content` (required) - Markdown supported
- `task_id` or `project_id` (one required for creation)
## Pagination
Some endpoints return paginated results. Handle pagination by checking for a `next_cursor` field in the response and making subsequent requests with the `cursor` parameter.
### Pagination Pattern
```bash
# Initial request
response=$(curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/ENDPOINT")
# Check for more results
next_cursor=$(echo "$response" | jq -r '.next_cursor // empty')
# If cursor exists, fetch next page
if [ -n "$next_cursor" ]; then
curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/ENDPOINT?cursor=$next_cursor"
fi
```
### Complete Data Retrieval Loop
To retrieve all data when pagination is involved:
```bash
all_results="[]"
cursor=""
while true; do
if [ -z "$cursor" ]; then
response=$(curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/ENDPOINT")
else
response=$(curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/ENDPOINT?cursor=$cursor")
fi
# Merge results (adjust .items or root array based on endpoint)
items=$(echo "$response" | jq '.items // .')
all_results=$(echo "$all_results $items" | jq -s 'add')
# Check for next page
cursor=$(echo "$response" | jq -r '.next_cursor // empty')
has_more=$(echo "$response" | jq -r '.has_more // false')
if [ "$has_more" != "true" ] || [ -z "$cursor" ]; then
break
fi
done
echo "$all_results"
```
## Common Patterns
### List All Tasks in a Project
```bash
curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/tasks?project_id=PROJECT_ID" | jq '.'
```
### Create a Task with Due Date
```bash
curl -s -X POST \
-H "Authorization: Bearer $TODOIST_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Task name", "due_string": "tomorrow", "priority": 2}' \
"https://api.todoist.com/rest/v2/tasks"
```
### Complete a Task
```bash
curl -s -X POST \
-H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/tasks/TASK_ID/close"
```
### Get Today's Tasks
```bash
curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/tasks?filter=today" | jq '.'
```
### Get Overdue Tasks
```bash
curl -s -H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/tasks?filter=overdue" | jq '.'
```
## Error Handling
Check HTTP status codes and handle errors appropriately:
- `200` - Success with response body
- `204` - Success, no content
- `400` - Bad request (check parameters)
- `401` - Authentication failed (check token)
- `403` - Forbidden (insufficient permissions)
- `404` - Resource not found
- `429` - Rate limited (wait and retry)
- `5xx` - Server error (safe to retry)
### Example with Error Handling
```bash
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: Bearer $TODOIST_API_TOKEN" \
"https://api.todoist.com/rest/v2/tasks")
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
echo "$body" | jq '.'
else
echo "Error: HTTP $http_code"
echo "$body"
fi
```
## Idempotency
For safe retries on write operations, include the `X-Request-Id` header (max 36 characters):
```bash
curl -s -X POST \
-H "Authorization: Bearer $TODOIST_API_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Request-Id: $(uuidgen)" \
-d '{"content": "New task"}' \
"https://api.todoist.com/rest/v2/tasks"
```
Duplicate requests with the same X-Request-Id are discarded by the server.
## Completed Tasks
The REST API v2 `/tasks` endpoint returns only active tasks. For completed tasks, use the Sync API or the newer unified API v1 endpoints:
- `GET /tasks/completed/by_completion_date` - Retrieve by completion date
- `GET /tasks/completed/by_due_date` - Retrieve by original due date
See `references/completed-tasks.md` for details on retrieving completed task history.
## Additional Reference
For detailed information on specific topics, consult:
- `references/completed-tasks.md` - Retrieving completed task history
- `references/filters.md` - Todoist filter query syntax
## Workflow Summary
1. **Resolve token** - Environment, context, or ask user
2. **Verify authentication** - Test with a simple GET request
3. **Read operations** - Execute directly without confirmation
4. **Write operations** - Ask for confirmation before executing
5. **Handle pagination** - Loop with cursor for complete data
6. **Parse responses** - Use jq to extract and format data
This skill provides practical, curl-and-jq based instructions for interacting with the Todoist REST API v2. It covers authentication, CRUD for tasks/projects/sections/labels/comments, pagination handling, error checks, and a required confirmation step before destructive actions. Use it to script or automate Todoist operations from a shell environment.
The skill explains how to resolve a Todoist API token from the environment, conversation context, or by prompting the user, and how to include it as a Bearer token in curl requests. It documents endpoints and payload fields for tasks, projects, sections, labels, and comments, plus patterns for pagination loops, idempotency with X-Request-Id, and standard error handling. Destructive operations require explicit user confirmation before executing.
How does the skill get the API token?
It checks TODOIST_API_TOKEN in the environment, then the conversation context, and prompts the user if neither is available.
Do read-only requests require confirmation?
No. GET requests do not require confirmation; only destructive or modifying actions require explicit confirmation.