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

# Pagination and filters

> Accumulate complete records with opaque cursors and strict query parameters.

## Read every page

Collections default to **50 parent records per page**, with a maximum of **100**. `data` contains the records, `pagination.next_cursor` contains a continuation token or null, and `meta` supplies request ID, generation time, and company timezone. Follow the cursor until null. Keep the same company, endpoint, and filters; the page size may change between requests. Most timestamped collections order by `created_at`, then `id`, ascending. Equipment, form responses, job financials and revenue attributions order by UUID `id` ascending; job classes order by code `id` ascending. These orders are fixed. Cursors are opaque and cannot be transferred to another company or endpoint. Report rows follow the same page-size rules.

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
GET /v1/invoices?limit=2
Authorization: Bearer YOUR_API_KEY

GET /v1/invoices?limit=1&cursor=example-opaque-cursor
Authorization: Bearer YOUR_API_KEY
```

The fictional first page contains invoices 1001 and 1002, with complete children. The second contains 1003 and a null cursor. `example-opaque-cursor` illustrates the format; only a real API response would supply a usable token. Both list and detail reads return the same invoice shape. Page limits apply to parents, never silently to their children. Large documents may therefore produce larger responses even at `limit=1`.

## Encode filters

Omit a filter to leave it unrestricted, and omit `cursor` to start the first page. A null query-schema default represents an omitted value; do not send the literal string `null` or an empty value.

Combine documented filters with AND. Repeated `ids` or `status` values mean OR within that field; use `ids=ID_A&ids=ID_B`, not comma-separated values. Up to 100 IDs may be supplied. Foreign or missing IDs contribute no list results. Repeated scalar parameters, empty values, invalid UUIDs, unknown query parameters, and unsupported filters return 400. Valid filters matching no records return an empty page with a null cursor.

`created_from` and `created_before` are inclusive/exclusive instants. Invoices and payments support `updated_since` as an inclusive parent-row edit instant; payments with null `updated_at` do not match it. Refunds do not support this filter. `issued_from`/`issued_before` and `occurred_from`/`occurred_before` are inclusive/exclusive company-local dates. A supplied upper bound must be later than its lower bound. Null dates do not match date filters. Invoice lists include every status by default; `status=OPEN` provides AR detail. The invoice-activity summary defaults to OPEN and PAID instead.

Use a query-string encoder rather than assembling cursor values or timestamp offsets by hand:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --fail-with-body --silent --show-error --get "https://api.getbreezyapp.com/v1/invoices" \
  --header "Authorization: Bearer $BREEZY_API_KEY" \
  --data-urlencode "ids=$BREEZY_INVOICE_ID_A" \
  --data-urlencode "ids=$BREEZY_INVOICE_ID_B" \
  --data-urlencode "limit=10"
```

## Refresh after the first pass

Keep successful pages when a request fails and retry the same cursor. Treat a multi-page report as incomplete until its last page succeeds. See [Build a reporting store](/reporting-store) for refresh and reconciliation strategies.

Reads use latest corrected records. A cursor and `generated_at` do not freeze data across requests. The API offers no guaranteed incremental synchronization or deletion feed, and an `updated_since` query does not cover all dependent changes. Clients may observe corrections between pages; retry or refresh the relevant query when reconciling current results. Responses should be treated as private company data and use `Cache-Control: private, no-store`.
