Pagination
Cursor-based paging, and why this API does not use offsets.
List endpoints are paged with an opaque cursor. Follow next_cursor until it is null.
# First page
curl -sS "https://api.cruxal.in/v1/filings?limit=50" \
-H "Authorization: Bearer $CRUXAL_API_KEY"
# Next page
curl -sS "https://api.cruxal.in/v1/filings?limit=50&cursor=eyJ2IjoxLCJ0Ijo..." \
-H "Authorization: Bearer $CRUXAL_API_KEY"
Every list response has the same envelope:
{
"data": [ ... ],
"next_cursor": "eyJ2IjoxLCJ0Ijo...",
"has_more": true
}
When has_more is false, next_cursor is null and you are done.
Why there is no ?page= or ?offset=
The filings feed grows continuously — new rows arrive at the top throughout the trading day.
With offset paging, rows shift down between your request for page 1 and your request for page
2, so OFFSET 50 lands somewhere different than it would have a moment earlier. You silently
skip filings and see others twice. That is unacceptable for a feed people trade on.
A cursor anchors on the last row you actually received, so new arrivals cannot disturb pages you have already read.
There is no total count
Deliberately. Counting the full matching set requires scanning it, on every page — the precise
cost cursor paging exists to avoid — and on a feed that changes every thirty seconds the number
would be stale before you read it. Page until has_more is false.
Cursors are opaque
Do not parse, construct or modify a cursor. The encoding is an implementation detail and may change without a version bump. Store it as a string and hand it back.
Changing a filter invalidates the cursor
A cursor is issued against a specific set of filters and sort order. Reusing it with different
ones returns a 400:
{
"type": "https://www.cruxal.in/docs/errors#bad-request",
"title": "Bad Request",
"status": 400,
"detail": "Cursor was issued for a different set of filters. Restart pagination without a cursor after changing any filter or sort order."
}
This is a guard rail, not an obstacle. Without it, the cursor would silently anchor to a position in a result set you are no longer requesting, and the results would be quietly meaningless. Change a filter, drop the cursor, start again.
How long a cursor stays valid
For the duration of a paging session. Cursors do not expire on a clock, but they describe a position in a live feed: if a filing's publication time is later corrected, one row near that boundary could be skipped or repeated. Page through a result set promptly rather than storing a cursor for days.