Room ID:
Endpoint:
Rate: 0.005 credits per message
polymarket_trader_positions Endpoint:
wss://api.struct.to/ws Rate: 0.005 credits per message
Related guide: Real-time positions tracking seeds a portfolio from REST and keeps it live through this room.
Envelope types
| Event | Trigger | dirty_kinds |
|---|---|---|
trader_position_batch | A trade landed | ["trade"] (may include others) |
trader_position_price_batch | Mark-to-market refresh | ["price"] |
trader_position_resolution_batch | The position’s market resolved | ["position_resolved"] |
{ type, room_id, block, data: [ ...rows ] }. Empty batches are not sent. Resolution rows cover lifetime non-redeemers as well as fresh resolutions.
dirty_kinds
| Value | Meaning |
|---|---|
trade | A buy, sell, merge, split, redemption, or NegRisk convert landed |
price | An outcome price moved (mark-to-market refresh) |
position_resolved | The position’s market resolved |
Subscribe
Thetraders filter is required.
Filters
| Filter | Type | Required | Description |
|---|---|---|---|
traders | string[] | Yes | EVM wallet addresses (0x-prefixed), non-empty |
dirty_kinds | string[] | No | Subset of ["trade","price","position_resolved"], or ["all"]. A row is delivered only if its dirty_kinds intersects this set. |
Example
{
"type": "join_room",
"payload": {
"room_id": "polymarket_trader_positions"
}
}
{
"type": "room_message",
"payload": {
"room_id": "polymarket_trader_positions",
"message": {
"action": "subscribe",
"traders": ["0x1234567890abcdef1234567890abcdef12345678"]
}
}
}
Response
{
"type": "trader_positions_stream_subscribe_response",
"room_id": "polymarket_trader_positions",
"data": {
"traders": ["0x1234567890abcdef1234567890abcdef12345678"],
"rejected": [],
"error": null
}
}
Events
trader_position_batch
Full position rows, fired on trades.
{
"type": "trader_position_batch",
"room_id": "polymarket_trader_positions",
"block": 68420001,
"data": [
{
"trader": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"position_id": "12345678901234567",
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"market_slug": "will-bitcoin-hit-100k",
"event_slug": "bitcoin-price-markets",
"title": "Will Bitcoin hit $100k?",
"question": "Will Bitcoin hit $100k by end of year?",
"image_url": "https://polymarket.com/images/market.png",
"outcome": "Yes",
"outcome_index": 0,
"open": true,
"won": null,
"total_buys": 3,
"total_sells": 1,
"converted_count": 0,
"converted_shares_gained": 0.0,
"converted_shares_lost": 0.0,
"total_shares_bought": 1500.0,
"total_shares_sold": 500.0,
"total_buy_usd": 975.0,
"total_sell_usd": 350.0,
"redemption_usd": 0.0,
"merge_usd": 0.0,
"avg_entry_price": 0.65,
"avg_exit_price": 0.7,
"avg_price": 0.66,
"realized_pnl_usd": 125.5,
"realized_pnl_pct": 12.87,
"total_fees": 2.65,
"first_trade_at": 1742000000000,
"last_trade_at": 1743500000000,
"current_price": 0.72,
"current_shares_balance": 1000.0,
"current_value": 720.0,
"last_traded_price": 0.71,
"end_date": 1751328000,
"is_neg_risk": false,
"redeemable": false,
"mergeable": false,
"dirty_kinds": ["trade"]
}
]
}
| Field | Type | Description |
|---|---|---|
position_id | string | ERC-1155 token ID (decimal string) |
condition_id | string | Condition ID |
market_slug | string | Market slug |
event_slug | string | Owning event slug |
title | string | Market title |
question | string | Market question |
image_url | string | Market image URL |
outcome | string | Outcome label (for example Yes) |
outcome_index | int | Outcome index |
open | bool | Whether the position is open |
won | bool | Set once the market resolves |
total_buys | int64 | Buy count |
total_sells | int64 | Sell count |
converted_count | int64 | NegRisk conversion count |
converted_shares_gained | number | Shares gained via conversion |
converted_shares_lost | number | Shares lost via conversion |
total_shares_bought | number | Cumulative shares bought |
total_shares_sold | number | Cumulative shares sold |
total_buy_usd | number | Buy spend in USD |
total_sell_usd | number | Sell proceeds in USD |
redemption_usd | number | Redemption proceeds in USD |
merge_usd | number | Merge proceeds in USD |
avg_entry_price | number | Volume-weighted entry price (0-1) |
avg_exit_price | number | Volume-weighted exit price (0-1) |
avg_price | number | Volume-weighted price across buys and sells |
realized_pnl_usd | number | Realized PnL in USD |
realized_pnl_pct | number | Realized PnL as a percentage |
total_fees | number | Total fees in USD |
first_trade_at | int64 | First trade (Unix milliseconds) |
last_trade_at | int64 | Last trade (Unix milliseconds) |
current_price | number | Current outcome price |
current_shares_balance | number | Current shares held |
current_value | number | current_price times current_shares_balance |
last_traded_price | number | Last on-chain traded price |
end_date | int64 | Resolution deadline (Unix seconds) |
is_neg_risk | bool | Whether the market is NegRisk |
redeemable | bool | Resolved and still holding shares |
mergeable | bool | NegRisk, unresolved, and holding shares |
dirty_kinds | string[] | What triggered this row |
trader_position_price_batch
Compact price ticks. dirty_kinds is always ["price"].
{
"type": "trader_position_price_batch",
"room_id": "polymarket_trader_positions",
"block": 68420002,
"data": [
{
"trader": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"position_id": "12345678901234567",
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"current_price": 0.74,
"current_value": 740.0,
"realized_pnl_usd": 125.5,
"realized_pnl_pct": 12.87,
"last_block": 68420002,
"last_trade_at": 1743500000000,
"dirty_kinds": ["price"]
}
]
}
| Field | Type | Description |
|---|---|---|
trader | string | Wallet address |
position_id | string | ERC-1155 token ID (decimal string) |
condition_id | string | Condition ID |
current_price | number | Current outcome price |
current_value | number | Current position value in USD |
realized_pnl_usd | number | Realized PnL in USD |
realized_pnl_pct | number | Realized PnL as a percentage |
last_block | int64 | Block of this tick |
last_trade_at | int64 | Last trade (Unix milliseconds) |
dirty_kinds | string[] | Always ["price"] |
trader_position_resolution_batch
Resolution ticks. dirty_kinds is always ["position_resolved"].
{
"type": "trader_position_resolution_batch",
"room_id": "polymarket_trader_positions",
"block": 68420003,
"data": [
{
"trader": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"position_id": "12345678901234567",
"condition_id": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"resolved": true,
"won": true,
"realized_pnl_usd": 350.25,
"realized_pnl_pct": 35.9,
"last_block": 68420003,
"last_trade_at": 1743500000000,
"dirty_kinds": ["position_resolved"]
}
]
}
| Field | Type | Description |
|---|---|---|
trader | string | Wallet address |
position_id | string | ERC-1155 token ID (decimal string) |
condition_id | string | Condition ID |
resolved | bool | Whether the market resolved |
won | bool | null | Whether the position won |
realized_pnl_usd | number | Realized PnL in USD |
realized_pnl_pct | number | Realized PnL as a percentage |
last_block | int64 | Block of this tick |
last_trade_at | int64 | Last trade (Unix milliseconds) |
dirty_kinds | string[] | Always ["position_resolved"] |