The trades channel ("orders") streams real-time trade events from Polymarket. By default, you receive confirmed events - trades that have been mined on-chain. Covers both V1 and V2 Polymarket contracts.
Want even earlier signals? Pending trade events deliver trades 3–5 seconds before confirmation by decoding transactions from the Polygon mempool. Use status: "all" to receive both.
V1 vs V2: Every order_filled event has a version field (1 or 2). V2 trades add builder and metadata fields (bytes32 hex, currently zero). fee_refund events are V1-only - V2 emits net fees directly on order_filled (no refund flow). See the V2 Migration Guide.
A single matchOrders transaction emits multiple order_filled events - one per maker matched, plus one synthetic taker-aggregate emission summarizing the taker’s overall fill. The role field tells you which one you’re looking at:
role
Description
When to use
"maker"
Per-maker fill. One row per maker order matched in the tx. taker is the real taker user address.
Default for almost all use cases - counting fills, attributing volume to maker wallets, copytrading specific makers.
"taker"
Synthetic taker-aggregate. One row per matchOrders tx, summing across all makers. taker equals the exchange contract address.
Use when you want one row per taker action - e.g. dashboards keyed on the taker, or to avoid double-counting volume across the per-maker rows.
Pending events set role directly from the maker/taker builder; confirmed events derive it from the chain log (taker == exchange contract ⇒ "taker", else "maker"). Empirically the two agree 100%, so you can dedupe pending → confirmed by tx_hash + order_hash regardless of role.
Don’t sum volume across both roles - the taker-aggregate row covers the same shares as the per-maker rows. Pick one set: filter on role === "maker" for maker-attribution, or role === "taker" for taker-attribution.
Polymarket implements a maker fee rebate program. Here’s how it works:
1
Trade executes
An order_filled event arrives with a fee field representing the gross fee charged.
2
Rebate processes
A fee_refund event for the same order_hash arrives 2–5ms later (same block, usually same tx). Rarely up to 50ms.
3
Calculate net fee
The maker’s actual net fee is fee_refund.fee_charged (or equivalently order_filled.fee - fee_refund.refund).
If you don’t need exact fee accounting, you can ignore fee_refund events. The fee field on order_filled is directionally correct for most purposes. Fee refunds are only necessary for precise PnL tracking or cost basis accounting.