---
title: "Replay historical whale trades"
method: GET
path: "/api/v1/whale-trades/history"
tags: ["Whale Trades"]
---

# Replay historical whale trades

`GET /api/v1/whale-trades/history`

Returns historical whale trades from local whale_alerts rows, not request-time provider fetches. Filter by condition_id, trader, category, minimum grade, platform, and RFC3339 from/to windows. All filters are pushed into SQL before LIMIT, every request uses SQL-backed limit + 1 pagination, and results are ordered newest first by traded_at desc, id desc. Metadata exposes local_replay source and best_effort completeness.

## Query parameters

- `limit` integer
- `cursor` string
- `min_size` number
- `condition_id` string
- `trader` string
- `category` string
- `min_grade` 'S' | 'A' | 'B' | 'C' | 'D' | 'F'
- `platform` 'polymarket' | 'kalshi' | 'all'
- `from` string, date-time
- `to` string, date-time

## Headers

- `If-None-Match` string

## Response `200`

Historical whale trade replay

- object
  - `object` 'list', required
  - `data` WhaleTrade[], required
    - `id` string, required — Prefixed ID (wt_...).
    - `traded_at` string, date-time, required
    - `size_usd` number, required
    - `side` 'BUY' | 'SELL', required
    - `outcome` string, nullable — Traded outcome label (e.g. "Yes"/"No"/team name), resolved provider-first from the trade's outcome_index against market_canonical (index 0 -> yes, 1 -> no). Distinct axis from side (BUY/SELL): side is the trade direction, outcome is which leg was traded. null for multi-outcome (outcome_index >= 2) or unsynced markets; a Kalshi row carries its provider label here (only token_id is null for Kalshi, since there is no CLOB token).
    - `token_id` string, nullable — The Polymarket CLOB token id (ERC1155 asset id, decimal string) for the traded outcome; null when unavailable (e.g. Kalshi markets, unsynced markets).
    - `price` number, required
    - `signal_score` number, required — Current 0.0–1.0 normalized signal score. This value can change as scoring context changes.
    - `recorded_signal_score` number, nullable, required — 0.0–1.0 signal score written once when the trade row is inserted. Available for new rows after this field launched; legacy rows return null. If a trade is added later, its time-sensitive recorded score reflects that delay.
    - `trader` object, required
      - `id` string, required
      - `address` string, required
      - `username` string, nullable
      - `grade` string, nullable
    - `market` object, required
      - `id` string, required
      - `condition_id` string, required
      - `title` string, required
      - `slug` string, nullable
      - `category` string, nullable — Provider-backed market_canonical category.
  - `has_more` boolean, required
  - `next_cursor` string, nullable
  - `total` integer, nullable — Total matching rows when the read model exposes a count; absent (or null) when it does not.
  - `meta` WhaleTradeHistoryMeta, required
    - `request_id` string, required — Unique request ID (req_ prefix).
    - `cached` boolean, required
    - `cache_age_s` integer, nullable — Cache age in seconds, null if not cached.
    - `source` object, required
      - `kind` 'local_replay', required
      - `table` 'whale_alerts', required
      - `provider_fetch_at_request_time` false, required
    - `completeness` object, required
      - `status` 'best_effort', required
      - `reason` string, required — Explains that local replay completeness can vary by market and time window.

## Other responses

- `304` — Not Modified. Returned when If-None-Match matches the current payload.
- `400` — Invalid request parameter
- `401` — Missing or invalid API key
- `402` — Active Pro subscription required
- `403` — Account access denied
- `408` — Request exceeded the server's 30-second transport timeout. The timeout response has an empty body because it is generated before handler-level JSON error shaping.
- `423` — Account is locked
- `429` — Rate limit exceeded. Two independent budgets. (1) 100 requests/minute per user (sliding window), on every authenticated route. (2) On the BATCH routes only: 2500 batch item units/minute per user, reserved before any item is executed. A batch with N requested items costs N item units, including duplicate and invalid items. 2500 = 100 requests x 25 items per batch, which is the most item work a key can buy through the request limiter at all: a caller may spend their entire 100-request minute on full 25-item batches without the item budget being what stops them. The REQUEST budget is the effective ceiling, and batching is never the more expensive choice. The item budget can still deny at a sliding-window boundary (both counters carry the previous window forward with a floor, and the item counter runs 25x the request counter), so honor a 429 from either. Over-quota batches return 429 with Retry-After before any item work is done.
- `503` — Redis-backed authenticated rate limiter unavailable; retry after the per-process outage cooldown

---

[API](https://skmtc.net/0xinsider/apis/0xinsider-api.md) · [All operations](https://skmtc.net/0xinsider/apis/0xinsider-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/0xinsider/0xinsider-api/revisions/918e082b045a/schema)
