Reference
Pagination
List endpoints page with an opaque cursor, not page numbers. Cursors are stable under inserts — new rows arriving while you page won't shift or duplicate results — which makes them the right tool for high-write logs like events and the ledger.
Requesting a page
Two parameters, both optional:
limit— page size, default 50, max 200.cursor— the opaque cursor for the next (or previous) page. Omit it for the first page.
curl "https://api.flyhalf.run/v1/events?limit=50" \ -H "Authorization: Bearer fh_live_…"
The response shape
{
"data": [ /* … up to `limit` items, newest first … */ ],
"links": {
"first": null,
"last": null,
"prev": null,
"next": "https://api.flyhalf.run/v1/events?cursor=eyJpZCI6MTA0Mn0"
},
"meta": {
"path": "https://api.flyhalf.run/v1/events",
"per_page": 50,
"next_cursor": "eyJpZCI6MTA0Mn0",
"prev_cursor": null
}
}
Cursor pagination doesn't know first/last positions, so links.first and
links.last are always null. Walk forward with
links.next (or meta.next_cursor) and stop when
next is null. Results are ordered newest-first.
Walking every page
let url = 'https://api.flyhalf.run/v1/events?limit=200'; while (url) { const res = await fetch(url, { headers: { Authorization: 'Bearer fh_live_…' } }); const page = await res.json(); handle(page.data); url = page.links.next; // null on the last page → loop ends }
Treat the cursor as opaque
Cause of subtle breakage: parsing or hand-building the cursor. It's an encoded
token whose format is not a contract and can change. Fix: only ever pass back a
cursor the API handed you, via links.next or meta.next_cursor.
Filters compose with the cursor
Endpoint filters carry across pages automatically as long as you follow the returned
links. For example the event log takes status, event_type,
participant (external id) and since (ISO timestamp);
GET /v1/participants takes search. The
links.next URL already includes your filters alongside the cursor.
Every list endpoint pages this way — events, participants, the ledger, flows, flow runs, event types, ingest endpoints, message templates and webhook subscriptions. One convention, no exceptions.