---
title: "TaskPocket API: a REST API for tasks, projects and areas"
description: "The TaskPocket public API: REST over tasks, projects and areas, tokens you issue yourself with read and write scopes, cursor paging, and an OpenAPI document."
canonical: https://taskpocket.io/api/
lastUpdated: 2026-09-30
---
1. [Home](https://taskpocket.io/)
2. API

# A REST API for your tasks, projects and areas

The TaskPocket API is a documented REST interface over your tasks, projects and areas. You issue your own tokens with a read scope, a write scope or both, call JSON endpoints with a bearer header, and every change appears in the apps through the normal sync. It is free on every plan, and an OpenAPI document describes it exactly.

By [Bohdan Stefaniuk](https://taskpocket.io/about/) Last updated 2026-09-30

## What it is for

The API exists so your list is reachable by things that are not this app. The cases it was built around:

- Capture from anywhere. A shortcut, a script or a form that creates a task with one request. The browser extension is built on this API and nothing else.
- Your own reports. Pull the logbook, the overdue list or a project's tasks into a spreadsheet, a dashboard or a weekly email you write yourself.
- Mirroring from another system. Create a task when a ticket is assigned to you, complete it when the ticket closes, and keep the two in step with updatedSince.
- An assistant that speaks REST. Anything that can call an HTTP API can plan your day from it. If the assistant speaks MCP instead, the [MCP server](https://taskpocket.io/mcp/) wraps the same operations with a consent screen and no token to paste.

What it is not: there are no webhooks and no integration catalogue. Polling with updatedSince is the way to notice changes. Compare that with Todoist or TickTick before you depend on it.

## Quick start

1. Create a token In TaskPocket, open Settings → API, name the token, tick Read and Write, and set an expiry if you want one. The secret is shown once; only its hash is stored. It looks like tp_pat_ followed by 43 characters.
2. Check it works GET /me answers with the account id and the scopes the token carries. It is the cheapest way to fail loudly at start-up instead of at the first write. Request curl https://api.taskpocket.io/api/public/v1/me \ -H "Authorization: Bearer tp_pat_your_token" Response { "accountId": "0f7c…", "tokenId": "6a21…", "tokenName": "Weekly report script", "scopes": ["read", "write"] }
3. Create a task Dates are calendar dates in the account's timezone. Notes are Markdown. The response is the task as stored. Request curl -X POST https://api.taskpocket.io/api/public/v1/tasks \ -H "Authorization: Bearer tp_pat_your_token" \ -H "Content-Type: application/json" \ -d '{ "title": "Send the Q3 invoice", "description": "Attach the **signed** timesheet.", "dueDate": "2026-10-03", "reminderTime": "09:30" }'

The [interactive reference](https://api.taskpocket.io/api/public/v1/docs) lets you try every endpoint with your token, and the [OpenAPI document](https://api.taskpocket.io/api/public/v1/openapi.json) is served in every environment, so a generated client is a better idea than a hand-written one.

## Authentication and scopes

Every request carries Authorization: Bearer and a token. A token in a query string is refused on purpose: URLs end up in logs, proxies and browser history. Scopes are independent: write does not imply read. A token without the scope an endpoint needs gets 403; a token that is missing, malformed, revoked or expired gets 401.

*The two token scopes*

| Scope | Grants |
| --- | --- |
| read | List and fetch tasks, projects and areas. |
| write | Create, update, move, complete, cancel, trash, restore and delete them. |

Revoke or delete a token in Settings and it stops working on the next request. Apps you did not write should not hold a token at all: the [OAuth flow the MCP server uses](https://taskpocket.io/mcp/) gives them a short-lived access token through a consent screen, and Settings lists each one as a connected app you can disconnect.

## Conventions

- Base URL. https://api.taskpocket.io/api/public/v1. All paths below are relative to it.
- Dates and times. Calendar dates are YYYY-MM-DD in the account's timezone. A reminder time is HH:mm in the same zone and needs a start date. Timestamps such as updatedAt are ISO 8601 in UTC. Enums are lowercase strings.
- Notes are Markdown. You send Markdown and receive Markdown; the stored HTML the apps render is sanitised on the way in and out. A descriptionHtml field carries the rendered form if you need it.
- Paging. Every list returns items, nextCursor and hasMore. Pass the cursor back as?cursor= until it is null. Cursors are keyset cursors: completing a task mid-page does not skip the next one.?limit= defaults to 50 and caps at 200.
- Updates are merge patches (RFC 7396). Send only the fields you mean to change; send null to clear one. A field the endpoint does not take is a 400 that names it, not a silent no-op. Moving a task between lists is its own operation, POST /tasks/{id}/move, because it repositions the task too.
- Errors share one JSON shape with an errorCode, a message, per-field errors and a requestId to quote in a support request. 404 means not found or not yours, deliberately indistinguishable. 423 means the account is suspended and read-only.
- Limits. 120 requests a minute per token, 600 a minute per address. Titles cap at 1,024 characters, notes at 100,000, checklists at 200 items.

A 400, as every error looks

```
{ "errorType": "validation", "errorCode": "validation_error", "message": "One or more validation errors occurred.", "errors": { "projectId": ["Unknown field(s): projectId. Moving a task goes through POST /tasks/{id}/move."] }, "requestId": "9e9535338712437aac5d6814d700f1ac" }
```

## Tasks

A task lives in exactly one list: the inbox, Someday, or a project (optionally in one of its sections). Today, Upcoming and Anytime are views over those lists, not lists. A task with a start date or a deadline cannot stay in the inbox; it moves to Someday.

*Task endpoints*

| Method | Path | Scope | What it does |
| --- | --- | --- | --- |
| GET | /tasks | read | List a view: inbox, today, upcoming, anytime, someday, logbook, trash or all. Filter by projectId, areaId, status and updatedSince. |
| GET | /tasks/{id} | read | One task, trashed ones included. |
| POST | /tasks | write | Create. Title, Markdown notes, list, project and section, start date, deadline, reminder, repeat rule, checklist. |
| PATCH | /tasks/{id} | write | Merge patch of title, notes, dates, reminder, repeat rule or checklist. Null clears a field. |
| POST | /tasks/{id}/move | write | Change the list, project or section. The task lands at the top of its destination. |
| POST | /tasks/{id}/complete | write | Complete. A repeating task rolls to its next occurrence and returns it. |
| POST | /tasks/{id}/uncomplete | write | Reopen a completed task. |
| POST | /tasks/{id}/cancel | write | Cancel. A repeating task stops repeating. |
| POST | /tasks/{id}/uncancel | write | Reopen a cancelled task. |
| DELETE | /tasks/{id} | write | Move to the trash. Reversible. |
| POST | /tasks/{id}/restore | write | Take a task out of the trash. |

The task object

```
{ "id": "2c9b…", "title": "Send the Q3 invoice", "description": "Attach the **signed** timesheet.", "descriptionHtml": "<p>Attach the <strong>signed</strong> timesheet.</p>", "status": "open", "list": "project", "projectId": "8d1e…", "sectionId": null, "dueDate": "2026-10-03", "deadlineDate": null, "reminderTime": "09:30", "recurrence": { "frequency": "weekly", "interval": 1, "weekdays": ["monday", "friday"], "fromCompletion": false }, "checklist": [ { "id": "…", "title": "Export the hours", "completed": true } ], "inTrash": false, "inLogbook": false, "completedAt": null, "cancelledAt": null, "createdAt": "2026-09-28T07:12:40Z", "updatedAt": "2026-09-30T16:03:11Z" }
```

dueDate is the start date, the day you plan to do the task; it is called When in the app. deadlineDate is the hard date, and it is a Premium field: a free account gets 403 when it sets one. The [page on start dates and deadlines](https://taskpocket.io/features/start-dates-and-deadlines/) explains why the two are kept apart. A repeat rule is daily, weekly, monthly or yearly with named weekdays, never a bitmask, and the [recurring tasks page](https://taskpocket.io/features/recurring-tasks/) covers what the rules can express.

## Projects and areas

A project holds tasks and optional sections. An area groups projects and nothing else: a task is never filed directly in an area. The free plan allows five projects and two areas; the sixth and the third get 403 with a message that says so.

*Project endpoints*

| Method | Path | Scope | What it does |
| --- | --- | --- | --- |
| GET | /projects | read | List projects with their sections. Filter by areaId and status. |
| GET | /projects/{id} | read | One project. |
| GET | /projects/{id}/sections | read | Its sections. |
| GET | /projects/{id}/tasks | read | Its tasks, paged like the task list. |
| POST | /projects | write | Create, with Markdown notes, an area and (on Premium) a deadline. |
| PATCH | /projects/{id} | write | Merge patch of title, notes, areaId and deadlineDate. |
| POST | /projects/{id}/complete | write | Complete. Open tasks are cancelled unless completeChildTasks is true. |
| POST | /projects/{id}/uncomplete | write | Reopen. |
| DELETE | /projects/{id} | write | Moves it to the Trash with its open tasks. Finished tasks stay in the logbook. Restore from the app. |

*Area endpoints*

| Method | Path | Scope | What it does |
| --- | --- | --- | --- |
| GET | /areas | read | List areas. |
| GET | /areas/{id} | read | One area. |
| POST | /areas | write | Create. |
| PATCH | /areas/{id} | write | Rename. |
| DELETE | /areas/{id} | write | Delete. Its projects survive, ungrouped. |

## Plan rules through the API

The API never widens what the plan allows. On the free plan: five projects, two areas, no deadlines, and the logbook view shows the last fourteen days. Reminders, repeats, notes and unlimited tasks are free. Premium lifts the four caps. A suspended account keeps read access and gets 423 on every write, and that rule holds for the API, for MCP and for the apps alike.

## Questions people ask

### Is the API free?

Yes. Tokens, the REST API, the OpenAPI document and the MCP server are on every plan, including free. The plan limits apply through the API exactly as in the app.

### Are there webhooks?

No. Poll a list with updatedSince, which returns tasks changed at or after a UTC timestamp, and page with the cursor. That is deliberate: a webhook is a promise about delivery that a one-person product should not make yet.

### Can I use the API from a browser page?

Yes. The API answers CORS preflight for any origin without credentials, so a page can call it with a bearer header. Keep the token server-side where you can; a token in a public page is a token anyone can read.

### What happens to my integration if a task repeats?

Completing a repeating task returns the next occurrence, on the same id, with a new start date. The completed occurrence appears in the logbook view with its own id. A retry of the same complete call completes the next occurrence, so do not retry it blindly.

### Does the API see the same data as the apps?

Yes. Every endpoint runs through the same service layer as the web app and the iPhone app, and every write enters the same sync feed, so a task created by a script is on your phone within the next sync.

### Is there a client library?

Not an official one. Generate a client from the OpenAPI document in the language you use; it is served from the API host and describes every endpoint, field and status code.

## Sources

1. [RFC 7396, JSON Merge Patch (the update format)](https://www.rfc-editor.org/rfc/rfc7396) checked 2026-09-30
2. [RFC 6750, bearer token usage (why the token travels only in the header)](https://www.rfc-editor.org/rfc/rfc6750) checked 2026-09-30
3. [OpenAPI Specification, the format of the published document](https://spec.openapis.org/oas/latest.html) checked 2026-09-30
4. [Cultured Code, Things does not provide a public API (for the comparison on the answers page)](https://culturedcode.com/things/support/articles/2803573/) checked 2026-08-26

A token takes a minute to make. The free plan has unlimited tasks and needs no card.

## Related reading

- [Connect Claude or ChatGPT to your to-do list with MCP](https://taskpocket.io/mcp/) — TaskPocket hosts an MCP server. Add one URL in Claude or ChatGPT, approve access on a consent screen, and your assistant can read and change your tasks.
- [Does Things 3 have an API?](https://taskpocket.io/answers/does-things-3-have-an-api/) — No public API — Cultured Code say so themselves. What exists instead is four on-device mechanisms, and only two of them can read your tasks back out.
- [Start dates and deadlines — two dates, two questions](https://taskpocket.io/features/start-dates-and-deadlines/) — When you plan to start and when it is actually due are different questions. Here is how the two dates work in TaskPocket, and which apps have both.
- [Recurring tasks that survive real life](https://taskpocket.io/features/recurring-tasks/) — Nth weekday, the last business day, stop after ten, skip one, and repeats counted from the day you finish. What each app can express, with sources.
- [No AI in TaskPocket — and why that is deliberate](https://taskpocket.io/no-ai/) — No assistant, no summariser, no model reading your list. The date parser is a grammar, not an LLM. What that buys you, and what it costs you.
