> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polynode.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

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. `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.

<Note>
  Field shape is camelCase (`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.
</Note>

## Request

```
GET /v1/markets/{slug-or-condition-id}/positions
```

| 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.                                                                                      |

<Note>
  `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.
</Note>

## Response

```json theme={null}
{
  "condition_id": "0xa7ae8a4119fe00f231e693ed717339dd1e13da4617c79f3b1522ab1aee3965b6",
  "market_title": "Bitcoin Up or Down - April 26, 12:50AM-12:55AM ET",
  "slug": "btc-updown-5m-1777179000",
  "image": "https://polymarket-upload.s3.us-east-2.amazonaws.com/BTC+fullsize.png",
  "outcome_names": ["Up", "Down"],
  "outcomes": [
    {
      "token": "90684694382683135738693577247532961739938461809085935450142382916430459093778",
      "positions": [
        {
          "proxyWallet": "0x9a1d392572d0e6bfefbf9302101b9e44c8ee86d6",
          "name": "kq9000",
          "profileImage": "",
          "verified": false,
          "asset": "90684694382683135738693577247532961739938461809085935450142382916430459093778",
          "conditionId": "0xa7ae8a4119fe00f231e693ed717339dd1e13da4617c79f3b1522ab1aee3965b6",
          "outcome": "Up",
          "outcomeIndex": 0,
          "size": 0,
          "avgPrice": 0.4592,
          "currPrice": 1,
          "currentValue": 0,
          "totalBought": 1633.1987,
          "realizedPnl": 812.5754,
          "cashPnl": 0,
          "totalPnl": 812.5754,
          "firstTradeAt": 1777179030,
          "lastTradeAt": 1777179152
        }
      ]
    },
    { "token": "96824…", "positions": [ "…" ] }
  ]
}
```

### 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

```bash theme={null}
curl "https://api.polynode.dev/v1/markets/btc-updown-5m-1777179000/positions?limit=10&sortBy=TOTAL_PNL&sortDirection=DESC" \
  -H "x-api-key: YOUR_KEY"
```

### By condition\_id, with first/last trade timestamps

```bash theme={null}
curl "https://api.polynode.dev/v1/markets/0xa7ae8a4119fe00f231e693ed717339dd1e13da4617c79f3b1522ab1aee3965b6/positions?includeTrades=true&limit=20" \
  -H "x-api-key: YOUR_KEY"
```

### Drill into specific wallets within a market

```bash theme={null}
curl "https://api.polynode.dev/v1/markets/btc-updown-5m-1777179000/positions?user=0x9a1d392572d0e6bfefbf9302101b9e44c8ee86d6,0x44bd2993a69d8b569859ed8c0bf0b946f733f71a" \
  -H "x-api-key: YOUR_KEY"
```

### Closed positions only

```bash theme={null}
curl "https://api.polynode.dev/v1/markets/btc-updown-5m-1777179000/positions?status=CLOSED&sortBy=REALIZED_PNL" \
  -H "x-api-key: YOUR_KEY"
```

## Notes

* **Default cap of 50 rows** per outcome unless `limit` is set higher (max 500). On very large markets with deep tail traders, paginate with `offset`.
* **Sort ties on equal P\&L are non-deterministic** — two wallets at the same `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.

## 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`](/api-reference/wallets/onchain-positions) |
| All trades on a market (chronological fill feed) | [`GET /v2/onchain/markets/{tokenId}/trades`](/api-reference/onchain/market-trades)     |


## OpenAPI

````yaml GET /v1/markets/{id}/positions
openapi: 3.1.0
info:
  title: PolyNode API
  description: >-
    Real-time Polymarket data API with decoded mempool settlements, OHLCV
    candles, and full Polygon JSON-RPC proxy.
  contact:
    name: PolyNode
    url: https://polynode.dev
  license:
    name: ''
  version: 2.0.0
servers:
  - url: https://api.polynode.dev
    description: Production
security:
  - api_key: []
