Market Stream
Use the market stream to keep your application in sync with changes to a market’s order book and trading state.- TypeScript
- Python
- API
Given a
Enable
PublicClient or SecureClient, subscribe to the market topic with one or
more token IDs:const tokenId = "<token_id>";
const stream = await client.subscribe([
{
topic: "market",
tokenIds: [tokenId],
},
]);
for await (const event of stream) {
switch (event.type) {
case "book":
// event: MarketBookEvent
break;
case "price_change":
// event: MarketPriceChangeEvent
break;
case "last_trade_price":
// event: MarketLastTradePriceEvent
break;
case "tick_size_change":
// event: MarketTickSizeChangeEvent
break;
}
}
Standard Market Events
Standard Market Events
Order Book
type OrderBookLevel = {
price: DecimalString;
size: DecimalString;
};
type MarketBookEvent = {
topic: "market";
type: "book";
payload: {
market: string;
tokenId: TokenId;
bids: OrderBookLevel[];
asks: OrderBookLevel[];
hash?: string | null;
timestamp?: string | null;
minOrderSize?: DecimalString | null;
tickSize?: DecimalString | null;
negRisk?: boolean | null;
lastTradePrice?: DecimalString | null;
};
};
{
"topic": "market",
"type": "book",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"tokenId": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"bids": [{ "price": "0.08", "size": "33343.4" }],
"asks": [{ "price": "0.09", "size": "163939.58" }],
"hash": "0xabc123…",
"timestamp": "1782753357257"
}
}
Price Change
type PriceChange = {
tokenId: TokenId;
price: DecimalString;
size: DecimalString;
side: OrderSide;
hash?: string | null;
bestBid?: DecimalString | null;
bestAsk?: DecimalString | null;
};
type MarketPriceChangeEvent = {
topic: "market";
type: "price_change";
payload: {
market: string;
priceChanges: PriceChange[];
timestamp?: string | null;
};
};
{
"topic": "market",
"type": "price_change",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"priceChanges": [
{
"tokenId": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"price": "0.08",
"size": "33343.4",
"side": "BUY",
"hash": "56621a121a47ed9333273e21c83b660cff37ae50",
"bestBid": "0.08",
"bestAsk": "0.09"
}
],
"timestamp": "1782753357257"
}
}
Last Trade Price
type MarketLastTradePriceEvent = {
topic: "market";
type: "last_trade_price";
payload: {
market: string;
tokenId: TokenId;
price: DecimalString;
size?: DecimalString | null;
feeRateBps?: DecimalString | null;
side: OrderSide;
timestamp?: string | null;
transactionHash?: string | null;
};
};
{
"topic": "market",
"type": "last_trade_price",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"tokenId": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"price": "0.08",
"size": "219.217767",
"feeRateBps": "0",
"side": "SELL",
"timestamp": "1782753357257",
"transactionHash": "0xeeefff…"
}
}
Tick Size Change
type MarketTickSizeChangeEvent = {
topic: "market";
type: "tick_size_change";
payload: {
market: string;
tokenId: TokenId;
oldTickSize?: DecimalString | null;
newTickSize: DecimalString;
timestamp?: string | null;
};
};
{
"topic": "market",
"type": "tick_size_change",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"tokenId": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"oldTickSize": "0.01",
"newTickSize": "0.001",
"timestamp": "1782753357257"
}
}
customFeatureEnabled to include top-of-book and market lifecycle
updates:const stream = await client.subscribe([
{
topic: "market",
tokenIds: [tokenId],
customFeatureEnabled: true,
},
]);
for await (const event of stream) {
switch (event.type) {
case "book":
// event: MarketBookEvent
break;
case "price_change":
// event: MarketPriceChangeEvent
break;
case "last_trade_price":
// event: MarketLastTradePriceEvent
break;
case "tick_size_change":
// event: MarketTickSizeChangeEvent
break;
case "best_bid_ask":
// event: MarketBestBidAskEvent
break;
case "new_market":
// event: NewMarketEvent
break;
case "market_resolved":
// event: MarketResolvedEvent
break;
}
}
Additional Market Events
Additional Market Events
Best Bid and Ask
type MarketBestBidAskEvent = {
topic: "market";
type: "best_bid_ask";
payload: {
market: string;
tokenId: TokenId;
bestBid?: DecimalString | null;
bestAsk?: DecimalString | null;
spread?: DecimalString | null;
timestamp?: string | null;
};
};
{
"topic": "market",
"type": "best_bid_ask",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"tokenId": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"bestBid": "0.08",
"bestAsk": "0.09",
"spread": "0.01",
"timestamp": "1782753357257"
}
}
New Market
type NewMarketEvent = {
topic: "market";
type: "new_market";
payload: {
id: string;
question?: string | null;
market: string;
slug?: string | null;
description?: string | null;
tokenIds?: TokenId[] | null;
outcomes?: string[] | null;
eventMessage?: {
id: string;
ticker?: string | null;
slug?: string | null;
title?: string | null;
description?: string | null;
} | null;
timestamp?: string | null;
tags?: string[] | null;
conditionId?: CtfConditionId | null;
active?: boolean | null;
clobTokenIds?: string[] | null;
sportsMarketType?: string | null;
line?: DecimalString | null;
gameStartTime?: IsoDateTimeString | null;
orderPriceMinTickSize?: DecimalString | null;
groupItemTitle?: string | null;
takerBaseFee?: DecimalString | null;
feesEnabled?: boolean | null;
feeSchedule?: unknown;
};
};
{
"topic": "market",
"type": "new_market",
"payload": {
"id": "123456",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"question": "Will the US confirm that aliens exist before 2027?",
"slug": "will-the-us-confirm-that-aliens-exist-before-2027",
"tokenIds": [
"107505882767731489358349912513945399560393482969656700824895970500493757150417",
"7305630249804085635496399869905769372294302716159034447326228509068694952392"
],
"outcomes": ["Yes", "No"],
"active": true,
"timestamp": "1782753357257"
}
}
Market Resolved
type MarketResolvedEvent = {
topic: "market";
type: "market_resolved";
payload: {
id: string;
market: string;
tokenIds?: TokenId[] | null;
winningTokenId?: TokenId | null;
winningOutcome?: string | null;
eventMessage?: {
id: string;
ticker?: string | null;
slug?: string | null;
title?: string | null;
description?: string | null;
} | null;
timestamp?: string | null;
tags?: string[] | null;
};
};
{
"topic": "market",
"type": "market_resolved",
"payload": {
"id": "123456",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"tokenIds": [
"107505882767731489358349912513945399560393482969656700824895970500493757150417",
"7305630249804085635496399869905769372294302716159034447326228509068694952392"
],
"winningTokenId": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"winningOutcome": "Yes",
"timestamp": "1782753357257"
}
}
Given an
Enable
AsyncPublicClient or AsyncSecureClient, subscribe to the market
stream with a MarketSpec containing one or more token IDs:from polymarket.streams import MarketSpec
token_id = "<token_id>"
async with await client.subscribe(
MarketSpec(token_ids=[token_id]),
) as stream:
async for event in stream:
if event.type == "book":
... # event: MarketBookEvent
elif event.type == "price_change":
... # event: MarketPriceChangeEvent
elif event.type == "last_trade_price":
... # event: MarketLastTradePriceEvent
elif event.type == "tick_size_change":
... # event: MarketTickSizeChangeEvent
Standard Market Events
Standard Market Events
Order Book
class OrderBookLevel:
price: Decimal
size: Decimal
class MarketBookPayload:
market: str
token_id: TokenId
bids: tuple[OrderBookLevel, ...]
asks: tuple[OrderBookLevel, ...]
hash: str | None
timestamp: datetime | None
min_order_size: Decimal | None
tick_size: Decimal | None
neg_risk: bool | None
last_trade_price: Decimal | None
class MarketBookEvent:
topic: Literal["market"]
type: Literal["book"]
payload: MarketBookPayload
{
"topic": "market",
"type": "book",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"token_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"bids": [{ "price": "0.08", "size": "33343.4" }],
"asks": [{ "price": "0.09", "size": "163939.58" }],
"hash": "0xabc123…",
"timestamp": "2026-06-29T17:15:57.257000Z"
}
}
Price Change
class PriceChange:
token_id: TokenId
price: Decimal
size: Decimal
side: Literal["BUY", "SELL"]
hash: str | None
best_bid: Decimal | None
best_ask: Decimal | None
class MarketPriceChangePayload:
market: str
price_changes: tuple[PriceChange, ...]
timestamp: datetime | None
class MarketPriceChangeEvent:
topic: Literal["market"]
type: Literal["price_change"]
payload: MarketPriceChangePayload
{
"topic": "market",
"type": "price_change",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"price_changes": [
{
"token_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"price": "0.08",
"size": "33343.4",
"side": "BUY",
"hash": "56621a121a47ed9333273e21c83b660cff37ae50",
"best_bid": "0.08",
"best_ask": "0.09"
}
],
"timestamp": "2026-06-29T17:15:57.257000Z"
}
}
Last Trade Price
class MarketLastTradePricePayload:
market: str
token_id: TokenId
price: Decimal
size: Decimal | None
side: Literal["BUY", "SELL"]
fee_rate_bps: Decimal | None
transaction_hash: str | None
timestamp: datetime | None
class MarketLastTradePriceEvent:
topic: Literal["market"]
type: Literal["last_trade_price"]
payload: MarketLastTradePricePayload
{
"topic": "market",
"type": "last_trade_price",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"token_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"price": "0.08",
"size": "219.217767",
"side": "SELL",
"fee_rate_bps": "0",
"transaction_hash": "0xeeefff…",
"timestamp": "2026-06-29T17:15:57.257000Z"
}
}
Tick Size Change
class MarketTickSizeChangePayload:
market: str
token_id: TokenId
old_tick_size: Decimal | None
new_tick_size: Decimal
timestamp: datetime | None
class MarketTickSizeChangeEvent:
topic: Literal["market"]
type: Literal["tick_size_change"]
payload: MarketTickSizeChangePayload
{
"topic": "market",
"type": "tick_size_change",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"token_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"old_tick_size": "0.01",
"new_tick_size": "0.001",
"timestamp": "2026-06-29T17:15:57.257000Z"
}
}
custom_feature_enabled to include top-of-book and market lifecycle
updates:async with await client.subscribe(
MarketSpec(token_ids=[token_id], custom_feature_enabled=True),
) as stream:
async for event in stream:
if event.type == "book":
... # event: MarketBookEvent
elif event.type == "price_change":
... # event: MarketPriceChangeEvent
elif event.type == "last_trade_price":
... # event: MarketLastTradePriceEvent
elif event.type == "tick_size_change":
... # event: MarketTickSizeChangeEvent
elif event.type == "best_bid_ask":
... # event: MarketBestBidAskEvent
elif event.type == "new_market":
... # event: NewMarketEvent
elif event.type == "market_resolved":
... # event: MarketResolvedEvent
Additional Market Events
Additional Market Events
Best Bid and Ask
class MarketBestBidAskPayload:
market: str
token_id: TokenId
best_bid: Decimal | None
best_ask: Decimal | None
spread: Decimal | None
timestamp: datetime | None
class MarketBestBidAskEvent:
topic: Literal["market"]
type: Literal["best_bid_ask"]
payload: MarketBestBidAskPayload
{
"topic": "market",
"type": "best_bid_ask",
"payload": {
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"token_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"best_bid": "0.08",
"best_ask": "0.09",
"spread": "0.01",
"timestamp": "2026-06-29T17:15:57.257000Z"
}
}
New Market
class MarketEventMessage:
id: str
ticker: str | None
slug: str | None
title: str | None
description: str | None
class NewMarketPayload:
id: str
market: str
question: str | None
slug: str | None
description: str | None
token_ids: tuple[TokenId, ...] | None
outcomes: tuple[str, ...] | None
event_message: MarketEventMessage | None
timestamp: datetime | None
tags: tuple[str, ...] | None
condition_id: CtfConditionId | None
active: bool | None
clob_token_ids: tuple[str, ...] | None
sports_market_type: str | None
line: Decimal | None
game_start_time: datetime | None
order_price_min_tick_size: Decimal | None
group_item_title: str | None
taker_base_fee: Decimal | None
fees_enabled: bool | None
fee_schedule: object | None
class NewMarketEvent:
topic: Literal["market"]
type: Literal["new_market"]
payload: NewMarketPayload
{
"topic": "market",
"type": "new_market",
"payload": {
"id": "123456",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"question": "Will the US confirm that aliens exist before 2027?",
"slug": "will-the-us-confirm-that-aliens-exist-before-2027",
"token_ids": [
"107505882767731489358349912513945399560393482969656700824895970500493757150417",
"7305630249804085635496399869905769372294302716159034447326228509068694952392"
],
"outcomes": ["Yes", "No"],
"active": true,
"timestamp": "2026-06-29T17:15:57.257000Z"
}
}
Market Resolved
class MarketResolvedPayload:
id: str
market: str
token_ids: tuple[TokenId, ...] | None
winning_token_id: TokenId | None
winning_outcome: str | None
event_message: MarketEventMessage | None
timestamp: datetime | None
tags: tuple[str, ...] | None
class MarketResolvedEvent:
topic: Literal["market"]
type: Literal["market_resolved"]
payload: MarketResolvedPayload
{
"topic": "market",
"type": "market_resolved",
"payload": {
"id": "123456",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"token_ids": [
"107505882767731489358349912513945399560393482969656700824895970500493757150417",
"7305630249804085635496399869905769372294302716159034447326228509068694952392"
],
"winning_token_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"winning_outcome": "Yes",
"timestamp": "2026-06-29T17:15:57.257000Z"
}
}
Connect to the market WebSocket:Once connected, send a
Enable
You can add or remove token IDs without opening a new connection:These frames update only the token set for the current market-stream
connection.
wss://ws-subscriptions-clob.polymarket.com/ws/market
The market WebSocket uses an application-level heartbeat. Send the text frame
PING every 10 seconds; the server replies with PONG.market subscription frame with one or more token
IDs:{
"assets_ids": ["<token_id>"],
"type": "market"
}
Standard Market Events
Standard Market Events
Order Book
{
"event_type": "book",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"asset_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"timestamp": "1782753357257",
"hash": "0xabc123…",
"bids": [
{ "price": "0.08", "size": "33343.4" },
{ "price": "0.09", "size": "163939.58" }
],
"asks": [
{ "price": "0.99", "size": "218442.27" },
{ "price": "0.98", "size": "13229.55" }
]
}
Price Change
{
"event_type": "price_change",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"price_changes": [
{
"asset_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"price": "0.08",
"size": "33343.4",
"side": "BUY",
"hash": "56621a121a47ed9333273e21c83b660cff37ae50",
"best_bid": "0.08",
"best_ask": "0.09"
}
],
"timestamp": "1782753357257"
}
Last Trade Price
{
"event_type": "last_trade_price",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"asset_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"price": "0.08",
"size": "219.217767",
"fee_rate_bps": "0",
"side": "SELL",
"timestamp": "1782753357257",
"transaction_hash": "0xeeefff…"
}
Tick Size Change
{
"event_type": "tick_size_change",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"asset_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"old_tick_size": "0.01",
"new_tick_size": "0.001",
"timestamp": "1782753357257"
}
custom_feature_enabled to include top-of-book and market lifecycle
updates:{
"assets_ids": ["<token_id>"],
"type": "market",
"custom_feature_enabled": true
}
Additional Market Events
Additional Market Events
Best Bid and Ask
{
"event_type": "best_bid_ask",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"asset_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"best_bid": "0.08",
"best_ask": "0.09",
"spread": "0.01",
"timestamp": "1782753357257"
}
New Market
{
"event_type": "new_market",
"id": "123456",
"question": "Will the US confirm that aliens exist before 2027?",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"slug": "will-the-us-confirm-that-aliens-exist-before-2027",
"assets_ids": [
"107505882767731489358349912513945399560393482969656700824895970500493757150417",
"7305630249804085635496399869905769372294302716159034447326228509068694952392"
],
"outcomes": ["Yes", "No"],
"timestamp": "1782753357257"
}
Market Resolved
{
"event_type": "market_resolved",
"id": "123456",
"market": "0x747dc809fb79e1b05be09c42d6179459a58de2ef3e40f02484a4e1260f741f75",
"assets_ids": [
"107505882767731489358349912513945399560393482969656700824895970500493757150417",
"7305630249804085635496399869905769372294302716159034447326228509068694952392"
],
"winning_asset_id": "107505882767731489358349912513945399560393482969656700824895970500493757150417",
"winning_outcome": "Yes",
"timestamp": "1782753357257"
}
{
"assets_ids": ["<new_token_id>"],
"operation": "subscribe"
}
{
"assets_ids": ["<old_token_id>"],
"operation": "unsubscribe"
}
Sports Stream
Use the sports stream to keep live game information current alongside sports markets. Updates arrive when a game goes live, its score or period changes, or it ends. NFL and CFB updates can also reflect possession changes.Sports data is provided for informational purposes only. It may be delayed,
contain errors, or omit recent events. Polymarket does not provide trading or
investment advice, and this data should not be used as the basis for a trading
decision.
- TypeScript
- Python
- API
Given a
PublicClient or SecureClient, subscribe to the sports topic to receive
every game update:const stream = await client.subscribe([{ topic: "sports" }]);
for await (const event of stream) {
// event: SportsEvent
}
Sports Event
Sports Event
type SportsEvent = {
topic: "sports";
type: "sport_result";
payload: {
gameId: number;
sportradarGameId?: string | null;
slug?: string | null;
leagueAbbreviation: string;
homeTeam?: string | null;
awayTeam?: string | null;
status: string;
live: boolean;
ended: boolean;
score: string;
period?: string | null;
elapsed?: string | null;
finishedAt?: IsoDateTimeString | null;
turn?: string | null;
};
};
{
"topic": "sports",
"type": "sport_result",
"payload": {
"gameId": 5127839,
"leagueAbbreviation": "NBA",
"homeTeam": "Los Angeles Lakers",
"awayTeam": "Boston Celtics",
"status": "InProgress",
"live": true,
"ended": false,
"score": "98-94",
"period": "Q4",
"elapsed": "05:12"
}
}
score is a combined "<home>-<away>" string, not separate home and away
fields.Given an
AsyncPublicClient or AsyncSecureClient, subscribe with a
SportsSpec to receive every game update:from polymarket.streams import SportsSpec
async with await client.subscribe(SportsSpec()) as stream:
async for event in stream:
... # event: SportsEvent
Sports Event
Sports Event
class SportsGameResult:
game_id: int
sportradar_game_id: str | None
slug: str | None
league_abbreviation: str
home_team: str | None
away_team: str | None
status: str
live: bool
ended: bool
score: str
period: str | None
elapsed: str | None
finished_at: datetime | None
turn: str | None
class SportsResultEvent:
topic: Literal["sports"]
type: Literal["sport_result"]
payload: SportsGameResult
SportsEvent = SportsResultEvent
{
"topic": "sports",
"type": "sport_result",
"payload": {
"game_id": 5127839,
"league_abbreviation": "NBA",
"home_team": "Los Angeles Lakers",
"away_team": "Boston Celtics",
"status": "InProgress",
"live": true,
"ended": false,
"score": "98-94",
"period": "Q4",
"elapsed": "05:12"
}
}
score is a combined "<home>-<away>" string, not separate home and away
fields.Connect to the sports WebSocket:Once connected, the server starts streaming every game update. No
subscription frame is required.
Sports messages have no envelope or event-type field. Each message is the
game update object itself, and
wss://sports-api.polymarket.com/ws
The sports WebSocket uses an application-level heartbeat. The server sends the
text frame
ping every 5 seconds; reply with pong within 10 seconds or the
server closes the connection.Sports Event
Sports Event
{
"gameId": 5127839,
"leagueAbbreviation": "NBA",
"homeTeam": "Los Angeles Lakers",
"awayTeam": "Boston Celtics",
"status": "InProgress",
"live": true,
"ended": false,
"score": "98-94",
"period": "Q4",
"elapsed": "05:12"
}
score is a combined "<home>-<away>"
string.Period Values
The meaning and format of a period depend on the sport:| Values | Meaning |
|---|---|
1H, 2H | First or second half |
1Q, 2Q, 3Q, 4Q | Quarter |
HT | Halftime |
FT | Full time in regulation |
FT OT | Full time after overtime |
FT NR | Full time with no result |
End 1, End 2, … | End of an MLB inning |
1/3, 2/3, 3/3 | Map number in a best-of-three series |
1/5, 2/5, … | Map number in a best-of-five series |
Game Status Values
Status values vary by sport and are case-sensitive:| Sport | Values |
|---|---|
| NFL | Scheduled, InProgress, Final, F/OT, Suspended, Postponed, Delayed, Canceled, Forfeit, NotNecessary |
| NHL | Scheduled, InProgress, Final, F/OT, F/SO, Suspended, Postponed, Delayed, Canceled, Forfeit, NotNecessary |
| MLB | Scheduled, InProgress, Final, Suspended, Delayed, Postponed, Canceled, Forfeit, NotNecessary |
| NBA and CBB | Scheduled, InProgress, Final, F/OT, Suspended, Postponed, Delayed, Canceled, Forfeit, NotNecessary |
| CFB | Scheduled, InProgress, Final, F/OT, Suspended, Postponed, Delayed, Canceled, Forfeit |
| Soccer | Scheduled, InProgress, Break, Suspended, PenaltyShootout, Final, Awarded, Postponed, Canceled |
| Esports | not_started, running, finished, postponed, canceled |
| Tennis | scheduled, inprogress, suspended, finished, postponed, cancelled |
Reference Prices
Stream crypto, equity, and time-weighted average reference prices through Polymarket. Authenticate, select the symbols you need, and process historical prices and live updates.Reference price subscriptions require authentication.
Existing RTDS integrations should follow the migration
guide.
Historical Snapshot
Each new subscription provides a snapshot of the preceding two minutes of prices and live updates. Seed local state from the snapshot, then apply the latest price. Applications that only need live prices can ignore the snapshot.Crypto Prices
Stream crypto reference prices in USD to keep prices current alongside related markets.- TypeScript
- Python
- API
Call
For live prices only, skip events whose
client.subscribe with an authenticated SecureClient from @polymarket/client 0.11.0 or later. See Wallet Integrations to create the client.const stream = await client.subscribe([
{ topic: "prices.crypto", symbols: ["btcusd", "ethusd"] },
]);
try {
for await (const event of stream) {
// event: CryptoPriceEvent
if (event.type === "subscribe") {
const history = event.payload.data;
// Seed local state from the snapshot.
} else {
const price = event.payload.value;
const observedAt = event.payload.timestamp;
// Apply the latest price.
}
}
} finally {
await stream.close();
}
Output: CryptoPriceEvent
Output: CryptoPriceEvent
events: CryptoPriceEvent[]
type CryptoPriceEvent =
| {
topic: "prices.crypto";
type: "subscribe";
timestamp: EpochMilliseconds;
seq?: number;
dropped?: number;
payload: {
symbol: string;
data: { timestamp: EpochMilliseconds; value: DecimalString }[];
};
}
| {
topic: "prices.crypto";
type: "update";
timestamp: EpochMilliseconds;
seq?: number;
dropped?: number;
payload: {
symbol: string;
timestamp: EpochMilliseconds;
value: DecimalString;
receivedAt: EpochMilliseconds | undefined;
isCarriedForward: boolean | undefined;
};
};
[
{
"topic": "prices.crypto",
"type": "subscribe",
"timestamp": 1788886176000,
"seq": 1,
"payload": {
"symbol": "btcusd",
"data": [
{
"timestamp": 1788886057000,
"value": "78803.76173179"
},
{
"timestamp": 1788886058000,
"value": "78801.86287741"
},
{
"timestamp": 1788886059000,
"value": "78798.28703224"
}
]
}
},
{
"topic": "prices.crypto",
"type": "update",
"timestamp": 1788886177000,
"seq": 5,
"payload": {
"symbol": "btcusd",
"timestamp": 1788886177000,
"value": "78794.15450441"
}
}
]
type is "subscribe".Call
Values are
client.subscribe with an authenticated AsyncSecureClient from polymarket-client 0.11.0 or later. Complete Secure Client setup first, and run this example inside an async function.from polymarket.streams import CryptoPriceSpec
async with await client.subscribe(
CryptoPriceSpec(symbols=["btcusd", "ethusd"])
) as stream:
async for event in stream:
# event: CryptoPriceEvent
if event.type == "subscribe":
history = event.payload.data
# Seed local state from the snapshot.
else:
price = event.payload.value
observed_at = event.payload.timestamp
# Apply the latest price.
Output: CryptoPriceEvent
Output: CryptoPriceEvent
event: CryptoPriceEvent
class RealtimePricePoint:
timestamp: datetime
value: Decimal
class RealtimePriceSnapshot:
symbol: str
data: tuple[RealtimePricePoint, ...]
class RealtimePriceUpdate:
symbol: str
timestamp: datetime
value: Decimal
received_at: datetime | None
is_carried_forward: bool | None
class CryptoPriceSnapshotEvent:
topic: Literal["prices.crypto"]
type: Literal["subscribe"]
timestamp: datetime
seq: int | None
dropped: int | None
payload: RealtimePriceSnapshot
class CryptoPriceUpdateEvent:
topic: Literal["prices.crypto"]
type: Literal["update"]
timestamp: datetime
seq: int | None
dropped: int | None
payload: RealtimePriceUpdate
CryptoPriceEvent = CryptoPriceSnapshotEvent | CryptoPriceUpdateEvent
{
"timestamp": "2026-09-08T16:49:37Z",
"seq": 5,
"topic": "prices.crypto",
"type": "update",
"payload": {
"timestamp": "2026-09-08T16:49:37Z",
"value": "78794.15450441",
"symbol": "btcusd"
}
}
Decimal, and timestamps are UTC datetime objects.For live prices only, skip events whose type is "subscribe".Connect to PolyBolt and authenticate before subscribing to crypto prices.
1
Connect
Open a WebSocket connection to:
wss://ws-live-v2.polymarket.com/ws
2
Authenticate
Send your CLOB API credentials on the open connection:
{
"op": "auth",
"rid": "a1",
"auth": {
"apiKey": "<api key>",
"secret": "<api secret>",
"passphrase": "<api passphrase>"
}
}
3
Wait for Authentication
Wait for the server to confirm authentication before sending a subscription:
{
"op": "authed",
"rid": "a1"
}
4
Subscribe to Crypto Prices
Send this frame on the authenticated connection to subscribe to BTC/USD:
{
"op": "subscribe",
"rid": "s1",
"subscriptions": [
{
"channel": "price.crypto",
"filter": {
"symbol": "btcusd"
}
}
]
}
Equity Prices
Stream reference prices for stocks, ETFs, forex pairs, precious metals, and commodities.- TypeScript
- Python
- API
Call
For live prices only, skip events whose
client.subscribe to subscribe to the prices.equity topic and your chosen symbols with an authenticated SecureClient.const stream = await client.subscribe([
{ topic: "prices.equity", symbol: "aapl" },
]);
try {
for await (const event of stream) {
// event: EquityPriceEvent
if (event.type === "subscribe") {
const history = event.payload.data;
// Seed local state from the snapshot.
} else {
const price = event.payload.value;
const observedAt = event.payload.timestamp;
// Apply the latest price.
}
}
} finally {
await stream.close();
}
Output: EquityPriceEvent
Output: EquityPriceEvent
events: EquityPriceEvent[]
type EquityPriceEvent =
| {
topic: "prices.equity";
type: "subscribe";
timestamp: EpochMilliseconds;
seq?: number;
dropped?: number;
payload: {
symbol: string;
data: { timestamp: EpochMilliseconds; value: DecimalString }[];
};
}
| {
topic: "prices.equity";
type: "update";
timestamp: EpochMilliseconds;
seq?: number;
dropped?: number;
payload: {
symbol: string;
timestamp: EpochMilliseconds;
value: DecimalString;
receivedAt: EpochMilliseconds | undefined;
isCarriedForward: boolean | undefined;
};
};
[
{
"topic": "prices.equity",
"type": "subscribe",
"timestamp": 1788886176400,
"seq": 1,
"payload": {
"symbol": "aapl",
"data": [
{
"timestamp": 1788886056800,
"value": "316.11"
},
{
"timestamp": 1788886057000,
"value": "316.11"
},
{
"timestamp": 1788886057200,
"value": "316.11001"
}
]
}
},
{
"topic": "prices.equity",
"type": "update",
"timestamp": 1788886176600,
"seq": 2,
"payload": {
"symbol": "aapl",
"timestamp": 1788886176600,
"value": "316.1",
"receivedAt": 1788886176600
}
}
]
type is "subscribe".Call
Values are
client.subscribe to subscribe to the prices.equity topic and your chosen symbols with an authenticated AsyncSecureClient.from polymarket.streams import EquityPriceSpec
async with await client.subscribe(
EquityPriceSpec(symbol="aapl")
) as stream:
async for event in stream:
# event: EquityPriceEvent
if event.type == "subscribe":
history = event.payload.data
# Seed local state from the snapshot.
else:
price = event.payload.value
observed_at = event.payload.timestamp
# Apply the latest price.
Output: EquityPriceEvent
Output: EquityPriceEvent
event: EquityPriceEvent
class RealtimePricePoint:
timestamp: datetime
value: Decimal
class RealtimePriceSnapshot:
symbol: str
data: tuple[RealtimePricePoint, ...]
class RealtimePriceUpdate:
symbol: str
timestamp: datetime
value: Decimal
received_at: datetime | None
is_carried_forward: bool | None
class EquityPriceSnapshotEvent:
topic: Literal["prices.equity"]
type: Literal["subscribe"]
timestamp: datetime
seq: int | None
dropped: int | None
payload: RealtimePriceSnapshot
class EquityPriceUpdateEvent:
topic: Literal["prices.equity"]
type: Literal["update"]
timestamp: datetime
seq: int | None
dropped: int | None
payload: RealtimePriceUpdate
EquityPriceEvent = EquityPriceSnapshotEvent | EquityPriceUpdateEvent
{
"timestamp": "2026-09-08T16:49:36.600000Z",
"seq": 2,
"topic": "prices.equity",
"type": "update",
"payload": {
"timestamp": "2026-09-08T16:49:36.600000Z",
"value": "316.1",
"symbol": "aapl",
"received_at": "2026-09-08T16:49:36.600000Z"
}
}
Decimal, and timestamps are UTC datetime objects.For live updates only, set types=["update"]. Omit types or pass an empty list to receive history and updates. Updates may include received_at and is_carried_forward.Reuse the authenticated connection from the Crypto Prices API example and send this frame to subscribe to AAPL:
{
"op": "subscribe",
"rid": "s2",
"subscriptions": [
{
"channel": "price.equity",
"filter": {
"symbol": "aapl"
}
}
]
}
Supported Equity Symbols
| Asset class | Supported symbols |
|---|---|
| Stocks | aapl, tsla, msft, googl, amzn, meta, nvda, nflx, pltr, open, rklb, abnb, coin, hood |
| ETFs | qqq, spy, ewy, vxx |
| Forex | eurusd, gbpusd, usdcad, usdjpy, usdkrw |
| Precious metals | xauusd, xagusd |
| Commodities | wti, cc, ngd |
Market Hours
When the market for an asset is closed, the stream continues with its last known price and marks that value as carried forward. During market hours, prices can update up to five times per second for each feed.TWAP Prices
A time-weighted average price (TWAP) represents an asset’s price across a lookback window. Stream Chainlink-computed crypto TWAPs with a fixed 60-second window through Polymarket.- TypeScript
- Python
- API
Call
For live prices only, skip events whose
client.subscribe to subscribe to the prices.crypto.twap topic and your chosen symbols with an authenticated SecureClient.const stream = await client.subscribe([
{ topic: "prices.crypto.twap", symbols: ["btcusd"] },
]);
try {
for await (const event of stream) {
// event: CryptoTwapPriceEvent
if (event.type === "subscribe") {
const history = event.payload.data;
// Seed local state from the snapshot.
} else {
const price = event.payload.value;
const observedAt = event.payload.timestamp;
// Apply the latest price.
}
}
} finally {
await stream.close();
}
Output: CryptoTwapPriceEvent
Output: CryptoTwapPriceEvent
events: CryptoTwapPriceEvent[]
type CryptoTwapPriceEvent =
| {
topic: "prices.crypto.twap";
type: "subscribe";
timestamp: EpochMilliseconds;
seq?: number;
dropped?: number;
payload: {
symbol: string;
data: { timestamp: EpochMilliseconds; value: DecimalString }[];
windowSeconds: 60;
};
}
| {
topic: "prices.crypto.twap";
type: "update";
timestamp: EpochMilliseconds;
seq?: number;
dropped?: number;
payload: {
symbol: string;
timestamp: EpochMilliseconds;
value: DecimalString;
windowSeconds: 60;
};
};
[
{
"topic": "prices.crypto.twap",
"type": "subscribe",
"timestamp": 1788886175000,
"seq": 2,
"payload": {
"symbol": "btcusd",
"data": [
{
"timestamp": 1788886057000,
"value": "78788.525642908795142144"
},
{
"timestamp": 1788886058000,
"value": "78788.786579938813673472"
},
{
"timestamp": 1788886059000,
"value": "78789.052518750893375488"
}
],
"windowSeconds": 60
}
},
{
"topic": "prices.crypto.twap",
"type": "update",
"timestamp": 1788886177000,
"seq": 3,
"payload": {
"symbol": "btcusd",
"timestamp": 1788886177000,
"value": "78803.715261094101516288",
"windowSeconds": 60
}
}
]
type is "subscribe". payload.value is already an exact decimal string. No E18 conversion is needed.Use a canonical symbol such as btcusd. The returned windowSeconds: 60 describes the lookback period, not the update interval. Use payload.timestamp to check price freshness.Call
Values are
client.subscribe to subscribe to the prices.crypto.twap topic and your chosen symbols with an authenticated AsyncSecureClient.from polymarket.streams import CryptoTwapPriceSpec
async with await client.subscribe(
CryptoTwapPriceSpec(symbols=["btcusd"])
) as stream:
async for event in stream:
# event: CryptoTwapPriceEvent
if event.type == "subscribe":
history = event.payload.data
# Seed local state from the snapshot.
else:
price = event.payload.value
observed_at = event.payload.timestamp
# Apply the latest price.
Output: CryptoTwapPriceEvent
Output: CryptoTwapPriceEvent
event: CryptoTwapPriceEvent
class RealtimePricePoint:
timestamp: datetime
value: Decimal
class RealtimeTwapSnapshot:
symbol: str
data: tuple[RealtimePricePoint, ...]
window_seconds: Literal[60]
class RealtimeTwapUpdate:
symbol: str
timestamp: datetime
value: Decimal
window_seconds: Literal[60]
class CryptoTwapPriceSnapshotEvent:
topic: Literal["prices.crypto.twap"]
type: Literal["subscribe"]
timestamp: datetime
seq: int | None
dropped: int | None
payload: RealtimeTwapSnapshot
class CryptoTwapPriceUpdateEvent:
topic: Literal["prices.crypto.twap"]
type: Literal["update"]
timestamp: datetime
seq: int | None
dropped: int | None
payload: RealtimeTwapUpdate
CryptoTwapPriceEvent = CryptoTwapPriceSnapshotEvent | CryptoTwapPriceUpdateEvent
{
"timestamp": "2026-09-08T16:49:37Z",
"seq": 3,
"topic": "prices.crypto.twap",
"type": "update",
"payload": {
"timestamp": "2026-09-08T16:49:37Z",
"value": "78803.715261094101516288",
"symbol": "btcusd",
"window_seconds": 60
}
}
Decimal, and timestamps are UTC datetime objects.payload.window_seconds is always 60 and describes the lookback window. Use payload.value directly without E18 scaling, and use payload.timestamp to check freshness.Reuse the authenticated connection from the Crypto Prices API example and send this frame to subscribe to the 60-second BTC/USD TWAP:
{
"op": "subscribe",
"rid": "s3",
"subscriptions": [
{
"channel": "price.crypto.twap",
"filter": {
"symbol": "btcusd",
"window_seconds": 60
}
}
]
}
Comments
Live comment and reaction streaming is being retired without a replacement
streaming channel. Check below for the corresponding fetch method.
- TypeScript
- Python
- API
Create a public client and call
client.listComments() to list comments for an event. This method does not provide live comment or reaction events.import {
CommentParentEntityType,
createPublicClient,
} from "@polymarket/client";
const client = createPublicClient();
const pages = client.listComments({
parentEntityId: "18396",
parentEntityType: CommentParentEntityType.Event,
pageSize: 20,
order: "id",
ascending: true,
});
const page = await pages.firstPage();
console.log(page.items);
page.items contains Comment objects. Check page.hasMore for more results and continue with pages.from(page.nextCursor).Output: Comment
Output: Comment
One comment from
page.items, serialized as JSON with selected fields shown.{
"id": "1020073",
"body": "@truce @yayyo",
"parentEntityType": "Event",
"parentEntityID": "18396",
"createdAt": "2025-02-12T00:48:05.40822Z",
"reactionCount": 2
}
Create a public client and call
client.list_comments() to list comments for an event. This method does not provide live comment or reaction events.from polymarket import AsyncPublicClient
async with AsyncPublicClient() as client:
pages = client.list_comments(
parent_entity_id="18396",
parent_entity_type="Event",
page_size=20,
order="id",
ascending=True,
)
page = await pages.first_page()
print(page.items)
page.items contains Comment objects. Check page.has_more for more results and continue with pages.from_cursor(page.next_cursor).Output: Comment
Output: Comment
One comment from
page.items, serialized as JSON with selected fields shown.{
"id": "1020073",
"body": "@truce @yayyo",
"parent_entity_type": "Event",
"parent_entity_id": "18396",
"created_at": "2025-02-12T00:48:05.408220Z",
"reaction_count": 2
}
Use The response is an array of comments.
GET /comments on the Gamma API to list comments for an event. This request does not provide live comment or reaction events.curl --get "https://gamma-api.polymarket.com/comments" \
--data-urlencode "parent_entity_id=18396" \
--data-urlencode "parent_entity_type=Event" \
--data-urlencode "limit=20" \
--data-urlencode "offset=0" \
--data-urlencode "order=id" \
--data-urlencode "ascending=true"
Output: Comment[]
Output: Comment[]
First comment in the response, with selected fields shown.
[
{
"id": "1020073",
"body": "@truce @yayyo",
"parentEntityType": "Event",
"parentEntityID": 18396,
"createdAt": "2025-02-12T00:48:05.40822Z",
"reactionCount": 2
}
]