Developers
Lists are read page by page with page and limit.
List routes accept two query parameters:
page: page number, starting at 1.limit: items per page. Each route has its own default and maximum; a value above the maximum is capped at the maximum.
The response carries the list in a property with its own name (documents, items,
contacts…) and the pagination fields total, page and limit,
plus hasMore on most routes. Every paginated route returns total.
hasMore, keep requesting pages while it is true.GET /contacts), compute the pages from total and limit, or use pages when the response carries it.Pagination is not identical on every route. The table below shows what each one does today, and the reference repeats it on each operation.
| Route | Default limit | Maximum limit | Pagination fields |
|---|---|---|---|
GET /billing | 50 | 500 | total, page, limit, hasMore |
GET /suppliers | 50 | 500 | total, page, limit, hasMore |
GET /books/{companyId}/journal-lines | 100 | 500 | total, page, limit, hasMore |
GET /books/{companyId}/accounts | 200 | 500 | total, page, limit, hasMore |
GET /contacts | 50 | 200 | total, page, limit, pages |
The remaining lists have no pagination parameters: they return the whole set matching the filter (for example treasury balances or the accounting reports, which are a single document per date range). Narrow the result with each route's date filters.
const items = [];
for (let page = 1; ; page++) {
const res = await fetch(`https://app.bm.consulting/api/v1/billing?page=${page}&limit=200`, {
headers: { Authorization: `Bearer ${process.env.BMC_TOKEN}` },
});
if (!res.ok) throw new Error(String(res.status));
const body = await res.json();
items.push(...body.documents);
if (!body.hasMore) break;
} import os
import requests
items, page = [], 1
while True:
res = requests.get(
"https://app.bm.consulting/api/v1/billing",
params={"page": page, "limit": 200},
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
body = res.json()
items += body["documents"]
if not body["hasMore"]:
break
page += 1 Request pages sequentially and respect the rate limits: loading a large history costs one request per page.