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

# Pagination

> Navigate large result sets with cursor-based pagination.

All list endpoints in the Toktra API use **cursor-based pagination**. Unlike page-number pagination, cursors remain stable as records are added or removed, so you never miss records or see duplicates when iterating through a large result set.

## How it works

Cursors are opaque strings — you should not attempt to parse or construct them. Pass the cursor you received in the previous response to advance to the next page.

### First page

Omit the `cursor` parameter entirely to fetch the first page:

```bash theme={null}
curl "https://api.toktra.io/v1/users?limit=10" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### Subsequent pages

Take `next_cursor` from the response and pass it as `cursor` on the next request:

```bash theme={null}
curl "https://api.toktra.io/v1/users?limit=10&cursor=eyJpZCI6IjAxOTQ1YjM2LTQ1NjctNzAwMC04MDAwLTAwMDAwMDAwMDAwMCJ9" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### End of results

When you reach the last page, `next_cursor` is `null` and `has_more` is `false`. Stop paginating.

## Pagination parameters

<ParamField query="cursor" type="string">
  Opaque cursor for pagination. Pass the `next_cursor` value from the previous response to fetch the next page. Omit for the first page.
</ParamField>

<ParamField query="limit" type="integer" default="25">
  Maximum number of items to return per page. Must be between `1` and `100`.
</ParamField>

## Response envelope

Every list endpoint wraps its results in this envelope:

<ResponseField name="items" type="array" required>
  The page of results.
</ResponseField>

<ResponseField name="next_cursor" type="string | null" required>
  Opaque cursor to pass as `cursor` on the next request. `null` when this is the last page.
</ResponseField>

<ResponseField name="has_more" type="boolean" required>
  `true` if there are more results beyond this page.
</ResponseField>

<ResponseField name="total_count" type="integer">
  Total number of matching items. May be approximate for very large datasets.
</ResponseField>

## Example: paginating through users

The following example shows a full pagination cycle using `GET /v1/users`.

**Request — page 1**

```bash theme={null}
curl "https://api.toktra.io/v1/users?limit=2" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

**Response — page 1**

```json theme={null}
{
  "items": [
    {
      "id": "a1b2c3d4-0000-0000-0000-000000000001",
      "email": "alice@acme.com",
      "name": "Alice Chen",
      "department": "Engineering",
      "role": "member",
      "status": "active"
    },
    {
      "id": "a1b2c3d4-0000-0000-0000-000000000002",
      "email": "bob@acme.com",
      "name": "Bob Patel",
      "department": "Marketing",
      "role": "member",
      "status": "active"
    }
  ],
  "next_cursor": "eyJpZCI6ImExYjJjM2Q0LTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMiJ9",
  "has_more": true,
  "total_count": 47
}
```

**Request — page 2**

```bash theme={null}
curl "https://api.toktra.io/v1/users?limit=2&cursor=eyJpZCI6ImExYjJjM2Q0LTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMiJ9" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

**Response — last page**

```json theme={null}
{
  "items": [
    {
      "id": "a1b2c3d4-0000-0000-0000-000000000046",
      "email": "zara@acme.com",
      "name": "Zara Okonkwo",
      "department": "Legal",
      "role": "admin",
      "status": "active"
    }
  ],
  "next_cursor": null,
  "has_more": false,
  "total_count": 47
}
```

`next_cursor` is `null` — you have fetched all records.

## Iterating all pages in code

<CodeGroup>
  ```python Python theme={null}
  import requests

  token = "YOUR_ACCESS_TOKEN"
  headers = {"Authorization": f"Bearer {token}"}
  url = "https://api.toktra.io/v1/users"
  cursor = None

  while True:
      params = {"limit": 100}
      if cursor:
          params["cursor"] = cursor

      response = requests.get(url, headers=headers, params=params)
      response.raise_for_status()
      data = response.json()

      for user in data["items"]:
          print(user["email"])

      if not data["has_more"]:
          break

      cursor = data["next_cursor"]
  ```

  ```javascript Node.js theme={null}
  const fetch = require('node-fetch');

  async function fetchAllUsers(token) {
    const headers = { Authorization: `Bearer ${token}` };
    let cursor = null;
    const users = [];

    do {
      const url = new URL('https://api.toktra.io/v1/users');
      url.searchParams.set('limit', '100');
      if (cursor) url.searchParams.set('cursor', cursor);

      const res = await fetch(url.toString(), { headers });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const data = await res.json();

      users.push(...data.items);
      cursor = data.next_cursor;
    } while (cursor);

    return users;
  }
  ```
</CodeGroup>

<Note>
  Cursors are not permanent. Do not store a cursor and attempt to resume pagination days later — use the cursor immediately within the same session.
</Note>