paths:
  /v1/markets/{id}/positions:
    get:
      tags:
        - Wallets
      summary: Market positions & P&L
      description: >-
        Returns all holder positions for a market with per-holder P&L breakdown.
        Results are grouped by outcome token, with each holder's cash P&L,
        realized P&L, total P&L, average entry price, and current value.


        Accepts a condition ID (0x-prefixed) or market slug. Supports sorting by
        P&L and filtering by position status (open/closed/all).


        When `includeTrades=true`, this endpoint is rate limited to **60
        requests per minute** per key (separate from your standard rate limit).
      operationId: get_market_positions
      parameters:
        - name: id
          in: path
          description: Condition ID (0x-prefixed) or market slug
          required: true
          schema:
            type: string
        - name: limit
          in: query
          description: Maximum holders per outcome token (default 50, max 500)
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 500
        - name: offset
          in: query
          description: Pagination offset (default 0)
          schema:
            type: integer
            default: 0
            minimum: 0
        - name: sortBy
          in: query
          description: Sort holders by field
          schema:
            type: string
            enum:
              - TOKENS
              - CASH_PNL
              - REALIZED_PNL
              - TOTAL_PNL
            default: TOTAL_PNL
        - name: sortDirection
          in: query
          description: Sort direction
          schema:
            type: string
            enum:
              - ASC
              - DESC
            default: DESC
        - name: status
          in: query
          description: Filter by position status
          schema:
            type: string
            enum:
              - OPEN
              - CLOSED
              - ALL
            default: ALL
        - name: includeTrades
          in: query
          description: >-
            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).
          schema:
            type: boolean
            default: false
        - name: user
          in: query
          description: >-
            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.
          schema:
            type: string
      responses:
        '200':
          description: Market positions grouped by outcome token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketPositionsResponse'
              example:
                condition_id: >-
                  0x895e01dbf3e6a33cd9a44ca0f8cdb5df1bd2b0b6ebed5300d28f8da7145145e4
                market_title: >-
                  Will Donald Trump win the 2028 Republican presidential
                  nomination?
                slug: >-
                  will-donald-trump-win-the-2028-republican-presidential-nomination
                outcome_names:
                  - 'Yes'
                  - 'No'
                outcomes:
                  - token: >-
                      3039641309958397001906153616677074061284510636203465131156925998487819889437
                    positions:
                      - proxyWallet: '0xa5ef39c3d3e10d0b270233af41cac69796b12966'
                        name: ''
                        outcome: 'No'
                        outcomeIndex: 1
                        size: 1735573.72
                        avgPrice: 0
                        currPrice: 0.9835
                        currentValue: 1706936.75
                        cashPnl: 1706936.75
                        realizedPnl: 0
                        totalPnl: 1706936.75
                      - proxyWallet: '0xc2e7800b5af46e6093872b177b7a5e7f0563be51'
                        name: beachboy4
                        outcome: 'Yes'
                        outcomeIndex: 0
                        size: 248651.26
                        avgPrice: 0.040276
                        currPrice: 0.0165
                        currentValue: 4102.75
                        cashPnl: -5911.93
                        realizedPnl: 0
                        totalPnl: -5911.93
                        firstTradeAt: 1753016057
                        lastTradeAt: 1765034355
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Market not found for the given slug
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: Upstream data source unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - api_key: []
components:
  schemas:
    MarketPositionsResponse:
      type: object
      description: Holder positions for a market, grouped by outcome token.
      required:
        - condition_id
        - outcomes
      properties:
        condition_id:
          type: string
          description: Market condition ID.
        market_title:
          type: string
          description: Market title (enriched by PolyNode).
        slug:
          type: string
          description: Market slug (enriched by PolyNode).
        outcome_names:
          type: array
          items:
            type: string
          description: Outcome names (e.g. ["Yes", "No"]).
        outcomes:
          type: array
          description: Array of outcome tokens, each containing a list of holder positions.
          items:
            type: object
            properties:
              token:
                type: string
                description: Token ID for this outcome.
              positions:
                type: array
                items:
                  $ref: '#/components/schemas/MarketHolderPosition'
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
    MarketHolderPosition:
      type: object
      description: A single holder's position in a market outcome.
      properties:
        proxyWallet:
          type: string
          description: Holder's wallet address.
        name:
          type: string
          description: Polymarket username (if set).
        outcome:
          type: string
          description: Outcome name.
        outcomeIndex:
          type: integer
          description: Outcome index (0 or 1).
        size:
          type: number
          description: Position size in outcome tokens.
        avgPrice:
          type: number
          description: Average entry price.
        currPrice:
          type: number
          description: Current market price.
        currentValue:
          type: number
          description: Current market value.
        cashPnl:
          type: number
          description: Unrealized cash P&L.
        realizedPnl:
          type: number
          description: Realized P&L from closed portions.
        totalPnl:
          type: number
          description: Total P&L (cash + realized).
        totalBought:
          type: number
          description: Total tokens bought.
        firstTradeAt:
          type: integer
          description: >-
            Unix timestamp of the holder's first trade on this market. Only
            present when `includeTrades=true`.
        lastTradeAt:
          type: integer
          description: >-
            Unix timestamp of the holder's most recent trade on this market.
            Only present when `includeTrades=true`.
  securitySchemes:
    api_key:
      type: apiKey
      in: header
      name: x-api-key

````