Room ID:
Endpoint:
Rate: 0.025 credits per message
polymarket_markets_stream Endpoint:
wss://api.struct.to/ws Rate: 0.025 credits per message
GET /polymarket/market returns, including per-outcome price with latest_block + latest_confirmed_at watermarks. The server maintains an in-memory cache of open markets only, refreshed via a slow full poll plus a fast 500ms newest-first poll, and merged live from the prediction_condition_metrics and prediction_trades Kafka streams with per-timeframe block/timestamp ordering.
No initial snapshot is pushed on subscribe. Clients seed from GET /polymarket/market and then apply deltas from this stream.
Subscription model
Each client has up to 8 active slots per room (4 cadences × 2 modes). Re-subscribing to the same(interval_ms, mode) pair replaces the previous subscription. Unsubscribe one slot with action: "unsubscribe" plus interval_ms and mode, or clear everything with action: "unsubscribe_all".
- Cadence (
interval_ms):500,1000,3000, or10000. - Filter mode: same validation as the REST list endpoint (timeframe, search length, list caps).
searchis a case-insensitive substring match ontitle. No sort / limit — you get every matching row that changed. - Ids mode: any combination of
condition_ids,market_slugs, andevent_slugs(matches all child markets of those events). Max 500 ids total per subscription.
latest_block >= cached, (b) a confirmed trade with block >= cached, (c) a slow-poll field diff, or (d) the fast newest-first poll discovering a brand-new market. Quiet markets produce zero messages.
Each outcome in outcomes[] carries latest_block and latest_confirmed_at (Unix seconds) — the block/ts of the most recent price write from prediction_position_metrics. Consumers can use these to reject out-of-order price merges locally.
Subscribe
Message fields
| Field | Type | Required | Description |
|---|---|---|---|
action | "subscribe" | "unsubscribe" | "unsubscribe_all" | Yes | Slot lifecycle action. |
interval_ms | 500 | 1000 | 3000 | 10000 | For subscribe / unsubscribe | Flush cadence. Defaults to 1000 if omitted. |
mode | "filter" | "ids" | No | Subscription mode. Defaults to filter. |
filter | MarketsStreamFilter | mode=filter only | Filter body; all fields optional. |
condition_ids | string[] | mode=ids only | 0x-prefixed lowercase 32-byte hex. |
market_slugs | string[] | mode=ids only | Market slug strings. |
event_slugs | string[] | mode=ids only | Event slugs — matches every child market of each event. |
Filter fields (mode=filter)
Supports the same filters as the REST markets list: search, categories, exclude_categories, tags, exclude_tags, min_volume / max_volume, min_txns / max_txns, min_unique_traders / max_unique_traders, min_liquidity / max_liquidity, min_holders / max_holders, start_time / end_time, has_rewards, and timeframe (1m, 5m, 30m, 1h, 6h, 24h, 7d, 30d).
status is not accepted — the cache only holds open markets.
Example — filter mode
Example — ids mode
Unsubscribe one slot
Response
Events
markets_stream_update
Server-pushed event fired only for rows that changed AND matched this subscription since the last flush tick. data contains full market rows — not deltas — so clients should merge by condition_id. Each outcome in data[i].outcomes carries latest_block + latest_confirmed_at price-update watermarks.
Envelope
| Field | Type | Description |
|---|---|---|
type | "markets_stream_update" | Envelope discriminator. |
room_id | "polymarket_markets_stream" | Room identifier. |
mode | "filter" | "ids" | The mode this subscription was created with. |
interval_ms | 500 | 1000 | 3000 | 10000 | The cadence slot this event is flushed under. |
data | MarketResponse[] | Full market rows, same shape as GET /polymarket/market. |
MarketResponse
| Field | Type | Description |
|---|---|---|
condition_id | string | 0x-prefixed condition ID. Required. |
id | string | null | Market ID. |
market_slug | string | null | URL-safe market slug. |
question | string | null | Market question. |
title | string | null | Market title. |
description | string | null | Long description. |
image_url | string | null | CDN image URL. |
oracle | string | null | Oracle contract address. |
status | string | Market status. Required (cache holds only open markets). |
created_time | integer | null | Unix seconds. |
start_time | integer | null | Unix seconds. |
game_start_time | integer | null | Unix seconds (sports markets). |
closed_time | integer | null | Unix seconds. |
end_time | integer | null | Unix seconds. |
accepting_orders | boolean | null | Whether CLOB is accepting new orders. |
uma_resolution_status | string | null | UMA oracle resolution status. |
is_neg_risk | boolean | null | Whether this market uses the neg-risk exchange. |
market_maker_address | string | null | Market maker contract. |
creator | string | null | Wallet address of creator. |
category | string | null | Category label. |
volume_usd | number | null | Lifetime USD volume. |
liquidity_usd | number | null | Current USD liquidity. |
highest_probability | number | null | Highest outcome probability (0 – 1). |
total_holders | integer | null | Unique holder count. |
total_daily_rate | number | null | Combined daily reward rate across sponsors. |
winning_outcome | MarketOutcome | null | Resolved winning outcome, when applicable. |
outcomes | MarketOutcome[] | Market outcomes. |
clob_rewards | ClobReward[] | Active reward configs. |
tags | string[] | Tag labels attached to the market. |
event_slug | string | null | Parent event slug. |
resolution_source | string | null | Resolution source URL. |
metrics | Record<Timeframe, SimpleTimeframeMetrics> | Keyed by timeframe (1m, 5m, 30m, 1h, 6h, 24h, 7d, 30d). |
relevance_score | number | null | Search relevance score, when applicable. |
MarketOutcome
| Field | Type | Description |
|---|---|---|
name | string | Outcome label (e.g. "Yes"). |
price | number | null | Latest price (0 – 1). |
position_id | string | null | ERC-1155 outcome token ID (decimal string). |
outcome_index | integer | null | 0-indexed outcome position. |
latest_block | integer | null | Block of the most recent price update for this outcome. |
latest_confirmed_at | integer | null | Unix seconds of the most recent price update. |
SimpleTimeframeMetrics
| Field | Type | Description |
|---|---|---|
volume | number | USD volume within the window. |
fees | number | USD fees within the window. |
txns | integer | Trade count within the window. |
unique_traders | integer | Unique wallet count within the window. |
ClobReward
| Field | Type | Description |
|---|---|---|
id | string | Reward config ID. Required. |
condition_id | string | Market condition ID. Required. |
asset_address | string | null | Reward token contract. |
rewards_amount | number | null | Total rewards remaining. |
rewards_daily_rate | number | null | Rewards emitted per day. |
start_date | string | null | ISO date the reward starts emitting. |
end_date | string | null | ISO date the reward stops emitting. |
rewards_max_spread | number | null | Max spread eligible for rewards (probability). |
rewards_min_size | number | null | Min order size eligible for rewards (USD). |
native_daily_rate | number | null | Native (Polymarket) daily rate. |
sponsored_daily_rate | number | null | Sponsored daily rate. |
total_daily_rate | number | null | Combined daily rate. |
sponsors_count | integer | null | Number of active sponsors. |