Concepts
Pagination
HubFit API lists are cursor-paginated. Pass nextCursor back as cursor to fetch the next page, and read totalCount for how many match.
A list returns a page of results in data, newest first unless the endpoint says otherwise, with nextCursor and totalCount.
limit: how many results a page holds, from 1 to 100. The default is 25.nextCursor: pass it back ascursorto get the next page. It'snullon the last page.totalCount: how many results match across every page, ignoringcursorandlimit. Counting stops at 10,000, so 10,000 means at least that many.
Cursors are opaque: don't parse or build them, as their length and format can change. Keep the other parameters the same from page to page.
A page
{
"data": ["…"],
"nextCursor": "eyJpZCI6IjZhZDZhZjNmMjljNTk3ZjE1In0",
"totalCount": 48
}Loop until nextCursor is null. To compare clients over a period, client summaries add it up for you in one row per client, so you don't need every record.
Fetch every client
async function listAll(path, params = {}) {
const results = [];
let cursor = null;
do {
const query = new URLSearchParams({ ...params, limit: "100", ...(cursor && { cursor }) });
const response = await fetch(`https://api.hubfit.com/v1${path}?${query}`, {
headers: { Authorization: `Bearer ${process.env.HUBFIT_API_KEY}` },
});
const page = await response.json();
results.push(...page.data);
cursor = page.nextCursor;
} while (cursor);
return results;
}
const clients = await listAll("/clients");import os
import requests
def list_all(path, params=None):
results, cursor = [], None
while True:
query = {**(params or {}), "limit": 100, **({"cursor": cursor} if cursor else {})}
page = requests.get(
f"https://api.hubfit.com/v1{path}",
headers={"Authorization": f"Bearer {os.environ['HUBFIT_API_KEY']}"},
params=query,
).json()
results.extend(page["data"])
cursor = page["nextCursor"]
if cursor is None:
return results
clients = list_all("/clients")