> For the complete documentation index, see [llms.txt](https://docs.currents.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.currents.dev/api/get-started/pagination.md).

# Pagination

List endpoints return collections in pages. Currents uses **cursor-based** and **offset-based** pagination for various API endpoints. This page describes both patterns.

## Cursor-based pagination

Use cursor pagination for list methods such as listing projects or runs for a project.

### Parameters

Optional query parameters:

| Parameter        | Description                                                                                                           |
| ---------------- | --------------------------------------------------------------------------------------------------------------------- |
| `limit`          | Maximum number of items in this page. **1–50**, default **10**.                                                       |
| `starting_after` | Cursor from a previous item. Returns the next page of items **older** than that item (see [Sort order](#sort-order)). |
| `ending_before`  | Cursor from a previous item. Returns the next page of items **newer** than that item (see [Sort order](#sort-order)). |

{% hint style="warning" %}
Only one of `starting_after` or `ending_before` may be sent in a single request. They are mutually exclusive.
{% endhint %}

### Response shape

Every list response includes `has_more`. Each item in `data` includes a `cursor` string you pass back as `starting_after` or `ending_before` on the next request.

Example: `GET https://api.currents.dev/v1/projects/bAYZ41/runs`

```json
{
  "status": "OK",
  "has_more": true,
  "data": [
    {
      "runId": "9ee42e4b85c02c634fe30b26d728624e",
      "cursor": "62c538efcbd7fab8a5edb371"
    },
    {
      "runId": "9af7a261f148d1b45d013eec6a22902e",
      "cursor": "62baacbf9f4689a83d2b24cb"
    }
  ]
}
```

When `has_more` is `true`, request the next page using the appropriate cursor parameter (see below).

### Sort order

Picture the full timeline as **newest at the top**, **oldest at the bottom** (like a “latest first” feed):

```
… newest …
cursor_D
cursor_C
cursor_B   ← reference cursor
cursor_A
… oldest …
```

| Request                                      | What you get                                                                                                                                                 |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Neither `starting_after` nor `ending_before` | First page, in that endpoint’s default order.                                                                                                                |
| `starting_after=cursor_B`                    | Items **older than B** (e.g. `cursor_A`, …)—continuing **down** toward the oldest. The API describes this page as **chronological** order.                   |
| `ending_before=cursor_B`                     | Items **newer than B** (e.g. `cursor_C`, `cursor_D`, …)—continuing **up** toward the newest. The API describes this page as **reverse chronological** order. |

### Example: next page (older items)

After the first request, take the **last** item’s `cursor` in `data` and call again with `starting_after`:

```http
GET /v1/projects/bAYZ41/runs?limit=20&starting_after=62baacbf9f4689a83d2b24cb
```

Stop when `has_more` is `false` or `data` is empty.

### Example: page toward newer items

Use `ending_before` with a cursor from an item **newer** than the slice you want to extend (often the **first** item of the current page when walking back toward the present):

```http
GET /v1/projects/bAYZ41/runs?limit=20&ending_before=62c538efcbd7fab8a5edb371
```

## Offset-based pagination

Some list operations (for example, aggregated lists such as **spec files** for a project) do not map to a stable row cursor. Those endpoints document offset pagination explicitly.

### Response shape

```typescript
{
  "status": "OK",
  "data": {
    // ... resource-specific fields
    "nextPage": number | false,
    "total": number
  }
}
```

| Field      | Meaning                                                              |
| ---------- | -------------------------------------------------------------------- |
| `total`    | Total number of items matching the query (across all pages).         |
| `nextPage` | Page index to request next, or `false` when there are no more pages. |

### Parameters

| Parameter | Description            |
| --------- | ---------------------- |
| `limit`   | Page size. **1–50**.   |
| `page`    | Zero-based page index. |

The slice applied server-side is:

```
items.slice(page * limit, page * limit + limit)
```

(Equivalent to `items.splice(page * limit, limit)` for a copy of the list.)

### Example

First page:

```http
GET /v1/projects/{projectId}/specs?limit=25&page=0
```

If `data.nextPage` is `1`, fetch the next page with `page=1`, same `limit`, until `nextPage` is `false`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.currents.dev/api/get-started/pagination.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
