Skip to main content
PredictStreet list endpoints use offset, page-number, cursor, or time-cursor pagination. Pagination parameters are endpoint-specific. Depending on the endpoint, an unsupported query parameter is either ignored or rejected with HTTP 400 (for example, /api/events rejects offset, cursor, skip, start and pageSize, and /api/orders/open / /api/orders/history reject any parameter they don’t define), so only send the parameters listed below. This page inventories both integration-facing endpoints and first-party retail endpoints. Rows marked Retail belong to the web app’s signed-in user session. They are included for completeness, but they are not part of the API-key integration surface.

General rules

  • Treat every cursor as opaque. Pass nextCursor back unchanged; do not parse or construct cursors.
  • Keep filters and limit unchanged when following a cursor.
  • before is a legacy time cursor on endpoints that also expose cursor; prefer cursor for new integrations.
  • A page shorter than its requested limit is the final page when the response does not expose nextCursor — except on /api/events, which has no nextCursor or hasMore: keep paging it until a response holds no events.
  • Limit overflow is endpoint-specific: some endpoints return HTTP 400, while others clamp to their maximum (/api/events serves any limit above 100 as 100). Follow the endpoint’s own reference when a maximum is listed.

Offset and page-number endpoints

For offset pagination, request the next page with offset = offset + limit. For /api/events, increment page — see Events list pages.

Events list pages

At most 100 events per response. GET /api/events never returns more than 100 events in one response. A limit above 100, or a numeric from/to span wider than 100, is served as 100 events — it is not rejected, and the response carries X-Events-Window-Capped: 100 (as does a request with no window at all — see below). Before this change the cap was 500, a request without page/limit returned up to 500 events, and a limit above 500 was a 400 invalid_limit. Migration notes: Changelog.
Positions are 0-based over the sorted result list.
  • page and limit take digits only, 1 or more; anything else is 400 invalid_page / 400 invalid_limit.
  • Beside page/limit, a from/to must be an ISO-8601 date that starts YYYY-MM-DD (2026-10-01, read as 00:00 UTC, or 2026-10-01T00:00:00Z). Any other value there is 400 ambiguous_pagination: a digits-only position would set the position twice, and a value not written as a date could be read either way.
  • A response whose request asked for more than 100 events — a limit above 100, or a digits-only to more than 100 past from (from defaults to 0) — or for no window at all (no page/limit and no digits-only to, which used to mean up to 500 events) carries the header X-Events-Window-Capped: 100, also on a 304. A limit, or a digits-only span, of 100 or less never carries it. The header describes the request, not the list: it does not mean more events follow, so keep paging until a page comes back empty. Browsers can read it cross-origin; it is in the CORS Access-Control-Expose-Headers allowlist.
  • Positions stop at 1,000,000: a page starting deeper is 400 invalid_page, a larger numeric from/to is 400 invalid_from / invalid_to (error.details.max is 1000000).
  • A digits-only value is always a position. from=2026 means position 2026, not the year 2026, and an epoch-millisecond timestamp is rejected with invalid_from. Send dates as full ISO-8601 with Z or an explicit offset, for example 2026-10-01T00:00:00Z.
  • offset, cursor, skip, start and pageSize are rejected with 400 (invalid_offset, invalid_cursor, invalid_skip, invalid_start, invalid_page_size; error.details.param names the parameter).
  • There is no hasMore or cursor. The first page — page=1, from=0, or no page and no digits-only from — also carries total, the number of events matching every filter, independent of paging, and openMarketCount / totalMarketCount, their market counts summed. Later pages carry none of them, except with q, where every page does (with facets). Treat them as optional: when they cannot be computed in time, the first page comes without them. They are as old as the page they come on (see Events). total is not a stop signal — keep paging until a page comes back empty.

Walking the whole list

Request page=1, 2, 3, … with limit=100 and every other parameter unchanged. Stop at the first empty page ("events": []). A page with fewer than 100 events is usually the last one, but not always: an event can take a slot in a page and then be left out of it (for example when its markets change status while the page is built), so a short page can appear mid-list.
-f stops the walk on a 429 or 5xx instead of reading the error body as an empty page (retry after Retry-After); --compressed cuts a full page from megabytes to a few hundred KB.
  • Do not stop on “shorter than limit” with a limit above 100: limit=500 returns 100 events per page, so every page is shorter than 500.
  • If you page with a numeric from/to, step by 100 (from=0&to=100, from=100&to=200, …). A step of 500 now skips events: from=500&to=1000 returns positions 500–599, and positions 100–499 are never read.
  • Pages are built and cached one by one, not from one snapshot. When the catalogue changes during a walk, an event can show up on two pages or be missed. De-duplicate by id.
  • To fetch fewer pages, narrow the query instead: vertical, competition, tag, status=closed or an ISO-8601 from/to range all combine with page/limit.

Cursor endpoints

Cursor endpoints with legacy before

Time-cursor and limit-only endpoints