Top Traders (Market)
Every wallet that holds (or has held) a position in a single market, grouped by outcome and sorted by P&L. The ‘who’s making money on this market’ feed.
btc-updown-5m-1777179000) or the condition_id (e.g. 0xa7ae8a41...). It does not accept an outcome token id — pass the market identifier, not the side.
avgPrice, realizedPnl, etc.) — distinct from polynode’s V2 onchain endpoints which use snake_case. Different schemas, different use cases. Default cap is 50 rows per outcome; configurable up to 500.Request
| Parameter | Type | Location | Description |
|---|---|---|---|
id | string | path | Market slug or condition_id (0x…). Not an outcome token id. |
limit | integer | query | Max rows per outcome. Default 50, max 500. |
offset | integer | query | Skip first N rows. |
sortBy | string | query | TOTAL_PNL (default), REALIZED_PNL, CURRENT_VALUE, SIZE, INITIAL_VALUE. |
sortDirection | string | query | DESC (default) or ASC. |
status | string | query | OPEN, CLOSED, or ALL (default). |
min_size | number | query | Drop positions with size < min_size from each outcome. Use min_size=0.0001 to filter to current holders only (excludes historical participants who closed out to zero). |
includeTrades | boolean | query | When true, adds firstTradeAt / lastTradeAt (unix seconds) per row. Heavy — separate 20 req/min rate limit per key. |
user | string | query | Filter to a single wallet, or up to 20 wallets comma-separated, scoped to this market. |
TOTAL_PNL and REALIZED_PNL are sorted by Polymarket’s data-api directly. CURRENT_VALUE, SIZE, and INITIAL_VALUE are sorted in-process after the fetch (and after min_size if set), so they pair cleanly with the holder-filtering use case.Response
Top-level fields
| Field | Type | Description |
|---|---|---|
condition_id | string | Market condition id |
market_title | string | Human-readable market question |
slug | string | Market slug |
image | string | Market image URL |
outcome_names | string[] | Ordered outcome labels (["Up","Down"], ["Yes","No"], etc.) |
outcomes[] | array | One entry per outcome — each holds a positions array |
outcomes[].token | string | Outcome token id |
outcomes[].positions[] | array | Traders with positions in this outcome, sorted by sortBy |
Per-trader fields (outcomes[].positions[])
| Field | Type | Description |
|---|---|---|
proxyWallet | string | Trader address (Gnosis Safe proxy) |
name | string | Display name (often empty or auto-generated) |
profileImage | string | Profile image URL (often empty) |
verified | boolean | Verified flag |
asset | string | Outcome token id (same as outcomes[].token) |
conditionId | string | Market condition id |
outcome | string | Outcome label ("Up", "No", etc.) |
outcomeIndex | number | 0-based position in outcome_names |
size | number | Current token balance. 0 = fully exited or never held. |
avgPrice | number | Volume-weighted average entry price |
currPrice | number | Current market price (or terminal 1.0/0.0 for resolved markets) |
currentValue | number | Mark-to-market value of remaining shares (size × currPrice) |
totalBought | number | Lifetime tokens acquired |
realizedPnl | number | Realized P&L from sells + redemptions, in USDC |
cashPnl | number | P&L from cash flows (separate accounting axis) |
totalPnl | number | Net portfolio P&L for this position |
firstTradeAt | number | Unix seconds — only with ?includeTrades=true |
lastTradeAt | number | Unix seconds — only with ?includeTrades=true |
Examples
Top 10 traders on a market by total P&L
By condition_id, with first/last trade timestamps
Drill into specific wallets within a market
Closed positions only
Notes
- Default cap of 50 rows per outcome unless
limitis set higher (max 500). On very large markets with deep tail traders, paginate withoffset. - Sort ties on equal P&L are non-deterministic — two wallets at the same
totalPnlmay swap positions between calls. UseproxyWalletas a stable secondary key on the client side if you need consistent ordering. size = 0is normal on closed positions, redeemed positions, or fully-exited positions. UserealizedPnlandtotalBoughtto detect history.firstTradeAt/lastTradeAtrequire?includeTrades=trueand trip a separate heavy-endpoint rate limit (20 req/min per key). Don’t request it on every refresh — fetch once and cache.
When to use this vs. other position endpoints
| If you want | Use |
|---|---|
| Top traders ranked on a single market | This endpoint |
| One wallet’s positions across all markets | GET /v2/wallets/{addr}/positions/onchain |
| All trades on a market (chronological fill feed) | GET /v2/onchain/markets/{tokenId}/trades |
Authorizations
Path Parameters
Condition ID (0x-prefixed) or market slug
Query Parameters
Maximum holders per outcome token (default 50, max 500)
1 <= x <= 500Pagination offset (default 0)
x >= 0Sort holders by field
TOKENS, CASH_PNL, REALIZED_PNL, TOTAL_PNL Sort direction
ASC, DESC Filter by position status
OPEN, CLOSED, ALL Enrich each position with firstTradeAt and lastTradeAt timestamps. Responses will be slower. Default false. Rate limited to 60 requests per minute per key (separate from your standard rate limit).
Filter to specific wallet address(es). Accepts a single address or multiple comma-separated addresses (max 20). Returns only those wallets' positions in this market.
Response
Market positions grouped by outcome token
Holder positions for a market, grouped by outcome token.

