Schemas Get a free key
Polymarket · WebSocket

Polymarket WebSocket API: live trades, positions and resolutions

5 live channels at wss://stream.vike.io/v1/stream/polymarket: every trade, every position change, every on-chain resolution, sharp price moves and new markets, pushed as they land. One free key; drop the connection and resume where you left off.

Ask your AI · Claude, ChatGPT, CursorConnect in a minute →

“Check this subscription before I connect: pm.trades, min_usd 1000, only top-5% wallets”

stream_check_filter

“What did pm.resolutions send in the last hour?”

stream_events
5
Polymarket channels (22 on the stream server)
3 days
to resume from your last cursor
100
subscriptions on one connection
at least once
dedupe on event.event_id
  1. Connect

    wss://stream.vike.io/v1/stream/polymarket with X-API-KEY on the handshake.

  2. Subscribe

    Send {"action": "subscribe", "id", "channel", "filter"}; up to 100 on one connection.

  3. Resume

    Keep the last cursor; subscribe with it after a drop and get what you missed, up to 3 days back.

Connect

Ten lines of Python

Every trade of $1,000 or more, printed as it lands.

python
import json, os
from websockets.sync.client import connect

with connect("wss://stream.vike.io/v1/stream/polymarket",
             additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
    ws.send(json.dumps({"action": "subscribe", "id": "s1", "channel": "pm.trades",
                        "filter": {"min_usd": 1000}}))
    for message in ws:
        frame = json.loads(message)
        if frame["type"] == "ping":
            ws.send(json.dumps({"action": "pong"}))
        elif frame["type"] == "event":
            e = frame["event"]
            print(e["subject"]["title"], e["data"]["usd"])
  • Every event has the same envelope: schema, event_id, source, kind, ts, cursor, chain, subject, data, labels.
  • The server pings every 15 s; answer with pong. 3 missed pongs close the connection.
  • 1 connection per key on this path, 3 per account; a newer one wins and the older is closed with a resume cursor.
  • A list is OR inside a key, keys are AND across, an empty filter matches everything.
  • A channel is produced only while someone subscribes to it (and 15 minutes after).
  • Missed something without a socket? The same events are on REST: /v1/polymarket/stream-events.
Build

Build your subscription

Pick a channel and fill the filters: the subscribe message and the CLI command update as you type.

Subscribe message
json
The same from the CLI
bash
Channels

The 5 Polymarket channels

What each sends, every field of a real event, the filters it takes and the subscribe call.

Polymarket · WebSocket · read every 15 s

pm.trades

Every trade, with the wallet, side, size, price, dollar value and maker or taker role.

Path
wss://stream.vike.io/v1/stream/polymarket
Kind
pm_trade
Filters
market, min_usd, pnl_tier, role, side, volume_tier, wallet
Read
every 15 s
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
subject.walletstringThe proxy wallet that traded
subject.condition_idstringThe market
subject.token_idstringThe outcome token
subject.slugstringMarket slug
subject.titlestringMarket title
subject.outcomestringOutcome name
subject.outcome_indexinteger0 = the first outcome (Yes, Up)
data.sidestringbuy | sell
data.sizenumberShares
data.pricenumberPrice, 0 to 1
data.usdnumberDollar value of the trade: size × price
data.rolestringmaker | taker
data.tx_hashstringPolygon transaction
data.log_indexintegerLog index in the transaction
data.block_numberintegerPolygon block
labels.pnl_tierstringThe wallet’s realized-P&L tier
labels.volume_tierstringThe wallet’s volume tier
labels.is_top1booleanAmong the top 1% by P&L

A real event captured 2026-11-03

json
{
 "schema": "vike.event.v1",
 "event_id": "pm.trades:0xae2bb65bc5df0ddb6da049d9828116b6a1ae5ba5facc0c4a104e557d95ebbf6c:937",
 "source": "pm.trades",
 "kind": "pm_trade",
 "ts": "2026-10-31T12:10:13.000Z",
 "cursor": "000096495438-000937",
 "chain": "polygon",
 "subject": {
  "wallet": "0x5c50e006298ae03ea9e73533f68b205b750ee0c9",
  "condition_id": "0x96672f8eee7ad956267a8f30ab5e17556d66c6f7da92a55bca7f0b525f2061ce",
  "token_id": "114456141470340804944829704354275432124926411877510254720302351729914418144391",
  "slug": "atp-machac-landalu-2026-10-31",
  "title": "Rolex Paris Masters, Qualification: Tomas Machac vs Martin Landaluce",
  "outcome": "Martin Landaluce",
  "outcome_index": 1
 },
 "data": {
  "side": "buy",
  "size": 10812.304043,
  "price": 0.46243612648287047,
  "usd": 5000.0,
  "role": "taker",
  "tx_hash": "0xae2bb65bc5df0ddb6da049d9828116b6a1ae5ba5facc0c4a104e557d95ebbf6c",
  "log_index": 937,
  "block_number": 96495438
 },
 "labels": {
  "pnl_tier": "bot1",
  "volume_tier": "whale",
  "is_top1": false
 }
}

Filters

FieldTypeDescription
marketlist ≤ 200markets are condition ids: 0x followed by 64 hex characters
min_usdnumbermust be a finite number >= 0
pnl_tierlist ≤ 50belowmedian, bot1, bot10, bot5, median, top1, top10, top5, unknown, unranked
roleone valuemaker, taker
sideone valuebuy, sell
volume_tierlist ≤ 50dolphin, fish, shrimp, unknown, whale
walletlist ≤ 1,000wallets are 0x followed by 40 hex characters

Subscribe

python
import json, os
from websockets.sync.client import connect

with connect("wss://stream.vike.io/v1/stream/polymarket",
             additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
    ws.send(json.dumps({"action": "subscribe", "id": "s1", "channel": "pm.trades",
                        "filter": {"min_usd": 1000}}))
    for message in ws:
        frame = json.loads(message)
        if frame["type"] == "ping":
            ws.send(json.dumps({"action": "pong"}))
        elif frame["type"] == "event":
            e = frame["event"]
            print(e["subject"]["title"], e["data"]["side"], e["data"]["usd"])
Polymarket · WebSocket · read every 15 s

pm.positions

What each trade did to the wallet’s position: open, increase, reduce, close or flip, with shares before and after and the average buy price.

Path
wss://stream.vike.io/v1/stream/polymarket
Kind
pm_position
Filters
action, market, min_usd, wallet
Read
every 15 s
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
subject.walletstringThe proxy wallet that traded
subject.condition_idstringThe market
subject.token_idstringThe outcome token
subject.slugstringMarket slug
subject.titlestringMarket title
subject.outcomestringOutcome name
subject.outcome_indexinteger0 = the first outcome (Yes, Up)
data.sidestringbuy | sell
data.sizenumberShares
data.pricenumberPrice, 0 to 1
data.usdnumberDollar value of the trade: size × price
data.rolestringmaker | taker
data.tx_hashstringPolygon transaction
data.log_indexintegerLog index in the transaction
data.block_numberintegerPolygon block
data.actionstringopen | increase | reduce | close | flip
data.shares_beforenumberNet shares before the trade
data.sharesnumberNet shares after the trade
data.avg_pricenumberAverage BUY price after the trade; null if it bought nothing
labels.pnl_tierstringThe wallet’s realized-P&L tier
labels.volume_tierstringThe wallet’s volume tier
labels.is_top1booleanAmong the top 1% by P&L

A real event captured 2026-11-03

json
{
 "schema": "vike.event.v1",
 "event_id": "pm.positions:0x48e9342600be46b278f9d301fe7c5979045962c880766f560c228ef0798d1cd9:800",
 "source": "pm.positions",
 "kind": "pm_position",
 "ts": "2026-11-02T14:28:37.000Z",
 "cursor": "000096616174-000800",
 "chain": "polygon",
 "subject": {
  "wallet": "0x958bdb8aa30b8e5bd1fe4ee071f309c84e97f826",
  "condition_id": "0xc6d7e35bc46f765775da937872c39c44dc4956e39fc604f7700220231276f496",
  "token_id": "82372917980430341396992188476134048035148682101989443667424605671912074667768",
  "slug": "nba-por-den-2026-11-02-total-232pt5",
  "title": "Trail Blazers vs. Nuggets: O/U 232.5",
  "outcome": "Under",
  "outcome_index": 1
 },
 "data": {
  "side": "buy",
  "size": 22464.82,
  "price": 0.5,
  "usd": 11232.41,
  "role": "maker",
  "tx_hash": "0x48e9342600be46b278f9d301fe7c5979045962c880766f560c228ef0798d1cd9",
  "log_index": 800,
  "block_number": 96616174,
  "action": "open",
  "shares_before": 0.0,
  "shares": 22464.82,
  "avg_price": 0.5
 },
 "labels": {
  "pnl_tier": "bot1",
  "volume_tier": "whale",
  "is_top1": false
 }
}

Filters

FieldTypeDescription
actionlist ≤ 50close, flip, increase, open, reduce
marketlist ≤ 200markets are condition ids: 0x followed by 64 hex characters
min_usdnumbermust be a finite number >= 0
walletlist ≤ 1,000wallets are 0x followed by 40 hex characters

Subscribe

python
import json, os
from websockets.sync.client import connect

with connect("wss://stream.vike.io/v1/stream/polymarket",
             additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
    ws.send(json.dumps({"action": "subscribe", "id": "s1", "channel": "pm.positions",
                        "filter": {"wallet": ["0x…"]}}))
    for message in ws:
        frame = json.loads(message)
        if frame["type"] == "ping":
            ws.send(json.dumps({"action": "pong"}))
        elif frame["type"] == "event":
            e = frame["event"]
            print(e["subject"]["title"], e["data"]["action"], e["data"]["shares"])
Polymarket · WebSocket · read every 60 s

pm.resolutions

Every on-chain resolution, traded or not: which outcome won and the payouts as stored on-chain; traded says whether the market was ever on Vike’s tape.

Path
wss://stream.vike.io/v1/stream/polymarket
Kind
pm_resolution
Filters
market
Read
every 60 s
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
subject.condition_idstringThe market
subject.slugstringMarket slug
subject.questionstringMarket question
subject.outcomesarrayOutcome names
data.winning_indexintegerIndex of the winning outcome; -1 when no single outcome won
data.winning_outcomestringName of the winning outcome
data.payoutsarrayPayout numerators as stored on-chain
data.invalidbooleanNo single winner (a tie or a void)
data.resolved_blockintegerBlock of the resolution
data.tradedbooleanThe market was ever on Vike’s trade tape

A real event captured 2026-11-03

json
{
 "schema": "vike.event.v1",
 "event_id": "pm.resolutions:0x1049c6dab88bea723bc960c9a6d8a1aac6ac1c1503124192d54986106db56ba4",
 "source": "pm.resolutions",
 "kind": "pm_resolution",
 "ts": "2026-10-31T12:10:55.000Z",
 "cursor": "000096495466-0x1049c6dab88bea723bc960c9a6d8a1aac6ac1c1503124192d54986106db56ba4",
 "chain": "polygon",
 "subject": {
  "condition_id": "0x1049c6dab88bea723bc960c9a6d8a1aac6ac1c1503124192d54986106db56ba4",
  "slug": "ethereum-above-2270-on-october-31-2026-8am-et",
  "question": "Ethereum above 2,270 on October 31, 8AM ET?",
  "outcomes": [
   "Yes",
   "No"
  ]
 },
 "data": {
  "winning_index": 1,
  "winning_outcome": "No",
  "payouts": [
   0,
   1
  ],
  "invalid": false,
  "resolved_block": 96495466,
  "traded": true
 },
 "labels": {}
}

Filters

FieldTypeDescription
marketlist ≤ 200markets are condition ids: 0x followed by 64 hex characters

Subscribe

python
import json, os
from websockets.sync.client import connect

with connect("wss://stream.vike.io/v1/stream/polymarket",
             additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
    ws.send(json.dumps({"action": "subscribe", "id": "s1", "channel": "pm.resolutions",
                        "filter": {"market": ["0x…"]}}))
    for message in ws:
        frame = json.loads(message)
        if frame["type"] == "ping":
            ws.send(json.dumps({"action": "pong"}))
        elif frame["type"] == "event":
            e = frame["event"]
            print(e["subject"].get("question"), e["data"]["winning_outcome"])
Polymarket · WebSocket · read every 30 s

pm.price_moves

An outcome’s mid price moved 0.05 or more within 300 seconds, up or down, with the best bid and ask at the end.

Path
wss://stream.vike.io/v1/stream/polymarket
Kind
pm_price_move
Filters
market, min_move, move, token_id
Read
every 30 s
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
subject.token_idstringThe outcome token
subject.condition_idstringThe market
subject.slugstringMarket slug
subject.outcomestringOutcome name
data.mid_fromnumberMid price at the window start
data.mid_tonumberMid price at the window end
data.movenumbermid_to − mid_from
data.directionstringup | down
data.window_sintegerWindow, seconds
data.bidnumberBest bid at the end
data.asknumberBest ask at the end

A real event captured 2026-11-03

json
{
 "schema": "vike.event.v1",
 "event_id": "pm.price_moves:1511524245571629932608167359009556854548643053077909198541619162127863963771:5978161:down",
 "source": "pm.price_moves",
 "kind": "pm_price_move",
 "ts": "2026-10-31T12:09:28.581Z",
 "cursor": "1793448568581-1511524245571629932608167359009556854548643053077909198541619162127863963771",
 "chain": "polygon",
 "subject": {
  "token_id": "1511524245571629932608167359009556854548643053077909198541619162127863963771",
  "condition_id": "0xfe3230e9efc339c84aec884d7b4a3c2633198c58f5085536efea1102121e5e66",
  "slug": "xrp-updown-5m-1793448300",
  "outcome": "Down"
 },
 "data": {
  "mid_from": 0.085,
  "mid_to": 0.01,
  "move": -0.075,
  "direction": "down",
  "window_s": 300,
  "bid": 0.01,
  "ask": 0.01
 },
 "labels": {}
}

Filters

FieldTypeDescription
marketlist ≤ 200markets are condition ids: 0x followed by 64 hex characters
min_movenumbermust be a finite number >= 0; must be a price move above 0 and at most 1 (0.05 = five points)
moveone valuedown, up
token_idlist ≤ 200token ids are 1 to 80 decimal digits

Subscribe

python
import json, os
from websockets.sync.client import connect

with connect("wss://stream.vike.io/v1/stream/polymarket",
             additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
    ws.send(json.dumps({"action": "subscribe", "id": "s1", "channel": "pm.price_moves",
                        "filter": {"min_move": 0.1}}))
    for message in ws:
        frame = json.loads(message)
        if frame["type"] == "ping":
            ws.send(json.dumps({"action": "pong"}))
        elif frame["type"] == "event":
            e = frame["event"]
            print(e["subject"]["slug"], e["subject"]["outcome"], e["data"]["move"])
Polymarket · WebSocket · read every 60 s

pm.new_markets

A new market as soon as it is listed, with its outcomes and token ids.

Path
wss://stream.vike.io/v1/stream/polymarket
Kind
pm_new_market
Filters
class
Read
every 60 s
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
subject.condition_idstringThe market
subject.slugstringMarket slug
subject.questionstringMarket question
subject.outcomesarrayOutcome names
subject.token_idsarrayOutcome token ids
data.classstringupdown_5m | updown_15m | other
data.first_seenstringWhen Vike first saw the market
data.end_datestringScheduled end
data.neg_riskbooleanNeg-risk market
data.tick_sizenumberPrice step of the book
data.activebooleanActive in the market catalogue
data.closedbooleanClosed in the market catalogue

A real event captured 2026-11-03

json
{
 "schema": "vike.event.v1",
 "event_id": "pm.new_markets:0x1d0a0fa7b01e63b1c2fe909c3a552d919e159ba827c12d5392d8e4a93dbbd5b9",
 "source": "pm.new_markets",
 "kind": "pm_new_market",
 "ts": "2026-11-02T09:51:30.403Z",
 "cursor": "1793613090403-0x1d0a0fa7b01e63b1c2fe909c3a552d919e159ba827c12d5392d8e4a93dbbd5b9",
 "chain": "polygon",
 "subject": {
  "condition_id": "0x1d0a0fa7b01e63b1c2fe909c3a552d919e159ba827c12d5392d8e4a93dbbd5b9",
  "slug": "bnb-updown-5m-1793613300",
  "question": "BNB Up or Down - November 2, 4:55AM-5:00AM ET",
  "outcomes": [
   "Up",
   "Down"
  ],
  "token_ids": [
   "95853262724305275692474634613186630565505623432729531159596758216209572513482",
   "109054760289612549909159513403492642659819464853087188514831720675883642802397"
  ]
 },
 "data": {
  "class": "updown_5m",
  "first_seen": "2026-11-02T09:51:30+00:00",
  "end_date": "2026-11-02T10:00:00+00:00",
  "neg_risk": true,
  "tick_size": 0.01,
  "active": true,
  "closed": false
 },
 "labels": {}
}

Filters

FieldTypeDescription
classlist ≤ 50other, updown_15m, updown_5m

Subscribe

python
import json, os
from websockets.sync.client import connect

with connect("wss://stream.vike.io/v1/stream/polymarket",
             additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
    ws.send(json.dumps({"action": "subscribe", "id": "s1", "channel": "pm.new_markets",
                        "filter": {"class": ["updown_5m"]}}))
    for message in ws:
        frame = json.loads(message)
        if frame["type"] == "ping":
            ws.send(json.dumps({"action": "pong"}))
        elif frame["type"] == "event":
            e = frame["event"]
            print(e["subject"]["question"], e["data"]["end_date"])
FAQ

Polymarket WebSocket FAQ

Is there a Polymarket WebSocket API for trades?
Yes: pm.trades on wss://stream.vike.io/v1/stream/polymarket sends every trade with the wallet behind it, filtered by wallet, market, size, side, role or the wallet's P&L and volume tier.
How do I get notified when a Polymarket market resolves?
Subscribe to pm.resolutions with market set to its condition id, or create a resolution alert.
Can I resume after a disconnect?
Yes: subscribe again with the last cursor you received and get what you missed, up to 3 days back. The same events are also on REST at /v1/polymarket/stream-events.