where a to-do lives, how it leaves the inbox, and what each count means
Lists, sorting and areas
A to-do answers two questions. When will it be done: today, a day, anytime, or someday. Where does it belong: an area, a project, a subproject, or no project. The lists are built from those two answers, and every open to-do is in exactly one of them.
The lists, and which one wins
The server tests each open to-do in this order and puts it in the first list that fits.
| list | an open to-do is here when | view key |
|---|---|---|
| inbox | it is unsorted: no parent, no whenDate, and no answer given yet |
unsortedTodos |
| today: overdue | its deadline is before today |
overdue |
| today: from earlier | its whenDate is before today |
fromEarlier |
| today | its whenDate or its deadline is today |
todayItems |
| planned | its whenDate is after today |
plannedDays, plannedLater |
| anytime | it has no whenDate, and its deadline, if any, is still ahead |
anytime |
Parked to-dos (status: "someday") are in someday, and done ones are in completed.
There is one overlap, on purpose. An unsorted to-do whose deadline has passed is in the inbox and in overdue, because a missed deadline must not hide. It counts in both, and not in the overview.
Planned always carries six day buckets, tomorrow through six days out, even when they are empty. After them, plannedLater lists only the dates that hold something. A deadline never places a to-do in planned: a to-do with a deadline next week and no date is in anytime until the deadline day.
Sorting: leaving the inbox
A to-do created with nothing but a title, tags, a deadline or a reminder is a capture: it waits in the inbox. It leaves with one answer.
- A when answer: a
whenDate, anytime, or someday. - A where answer: an area, a project, a subproject, or no project.
The to-do's sorted field turns true in the same write as the answer, and no API call turns it back. "No project" is a real answer: a to-do with no parent and no date that has been sorted lives in anytime.
| you want | REST | MCP |
|---|---|---|
| create it sorted, no project | POST /v1/todos with "parentId": null, "sorted": true |
create_todo with no_project: true |
| sort an existing one, no project | PATCH /v1/todos/{id} with "sorted": true |
update_todo with no_project: true |
| schedule it | PATCH /v1/todos/{id} with a whenDate |
update_todo with when |
| anytime | PATCH with "whenDate": null, or POST /v1/todos/{id}/anytime |
update_todo with when: null, or move_to_anytime |
| file it | POST /v1/todos/{id}/move with a parentId |
move_todo |
Not answers: tags, a deadline, a reminder, a priority, a title, a description. A reorder is not an answer either: moving a to-do within the list it is already in, with the same parent, leaves it where it was. sorted accepts only true; false and null are validation_failed.
The apps have an undo, and undoing the first answer puts the to-do back in the inbox. The API has no undo.
Order inside a list
Every list, and every filter, puts the to-dos with no project first, by their sort key. Then comes the tree in the order the apps show it: an area, the area's own items, its projects, each project's to-dos, then its subprojects.
Areas
An area can hold what a project holds, one level up: its own to-dos, its own notes, and attachments, as well as its projects. The area's to-dos and notes share one ordered list, like a project's, and containerItems in /v1/views/overview returns it under the area's id.
POST /v1/todosandPOST /v1/todos/{id}/movetake an area asparentId.POST /v1/notesandPOST /v1/notes/{id}/movetake an area asparentId.POST /v1/attachmentswithparentType: "container"takes an area asparentId.
An area's count includes its own to-dos and every project's below it.
Counts
navCounts in /v1/views/overview holds every number the home screen shows.
| member | counts |
|---|---|
inbox |
open capture rows plus unsorted to-dos |
today |
from earlier plus today |
overdue |
open to-dos with a missed deadline, unsorted ones included |
planned |
everything in planned |
anytime |
everything in anytime |
someday |
parked to-dos and parked capture rows |
overview |
every open to-do that is not unsorted |
notes |
live notes |
completed |
the done to-dos the completed view lists |
trash |
the rows the trash view lists |
The arithmetic holds exactly: overview equals today + overdue + planned + anytime, minus the unsorted to-dos that are overdue.
The completed section of a container
Every area, project and subproject page ends with its completed to-dos, its descendants' included, newest first. GET /v1/views/completed returns them as containerCompleted: a map from container id to to-do ids. The apps show the first ten and a more. The MCP get_completed tool returns the same thing per container as byContainer, with the latest ten resolved.
Old names
upcoming and next 7 days were merged into planned, and logbook is now completed. The old names still answer, with the new payload: /v1/views/upcoming and /v1/views/logbook on REST, get_upcoming, get_logbook and get_next_7_days on MCP. New code should use the new names.
Next
- The data model for the rows behind the lists.
- Dates and time zones for whose "today" the lists use.
- REST and MCP for where the two surfaces differ.