> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usertick.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination

> How lists page with cursors, how big a page can be, and how to keep a copy of your responses in sync.

Every list returns one page and a cursor to the next page:

```json theme={null}
{
  "data": [ { "id": "9b1c2d3e-4f50-4a61-8b72-93a4b5c6d7e8", "...": "..." } ],
  "nextCursor": "eyJ2IjoxLCJ0IjoiMjAyNi0wOS0zMFQxMDowMDowMC4xMjNaIn0"
}
```

* `limit` sets the page size, from 1 to 100, and defaults to 25. A value outside that range returns `400` with `PUB-001-001` instead of being adjusted.
* `nextCursor` points to the next page and is `null` on the last page. To get the next page, send it back as `cursor`, exactly as it came.
* While paging, keep the other parameters the same.
* Each page starts strictly after the last item of the page before. An item that is deleted or renamed while you page doesn't end the list early or make it skip items.
* A cursor that the list didn't hand out returns `400` with `PUB-001-002`. In that case, start again without a cursor.

Short lists, such as [the analysis tree](https://docs.usertick.com/developers/api/reference/list-themes.md) and [the recent responses](https://docs.usertick.com/developers/api/reference/list-recent-responses.md), return a single page with `nextCursor: null`.

## Page through every response

```javascript JavaScript theme={null}
const base = "https://app.usertick.com/api/public/v1";
const headers = { Authorization: `Bearer ${process.env.USERTICK_API_KEY}` };

let cursor = null;
do {
  const url = new URL(`${base}/responses`);
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);

  const res = await fetch(url, { headers });
  if (!res.ok) throw new Error(`Usertick API error ${(await res.json()).code}`);
  const page = await res.json();

  for (const response of page.data) console.log(response.id, response.survey.name);
  cursor = page.nextCursor;
} while (cursor);
```

```python Python theme={null}
import os, requests

base = "https://app.usertick.com/api/public/v1"
headers = {"Authorization": f"Bearer {os.environ['USERTICK_API_KEY']}"}

cursor = None
while True:
    params = {"limit": 100}
    if cursor:
        params["cursor"] = cursor
    page = requests.get(f"{base}/responses", headers=headers, params=params).json()
    for response in page["data"]:
        print(response["id"], response["survey"]["name"])
    cursor = page["nextCursor"]
    if not cursor:
        break
```

## Keep a copy in sync

A response changes after it is received: Usertick AI analyzes it, and people change its status, assignees and notes. Its `updatedAt` moves forward each time.

To keep your copy current, store the time your last sync started and ask for what changed since then:

```bash theme={null}
curl "https://app.usertick.com/api/public/v1/responses?updatedSince=2026-09-30T10:00:00.000Z&sort=asc&limit=100" \
  -H "Authorization: Bearer utk_live_your_key_here"
```

`updatedSince` returns responses that were received, analyzed or changed by a person since that time. Page through every result, store each response by `id`, and use the start time of this run as the next run's `updatedSince`.

Every change since that time is listed. When people changed more than 100,000 responses since then, the request is refused with `400` and `PUB-003-009`. Use a later time, or read the whole list once without `updatedSince` and sync from the time that read started.

To receive changes as they happen instead of polling, use [webhooks](https://docs.usertick.com/developers/webhooks/overview.md).

## Lists and their order

| List | Order |
| - | - |
| `GET /responses` | Newest first. `sort=asc` for oldest first. |
| `GET /surveys` | Newest first |
| `GET /sites` | By domain. Every site is listed, connected or not; `connected` says which. |
| `GET /members` | By name, or by email for a member without a name, then by email |
| `GET /responses/{responseId}/comments` | Oldest first |
| `GET /webhooks` and `GET /webhooks/{webhookId}/deliveries` | Newest first |
| `GET /workflows/zapier-steps` | By workflow name, then by the step's place in the workflow |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.