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

# Pagination

> Navigate through large datasets with offset or incremental cursor pagination.

All list endpoints return paginated results using offset-based pagination.

## Parameters

| Parameter | Type    | Default | Description            |
| --------- | ------- | ------- | ---------------------- |
| `limit`   | integer | 50      | Items per page (1-100) |
| `offset`  | integer | 0       | Items to skip          |

## Response format

```json theme={null}
{
  "data": [...],
  "meta": {
    "total": 1250,
    "limit": 50,
    "offset": 0,
    "has_more": true
  }
}
```

| Field      | Description                               |
| ---------- | ----------------------------------------- |
| `total`    | Total number of items matching the query  |
| `limit`    | Page size used                            |
| `offset`   | Number of items skipped                   |
| `has_more` | Whether more items exist beyond this page |

## Iterating through all results

```python theme={null}
import requests

BASE_URL = "https://app.leonar.app/api/v1"
HEADERS = {"Authorization": "Bearer leo_your_api_key"}

def get_all_contacts():
    contacts = []
    offset = 0
    limit = 100

    while True:
        response = requests.get(
            f"{BASE_URL}/contacts",
            headers=HEADERS,
            params={"limit": limit, "offset": offset},
        )
        result = response.json()
        contacts.extend(result["data"])

        if not result["meta"]["has_more"]:
            break

        offset += limit

    return contacts
```

## Filtering and sorting

Most list endpoints support filtering and sorting via query parameters. Filters use operator-based syntax:

| Operator        | Example                       | Description            |
| --------------- | ----------------------------- | ---------------------- |
| `eq.value`      | `?global_status=eq.new`       | Equals                 |
| `neq.value`     | `?global_status=neq.archived` | Not equals             |
| `gt.value`      | `?created_at=gt.2026-01-01`   | Greater than           |
| `gte.value`     | `?created_at=gte.2026-01-01`  | Greater than or equal  |
| `lt.value`      | `?amount=lt.50000`            | Less than              |
| `lte.value`     | `?amount=lte.50000`           | Less than or equal     |
| `like.%value%`  | `?first_name=like.%Sophie%`   | Case-sensitive match   |
| `ilike.%value%` | `?first_name=ilike.%sophie%`  | Case-insensitive match |
| `is.null`       | `?archived_at=is.null`        | Is null                |
| `is.not_null`   | `?archived_at=is.not_null`    | Is not null            |

Sorting uses a `sort` parameter with `-` prefix for descending order:

```
?sort=-created_at    # Newest first
?sort=last_name      # Alphabetical
```

## Incremental synchronization

Mutable CRM collections support `updated_after` and, except for contacts,
`updated_before`. These offset-paginated filters reduce full scans but are
best-effort during concurrent writes; consumers that require an exact mirror
should keep a lower-frequency reconciliation. Timestamps must be RFC 3339
values. The lower bound is strict and the upper bound is inclusive:

```text theme={null}
updated_at > updated_after AND updated_at <= updated_before
```

The contacts collection may redeliver rows exactly equal to `updated_after`.
This at-least-once behavior avoids gaps; consumers should upsert by resource ID.

The workspace-level pipeline entry collection provides the stronger contract:
keyset cursor pagination and a fixed checkpoint obtained from the database clock.

```http theme={null}
GET /api/v1/pipeline-entries
  ?updated_after=2026-07-22T08:00:00Z
  &include=contact,project,stage
  &limit=100
```

Follow `meta.next_cursor` until `meta.has_more` is false. Persist
`meta.checkpoint` only after the final page succeeds, then use it as the next
request's `updated_after`. Process entries idempotently by ID.

```json theme={null}
{
  "data": [],
  "meta": {
    "limit": 100,
    "has_more": false,
    "next_cursor": null,
    "checkpoint": "2026-07-22T08:05:00.000Z"
  }
}
```

Pipeline entry deletions are not yet emitted by this endpoint. Keep a
lower-frequency full reconciliation for deletion detection.
