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

# Pagination

> Read long lists page by page, without missing or repeating anything.

Operations that can return many items — leads, the leads of a list or a post, engagements, events, posts, deliveries, workflow matches — answer **one page at a time**:

```json theme={null}
{
  "data": [ "…" ],
  "page": { "next_cursor": "eyJ0IjoibGVhZHM6Zmlyc3Rfc2Vlbl9hdCIs…", "has_more": true }
}
```

| Parameter | |
| - | - |
| `limit` | Items per page, from 1 to 100. **50** by default. |
| `cursor` | The `next_cursor` of the previous page. Leave it out for the first page. |

When `has_more` is `false`, `next_cursor` is `null`: you have read everything.

## Read every page

Call again with `cursor` set to the last `next_cursor`, **with the same filters and the same `sort`**, until `has_more` is `false`.

```javascript Node theme={null}
const headers = { Authorization: `Bearer ${process.env.TIKT_API_KEY}` };
const leads = [];
let cursor = null;

do {
  const url = new URL("https://api.trytikt.com/v1/leads");
  url.searchParams.set("min_score", "4");
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);

  const res = await fetch(url, { headers });
  if (res.status === 429) {
    await new Promise((r) => setTimeout(r, Number(res.headers.get("retry-after") ?? 60) * 1000));
    continue;
  }
  if (!res.ok) throw new Error((await res.json()).error.message);

  const { data, page } = await res.json();
  leads.push(...data);
  cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
```

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

headers = {"Authorization": f"Bearer {os.environ['TIKT_API_KEY']}"}
leads, cursor = [], None

while True:
    params = {"min_score": "4", "limit": "100"}
    if cursor:
        params["cursor"] = cursor
    res = requests.get("https://api.trytikt.com/v1/leads", headers=headers, params=params)
    if res.status_code == 429:
        time.sleep(int(res.headers.get("retry-after", "60")))
        continue
    res.raise_for_status()
    body = res.json()
    leads += body["data"]
    if not body["page"]["has_more"]:
        break
    cursor = body["page"]["next_cursor"]
```

In n8n, the **HTTP Request** node does this for you: under **Options › Pagination**, choose **Update a Parameter in Each Request**, set the query parameter `cursor` to `{{ $response.body.page.next_cursor }}`, and stop when `{{ $response.body.page.has_more }}` is false.

## What the cursor guarantees

* **Nothing is missed or repeated** while you read, even while TIKT writes new leads. Pages are cut by the sort order and the item's identifier, never by position: a lead written while you read never shifts the others.
* A lead written **while you read** may not appear in this pass if it sorts before your current page — for example a new lead when you read newest first. You will get it at your next sync: see [Syncing changes](/api/syncing).
* The cursor is opaque: don't build or change it. A cursor that can't be read, or that comes from another `sort`, is refused with `400` and the code `curseur_invalide`. Start again without `cursor`.
* A cursor doesn't expire, but it only makes sense with the filters it was made with.

## Lists that are not paginated

A few lists are always short and come whole, with `data` only: your lists (`GET /v1/lists`), your tracked profiles, your blocklist, your workflows, your destinations, the event types, a lead's scores.


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