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

# Pagination conventions

> Use Lensmor pagination conventions with page and pageSize parameters, total counts, hasMore flags, and access semantics for list endpoints.

Many list endpoints return a shared pagination envelope.

## Common fields

| Field        | Description                                                  |
| ------------ | ------------------------------------------------------------ |
| `items`      | Records for the current page. Item shape varies by endpoint. |
| `page`       | Current page number.                                         |
| `pageSize`   | Number of items requested per page.                          |
| `total`      | Total matching items.                                        |
| `totalPages` | Total number of pages.                                       |
| `hasMore`    | Whether another page is available.                           |

## Request pattern

Most list endpoints accept `page` and `pageSize`.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl "https://platform.lensmor.com/external/events/list?page=1&pageSize=20" \
  -H "Authorization: Bearer $LENSMOR_API_KEY"
```

Use explicit values instead of relying on defaults in production clients.

## What to expect

* Exact item fields vary by endpoint family.
* Some endpoints return extra route-specific metadata in addition to the shared pagination fields.
* Event-scoped exhibitor and personnel list endpoints can include `semantics` metadata that explains preview access and unlock guidance.
* Identifiers such as `event_id`, `exhibitor_id`, and `personnel_id` are string values in API requests and responses.
* Parameter naming is route-specific. Treat each endpoint page as the source of truth for casing and field names.

## Preview semantics

Event-scoped exhibitor and personnel lists can return an additional `semantics` object:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "semantics": {
    "accessMode": "preview",
    "previewLimit": 50,
    "counts": {
      "actualTotal": 87,
      "visibleTotal": 50,
      "remainingLockedCount": 37
    },
    "unlock": {
      "requiredForMoreResults": true,
      "credits": 2000
    }
  }
}
```

Use `semantics` to decide whether a page is fully accessible or whether the user should unlock the event for more records.

## Requesting pages beyond the preview limit

When an event is locked and you request a page outside the accessible preview window, the API returns:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "items": [],
  "total": 0,
  "page": 4,
  "pageSize": 20,
  "totalPages": 0,
  "hasMore": false,
  "semantics": {
    "accessMode": "preview",
    "previewLimit": 50,
    "counts": {
      "actualTotal": 3256,
      "visibleTotal": 50,
      "remainingLockedCount": 3206
    },
    "pageState": {
      "requestedPage": 4,
      "accessible": false,
      "maxAccessiblePage": 1
    },
    "unlock": {
      "requiredForMoreResults": true,
      "actionType": "unlock_event_exhibitors",
      "credits": 2000
    },
    "guidance": {
      "code": "preview_page_inaccessible",
      "message": "This event is locked. Only the first 50 matching exhibitors are currently accessible. Unlock the event before requesting more results."
    }
  }
}
```

Key behaviors:

* `items` is empty — no records are returned for inaccessible pages.
* `total` and `totalPages` are `0` — they reflect the inaccessible current page, not the true matching total.
* `semantics.counts.actualTotal` is the true matching total when the API can calculate it.
* `pageState.accessible` is `false` — use this flag to detect when a page is outside the preview window.
* `pageState.maxAccessiblePage` tells you the last page you can request without unlocking. Treat this as authoritative instead of calculating from `previewLimit / pageSize`.
* `guidance.code` changes to `"preview_page_inaccessible"` (versus `"preview_results_truncated"` on accessible preview pages).

Handle this by checking `pageState.accessible` before rendering results. If `false`, show the unlock prompt rather than an empty state.

## Notes

* Most endpoints use a maximum `pageSize` of `100`.
* Personnel list endpoints use a maximum `pageSize` of `50`.
* Use each endpoint page as the source of truth for route-specific filters, item fields, and any additional metadata returned with paginated results.
