# Pagination

Every list endpoint returns the same envelope:

```json
{
  "data": [ ... ],
  "pagination": {
    "next_cursor": "MjAyNi0wOC0xOFQwOToz…",
    "has_more": true,
    "limit": 50
  }
}
```

To get the next page, pass `next_cursor` back verbatim as `cursor`:

```bash
curl "https://api.wearenoe.fr/v1/properties?limit=100" -H "Authorization: Bearer $KEY"
curl "https://api.wearenoe.fr/v1/properties?limit=100&cursor=MjAyNi0wOC0xOFQwOToz…" \
  -H "Authorization: Bearer $KEY"
```

Stop when `has_more` is `false`. `limit` defaults to 50 and caps at 200.

## Why there is no `page=2`

Results are ordered by **most recently modified**, and a busy workspace is being
written to while you page through it. With numbered pages, a record modified
between two requests shifts position — so you would silently skip rows, or read
the same one twice, with no way to tell.

A cursor points at a specific record rather than an offset, so the next page
resumes exactly where the previous one ended regardless of what changed. It is
also why paging stays fast on a large portfolio: the database seeks straight to
the cursor instead of counting past everything before it.

## Treat the cursor as opaque

It encodes ordering state and its format is not part of the contract. Pass it
back unchanged; do not parse, construct or store it long-term. If you need to
resume a sync later, store the `updated_at` of the last record you processed and
use [`updated_after`](/filtering-and-sync) instead — that is what it is for.

## A complete loop

```javascript
async function* listAll(path, params = {}) {
  let cursor;
  do {
    const query = new URLSearchParams({ ...params, limit: '200', ...(cursor ? { cursor } : {}) });
    const res = await fetch(`https://api.wearenoe.fr/v1/${path}?${query}`, {
      headers: { Authorization: `Bearer ${process.env.NOE_API_KEY}` },
    });
    if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error.message}`);

    const page = await res.json();
    yield* page.data;
    cursor = page.pagination.next_cursor;
  } while (cursor);
}
```
