init.Tasks openapi.json inittasks.com

18 routes

/todos

18 routes.

The to-dos themselves. A to-do is scheduled by whenDate (with an optional start whenTime, a length durationMin and up to 5 reminders), due by deadline, and those are different: a deadline alone does not put it on a day. A to-do can hold a checklist of subtasks.

GET /v1/todos

List to-dos

In (sortKey, id) order. Trashed to-dos are excluded unless ?include_trashed=true. Headings: ?heading_id= keeps the to-dos under one heading (null = under none), and ?parent_id=<project>&group_by=heading returns the project’s to-dos in PAGE order (no heading first, then each heading’s, in heading order) with the project’s headings alongside, the way the apps draw the project page. headings (their names and open counts) is included only when the credential also holds containers:read; without it the to-dos still come in page order, each with its headingId. The cursor follows the heading order at the time of the request, so reordering headings between page requests can skip or repeat rows: page through quickly, or start over after a reorder.

Scopes: todos:read

Query

parameter type notes
limit integer optional min 1, max 200
cursor string optional max 4096 chars
updated_since string (RFC 3339) optional max 24 chars. An RFC 3339 instant, e.g. 2026-09-16T08:30:00.000Z.
parent_id string optional max 64 chars
status open, someday, done optional
tag string or array of string optional max 64 chars, min 1
when_from string (yyyy-MM-dd) optional max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
when_to string (yyyy-MM-dd) optional max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
deadline_from string (yyyy-MM-dd) optional max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
deadline_to string (yyyy-MM-dd) optional max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
include_trashed true, false optional
group_by heading optional heading: return the project’s to-dos in PAGE order (no heading first, then each heading’s, in heading order) and add the headings array. Needs parent_id. groupBy is accepted as an alias.
groupBy heading optional Alias of group_by.
heading_id string optional max 64 chars. Only the to-dos under this heading, or the literal null for those under none.

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * account_too_large * validation_failed * rate_limited * internal

POST /v1/todos

Create a to-do (unknown tags are created)

Headings: headingId puts the new to-do under one of its project’s headings; it must be a heading of parentId. Scheduling: whenTime (a start, HH:mm), durationMin (5 to 1440) and reminders (at most 5, each { "before": minutes } or { "at": "yyyy-MM-ddTHH:mm" }); a start with no whenDate dates the to-do today, as the apps do. subtasks creates the checklist. status: "someday" creates it parked, unless it also has a whenDate, a deadline, a recurrenceRule or a whenTime: a dated to-do is not parked, so it is created open. reminderTime and reminders cannot be sent together.

Scopes: todos:write Idempotent. Send Idempotency-Key and a retry replays the first answer instead of writing twice.

Request body

