The core polynode event. A Polymarket settlement detected before or after on-chain confirmation. Pending settlements arrive 3–5 seconds before on-chain confirmation (1–2 Polygon blocks). This is the data that makes polynode unique.Documentation Index
Fetch the complete documentation index at: https://polynode.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
V2 compatible. Settlement events work identically for both V1 and V2 Polymarket exchanges. V2 settlements are detected automatically — no subscription changes needed. The event format, trade fields, and enrichment are the same. V2 settlement events may include
condition_id directly from the V2 matchOrders calldata. See the V2 Migration Guide.Every WebSocket event is wrapped with three top-level fields:
type, timestamp, and data. The data object also contains an event_type field that always matches the top-level type — use whichever is convenient for your parsing logic.Fields
Always
"settlement".Unix milliseconds. Use this as the canonical event time.
Ordering guarantees
Confirmed settlements are delivered in strict block order. All confirmed events from block N arrive before any from block N+1. Within a block, events are ordered by log index. Polygon uses Bor consensus with single-validator sprints, making chain reorganizations effectively nonexistent. Pending settlements are best-effort ordered by detection time. Because they are extracted from the mempool before block inclusion, there is no guaranteed global sequence. Two pending events detected within the same second may arrive in either order. Do not assume pending ordering reflects eventual on-chain ordering. Pending-to-confirmed pairing: every pending settlement will be followed by a correspondingstatus_update event when the same tx_hash confirms on-chain. You will never receive a confirmed update without a prior pending event for the same transaction.
A note on sender and nonce: Polymarket trades are submitted by Polymarket’s relayer EOAs, not by the traders themselves. Users sign EIP-712 orders off-chain, and the relayer submits the on-chain transaction. The transaction sender and nonce reflect the relayer’s state, not the trader’s intent or ordering. For this reason, sender address and nonce are not included in settlement events — they would be misleading to build on.
The full lifecycle
For every Polymarket settlement, polynode emits up to three events on the WebSocket stream as the transaction moves from mempool to confirmed block:| Event | When it fires | Source | What it contains |
|---|---|---|---|
settlement (pending) | 3–5s before block confirmation | Mempool calldata | All fills in data.trades[], decoded from the matchOrders calldata. Per-maker prices are estimated from aggregate amounts. |
status_update | At block confirmation | Receipt logs | Confirmation metadata (block, latency) plus data.confirmed_fills[] — exact per-fill data from the on-chain OrderFilled logs. |
settlement (confirmed) (legacy) | At block confirmation | Calldata replay | Same shape as the pending settlement, with status: "confirmed" and block_number set. Same calldata-derived prices. |
status_update with confirmed_fills gives you exactness — those are the canonical prices Polymarket itself reads from the chain.
Pending → confirmed pairing
Every pending settlement is followed by a correspondingstatus_update event when the same tx_hash confirms on-chain. Match them by tx_hash:
When to use which
- Pending
settlementonly — you want the 2–5 second lead time and you don’t mind ~0.01–0.04 estimation error on the rare multi-maker fill (e.g. copy trading, frontend price ticks). status_update.confirmed_fillsonly — you need exact prices and don’t care about pre-confirmation. (e.g. analytics, P&L, bookkeeping).- Both together (pending settlement + status_update with confirmed_fills) — you want the speed of pending detection AND the exact prices once confirmed. The recommended pattern for most production integrations.
confirmed_fills[] and a longer treatment of when to use each layer, see the Trade Tracking guide and the Status Update event reference.
Pending vs confirmed (field-level)
| Field | Pending | Confirmed |
|---|---|---|
status | "pending" | "confirmed" |
block_number | null | block number |
detected_at | when polynode first detected TX | same value |
| Latency | ~0ms from detection | 2–5s after detection (1–2 blocks) |
Use cases
- Copy trading — detect whale trades 1–2 blocks before confirmation and execute your own order
- Market making — adjust spreads based on incoming settlements
- Analytics — track real-time volume and price movements
- Alerts — notify on large trades or specific wallet activity
Tracking a specific wallet’s trades
Each entry indata.trades[] is one fill, and the maker field on that entry is the wallet whose trade it is. To track a specific wallet, find the entries in trades[] where maker === your_wallet:
maker === your_wallet.
Why not match by taker
If you match by taker === your_wallet, you get counterparty fills, not the wallet’s actual trade. The taker field on each fill is the opposite party, so matching it gives you the wrong wallet’s perspective — including the opposite token and the complement price. For example, if your wallet bought Up at 0.80, matching by taker returns a fill showing the counterparty buying Down at 0.20.
For a deeper explanation of why the on-chain OrderFilled events are structured this way, see the Trade Event reference or the Dome migration guide.
