Skip to content

Developers

Pagination

Lists are read page by page with page and limit.

The pattern

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.

Knowing whether there are more pages

  • If the response includes hasMore, keep requesting pages while it is true.
  • If it does not (today, 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.

Paginated routes

RouteDefault limitMaximum limitPagination 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.

Walking every page

TypeScript (fetch)
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;
}
Python (requests)
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.

Email
Contact