field type notes
title string required max 512 chars, min 1
parentId string optional or null, max 64 chars
headingId string optional or null, max 64 chars. A heading of the to-do’s project (/headings), or null for none. It must belong to the to-do’s parentId: a heading of another project, or a heading on a to-do with no project, is validation_failed at /headingId.
subtitle string optional or null, max 512 chars
description string optional or null, max 100000 chars
tags array of string optional max 64 items
whenDate string (yyyy-MM-dd) optional or null, max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
deadline string (yyyy-MM-dd) optional or null, max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
status open, someday, done optional
priority low, medium, high optional or null
colorHex string optional or null, 6-digit hex, with or without the #, max 16 chars. A 6-digit hex colour, with or without the leading #: #3A7BD5 or 3A7BD5. Three-digit shorthand is refused.
colorStyle text, fill optional or null. Stored for compatibility. The apps draw a to-do’s colour as a highlight behind the row (fill) whatever this says. Omit it: a colorHex set without a style is written as fill, and clearing colorHex clears it. An explicit text is still stored.
reminderTime string (yyyy-MM-ddTHH:mm) optional or null, max 16 chars. A LOCAL-NAIVE instant, yyyy-MM-ddTHH:mm: 24-hour, no seconds, no offset, no Z. It means that wall-clock time on the device that fires the reminder, so travelling never shifts it.
recurrenceRule string optional or null, max 512 chars. The recurrence rule, as JSON: {"freq":"weekly","interval":1,"byday":[1,4]}. Validated by the same engine the apps run. Setting one clears deadline and anchors the series on whenDate; with no whenDate the rule's first day from today is stamped as both (today in afterCompletion mode). A rule whose until falls before that first day is refused here. Given to a parked to-do, the rule dates it the same way and takes it out of someday (status becomes open), so it lists on planned. null clears the rule and its anchor.
sorted boolean optional Mark the to-do as sorted with no project (the "no project" answer). Only true is accepted: nothing clears it. A parent, a date or someday sort a to-do on their own.
id string (UPPERCASE UUID) optional max 64 chars. An uppercase UUID, all 36 characters, hex digits in capitals: 8E4F2A1B-7C3D-4E5F-9A0B-1C2D3E4F5A6B. Supplying one is how a create is made idempotent; a repeat is 409 duplicate_id. Lower case is refused, and so is a short id.
whenTime string optional or null, HH:mm, 24-hour. The start time on whenDate. On a to-do with no date (and no whenDate in this request) it dates the to-do TODAY (?today= or the server day), as the apps do. null removes the time: the start AND durationMin go, and every before reminder becomes a fixed at reminder at its old moment, so nothing the user set vanishes.
durationMin integer optional or null, min 5, max 1440. The length in minutes, 5 to 1440. It may exist without a start (it is the block’s length once the to-do gets one). null clears it.
reminders array of object optional or null, max 5 items. The WHOLE reminder list (at most 5), replacing the current one; null or [] clears it. Each is { "before": minutes } (needs a start) or { "at": "yyyy-MM-ddTHH:mm" }. Two that ring at the same moment are refused. reminderTime becomes the earliest of them. Do not send reminderTime in the same request.
reminders[].before integer optional min 0, max 525600. Minutes before the start: 0 = at the start, 15, 60, 1440 = a day, 10080 = a week. Needs a start time (whenTime).
reminders[].at string (yyyy-MM-ddTHH:mm) optional max 16 chars. A fixed local moment, yyyy-MM-ddTHH:mm (24-hour, no seconds, no offset).
subtasks array of object optional or null, max 50 items. The WHOLE subtask list, in order (at most 50; together at most 10,000 bytes), replacing the current one. null or [] clears it. To change one subtask, use /todos/{id}/subtasks/{subtaskId}.
subtasks[].id string optional max 64 chars. Keep an existing subtask’s id to keep its identity; omit it on a new one (the server issues a lowercase UUID).
subtasks[].title string required max 480 chars, min 1. One line, at most 120 characters (counted as characters, not bytes); trimmed.
subtasks[].done boolean optional Ticked. Default false.

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * conflict * duplicate_id * payload_too_large * unsupported_media_type * account_too_large * validation_failed * rate_limited * internal

GET /v1/todos/{id}

One to-do

Scopes: todos:read

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * account_too_large * rate_limited * internal

PATCH /v1/todos/{id}

Change a to-do (not parentId or status, use the actions for those)

parentId and status are refused here: they are transitions with side effects, not field assignments. Completing a recurring to-do spawns the next occurrence, and parking one strips its dates. A parked to-do given a whenDate, a deadline, a recurrenceRule or a whenTime here comes back open in place, as in the apps, and lists on planned (and on today when the date is today): a recurring one restarts its series on its new date, a rule with no date stamps its first day, a time with no date dates it today. Clearing a date leaves it parked. A recurrenceRule clears deadline and anchors on whenDate, stamping the rule’s first day when there is none (see recurrence on devs.inittasks.com). Send null to clear any nullable field. headingId moves the to-do under another heading of its OWN project (or out of any, with null); to move it to another project use /move, which takes headingId too. Scheduling follows the apps: changing whenDate moves every before reminder with it; clearing it drops the start and every before reminder (fixed ones and the length stay); whenTime: null removes the start and the length and turns each before reminder into a fixed one at its old moment; reminders replaces the whole list; a lone reminderTime on a to-do that has a list replaces only the earliest reminder. subtasks replaces the whole checklist (keep an item’s id to keep it); for one subtask use /todos/{id}/subtasks/{subtaskId}.

Scopes: todos:write

Request body

