# Paginate personal time entries

Source: https://www.tracktimer.app/docs/pagination

Read time-entry history with opaque cursors and understand ordering and concurrent changes.

Only [list time entries](https://www.tracktimer.app/docs/list-time-entries) is paginated. Client and project lists do not use cursors.

## First page

Omit `cursor` initially. `limit` defaults to 20 and accepts integers from 1 through 100. Optional `projectId` must be a UUID. There are no date-range, status, user, or offset parameters.

```sh
curl "https://www.tracktimer.app/api/v1/time-entries?limit=20" \
  --header "Authorization: Bearer $TRACKTIMER_API_KEY"
```

Responses contain `entries` and `nextCursor`. Non-null `nextCursor` means another row existed beyond the page when queried. `null` means no subsequent page was found at that time.

## Next page

Pass the returned cursor unchanged, retaining the same workspace key and project filter. Replace `CURSOR_FROM_RESPONSE` below with the returned value:

```sh
curl "https://www.tracktimer.app/api/v1/time-entries?limit=20&cursor=CURSOR_FROM_RESPONSE" \
  --header "Authorization: Bearer $TRACKTIMER_API_KEY"
```

Continue until `nextCursor` is `null`. Do not send literal `null`, an empty cursor, or a reconstructed cursor. Cursors are opaque, at most 1,024 characters, and use base64url characters. Their internal encoding is not an integration contract.

## Ordering and changes

Entries sort by `startedAt` descending, then ID descending to break ties. A cursor continues strictly after the last entry in that ordering. The server fetches one extra row to decide whether to return another cursor.

This is not a frozen snapshot. Newer entries created after the first page will not appear in subsequent older pages. Edits to start time can move entries relative to the boundary. For synchronization, deduplicate by entry ID and refresh leading pages as needed; a cursor is not a permanent synchronization token.

History includes active, completed, and voided personal entries in the workspace, including archived projects or projects the user is no longer assigned to. A project filter with no personal history returns an empty result rather than an access error: `{"entries":[],"nextCursor":null}`.

Examples use illustrative IDs and data. Use the values returned by your own workspace. [Review error handling and retry behavior.](https://www.tracktimer.app/docs/errors-and-retries)
