Room ID: polymarket_trades
Endpoint: wss://api.struct.to/ws
Rate: 0.002 credits per message
Stream real-time Polymarket trades as they happen. All filters are optional, and if none are provided the room auto-subscribes to every trade.
Subscribe
All filters are optional. You can combine multiple filters to narrow the stream. A maximum of 500 total filters is allowed per client. If all filters are empty and subscribe_all is false, the room automatically subscribes to all trades.
Filters
| Filter | Type | Required | Description |
|---|
condition_ids | string[] | No | Filter by market condition IDs |
market_slugs | string[] | No | Filter by market slug |
event_slugs | string[] | No | Filter by event slug |
position_ids | string[] | No | Filter by outcome token IDs |
traders | string[] | No | Filter by wallet addresses (lowercase 0x-prefixed) |
trade_types | string[] | No | Filter by trade type: OrderFilled, OrdersMatched, Redemption, Merge, Split, etc. |
status | string | No | One of confirmed (default), pending, or all |
subscribe_all | boolean | No | Subscribe to every trade with no filters |
Example
{
"type": "join_room",
"payload": {
"room_id": "polymarket_trades"
}
}
{
"type": "room_message",
"payload": {
"room_id": "polymarket_trades",
"message": {
"action": "subscribe",
"condition_ids": ["0xabc123..."]
}
}
}
Response
{
"type": "trade_stream_subscribe_response",
"room_id": "polymarket_trades",
"data": {
"condition_ids": ["0xabc123..."],
"market_slugs": [],
"event_slugs": [],
"position_ids": [],
"traders": [],
"trade_types": [],
"rejected": []
}
}
Events
trade_stream_update
The payload is a discriminated union based on the trade_type field. Each variant includes different fields. Below is an example of the most common type, OrderFilled.
OrderFilled / OrdersMatched
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "OrderFilled",
"id": "0xabc123def456",
"hash": "0xdeadbeef1234567890",
"block": 65000000,
"confirmed_at": 1743500000,
"log_index": 42,
"block_index": 3,
"trader": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"name": null,
"pseudonym": "vitalik.eth",
"profile_image": null,
"x_username": null,
"verified_badge": false
},
"taker": "0x1234567890abcdef1234567890abcdef12345678",
"side": "Buy",
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"position_id": "12345678901234567",
"outcome": "Yes",
"outcome_index": 0,
"slug": "will-bitcoin-hit-100k",
"event_slug": "bitcoin-price-markets",
"usd_amount": 1500.50,
"shares_amount": 2307.69,
"price": 0.65,
"probability": 0.65,
"fee": 3.0,
"fee_shares": 4.62,
"fee_pct": 0.002,
"exchange": "NegRiskExchange"
}
}
Redemption
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "Redemption",
"id": "0xredeem123",
"hash": "0xredeemhash",
"block": 65000100,
"confirmed_at": 1743500100,
"trader": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"name": null,
"pseudonym": "vitalik.eth",
"profile_image": null,
"x_username": null,
"verified_badge": false
},
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"outcome": "Yes",
"outcome_index": 0,
"usd_amount": 1000.0,
"winning_outcome_index": 0,
"position_details": [
{ "position_id": "12345678901234567", "outcome_index": 0, "outcome": "Yes", "amount": "1000" }
],
"exchange": "NegRiskExchange"
}
}
Merge
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "Merge",
"id": "0xmerge123",
"hash": "0xmergehash",
"block": 65000200,
"confirmed_at": 1743500200,
"trader": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"name": null,
"pseudonym": "vitalik.eth",
"profile_image": null,
"x_username": null,
"verified_badge": false
},
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"usd_amount": 500.0,
"position_details": [
{ "position_id": "12345678901234567", "outcome_index": 0, "outcome": "Yes", "amount": "500" },
{ "position_id": "98765432109876543", "outcome_index": 1, "outcome": "No", "amount": "500" }
],
"exchange": "NegRiskExchange"
}
}
Split
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "Split",
"id": "0xsplit123",
"hash": "0xsplithash",
"block": 65000300,
"confirmed_at": 1743500300,
"trader": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"name": null,
"pseudonym": "vitalik.eth",
"profile_image": null,
"x_username": null,
"verified_badge": false
},
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"usd_amount": 750.0,
"position_details": [
{ "position_id": "12345678901234567", "outcome_index": 0, "outcome": "Yes", "amount": "750" },
{ "position_id": "98765432109876543", "outcome_index": 1, "outcome": "No", "amount": "750" }
],
"exchange": "NegRiskExchange"
}
}
PositionsConverted
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "PositionsConverted",
"id": "0xconvert123",
"hash": "0xconverthash",
"block": 65000400,
"confirmed_at": 1743500400,
"trader": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"name": null,
"pseudonym": "vitalik.eth",
"profile_image": null,
"x_username": null,
"verified_badge": false
},
"market_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"index_set": "3",
"shares_amount": 200.0,
"exchange": "NegRiskExchange"
}
}
Cancelled
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "Cancelled",
"id": "0xcancel123",
"hash": "0xcancelhash",
"block": 65000500,
"confirmed_at": 1743500500,
"order_hash": "0xorderhash123",
"exchange": "NegRiskExchange"
}
}
Oracle Lifecycle
Covers Initialization, Proposal, Dispute, Settled, Resolution, ConditionResolution, Reset, Flag, Unflag, Pause, Unpause, ManualResolution, and NegRiskOutcomeReported.
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "Resolution",
"id": "0xoracle123",
"hash": "0xoraclehash",
"block": 65000600,
"confirmed_at": 1743500600,
"oracle_contract": "0xoraclecontract",
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"slug": "will-bitcoin-hit-100k",
"assertion_id": "0xassertion123",
"settled_price": 1,
"settlement_resolution": true
}
}
RegisterToken
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "RegisterToken",
"id": "0xregtoken123",
"hash": "0xregtokenhash",
"block": 65000700,
"confirmed_at": 1743500700,
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"token0": "0xtoken0address",
"token1": "0xtoken1address",
"exchange": "NegRiskExchange"
}
}
Approval
{
"type": "trade_stream_update",
"room_id": "polymarket_trades",
"status": "confirmed",
"data": {
"trade_type": "Approval",
"id": "0xapproval123",
"hash": "0xapprovalhash",
"block": 65000800,
"confirmed_at": 1743500800,
"trader": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"name": null,
"pseudonym": "vitalik.eth",
"profile_image": null,
"x_username": null,
"verified_badge": false
},
"operator": "0xoperatoraddress",
"approved": true,
"exchange": "NegRiskExchange"
}
}
Pending trades: Fields unavailable from mempool (block, confirmed_at, log_index, block_index, order_hash, taker, fee, fee_shares, fee_pct) are omitted. received_at (Unix milliseconds) is included instead.