field type notes
title string optional max 512 chars, min 1
headingId string optional or null, which clears it, max 64 chars. A heading of the to-do’s project (/headings), or null for none. It must belong to the to-do’s parentId: a heading of another project, or a heading on a to-do with no project, is validation_failed at /headingId.
subtitle string optional or null, which clears it, max 512 chars
description string optional or null, which clears it, max 100000 chars
tags array of string optional or null, which clears it, max 64 items
whenDate string (yyyy-MM-dd) optional or null, which clears it, max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
deadline string (yyyy-MM-dd) optional or null, which clears it, max 10 chars. A calendar date, yyyy-MM-dd. No time and no zone, so it is the same day everywhere.
priority low, medium, high optional or null, which clears it
colorHex string optional or null, which clears it, 6-digit hex, with or without the #, max 16 chars. A 6-digit hex colour, with or without the leading #: #3A7BD5 or 3A7BD5. Three-digit shorthand is refused.
colorStyle text, fill optional or null, which clears it. Stored for compatibility. The apps draw a to-do’s colour as a highlight behind the row (fill) whatever this says. Omit it: a colorHex set without a style is written as fill, and clearing colorHex clears it. An explicit text is still stored.
reminderTime string (yyyy-MM-ddTHH:mm) optional or null, which clears it, max 16 chars. A LOCAL-NAIVE instant, yyyy-MM-ddTHH:mm: 24-hour, no seconds, no offset, no Z. It means that wall-clock time on the device that fires the reminder, so travelling never shifts it.
recurrenceRule string optional or null, which clears it, max 512 chars. The recurrence rule, as JSON: {"freq":"weekly","interval":1,"byday":[1,4]}. Validated by the same engine the apps run. Setting one clears deadline and anchors the series on whenDate; with no whenDate the rule's first day from today is stamped as both (today in afterCompletion mode). A rule whose until falls before that first day is refused here. Given to a parked to-do, the rule dates it the same way and takes it out of someday (status becomes open), so it lists on planned. null clears the rule and its anchor.
sorted boolean optional Mark the to-do as sorted with no project (the "no project" answer). Only true is accepted: nothing clears it. A parent, a date or someday sort a to-do on their own.
whenTime string optional or null, which clears it, HH:mm, 24-hour. The start time on whenDate. On a to-do with no date (and no whenDate in this request) it dates the to-do TODAY (?today= or the server day), as the apps do. null removes the time: the start AND durationMin go, and every before reminder becomes a fixed at reminder at its old moment, so nothing the user set vanishes.
durationMin integer optional or null, which clears it, min 5, max 1440. The length in minutes, 5 to 1440. It may exist without a start (it is the block’s length once the to-do gets one). null clears it.
reminders array of object optional or null, which clears it, max 5 items. The WHOLE reminder list (at most 5), replacing the current one; null or [] clears it. Each is { "before": minutes } (needs a start) or { "at": "yyyy-MM-ddTHH:mm" }. Two that ring at the same moment are refused. reminderTime becomes the earliest of them. Do not send reminderTime in the same request.
reminders[].before integer optional min 0, max 525600. Minutes before the start: 0 = at the start, 15, 60, 1440 = a day, 10080 = a week. Needs a start time (whenTime).
reminders[].at string (yyyy-MM-ddTHH:mm) optional max 16 chars. A fixed local moment, yyyy-MM-ddTHH:mm (24-hour, no seconds, no offset).
subtasks array of object optional or null, which clears it, max 50 items. The WHOLE subtask list, in order (at most 50; together at most 10,000 bytes), replacing the current one. null or [] clears it. To change one subtask, use /todos/{id}/subtasks/{subtaskId}.
subtasks[].id string optional max 64 chars. Keep an existing subtask’s id to keep its identity; omit it on a new one (the server issues a lowercase UUID).
subtasks[].title string required max 480 chars, min 1. One line, at most 120 characters (counted as characters, not bytes); trimmed.
subtasks[].done boolean optional Ticked. Default false.

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * validation_failed * rate_limited * internal

POST /v1/todos/{id}/complete

Complete (spawns the next occurrence when recurring)

Sets status: "done" and stamps completedAt. ⚠ A RECURRING to-do with a whenDate does not become done itself: the completion is recorded as a NEW done row (a copy of this one with no rule, which the completed view lists), and THIS row stays open and moves to its next occurrence (whenDate advanced, a count decremented). The response is this row, so for a recurring to-do it is the NEXT occurrence, still open. The series’ last occurrence (its count or until used up) completes in place like a plain to-do.

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * rate_limited * internal

POST /v1/todos/{id}/uncomplete

Un-complete

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * rate_limited * internal

POST /v1/todos/{id}/someday

Park

Parking a to-do STRIPS its whenDate and deadline, because someday is timeline-free. A recurring to-do loses its dates too and keeps its rule, dormant: /move un-parks it with a new first date, and a PATCH with a whenDate un-parks it on that date. Any PATCH that gives a parked to-do a date, a deadline, a repeat rule or a start time takes it out of someday.

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * rate_limited * internal

POST /v1/todos/{id}/anytime

Detach and unschedule

