# Pagination

> MyStocks list endpoints use cursor-based pagination — pass ?limit= and ?cursor=; every response carries hasMore and nextCursor so you never calculate offsets. Per-endpoint defaults and maximums included.

List endpoints use **cursor-based pagination**. Pass `?limit=` to control page size and `?cursor=` to
advance to the next page. Every paginated response includes `hasMore` and `nextCursor` so you never
need to calculate offsets.

## Request parameters

limit (integer, optional): Items per page. Default and max vary by endpoint (see below). Clamped to the endpoint maximum if exceeded.

cursor (string, optional): Opaque cursor returned as nextCursor in the previous response. Omit on the first request. Treat cursors as opaque strings — do not construct or parse them.

## Response fields

count (integer, optional): Number of items in this page (≤ limit).

hasMore (boolean, optional): true if at least one more page exists. false means this is the last page.

nextCursor (string | null, optional): Pass as ?cursor= on the next request. null when hasMore is false.

## Limit defaults & maximums by endpoint

| Endpoint                           | Default | Max |
| ---------------------------------- | ------- | --- |
| `GET /users`                       | 100     | 500 |
| `GET /orders`                      | 50      | 200 |
| `GET /users/{userId}/orders`       | 50      | 200 |
| `GET /users/{userId}/transactions` | 50      | 200 |
| `GET /audit`                       | 50      | 200 |
| `GET /webhooks/{id}/deliveries`    | 20      | 100 |

## Fetching all pages — JavaScript

```javascript
async function fetchAllOrders(apiKey) {
  const orders = [];
  let cursor = null;

  do {
    const url = new URL('https://mystocks.africa/api/v1/partner/orders');
    url.searchParams.set('limit', '200');
    if (cursor) url.searchParams.set('cursor', cursor);

    const res = await fetch(url, { headers: { 'x-api-key': apiKey } });
    const page = await res.json();

    orders.push(...page.orders);
    cursor = page.nextCursor; // null on the last page
  } while (cursor);

  return orders;
}
```

> **Cursor stability.** Cursors are Firestore document IDs and remain valid indefinitely. New items
> inserted after your first request appear in subsequent pages if they sort after the cursor position —
> consistent forward-only iteration is guaranteed. Do not cache cursors across API-key rotations.
