API and command line
Add, list and complete tasks from a terminal or a script. Same capture syntax, same search, same automations as the app.
Get an API key
- Open the app and sign in (keys belong to an account; tasks reach the API through sync).
- Press Ctrl K (⌘ K on a Mac), choose Account and sync, open API keys, name the key and choose Create key.
- Copy it. It starts with
ptd_and is shown only once.
A key can read and change all your tasks: keep it like a password. Revoke it in the same place when you no longer need it; it stops working at once. You can have up to 10.
The pt command-line tool
One file, no installation steps beyond copying it. It needs Node.js 18 or newer.
macOS and Linux
mkdir -p ~/.local/bin
curl -fsSL https://ptd.pi3.in/cli/pt.js -o ~/.local/bin/pt
chmod +x ~/.local/bin/pt
pt login # paste your keyIf pt is not found, add ~/.local/bin to your PATH, or run it as node ~/.local/bin/pt.
Windows (PowerShell)
Invoke-WebRequest https://ptd.pi3.in/cli/pt.js -OutFile $HOME\pt.js
node $HOME\pt.js loginThen, everywhere:
pt add "Fix checkout bug @rahul #payments !P0 due:tomorrow ~2h"
pt add "Fix checkout bug" --project payments --priority P0 --due tomorrow
pt today # also: inbox, next, upcoming, waiting, all
pt list --priority P0 --due today
pt list project:payments
pt search "#payments due:overdue -is:blocked"
pt done 3f9a2c # the ref shown in every list
pt edit 3f9a2c --due friday --priority P1
pt show 3f9a2c
pt status
pt helpAdd --json to any command for machine-readable output. The key is stored in ~/.config/powertodo/cli.json (Windows: %APPDATA%\powertodo\cli.json), readable only by you; or set PTD_API_KEY instead.
The API
Base address https://ptd.pi3.in/api/v1. JSON in and out. Every request needs your key:
curl https://ptd.pi3.in/api/v1/tasks?view=today \
-H "Authorization: Bearer ptd_…" \
-H "X-PowerTodo-Today: 2026-10-15"X-PowerTodo-Today is optional: your local date, so due:tomorrow means your tomorrow (without it, the server uses the date in UTC).
| Request | Does |
|---|---|
GET /api/v1 | Checks the key; counts for today, overdue, inbox, next, waiting, open. |
GET /api/v1/tasks?view=today | Tasks in a view: inbox, today, upcoming, next, waiting, all, project:<name>, area:<name>, person:<name>, saved:<name>. |
GET /api/v1/tasks?q=… | Tasks matching a search, in the app’s search language. Add closed=1 for completed tasks, limit=n to cap. |
POST /api/v1/tasks | Creates a task from a capture line: { "line": "…", "parent": "<id>" }. |
GET /api/v1/tasks/<id> | One task and its subtasks. |
PATCH /api/v1/tasks/<id> | Changes fields; { "status": "done" } completes it. |
DELETE /api/v1/tasks/<id> | Deletes the task and its subtasks. |
POST /api/v1/tasks/bulk | Up to 500 tasks by "ids" or "q", with "set" (fields) or "delete": true. |
GET /api/v1/projects | Projects with open counts. Also /areas, /people, /views (saved views) and /rules (automations). |
<id> is a task’s id or any unique start of it of 4 characters or more, such as the 6-character ref in every answer.
Create a task:
curl -X POST https://ptd.pi3.in/api/v1/tasks \
-H "Authorization: Bearer ptd_…" -H "Content-Type: application/json" \
-d '{"line": "Review contract @priya #legal !P1 due:friday"}'Move every overdue payments task to Friday:
curl -X POST https://ptd.pi3.in/api/v1/tasks/bulk \
-H "Authorization: Bearer ptd_…" -H "Content-Type: application/json" \
-d '{"q": "#payments due:overdue", "set": {"due": "friday"}}'Changes made through the API sync to your devices like any other change, and your automations run on them (the answer’s notices says which).
Task fields
Answers describe a task with: id, ref, title, status (inbox, next, active, waiting, scheduled, someday, done, cancelled), priority (P0–P3 or null), due, start, expected (ISO dates), project, area, assignees, tags, estimateMinutes, notes, parent, dependsOn, blocked, repeat, subtasks (total and open), line (the task as one capture line) and timestamps.
PATCH and bulk set accept: title, notes, status, priority, due, start, expected (ISO dates or words such as friday, next-week, in 3 days), project, area, assignees, tags, estimate (minutes or "1h30m"), repeat, and line to replace everything a capture line holds. null clears a field. Unknown fields are refused, not ignored.
Errors and limits
Errors answer { "error": "…" } with a message that says what to do: 400 a field could not be read, 401 missing or revoked key, 404 no such task, 409 an id that matches several tasks, 502/503 the database could not be reached. Up to 500 tasks per bulk request and 1000 per list. Each request reads your tasks fresh, so changes from your devices appear once they have synced.