> Documentation index: https://beezr.io/developers/api/llms.txt

# Paging through results

## Read the metadata

`query` returns `data` as an array and `meta` with four fields. `meta` appears only on query responses.

| Field | Meaning |
|---|---|
| `total` | Records that match |
| `limit` | Page limit |
| `offset` | Page offset |
| `returned` | Records in this page |

`limit` defaults to 20 and is clamped to 1–100. `offset` defaults to 0 and is never negative. There are more pages while `offset + returned < total`. Advance by `returned`, not by a guessed page size.

## Loop through pages

These loops stop if the call fails or returns an empty page. Use [rate-limit handling](/developers/api/limits/) around each call in a running integration. Keep at most 2 calls in flight.

```curl
# This shell loop uses Python to read JSON metadata.
offset=0
while true; do
  body=$(printf '{"module":"cm_equipment_requests_base","fields":["title"],"limit":100,"offset":%s}' "$offset")
  response=$(curl --fail-with-body --silent --show-error \
    "https://services.beezr.io/generic/api/v4/records/query" \
    -H "X-API-Key: $BEEZR_API_KEY" -H "Content-Type: application/json" \
    --data "$body") || break
  printf '%s\n' "$response"
  next=$(printf '%s' "$response" | python -c 'import json,sys; r=json.load(sys.stdin); m=r["meta"]; print(m["offset"]+m["returned"] if r["success"] and m["returned"] and m["offset"]+m["returned"]<m["total"] else -1)') || break
  [ "$next" -lt 0 ] && break
  offset=$next
done
```

```javascript
let offset = 0;
while (true) {
  const response = await fetch("https://services.beezr.io/generic/api/v4/records/query", {
    method: "POST",
    headers: { "X-API-Key": process.env.BEEZR_API_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ module: "cm_equipment_requests_base", fields: ["title"], limit: 100, offset })
  });
  const page = await response.json();
  if (!response.ok || !page.success) throw new Error(JSON.stringify(page));
  console.log(page.data);
  const { returned, total } = page.meta;
  offset = page.meta.offset + returned;
  if (!returned || offset >= total) break;
}
```

```python
import os
import requests

offset = 0
while True:
    response = requests.post(
        "https://services.beezr.io/generic/api/v4/records/query",
        headers={"X-API-Key": os.environ["BEEZR_API_KEY"]},
        json={"module": "cm_equipment_requests_base", "fields": ["title"], "limit": 100, "offset": offset},
    )
    response.raise_for_status()
    page = response.json()
    if not page["success"]:
        raise RuntimeError(page)
    print(page["data"])
    meta = page["meta"]
    offset = meta["offset"] + meta["returned"]
    if not meta["returned"] or offset >= meta["total"]:
        break
```


## Keep exports small

Use `fields` to request only what you need. `id` always comes back. File fields in v4 are references, so a query doesn't include file bytes. Download files separately with [Download a file](/developers/api/reference/download-file/).

The [export guide](/developers/api/guides-export/) puts these steps together.

