REST API

Pagination

Offset and cursor pagination conventions used by list endpoints.

Two styles

The API uses two pagination styles depending on the resource:

StyleEndpointsWhy
Offset/projects, /workspaces, /members, /task-types, /tagsSmall, slow-changing lists. Returns a total so you can render page counts.
Cursor/tasks, /time-entriesLarger, fast-changing lists. Returns an opaque nextCursor for stable forward iteration.

Offset pagination

GET /api/v1/projects?limit=25&offset=50
ParamTypeDefaultRange
limitint501–100
offsetint0≥ 0

Response:

{
  "data": [ /* up to `limit` items */ ],
  "total": 137
}

The total is computed against the same filters as the page, so it stays accurate as filters change.

Offset pagination can skip or duplicate rows when items are inserted or deleted between pages. If your list is being mutated concurrently and you need exactness, prefer the cursor endpoints.

Cursor pagination

GET /api/v1/tasks?limit=50

Response:

{
  "data": [ /* up to `limit` items */ ],
  "pagination": { "nextCursor": "f4c2…" }
}

To fetch the next page, send the nextCursor as the cursor query parameter:

GET /api/v1/tasks?limit=50&cursor=f4c2…

When the list is exhausted, nextCursor is null. The cursor is an opaque UUID — treat it as a blob; do not parse it.

ParamTypeDefaultRange
limitint501–100
cursorUUIDfrom a previous response

Sorting

  • Cursor lists are ordered by (createdAt DESC, id DESC) for tasks and (startedAt DESC, id DESC) for time entries.
  • Offset lists use a per-resource natural order (name for tags/workspaces, name ASC on members, createdAt DESC for projects).

Custom sorting is not part of the public API in v1.

Limits

Both styles cap limit at 100. Asking for more returns a 422 validation error. If you need bulk export, page through the cursor list with limit=100.

On this page