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

# Traders

> The on-chain archive over REST — career card, markets, top markets, per-market summary, the sampled chart, the full tape, the equity curve, and cross-market fills.

Base: `https://api.polytape.io/api/agent/v1`

`{trader}` accepts a 0x wallet, a polymarket.com profile URL, or a display name.

<Note>
  **Depth is plan-gated.** Basic Intelligence reaches a trader's 5 most-recent
  markets; Pro and Max reach the full record. Basic is additionally capped at
  **3 distinct wallets per UTC day**. See [Plans & limits](/plans-and-limits).
</Note>

***

## `GET /traders/{trader}`

The career card, blending the on-chain archive with Polymarket's own profile.
`Cache-Control: no-store`.

<CodeGroup>
  ```bash Request theme={null}
  curl -H "Authorization: Bearer td_live_..." \
    https://api.polytape.io/api/agent/v1/traders/GoingInsolvent
  ```

  ```json Response theme={null}
  {
    "trader": { "wallet": "0x…", "name": "GoingInsolvent" },
    "card": {
      "markets_total": 8305,
      "resolved_total": 8305,
      "winrate": 0.5624,
      "volume_usd": 5780817.7,
      "first_seen": 1778776327,
      "last_seen": 1783189768,
      "avg_entry_price": 0.49,
      "avg_win_usd": 5.6,
      "avg_loss_usd": -10.0,
      "open_value_usd": 0.0,
      "open_markets": 0,
      "unmarked_markets": 0,
      "marked_at": null
    },
    "polymarket": {
      "pnl": 61240.0,
      "pnl_realized": 55010.0,
      "pnl_unrealized": 6230.0,
      "portfolio_value": 12400.0,
      "peak": 71000.0,
      "low": -3400.0,
      "max_drawdown": 42000.0,
      "profile_image": "https://…",
      "as_of": 1783200000
    }
  }
  ```
</CodeGroup>

**`polymarket.pnl` is THE P/L** — Polymarket's model, realized + unrealized, full
account history including pre-V2. If the upstream is down, `polymarket` becomes
`{"status": "pm_offline"}`, the card still serves, and **only then** does it carry
the archive's realized `career_pnl_usd` / `pnl_marked_usd` as the fallback voice.

`card.avg_entry_price` is the average cost **per token** across all buys — the
trader's **break-even winrate**, token-weighted. It is not the price they usually
click. `avg_win_usd` / `avg_loss_usd` are per-resolved-market averages, and one
blowup skews them.

<Warning>
  `avg_entry_price`, `avg_win_usd`, and `avg_loss_usd` are **absent or null until
  the career-stats rollup has populated a trader**. Treat missing as
  "unavailable", never as zero.

  `winrate` is null when nothing has resolved. An unknown-but-valid wallet returns
  an honest zeroed card, not a 404.
</Warning>

Full doctrine: [Reading the numbers](/concepts/pnl).

***

## `GET /traders/{trader}/top-markets`

The trader's standout markets in **one scan** — the whale drill-down the
recency-only markets list cannot do.

| Query | Type | Default | Notes                  |
| ----- | ---- | ------- | ---------------------- |
| `n`   | int  | `5`     | per slice; clamps 1–20 |

```json theme={null}
{ "trader": {…},
  "top_wins":    [ <market row>, … ],
  "top_losses":  [ … ],
  "most_traded": [ … ],
  "top_volume":  [ … ],
  "note": "wins/losses rank realized pnl over RESOLVED markets only" }
```

Each row uses the markets-list shape below. Uncached, since open markets shift.
Keep `n` modest on 100k-market makers — they sit near the heavy-query timeout
(`504 query_timeout`).

***

## `GET /traders/{trader}/markets`

Recency-ordered markets, one row each.

| Query    | Type   | Notes                                                  |
| -------- | ------ | ------------------------------------------------------ |
| `cursor` | string | opaque; pass back `next_cursor`                        |
| `limit`  | int    | caps the page (default \~200) — **pass a smaller one** |

Each row: `condition_id`, `title`, `outcome`, `resolved`, `winner`,
`last_traded_at`, `trader_last_action` (`BUY`/`SELL`), `last_price`,
`fills_count`, `pnl_usd`, `open`, `volume_usd`. Open rows also carry
`market_value_usd` and `pnl_marked_usd`.

<Warning>
  For extremes use `/top-markets`, never paging. This list is **recency-ordered
  only** by design — a 40,000-market bot has no "biggest win" on page one.
</Warning>

***

## `GET /traders/{trader}/markets/{condition_id}/summary`

The computed stat block. **Prefer this over raw events.** No arrays.

```json theme={null}
{
  "market": { "condition_id": "0x…", "title": "…", "outcome": "Up", "outcome2": "Down",
              "resolved": true, "winner": "Down", "pnl_usd": -21.96, "open": false },
  "summary": {
    "fills_count": 148, "buy_count": 148, "sell_count": 0,
    "buy_usd": 360.85, "sell_usd": 0.0, "avg_entry_price": 0.3302,
    "size_p50_usd": 2.5, "size_p90_usd": 4.15, "size_max_usd": 4.85,
    "first_fill_ts": 1783188908, "last_fill_ts": 1783189141, "hold_seconds": 233,
    "usd_share_first_tenth": 0.0, "usd_share_last_tenth": 0.4145,
    "pnl_usd": -21.96, "roi": -0.0609, "open": false, "won": false,
    "sides": [
      { "token_side": 1, "outcome": "Up", "buy_count": 89, "sell_count": 0,
        "buy_usd": 1820.0, "sell_usd": 0.0, "avg_entry": 0.48, "net_tokens": 3790.0 },
      { "token_side": 2, "outcome": "Down", "avg_entry": 0.55 }
    ]
  },
  "trader": { "wallet": "0x…", "name": "GoingInsolvent" }
}
```

