# 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

<ParamTable fields={[
  { name: 'limit',  type: 'integer', desc: 'Items per page. Default and max vary by endpoint (see below). Clamped to the endpoint maximum if exceeded.' },
  { name: 'cursor', type: 'string',  desc: '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

<ParamTable fields={[
  { name: 'count',      type: 'integer',       desc: 'Number of items in this page (≤ limit).' },
  { name: 'hasMore',    type: 'boolean',       desc: 'true if at least one more page exists. false means this is the last page.' },
  { name: 'nextCursor', type: 'string | null', desc: '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;
}
```

<Callout type="warn">
  **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.
</Callout>
