Skip to main content
List endpoints return a single page plus a pagination block on the response envelope:
const { data, pagination } = await client.markets.getMarkets({ limit: 100 });

pagination?.has_more;
pagination?.pagination_key;
You can walk pages manually by feeding pagination_key into the next call, or use the paginate helper to iterate through every item as a stream.

paginate

paginate(fetcher, params, pageSize?) is an async generator that lazily pulls each page and yields individual items. It terminates when the server reports has_more: false or returns a null pagination_key.
import { StructClient, paginate } from "@structbuild/sdk";

const client = new StructClient({ apiKey: "sk_live_xxx" });

for await (const market of paginate(
  (params) => client.markets.getMarkets(params),
  { tags: "politics" },
  100,
)) {
  console.log(market.slug, market.last_price);
}
ArgumentTypeDescription
fetcher(params) => Promise<HttpResponse<T[]>>A namespace method bound to the client.
paramsbase params objectEverything except limit and pagination_key, which are managed by the helper.
pageSizenumberOptional page size. Defaults to 100.
Any list-style namespace method works:
for await (const trade of paginate(
  (params) => client.markets.getTrades(params),
  { condition_ids: "0xabc..." },
)) {
}

for await (const event of paginate(
  (params) => client.events.getEvents(params),
  { tags: "politics" },
)) {
}

for await (const trader of paginate(
  (params) => client.trader.getGlobalPnl(params),
  {},
)) {
}

Early termination

You can stop iterating at any time. Exiting the for await loop stops fetching the next page, so you only pay for what you read.
let count = 0;

for await (const trade of paginate(
  (params) => client.markets.getTrades(params),
  { condition_ids: "0xabc..." },
)) {
  if (++count >= 500) break;
}

Manual pagination

If you prefer to walk pages yourself (for example, to render a paginated UI), skip the helper and drive the cursor directly:
let cursor: string | number | undefined;

while (true) {
  const page = await client.markets.getMarkets({
    limit: 100,
    pagination_key: cursor,
  });

  render(page.data);

  if (!page.pagination?.has_more || page.pagination.pagination_key == null) break;
  cursor = page.pagination.pagination_key;
}

Offset vs pagination_key

A few endpoints (the trader trades and PnL methods) also accept an offset param that skips a fixed number of rows. It exists for one case: server-rendered, deep-linkable pages, where ?page=42 maps to offset=4100 and you need to render that slice on the first request without replaying every page to obtain a cursor.
const page = await client.trader.getTraderTrades({
  address: "0x...",
  limit: 100,
  offset: 4100,
});
offset is capped at a few thousand rows (typically in the 3,000 to 5,000 range), so it cannot reach deep into a large dataset. For everything else, prefer pagination_key. Cursor pagination is the right default for any programmatic consumer, while offset is reserved for rendering a specific page directly from a URL.
When both offset and pagination_key are supplied on the same request, offset takes precedence and the cursor is ignored.
The paginate helper always uses cursor pagination, so it never sends an offset. See the API Reference for the underlying query parameters. For a complete worked backfill, see Fetching an entire dataset.
Last modified on June 8, 2026