For developers

API changelog

Every release and what it carried. The spec describes the API as it is today and has no memory of what it was; this page is that memory.

Current version v1.2.0

v1.2.0

CurrentReleased

Time spent on a task, written and read

A task now carries one field for how long it took. It is written through its own action rather than PATCH because the permission differs, and it is read on every task response with no plan condition.

  • AddedPOST /tasks/{ref}/time and POST /projects/{project}/lists/{list}/tasks/{task}/time: record the duration in one of three shapes that all mean ninety minutes, "1:30", "1.5" in decimal hours, and "90" in minutes, with an empty string clearing the field. The value replaces the previous total rather than adding to it, and "0" is refused because a caller sending it almost always meant to clear. Needs tasks:write and a plan that carries time tracking, 403 otherwise with nothing recorded.
  • Addedtime_spent_minutes on every task response, always present and null when nobody has measured the task. null is not zero: the first says nobody stated how long it took, the second says it took no time. Reading needs no plan, because the numbers are the customer's own record of their work.

v1.1.0

BreakingReleased

A flat address for every record, and comment reads

Every record gained a second, short address that stands on its own, without the chain of parents that used to precede it. Alongside it, comments gained its read half, and the task-list path segment changed.

  • ChangedThe task-list path segment is lists, not task-lists, across every nested path: /projects/{project}/lists, /projects/{project}/lists/{list}/tasks and everything under them.
  • Changedid in a response is now the record's ref: prj-8f3kd for a project, lst-4m2qp for a task list, tsk-9wb7t for a task, mjl-6khz2 for a majlis topic. It used to be the slug.
  • AddedA flat address for every record that carries a ref: GET/PATCH/DELETE on /lists/{ref}, /tasks/{ref} and /discussions/{ref}, plus DELETE /files/{ref}, and the complete, incomplete and move actions. It does not accept a slug, because a slug repeats across projects.
  • AddedCollections under a flat parent: GET/POST /lists/{ref}/tasks, /lists/{ref}/comments and /tasks/{ref}/comments. A collection stays under its parent, but the parent may be named by its ref alone.
  • AddedThe comments:read operation, and with it GET on a task list's comments and a task's comments, oldest first and paginated. comments was the one group that could write and never read.
  • AddedTwo fields on a comment: updated_at, equal to created_at until the comment is edited, and attachments, the names of files embedded in the body that the plain-text rendering drops.
  • ChangedSearch hits return the ref in id, alongside the *_slug keys as before. A folder is the one hit without an id: its numeric folder_id is the only handle its endpoints take.
  • Removed/projects/{project}/task-lists and everything under it no longer resolves. The segment is lists.

What your integration has to do

  • Replace task-lists with lists in every path you build. This is the only change that stops a working integration.
  • A slug is still accepted everywhere it was, and so is a file's numeric id, so nothing you stored has to be migrated. What is new is that you receive a ref instead.
  • If you show id to a person as a readable title, it is a ref now, not a name. Show title or name, or a *_slug key from a search hit.
  • To read comments, add comments:read to your key's allowed operations. Keys minted before this date do not carry it.

v1.0.0

Released

First release

The first public release of the API, in preview and switched on per company.

  • AddedProjects, task lists, tasks, majlis topics, comments, files, folders, calendar events, members, unified search, and the calling key's own identity.
  • AddedBearer key authentication behind two gates: the scope as a ceiling, and an explicit allowed-operations list as the operative gate. Deletes sit outside the default grant.
  • AddedUniform response envelopes, pagination, and a per-company daily quota with headers set on every served response.

How we number

The number here versions the contract these docs describe. It is not the v1 in the base URL: that is the path version, and it moves only when a new surface stands beside the old one. The API is in preview, so every update raises the middle number and the first stays reserved for general availability. Each release here matches info.version in the OpenAPI file, and a build check keeps the two from drifting apart.