> ## Documentation Index
> Fetch the complete documentation index at: https://docs.horizonpay.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination

> Page through list endpoints with a cursor.

List endpoints return records newest first. Pass `next_cursor` back as `cursor` to get the next page.

<ParamField query="limit" type="integer" default="25">
  Records per page, from `1` to `100`. Larger values are capped at `100`.
</ParamField>

<ParamField query="cursor" type="string">
  The `next_cursor` from the previous page. Leave it out for the first page.
</ParamField>

```json Response theme={null}
{
  "data": [
    { "id": "in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8", "object": "invoice", "status": "open" },
    { "id": "in_Hc8Wq2Lp5Zr7Ty3Mn9Kd4Bv6", "object": "invoice", "status": "paid" }
  ],
  "next_cursor": "MjAyNi0wOS0xN1QwOToxMjo0NC4wMDBafDdmM2M..."
}
```

`next_cursor` is `null` on the last page.

## Fetch every page

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://invoice.horizonpay.co/api/v1/invoices?status=open&limit=100" \
    -H "Authorization: Bearer $INVOICE_AI_API_KEY"

  # Repeat with the next_cursor from each response until it's null
  curl "https://invoice.horizonpay.co/api/v1/invoices?status=open&limit=100&cursor=MjAyNi0wOS0xN..." \
    -H "Authorization: Bearer $INVOICE_AI_API_KEY"
  ```

  ```ts Node.js theme={null}
  // for await fetches the next page for you
  for await (const invoice of invoiceai.invoices.list({ status: 'open', limit: 100 })) {
    console.log(invoice.number, invoice.amount_due)
  }

  // Or take one page at a time
  const page = await invoiceai.invoices.list({ status: 'open' })
  page.data            // this page
  page.nextCursor      // null on the last page
  ```

  ```python Python theme={null}
  # Iterating fetches the next page for you
  for invoice in client.invoices.list(status="open", limit=100):
      print(invoice.number, invoice.amount_due)

  # Or take one page at a time
  page = client.invoices.list(status="open")
  page.data         # this page
  page.next_cursor  # None on the last page
  ```
</CodeGroup>

## Filters

| Endpoint | Filters |
| - | - |
| `GET /customers` | `query` (name contains), `include_deleted` |
| `GET /products` | `query`, `active` |
| `GET /prices` | `product`, `active`, `currency`, `type` (`one_time` or `recurring`) |
| `GET /invoices` | `status` (`draft`, `open`, `paid`, `overdue`, `void`), `customer`, `from`, `to` (`YYYY-MM-DD`, on the issue date) |
| `GET /invoices/{id}/events` | None |
| `GET /webhook-endpoints` | None |

`GET /invoice-items?invoice=in_...` returns every line of an invoice in one response.

## Rules

* Treat cursors as opaque strings. Don't build or edit them.
* Send the same filters on every page.
* A cursor we didn't issue returns `422 validation`.
* A `customer` or `product` filter that matches nothing of yours returns `404`.
* Unknown `status` or `type` values are ignored, and the list comes back unfiltered.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.