Pagination

When it applies

Pagination only applies to table-shaped tools: endpoints that return rows, one per record. Aggregation tools (Net Drift, Net Flow, Gainers / Losers, Heat Map, …) return a complete result for the requested window in a single response; there is nothing to page through.

Paginated endpoints
  • /v1/options/tool/order-flow/consolidated: blocks, splits, sweeps, and their comprising trades.
  • /v1/options/tool/order-flow/unconsolidated: trade-by-trade option tape.
  • /v1/equities/tool/equity-prints: trade-by-trade equity tape (lit and dark venues).

Page size

The size request field controls how many rows come back per page. It is bounded so a single request cannot ask the server for an unbounded result set.

Size rules
  • size is optional. Omitted requests get 50 rows.
  • Valid range is 1100 inclusive. Anything outside that returns a 400 · validation response naming the offending field.
  • The chosen size applies to every page in a walk; the cursor does not carry it. Setting size: 25 on the first request and size: 100 on the next is allowed but unusual.
  • A short final page does not signal the end on its own. Only a null nextSearchAfter in the response means there is nothing else to fetch.

The cursor

Each response carries nextSearchAfter, an opaque cursor. Pass it back as searchAfter on the next request to continue where the previous page ended. null means there is no next page.

Cursor rules
  • nextSearchAfter is a list of strings. The shape is intentionally opaque; its meaning is an implementation detail and is not stable across endpoints or versions.
  • Pass the value back verbatim as searchAfter on the next request. Do not parse, edit, or transcribe it across requests with different filter or sort fields.
  • Cursors are tied to the request that produced them. Changing the filter, the sort, the session date, or the time range between pages can produce duplicate or skipped rows.
  • On the first request, searchAfter is null (or omitted entirely).

Walking a result set

Three requests walk a result set start to finish: the first page (no cursor), the second page (paste back the cursor), and the last page (cursor comes back as null).

First page
Send the request without searchAfter. The server returns the first size rows along with a nextSearchAfter cursor.
Subsequent pages
Send the same request body, plus searchAfter set to the prior response's nextSearchAfter. Repeat until nextSearchAfter comes back as null.
Stop on null
A null cursor is the only signal that the walk is complete. A response shorter than size on its own does not mean the end; that can happen mid-walk too.

First page · request

POST /v1/equities/tool/equity-prints
// First page: no searchAfter.
{
  "sessionDate": "2026-05-13",
  "filter": {
    "tickers": ["AAPL"]
  },
  "size": 50,
  "sort": {
    "field": "tradeTime",
    "direction": "DESCENDING"
  }
}

First page · response (truncated)

200 OK · 50 prints
{
  "nextSearchAfter": [
    "1747144203000",
    "9f7f7d52-..."
  ],
  "prints": [
    {
      "ticker": "AAPL",
      "price": 185.41,
      "size": 100,
      "tradeTime": 1747144203000,
      "...": "..."
    }
    // ... 49 more
  ]
}

Next page · request

POST /v1/equities/tool/equity-prints
// Next page: paste the prior response's nextSearchAfter verbatim.
{
  "sessionDate": "2026-05-13",
  "filter": {
    "tickers": ["AAPL"]
  },
  "size": 50,
  "sort": {
    "field": "tradeTime",
    "direction": "DESCENDING"
  },
  "searchAfter": [
    "1747144203000",
    "9f7f7d52-..."
  ]
}

Final page · response

200 OK · cursor null
// nextSearchAfter is null on the last page: stop paging.
{
  "nextSearchAfter": null,
  "prints": [
    {
      "ticker": "AAPL",
      "price": 184.92,
      "size": 200,
      "tradeTime": 1747147800000,
      "...": "..."
    }
    // ... fewer than 'size' rows if you ran out before filling the page.
  ]
}

Sort and stability

The cursor encodes the sort. Pagination is stable across page boundaries only when the filter, sort, and time window stay the same between requests. Changing any of them invalidates the cursor.

Each paginated tool has a default sort. For the tape endpoints, that is tradeTime DESCENDING. You can override it via sort on the first request, then keep paging with the same sort to walk the result set in that order. Mid-walk sort changes are not supported; start a new walk with a fresh first request instead.

A note on duplicates: if new rows arrive in the underlying data store between page N and page N+1, you can see the same row twice across pages; the cursor is positional, not a snapshot. For walks that need to be perfectly snapshot-consistent, narrow the time range to a window that has already closed (a past session date, or a timeRange whose endTime is in the past).

Where to go next