| Field                                   | Meaning                                                                                                                               |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `avg_entry_price`                       | **UP-space** VWAP of the trader's buys in this market                                                                                 |
| `sides[].avg_entry`                     | the same idea in the token's **own** frame — what they paid                                                                           |
| `usd_share_first_tenth` / `_last_tenth` | fraction of their USD placed in the first / last 10% of the market's whole traded window. Near-zero first + high last = a late piler. |
| `roi`                                   | pnl ÷ buy notional — **meaningless for split-sellers**                                                                                |

Resolved markets are immutable and ETag'd — send `If-None-Match` for a `304`.

***

## `GET /traders/{trader}/markets/{condition_id}`

**The sampled market chart in one call** — no cursor, no tick flood.

| Query               | Type | Default | Notes                                                       |
| ------------------- | ---- | ------- | ----------------------------------------------------------- |
| `points`            | int  | `300`   | target count; clamps 20–600, snapped to the fidelity ladder |
| `from_ts` / `to_ts` | int  | —       | epoch seconds; zoom a window                                |
| `resolution`        | int  | —       | force a bucket size in seconds (snapped)                    |
| `raw`               | bool | `false` | verbatim keyset tick paging instead                         |

```json theme={null}
{
  "market": { "condition_id": "0x…", "title": "…", "outcome": "Up", "outcome2": "Down",
              "resolved": true, "winner": "Up", "pnl_usd": 81.08, "open": false },
  "trader": { "wallet": "0x…", "name": "GoingInsolvent" },
  "series": { "from_ts": 1783189500, "to_ts": 1783189800, "fidelity": 1,
              "points": [ [1783189500, 0.5088, 0.47, 0.51], … ] },
  "fills":  [ { "ts": 1783189505, "side": "BUY", "price": 0.48, "token_side": 2,
                "outcome": "Down", "size_tokens": 5.0, "usd": 2.6 }, … ]
}
```

* `points` are `[ts, last, lo, hi]`, UP-normalized. **Draw `(lo + hi) / 2`** —
  every value is a real traded level; the server never emits a computed price.
* Omit `from_ts` / `to_ts` for the title-anchored default window (a "2:25–2:30PM
  ET" market opens at the title's start).
* `fills` is the trader's **complete** fill set, always present, each carrying
  `token_side` and `outcome`.

<Note>
  `raw=1` returns the old verbatim contract instead: `ticks: [{ts, price}]` plus
  `window` / `cursor` / `limit` keyset paging. Raw ticks duplicate about **36×**,
  so this is the export path. For a chart you want the sampled default.
</Note>

***

## `GET /traders/{trader}/markets/{condition_id}/tape`

The whole market as a **change-compressed per-second tape** in one gzipped
response (`Content-Encoding: gzip`), uncapped — for the interactive TradingView
template.

```json theme={null}
{ "market": {…}, "trader": {…}, "tape": [ [ts, last, lo, hi], … ] }
```

Rows are UP-normalized and emitted only when a second's `(last, lo, hi)` differs
from the previously emitted second. A 53-day market is roughly 27,000 rows /
\~150KB gzipped, not millions. Do all bucketing and the band-mid walk client-side.

<Warning>
  Fine for a file or a browser; **too big for a chat artifact**. For chat, use the
  sampled endpoint above with `points=120`.
</Warning>

There is no MCP tool for this endpoint — it is REST-only.

***

## `GET /traders/{trader}/pnl-series`

Polymarket's cumulative-P/L series for the career **equity curve**.

| Query    | Values                                           | Default |
| -------- | ------------------------------------------------ | ------- |
| `window` | `24h` \| `7d` \| `30d` \| `ytd` \| `1y` \| `all` | `all`   |

```json theme={null}
{ "trader": {…}, "window": "all", "model": "polymarket_profile",
  "series": [ [1733000000, 0.0], [1733086400, 152.4], … ],
  "peak": 231000.5, "low": -12400.2, "max_drawdown": 88211.0,
  "as_of": 1752710000 }
```

Drawdown is a one-line derivation the equity template does for you:
`dd[i] = p[i] − running_max`. Degrades to `{"status": "pm_offline"}` if the
upstream is down.

***

## `GET /traders/{trader}/fills`

Cross-market fills since a timestamp — **the monitoring primitive**. Any wallet,
no live-slot cost, freshness bounded by the archive pipeline (minutes).

| Query    | Type   | Notes                                       |
| -------- | ------ | ------------------------------------------- |
| `since`  | int    | epoch seconds                               |
| `cursor` | string | pass back `next_cursor`                     |
| `limit`  | int    | **cap it** — a full page is \~10–15k tokens |

Each fill: `{ts, condition_id, title, side, price, token_side, outcome,
size_tokens, usd}`.

Record the last fill's `ts` and pass it back as `since` next poll, so you only
pull what is new. Poll on a **minutes** cadence — see
[Monitor a wallet](/guides/recipes#monitor-a-wallet).
