> This is the Markdown of https://backed.giving/developers/guides/pagination, a page of the Backed developer documentation. Every page is listed at https://backed.giving/developers/llms.txt.

# Pagination

Read a long list 50 records at a time with the limit, gt and lt parameters, in ascending id order.

Every list (`GET /api/v2/funding_rounds`, `/funding_applications`, `/contracts`, `/registration_entities`, `/milestones`) answers a bare JSON array of records in ascending `id` order, at most 50 at a time. There is no page number and no cursor: you page by id.

## The parameters

Paging parameters:

| Parameter | What it does |
| --- | --- |
| `limit` | Records per page. Default 50, at most 50: a larger value is read as 50. Not an integer, or below 1, answers `400 invalid_request` with `limit is invalid`. |
| `gt` | Only records whose id is greater than this. Pass the last id you received to read the next page. |
| `lt` | Only records whose id is less than this. |

Each parameter is an integer, sent once. A parameter that is not an integer, or is sent twice, answers `400 invalid_request` naming it. A `gt` or `lt` that no id can meet is an empty page, not an error. A parameter a route does not document is ignored, except a `filters[…]` key the milestones list does not know, which is `400`.

## Read every page

1. Ask for the first page with no `gt`.
2. Keep the `id` of the last record on the page.
3. Ask again with `gt` set to that id.
4. Stop when a page holds fewer records than the `limit`: there are no more.

The first two pages:

```bash
curl "https://your-org.backed.giving/api/v2/funding_applications?limit=50" -H "Authorization: Bearer $BACKED_TOKEN"
curl "https://your-org.backed.giving/api/v2/funding_applications?limit=50&gt=1287" -H "Authorization: Bearer $BACKED_TOKEN"
```

Node.js:

```js
async function* everyRecord(path, token) {
  let after = null;
  for (;;) {
    const query = new URLSearchParams({ limit: '50' });
    if (after !== null) query.set('gt', String(after));
    const response = await fetch(`https://your-org.backed.giving${path}?${query}`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    if (!response.ok) throw new Error(`${path}: ${response.status}`);
    const page = await response.json();
    yield* page;
    if (page.length < 50) return;
    after = page[page.length - 1].id;
  }
}

for await (const application of everyRecord('/api/v2/funding_applications', token)) {
  console.log(application.id, application.state);
}
```

Filters, such as `submitted=1` on funding applications or `filters[ids][]` on milestones, narrow the list before it is paged: keep sending them with every page.

> The OData reporting feed pages differently: up to 1000 rows a page, each ending with \`@odata.nextLink\` while more remain. See [Power BI](https://backed.giving/developers/guides/power-bi.md).
