# Pagination, filters and sorting

> How every list works. Cursor pages, page size, filters and the order of results.

Last updated: 2026-10-30. Source: https://docs.smartchat.marketing/en/concepts/pagination/

Every list in the API works the same way. Lists never return everything at once.

## Pages

| Parameter | Meaning |
|---|---|
| `limit` | Items per page, 1 to 100. Default 20. (MCP tools: default 20, at most 50.) |
| `cursor` | The value of `next_cursor` from the previous page. |

The answer tells you if there is more:

```json
{
  "object": "list",
  "data": [],
  "has_more": true,
  "next_cursor": "eyJ0IjoiMjAyNi0xMC0yNVQwOTo0MTowN1oiLCJpIjoiLi4uIn0",
  "url": "/v1/contacts"
}
```

The Python examples use the package `requests` (`pip install requests`). To read everything, repeat the call with `cursor` set to `next_cursor` until `has_more` is `false`:

**Python**

```python
import os
import requests

url = "https://api.smartchat.marketing/v1/contacts"
headers = {"Authorization": "Bearer " + os.environ["SMARTCHAT_API_KEY"]}
params = {"limit": 100}
while True:
    page = requests.get(url, headers=headers, params=params).json()
    for item in page["data"]:
        print(item["id"])
    if not page["has_more"]:
        break
    params["cursor"] = page["next_cursor"]
```

**TypeScript**

```typescript
const headers = { Authorization: `Bearer ${process.env.SMARTCHAT_API_KEY}` };
let cursor: string | null = null;
do {
  const query = new URLSearchParams({ limit: "100", ...(cursor ? { cursor } : {}) });
  const page = await (await fetch(`https://api.smartchat.marketing/v1/contacts?${query}`, { headers })).json();
  for (const item of page.data) console.log(item.id);
  cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
```

## The cursor

- The cursor is an opaque text. Do not read it or build it yourself.
- It only works with the **same filters** and for the **same account**. With other filters the answer is [`invalid_cursor`](https://docs.smartchat.marketing/en/errors/#invalid_cursor). Start again without a cursor.
- The order is stable: new items that appear while you page do not make you miss or repeat items.

## Filters

Filters are query parameters named like the field, for example `tag=` or `optin_whatsapp=`. Every list page in the [API reference](https://docs.smartchat.marketing/en/api/) shows its filters in the section "Lists, filters and sorting". An unknown filter gives [`unknown_parameter`](https://docs.smartchat.marketing/en/errors/#unknown_parameter); it is never ignored silently.

## Sorting

The default order is newest first (`created_at` descending, then `id` descending). A list that can be sorted differently says so on its reference page and accepts `order_by`.

## The one exception: knowledge search

`GET /knowledge/search` (MCP: `search_knowledge`) is a search, not a list. It returns the best passages only: `limit` is 1 to 12 (default 5) and there is no `cursor`. To read the documents themselves, use the normal list `GET /knowledge-documents`.

## Totals

Most lists have no total. Where `total_count` exists it is approximate and may be a little off.