No project, no whenDate, status: "open" (a done to-do re-opens and loses completedAt); deadline and tags stay. A parked RECURRING to-do comes back undated with its rule, as in the apps: with no date it has nothing to roll from, so completing it finishes it. Give it a whenDate and it rolls again.

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * rate_limited * internal

POST /v1/todos/{id}/move

Re-parent and reorder

after/before name a to-do or a note in the destination list. Headings: headingId (a heading of the destination) files it under that heading; omitted, a move to ANOTHER container clears the heading (a heading belongs to one project) and a reorder in place keeps it.

Scopes: todos:write

Request body

field type notes
parentId string required or null, max 64 chars
headingId string optional or null, max 64 chars. A heading of the DESTINATION parentId, or null for none. Omitted: a move to another container clears the heading (a heading belongs to one project); a reorder in the same container keeps it.
after string optional max 64 chars
before string optional max 64 chars

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * validation_failed * rate_limited * internal

POST /v1/todos/{id}/trash

Trash a to-do

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * rate_limited * internal

POST /v1/todos/{id}/restore

Restore a to-do

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * rate_limited * internal

DELETE /v1/todos/{id}

Delete permanently

Irreversible. Its attachments are released: one that is also somewhere else stays there, and one with no other place is deleted with its stored file. ⚠ It works on ANY to-do, trashed or not, and asks for no confirmation: trash it first (/trash) if you want a way back.

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * account_too_large * rate_limited * internal

GET /v1/todos/{id}/notes

The notes linked to a to-do

Live notes linked to the to-do, pinned first, then editedAt descending (the to-do page’s notes section).

Scopes: notes:read, todos:read

Query

parameter type notes
limit integer optional min 1, max 200
cursor string optional max 4096 chars

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * account_too_large * validation_failed * rate_limited * internal

POST /v1/todos/{id}/duplicate

Duplicate a to-do

The apps’ duplicate: a new OPEN to-do right after this one, in the same project and heading, with every content field copied (dates, time, length, reminders, tags, priority, colour, repeat rule). Its subtasks are copied UNTICKED with new ids. A done to-do’s copy is open; a trashed to-do can be duplicated and its copy is live. The body is optional: { "id": … } chooses the new id.

Scopes: todos:write Idempotent. Send Idempotency-Key and a retry replays the first answer instead of writing twice.

Request body

field type notes
id string (UPPERCASE UUID) optional max 64 chars. An uppercase UUID, all 36 characters, hex digits in capitals: 8E4F2A1B-7C3D-4E5F-9A0B-1C2D3E4F5A6B. Supplying one is how a create is made idempotent; a repeat is 409 duplicate_id. Lower case is refused, and so is a short id.

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * conflict * duplicate_id * payload_too_large * unsupported_media_type * account_too_large * validation_failed * rate_limited * internal

POST /v1/todos/{id}/subtasks

Add a subtask

At the end of the checklist, or right after after. At most 50 per to-do; a title is one line of at most 120 characters.

Scopes: todos:write Idempotent. Send Idempotency-Key and a retry replays the first answer instead of writing twice.

Request body

field type notes
title string required max 480 chars, min 1. One line, at most 120 characters; trimmed.
after string optional max 64 chars. Insert right after this subtask; omitted = at the end.

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * conflict * payload_too_large * unsupported_media_type * account_too_large * validation_failed * rate_limited * internal

PATCH /v1/todos/{id}/subtasks/{subtaskId}

Rename, tick or move a subtask

Ticking the last open subtask does not complete the to-do. after moves it (an id, or null for first).

Scopes: todos:write

Request body

field type notes
title string optional max 480 chars, min 1. The new title (one line, at most 120 characters).
done boolean optional Tick or untick it.
after string optional or null, which clears it, max 64 chars. Move it: right after this subtask, or null for first.

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * payload_too_large * unsupported_media_type * account_too_large * validation_failed * rate_limited * internal

DELETE /v1/todos/{id}/subtasks/{subtaskId}

Delete a subtask

Scopes: todos:write

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * account_too_large * rate_limited * internal

POST /v1/todos/{id}/subtasks/{subtaskId}/promote

Make a subtask a to-do

The apps’ make task: a new open to-do titled as the subtask, right after its parent, in the same project, heading and day; the subtask leaves the list.

Scopes: todos:write Idempotent. Send Idempotency-Key and a retry replays the first answer instead of writing twice.

Response

Errors: grant_expired * grant_revoked * unauthorized * forbidden_scope * not_found * conflict * payload_too_large * unsupported_media_type * account_too_large * rate_limited * internal