Real-time state for markets — either keyed by a milestone (score, clock, period, weather, …) or by an event ticker (crypto charts, commodity timeseries, weather observations).
Public — no auth required.
| Method | Endpoint |
|---|---|
get(milestone_id, *, include_player_stats=None) |
GET /live_data/milestone/{milestone_id} |
get_event(event_ticker, *, range=None) |
GET /live_data/events/{event_ticker} |
batch(milestone_ids, *, include_player_stats=None) |
GET /live_data/batch |
game_stats(milestone_id) |
GET /live_data/milestone/{milestone_id}/game_stats |
get_typed(milestone_type, milestone_id) |
GET /live_data/{type}/milestone/{milestone_id} (legacy) |
live = client.live_data.get("ms_abc", include_player_stats=True)
print(live.type, live.milestone_id, live.details)LiveData.details is a loose dict[str, Any] — the shape varies by
type (football vs political race vs weather).
live = client.live_data.get_event("KXBTCD-25", range="1h")
print(live.type, live.details, live.default_range, live.range_options)
print(live.is_historical) # True for matured crypto snapshotsEventLiveData has no milestone_id. Optional range is a chart-window
hint (15min, 1h, 1d, …) when the underlying type supports it.
entries = client.live_data.batch(
milestone_ids=["ms_a", "ms_b", "ms_c"],
include_player_stats=False,
)
for entry in entries:
print(entry.milestone_id, entry.type, entry.details)milestone_ids is required and non-empty — passing [] raises ValueError.
Cap: 100 ids per call.
resp = client.live_data.game_stats("ms_abc")
if resp.pbp is None:
print("no play-by-play for this milestone type")
else:
for period in resp.pbp.periods:
for event in period.events:
print(event) # free-form dict; shape varies by sportgame_stats works only for sports milestones with play-by-play coverage.
Other milestone types return pbp=None. Each period's events is a list of
loose dicts (no fixed play schema upstream).
live = client.live_data.get_typed("sports_game", "ms_abc")Prefer get() over get_typed(). The latter wraps the legacy
/live_data/{type}/milestone/{id} path and is retained only for callers that
still depend on it. The Python kwarg is milestone_type (not type) to avoid
shadowing the built-in; the wire path still uses {type}.
::: kalshi.resources.live_data.LiveDataResource options: heading_level: 3
::: kalshi.resources.live_data.AsyncLiveDataResource options: heading_level: 3