Skip to main content
Executed-trade records and windowed volume aggregates for one contract. Use GET /v1/trades for the tape, GET /v1/trades/metrics when you only need totals.

Trade history

Returns executed trades for one contract, newest first, within a lookback window. Auth: none required — works on the anonymous free tier. heavy bucket, cost 1 per started 250 rows of limit (so 2 at limit=500).

Request

Out-of-range values are rejected, not clamped. A window_seconds of 100 or a limit of 1000 returns 400, not the nearest legal value.

Example

Response

Records are ordered newest first, deduplicated by trade id, and filtered to 0 < price ≤ 100 with a non-zero size.

Errors

There is no 404. An unknown contract_id returns an empty result, not an error.

Paging backwards

Repeat the request with before set to the oldest timestamp you received (as integer seconds), while has_more is true.
has_more only means “the page came back full.” It is true whenever exactly limit records were returned — it is not a lookahead. Expect one final empty or short page at the end of the tape.
window_seconds always measures back from now, never from before. Page far enough back and your window no longer contains the trades you asked for, so the primary query empties out — at which point the fallback below takes over and paging keeps working.

The empty-window fallback

If the window contains no trades, the query is retried with no lower bound at all (still bounded above by before, or now). The response then carries the most recent trades the contract has before that point, which may be far older than the window you asked for.
Inspect oldest_available_ts to detect this. A value far outside your requested window means you are looking at the fallback, not at trades inside window_seconds.

Notes

  • The implicit “now” upper bound is quantized to a few seconds so repeated polls share a server-side cache. Responses are Cache-Control: private, max-age=5 with no ETag, so this route never returns 304.
  • Prices always refer to the outcome actually traded. To express a trade on any outcome in terms of the other outcome of a binary market, use 100 − price.

Volume metrics

Returns aggregate notional, per-outcome split, and trade count for one contract over a window. Cheaper than paging the tape when you only need totals. Auth: none required. light bucket, flat 1 unit.

Request

Example

Response

Notional is computed per trade as size × price / 100.

Errors

A contract with no trades in the window returns 200 with zeroed volumes and outcome_0_volume_share_pct: 50.0, not a 404.

Notes

outcome_0 / outcome_1 are not a guaranteed Yes/No mapping. On Kalshi they are the yes and no sides. On every other venue they are the two highest-volume outcome tokens in the window, in descending volume order — a volume ranking, recomputed per window. If you need a specific outcome, resolve its token_id from market metadata.
Like /v1/trades, this endpoint is Cache-Control: private, max-age=5 with no ETag.