---
title: "Pagination"
description: "Page lists with limit, starting_after and ending_before, and filter by creation time."
url: https://docs.fluveo.com/start/pagination/
---

> Index of every page: https://docs.fluveo.com/llms.txt. Integrating Fluveo? Read https://docs.fluveo.com/agents/integrate.md first.

> Too long? This page with code in one language only: https://docs.fluveo.com/start/pagination.curl.md (cURL), https://docs.fluveo.com/start/pagination.node.md (Node.js), https://docs.fluveo.com/start/pagination.python.md (Python), https://docs.fluveo.com/start/pagination.php.md (PHP).

# Pagination

Page lists with limit, starting_after and ending_before, and filter by creation time.

Every list endpoint, such as `GET /v1/payment_intents`, `GET /v1/charges` or `GET /v1/events`, answers with the same envelope and takes the same paging parameters.

## Read the list envelope

*GET /v1/payment_intents?limit=2*

```json
{
  "object": "list",
  "url": "/v1/payment_intents",
  "has_more": true,
  "data": [
    { "id": "pi_2", "object": "payment_intent", "created": 1767225700 },
    { "id": "pi_1", "object": "payment_intent", "created": 1767225600 }
  ]
}
```

- `data` holds the objects of this page, newest first. Objects created in the same second are listed in reverse order of creation, the last one made first. Search results order the objects of one second by id instead.
- `has_more` is `true` when more objects follow this page.
- `url` is the path of the list.

## Page parameters

| Parameter | Meaning |
| --- | --- |
| `limit` | How many objects a page holds, from 1 to 100. The default is 10. |
| `starting_after` | An object id. The page starts right after that object, which pages toward older objects. |
| `ending_before` | An object id. The page ends right before that object, which pages back toward newer objects. |
| `created` | A Unix timestamp: only objects created in that exact second. |
| `created[gt]`, `created[gte]`, `created[lt]`, `created[lte]` | Only objects created after, from, before or up to a Unix timestamp. Combine them for a range. |

Send at most one of `starting_after` and `ending_before`. A request with both answers `400`. A `limit` outside 1 to 100 answers `400` with `param` `limit`.

For object lists, a cursor that is not found in your store or is the wrong resource type returns an empty page with `has_more: false`. The Events list rejects a missing cursor with `400` and `resource_missing`.

## Read every page

Ask for the first page. While `has_more` is `true`, ask again with `starting_after` set to the last id in `data`.

**Read every PaymentIntent**

cURL:

```bash
curl -G https://api.fluveo.com/v1/payment_intents \
  -H "Authorization: Bearer sk_test_..." \
  -d limit=100

# then, with the id of the last object of the previous page:
curl -G https://api.fluveo.com/v1/payment_intents \
  -H "Authorization: Bearer sk_test_..." \
  -d limit=100 \
  -d starting_after=pi_...
```

Node.js:

```javascript
async function listAll(path) {
  const all = [];
  let startingAfter;
  for (;;) {
    const params = new URLSearchParams({ limit: "100" });
    if (startingAfter) params.set("starting_after", startingAfter);
    const response = await fetch(`https://api.fluveo.com/v1${path}?${params}`, {
      headers: { Authorization: "Bearer sk_test_..." },
    });
    const page = await response.json();
    all.push(...page.data);
    if (!page.has_more) return all;
    startingAfter = page.data[page.data.length - 1].id;
  }
}

const paymentIntents = await listAll("/payment_intents");
```

Python:

```python
import requests

def list_all(path):
    objects, starting_after = [], None
    while True:
        params = {"limit": 100}
        if starting_after:
            params["starting_after"] = starting_after
        page = requests.get(
            "https://api.fluveo.com/v1" + path,
            headers={"Authorization": "Bearer sk_test_..."},
            params=params,
        ).json()
        objects.extend(page["data"])
        if not page["has_more"]:
            return objects
        starting_after = page["data"][-1]["id"]

payment_intents = list_all("/payment_intents")
```

PHP:

```php
<?php
function listAll(string $path): array {
    $all = [];
    $startingAfter = null;
    do {
        $params = ["limit" => 100];
        if ($startingAfter) $params["starting_after"] = $startingAfter;
        $ch = curl_init("https://api.fluveo.com/v1" . $path . "?" . http_build_query($params));
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
        ]);
        $page = json_decode(curl_exec($ch), true);
        $all = array_merge($all, $page["data"]);
        $startingAfter = end($page["data"])["id"] ?? null;
    } while ($page["has_more"]);
    return $all;
}

$paymentIntents = listAll("/payment_intents");
```

## Search endpoints

Fluveo serves search for products, prices, customers, charges and PaymentIntents, such as `GET /v1/payment_intents/search?query=status:"succeeded"`. A search pages with `page` and `next_page`, not with `starting_after`. Every other `/search` endpoint is refused: use the list endpoints with `created` and the filters each one takes. The [API reference](https://docs.fluveo.com/api/payment_intents.md) lists the fields of each search and the filters of each list.

## Test it

1. Create three test PaymentIntents.
2. List with `limit=2`. You get two objects and `has_more: true`.
3. List again with `starting_after` set to the second id. You get the oldest one.
4. Send both `starting_after` and `ending_before`. You get `400`.

> **For AI agents:**
>
> limit is 1 to 100 (default 10). Page with starting_after = the last id of data until has_more is false. Never send starting_after and ending_before together. Search (products, prices, customers, charges, PaymentIntents) pages with page = next_page instead. There is no auto-pagination on the server.

## Next

- [Expanding responses](https://docs.fluveo.com/start/expand.md): Get related objects in the same answer.
- [Metadata](https://docs.fluveo.com/start/metadata.md): Store your own ids on Fluveo objects.
