Messages & lifecycle
The shape of trade events, how to stop a stream, and how the connection stays healthy.
Event messages
Each event is a JSON frame carrying the event type, its source, the delivery timestamp, and a data object with the trade. Here is a live polymarket.trade event (long hashes abbreviated):
{
"type": "polymarket.trade",
"source": "polymarket-trade-scraper",
"timestamp": "2026-05-27T13:50:00.167247+00:00",
"data": {
"id": "0x8902f2…498832_0x31ba8c…a5aa09",
"side": "BUY",
"size": 11,
"price": 0.53,
"timestamp": "2026-05-27T13:49:52+00:00",
"transaction_hash": "0x8902f299…d6d498832",
"order_hash": "0x31ba8c8c…454aa5aa09",
"block_number": 87514326,
"condition_id": "0x9ad19824…2d7f2d9",
"asset": "67025362…363793",
"title": "Bitcoin Up or Down - May 27, 9:50AM-9:55AM ET",
"slug": "btc-updown-5m-1779889800",
"event_slug": "btc-updown-5m",
"outcome": "Up",
"outcome_index": 0,
"icon": "https://polymarket-upload.s3…/BTC+fullsize.png",
"maker": "0x55338c…d1b8220",
"taker": "0x6833c0…1b5cfe1",
"proxy_wallet": "0x55338c…d1b8220",
"name": null,
"pseudonym": null,
"bio": null,
"profile_image": null,
"profile_image_optimized": null
}
}Filterable fields
The fields you can filter on (from /event-types). Every event also carries the additional non-filterable fields shown in the payload above.
| Field | Type | Description |
|---|---|---|
proxy_wallet | string | Trader's proxy wallet |
slug | string | Market slug |
condition_id | string | Market condition ID |
event_slug | string | Parent event slug |
outcome | string | Outcome traded (e.g. Up, No) |
outcome_index | integer | Index of the traded outcome |
side | string | Trade direction — BUY or SELL |
asset | string | Outcome token (asset) ID |
maker | string | Maker wallet address |
taker | string | Taker wallet address |
transaction_hash | string | On-chain transaction hash |
order_hash | string | On-chain order hash |
Unsubscribe
Stop one or more streams by sending an unsubscribe frame with the subscription_ids returned when you subscribed. The server confirms with an unsubscribed acknowledgement.
{
"action": "unsubscribe",
"subscription_ids": ["cede7755-c0a6-41b8-b316-ca4377dedb5d"]
}{
"action": "unsubscribed",
"subscription_ids": ["cede7755-c0a6-41b8-b316-ca4377dedb5d"]
}Connection lifecycle
Heartbeat
Connections are kept healthy by a built-in ping/pong heartbeat. Most WebSocket libraries respond to pings automatically, so there's nothing to implement — your stream stays alive as long as your client is connected.
Reconnection
Connections are long-lived. For a resilient client, reconnect automatically with exponential backoff and re-send your subscribe frames once reconnected — the standard pattern for any streaming integration. A close with code 4001 is simply a cue to reconnect to a fresh upstream feed, and deploys roll out with graceful connection draining so reconnects stay clean. You can confirm gateway health any time with GET /health (returns 200 OK). The SDK does all of this for you.