---
title: "Api V2 Replay Range Get"
method: GET
path: "/api/v2/replay/range"
tags: ["Replay (v2)"]
---

# Api V2 Replay Range Get

`GET /api/v2/replay/range`

## Request

- Base URL: `https://api.zerogex.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.zerogex.io/api/v2/replay/range`
- Auth: HTTP bearer

All replay frames for one session — bundled for the playhead buffer.

Returns per-minute ``gex_summary`` + ``gex_by_strike`` bars for the
requested ET session date so a single round-trip pre-warms an entire
session into the browser. The scrubber then renders locally without
a per-frame fetch.

``strike_band_pct`` filters strikes to a ±band around each bar's
spot so the payload stays bounded — a full-chain SPX session would
be ~40k rows otherwise. Default 4% covers the strikes that actually
matter for a same-day dealer-positioning view.

``timeframe`` is accepted but currently ignored: we always return
1-min frames. 5-min / 15-min down-sampling is a v2 optimization
when payload size becomes a real problem.

``include_expirations`` opts into the per-strike expiration mix that
drives the scrubber's expiry colour gradient. Each strike then also
carries ``call_shares`` / ``put_shares`` — fractions summing to 1,
aligned positionally to the response's top-level ``expirations`` legend
(nearest-first, with a trailing "far" slot when the chain runs deeper
than ``max_expirations``). Shares only ever SUBDIVIDE the call/put totals
already in the payload, so a client that ignores them renders exactly what
it renders today. Off by default because it costs a second session-wide
scan and grows the bundle; callers that only need the aggregate ladder
(e.g. the pair-comparison scrubber) should leave it off.

``expirations`` scopes the session.  ``0dte`` — the case the replay exists
for — is the session's own expiry: on ``/replay/SPY/2026-09-15`` that is
2026-09-15, resolved from the requested date rather than from today, so a
shared link keeps meaning what it meant.  Under a scope every per-strike
bar carries only those expirations, and ``call_wall`` / ``put_wall`` /
``gamma_flip`` / ``max_pain`` are re-derived from that same filtered book
(the stored ones are whole-chain and would describe bars that aren't on
screen).  ``pin_strike`` / ``pin_confidence`` and ``max_gamma_strike`` do
NOT move with the scope — both are whole-chain by definition, exactly as
they behave under ``/api/gex/strike-profile-timeseries``'s filter and in
the live charts' Expiry selector.  The response echoes the resolved scope
as ``expiration_filter`` (``null`` for All) so a client never has to infer
what it got.

A scoped session with no matching contracts (0DTE on a day the chain had
no same-day expiry) returns its frames with EMPTY ladders and null levels
rather than silently falling back to the whole chain — "all expirations" is
the one answer a 0DTE request must not quietly become.

## Query parameters

- `symbol` string
- `date` string, required: Trading day YYYY-MM-DD (ET).
- `timeframe` string
- `strike_band_pct` number
- `include_expirations` boolean: Attach the per-strike expiration mix (shares) so a client can colour-grade each bar by time-to-expiry. Off by default: it is a second session-wide scan and it grows the payload.
- `max_expirations` integer
- `expirations` string: Expiration scope for the whole session: 'all' (default, every expiration aggregated), '0dte' (the session's own expiry), or a comma-separated list of YYYY-MM-DD dates. Under a scope the ladder carries only those expirations and the walls / flip / max pain are re-derived from it.

## Response `200`

Successful Response

- EnvelopeAny
  - `data` unknown, required
  - `freshness` Freshness, required: The v2 freshness envelope. Present on every ``/api/v2/*`` response.
    - `evaluated_at` string, date-time, required: When the API evaluated this response (server wall clock, UTC). Endpoint-health signal: advances on every request even when the underlying data is unchanged.
    - `generated_at` string, date-time, required: When the served data was computed. Equals the snapshot stamp for cycle-backed endpoints, or evaluated_at for endpoints computed on demand for this request.
    - `source_timestamp` string, date-time, nullable: Timestamp of the upstream market observation the payload derives from. This is what freshness_status is measured against. Null when the endpoint has no upstream feed or returned no rows.
    - `latest_event_at` string, date-time, nullable: Newest event timestamp present in the payload (last bar, last trade, last scored row). Best-effort on very large responses, which are sampled rather than fully walked.
    - `age_seconds` number, nullable: evaluated_at - source_timestamp, in seconds. Null when source_timestamp is null.
    - `market_session_status` string, required: pre-market | regular | after-hours | closed (US/Eastern).
    - `expected_update_cadence` string, nullable: ISO-8601 duration for how often this endpoint's data is expected to change right now, e.g. PT60S. Null means no updates are expected (weekend, holiday, or a feed that only runs during the session).
    - `expected_update_cadence_seconds` number, nullable: expected_update_cadence as a number of seconds.
    - `cadence_profile` string, required: Identifier of the cadence class this endpoint belongs to, e.g. analytics_cycle. Stable across releases; the seconds behind it may be retuned.
    - `stale_after` string, date-time, nullable: Instant after which this payload should be treated as stale. Null whenever expected_update_cadence is null.
    - `freshness_status` 'fresh' | 'aging' | 'stale' | 'session_closed' | 'static' | 'unknown', required: The rolled-up freshness verdict for one response. ``fresh`` ``source_timestamp`` is within one expected update cadence. ``aging`` Past one cadence but not yet past ``stale_after`` — the grace band that absorbs normal cycle jitter. Not an error; a client that polls faster than the cadence sees this routinely. ``stale`` Past ``stale_after`` while updates *were* expected. This is the actionable state: the feed behind this endpoint is late. ``session_closed`` A feed-backed endpoint whose feed is not due to produce anything right now (weekend, holiday, or a feed that only runs during the session). The payload is the last good value — deliberately NOT reported as ``stale``, because an overnight consumer polling a closed market is not observing a fault and should not page on it. ``static`` The endpoint is not feed-backed at all: completed history, or a result computed from the caller's own inputs. Age here carries no health meaning and never becomes a fault. ``unknown`` No source timestamp could be resolved from the payload (e.g. a pure calculator, an admin endpoint, or an empty result set). A consumer should fall back to ``evaluated_at`` for endpoint health and make no claim about data age.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/zerogex/apis/zerogex-api.md) · [All operations](https://skmtc.dev/zerogex/apis/zerogex-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zerogex/apis/zerogex-api/revisions/753b26bf0592?raw)
