Guide
Pagination
On this page
The pagination object#
Paginated endpoints are marked with the paginated badge in the reference. They take limit and cursor_id.
Pagination object
countintegerrequiredhas_morebooleanrequiredlimitintegerrequirednext_cursor_idstring | nullrequiredPass as cursor_id to fetch the next page; null on the last page.next_urlstring | nullrequiredRelative URL of the next page; null on the last page.
| Member | Meaning |
|---|---|
limit | The page size that was applied. |
count | Rows in this page. |
has_more | true when another page exists. |
next_cursor_id | Opaque token for the next page, null on the last page. |
next_url | The same request with cursor_id set: a relative URL you can call as is, null on the last page. |
Read everything#
Call the endpoint, then repeat with cursor_id=<pagination.next_cursor_id> (or request next_url) until next_cursor_id is null.
async function* pages(path, params) {
let cursor;
do {
const query = new URLSearchParams(params);
if (cursor) query.set("cursor_id", cursor);
const res = await fetch(`https://api.ordermap.si${path}?${query}`, {
headers: { Authorization: `Bearer ${process.env.ORDERMAP_API_KEY}` },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const body = await res.json();
yield* body.data;
cursor = body.pagination.next_cursor_id; // null on the last page
} while (cursor);
}
for await (const print of pages("/v1/options/trades", { underlying_symbol: "SPXW", date: "2026-10-16", limit: "500" })) {
console.log(print.option_symbol, print.price, print.size);
}url="https://api.ordermap.si/v1/options/trades?underlying_symbol=SPXW&date=2026-10-16&limit=500"
while [ -n "$url" ]; do
page=$(curl -sS --compressed "$url" -H "Authorization: Bearer $ORDERMAP_API_KEY")
echo "$page" | jq -c '.data[]'
next=$(echo "$page" | jq -r '.pagination.next_url // empty')
url=${next:+https://api.ordermap.si$next}
doneCursors#
- Keep every other parameter the same. A cursor is bound to your account, the endpoint and the query. A changed query, another account's cursor, a garbled cursor or an expired one (cursors live 24 hours) is
400 invalid_cursor.limitmay change between pages. - Treat cursors as opaque: their format is not part of the contract.
- Most cursors are keysets and never repeat or skip a row. Endpoints that page by offset over a snapshot (/v1/options/screener and /v1/options/open-interest/change) answer
snapshot_changedinmeta.warningswhen the underlying data was refreshed between pages. Rows may then repeat or be skipped.
A page can be short#
A page can hold fewer than `limit` rows while more remain. Filters are applied while the data is scanned, chain endpoints read one expiration at a time, and sparse ranges can yield an empty page that still has a cursor. Stop on next_cursor_id: null (or has_more: false), never on a short page.
When a filtered scan used up its per-request budget before filling the page, meta.coverage.scan_complete is false and scanned_through says how far it got. The cursor continues the scan.
Order#
- Raw tick and trade tapes are returned oldest first and page forward: /v1/options/contract/trades, /v1/stocks/trades and /v1/futures/trades.
- The engine-backed option flow endpoints (/v1/options/flow, /v1/options/trades, /v1/options/flow/unusual and /v1/options/flow/overnight) are newest first and page back through the session.
- Each endpoint's description states its order.
Pagination over WebSockets and exports#
- A paginated endpoint streamed over /v1/ws/analytics returns its first page only, with
next_cursor_idandnext_urlset tonull. - An export follows the pages for you. On a paginated endpoint
limitis then the maximum number of rows in the file, andcursor_idis not accepted.