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

# Pagination

> How the Business API pages large collections: page numbers for stored data, scroll tokens and cursors for search and timelines.

Stored collections — your lists and their rows — use **page-number pagination**, because they live in a database where jumping to an arbitrary page is cheap. Prospect search uses **scroll-token pagination**, because results stream from a search index where a cursor is the only reliable way to walk a large result set without skipping or duplicating profiles. A few other endpoints use their own cursor or page fields, listed under [Other collections](#other-collections).

| Mechanism | Endpoints | You send | You get back |
| - | - | - | - |
| Page numbers | `GET /business/lists`, `GET /business/lists/{listId}/rows` | `limit` and `pageNum` query parameters | `data` array plus a `pagination` object |
| Scroll tokens | `POST /business/prospects/search`, `POST /business/saved-searches/{savedSearchId}/run` | `scrollToken` in the request body | `profiles` array plus a `scrollToken` string |

## Page-number pagination

List endpoints accept two query parameters:

| Parameter | Type | Default | Constraints |
| - | - | - | - |
| `limit` | integer | `50` on `GET /business/lists`, `100` on `GET /business/lists/{listId}/rows` | 1–1000 |
| `pageNum` | integer | `1` | Starts at 1, not 0 |

Paginated responses always put the records in a `data` array and the paging metadata in a `pagination` object:

```bash theme={null}
curl "https://api.tryfuse.ai/api/v1/business/lists?limit=50&pageNum=1" \
  -u "af_YOUR_KEY:"
```

```json theme={null}
{
  "data": [
    {
      "id": "68a1f20b9c41d20014b3e901",
      "name": "Q3 Fintech CFOs",
      "entityType": "contactList",
      "contactsCount": 412,
      "companiesCount": 0,
      "createdAt": "2026-07-01T09:12:44.000Z"
    }
  ],
  "pagination": {
    "pageNum": 1,
    "totalPages": 3,
    "totalRecords": 52
  }
}
```

To walk the whole collection, increment `pageNum` until it reaches `totalPages`. Requesting a page past the end returns an empty `data` array, so an off-by-one in your loop fails soft rather than erroring.

<Note>
  The `data` key is reserved for paginated collections. Non-paginated responses are keyed by entity name instead — `GET /business/me` returns `{ "user": ... }`, not `{ "data": ... }`. If you see `data`, expect `pagination` next to it. Some paginated collections are keyed by entity name too, such as `campaigns` or `agents`; see [Other collections](#other-collections).
</Note>

### Counts are read-time, not snapshot

`totalRecords` and `totalPages` reflect the collection at the moment of each request. If contacts are being added or removed while you paginate — an enrichment job filling a list, a teammate deleting rows — records can shift between pages, so a full walk may see a row twice or miss one. For a point-in-time copy of a list, use an [export](/guides/export-a-list) instead of paginating rows.

## Scroll-token pagination

Search endpoints return a `scrollToken` alongside each page of profiles. Pass it back as `scrollToken` in the next request body to fetch the following page. When a response has no `scrollToken`, you have reached the end of the results.

Request the first page as usual — `size` controls the page size (default 10, maximum 100):

```bash theme={null}
curl -X POST https://api.tryfuse.ai/api/v1/business/prospects/search \
  -u "af_YOUR_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "job_title_levels": [{ "status": "include", "value": "cxo" }]
    },
    "size": 25
  }'
```

```json theme={null}
{
  "profiles": [
    {
      "full_name": "ada nwosu",
      "first_name": "ada",
      "last_name": "nwosu",
      "job_title": "chief financial officer",
      "job_title_levels": ["cxo"],
      "job_company_name": "brightpay",
      "job_company_website": "brightpay.com",
      "industry": "financial services",
      "location_name": "san francisco, california, united states",
      "linkedin_url": "linkedin.com/in/ada-nwosu",
      "savedProfile": false,
      "savedBy": null
    }
  ],
  "scrollToken": "eyJwYWdlIjoyfQ"
}
```

Then repeat the same request with the token added:

```bash theme={null}
curl -X POST https://api.tryfuse.ai/api/v1/business/prospects/search \
  -u "af_YOUR_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "job_title_levels": [{ "status": "include", "value": "cxo" }]
    },
    "size": 25,
    "scrollToken": "eyJwYWdlIjoyfQ"
  }'
```

Running a saved search with `POST /business/saved-searches/{savedSearchId}/run` pages the same way: each response carries a `scrollToken` for the next page.

<Warning>
  Scroll tokens are short-lived and tied to the query that produced them. Do not persist them, share them across queries, or resume a scroll after a long pause — start a fresh search instead. There is no way to jump to an arbitrary page mid-scroll; the token only moves forward.
</Warning>

If your goal is to collect search results rather than browse them, you usually do not need to scroll at all — `POST /business/prospects/search/save-to-list` runs the search server-side and saves the matches in one call. See [build a list from search](/guides/build-a-list-from-search).

## Other collections

| Endpoints | You send | You get back |
| - | - | - |
| `GET /business/campaigns`, `GET /business/campaigns/{campaignId}/leads`, `GET /business/campaigns/{campaignId}/scheduled-sends` | `limit` (1–100, default 25) and `pageNum` | `campaigns`, `leads` or `sends`, plus `pagination: { page, pageSize, total, totalPages }` |
| `GET /business/agents` | `limit` (1–100, default 25) and `pageNum` | `agents`, plus `pagination: { pageNum, totalPages, totalRecords }` |
| `POST /business/companies/search` | `cursor` in the body, from the previous `nextCursor`; `size` 1–100, default 25 | `companies` and `nextCursor`, `null` on the last page |
| `GET /business/contacts/{contactId}/activities` | `cursor` from the previous `nextCursor`; `limit` 1–100 | `activities` and `nextCursor`, `null` on the last page |
| `GET /business/research/runs/{runId}/events` | `sinceSeq`, the last `seq` you saw; `limit` 1–500 | `events` and `nextSinceSeq`, `null` when you are caught up |
| `GET /business/website-visitors` | `page` and `pageSize` (1–100, default 20) | `visitors`, plus `pagination: { total, page, pageSize, totalPages }` |
| `GET /business/lists/{listId}/filter-values` | `start` (default 1) and `amount` (1–1000, default 1000), counted in rows | `values` and `total` |

## Which mechanism am I looking at?

You never choose — the endpoint does. A quick way to tell from a response body:

* `data` + `pagination` → page numbers. Iterate with `pageNum`.
* `profiles` + `scrollToken` → scroll. Iterate by echoing the token.

Per-endpoint parameters and response shapes are in the [API reference](/api-reference). Pagination requests count against your rate limit like any other call — see [rate limits](/concepts/rate-limits) for budgeting long walks.


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