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.
Returns every wallet with a position in a single market, broken out by outcome (e.g. Up/Down or Yes/No) and ranked by P&L. The natural feed for “top traders on this market” leaderboards, top-X-by-PnL widgets, and per-market trader audits. Path accepts either the market slug (e.g.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.
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.| 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.| 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 |
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 |
limit is set higher (max 500). On very large markets with deep tail traders, paginate with offset.totalPnl may swap positions between calls. Use proxyWallet as a stable secondary key on the client side if you need consistent ordering.size = 0 is normal on closed positions, redeemed positions, or fully-exited positions. Use realizedPnl and totalBought to detect history.firstTradeAt / lastTradeAt require ?includeTrades=true and trip a separate heavy-endpoint rate limit (20 req/min per key). Don’t request it on every refresh — fetch once and cache.| 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 |
Condition ID (0x-prefixed) or market slug
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. Adds one upstream call per holder, so 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.
Market positions grouped by outcome token
Holder positions for a market, grouped by outcome token.