Skip to content

Guide

Pagination

Paginated endpoints take limit and cursor_id and add a pagination object to the response. Stop on a null cursor, never on a short page.
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

  • countintegerrequired
  • has_morebooleanrequired
  • limitintegerrequired
  • next_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.
MemberMeaning
limitThe page size that was applied.
countRows in this page.
has_moretrue when another page exists.
next_cursor_idOpaque token for the next page, null on the last page.
next_urlThe 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);
}

Cursors#

  • 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. limit may 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_changed in meta.warnings when 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#

Pagination over WebSockets and exports#

  • A paginated endpoint streamed over /v1/ws/analytics returns its first page only, with next_cursor_id and next_url set to null.
  • An export follows the pages for you. On a paginated endpoint limit is then the maximum number of rows in the file, and cursor_id is not accepted.