> The index of these docs, for agents: https://traktor.fun/llms.txt

# Traders

The Traders page under a key: the directory, one wallet's page and its portfolio.

The trader routes answer with the same views Traktor's Traders page and trader pages read, in the v1 envelope and drawn from your plan's units.

### `GET /v1/traders/directory`

Every named trader and each chain's best by a year's realized profit, ranked and screened, a page at a time. With any of the market filter's token screens, only traders with a year who traded a passing token in the window are listed, their window counted in those tokens alone.

- URL: `https://api.traktor.fun/v1/traders/directory`
- Credential: API key
- REST units: 3 units

| Parameter | In | Type | Required | Default | Bounds | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `sort` | query | enum | no | volume | volume, net, bought, sold, buyShare, trades, avgTrade, holdings, pnl, pnlMonth, pnlWeek, winRate, active, recent, firstSeen, rank | The ranking. |
| `dir` | query | enum | no | desc | desc, asc | Ranking direction. |
| `chain` | query | list | no |  | solana, robinhood, bnb, base, arc, arbitrum, ethereum, monad, hyperevm, elysium | Chains to include; empty means all. |
| `window` | query | enum | no | 1440 | 5, 15, 30, 60, 240, 1440 | The activity window, in minutes. |
| `q` | query | string | no |  |  | A name, handle or address to search for. |
| `side` | query | enum | no | all | all, buying, selling | Traders net buying or net selling in the window. |
| `minVolume` | query | number | no |  |  | A floor on `volume`. |
| `minTrades` | query | number | no |  |  | A floor on `trades`. |
| `minHoldings` | query | number | no |  |  | A floor on `holdings`. |
| `minPnl` | query | number | no |  |  | A floor on `pnl`. |
| `minWinRate` | query | number | no |  |  | A floor on `winRate`. |
| `minAvgTrade` | query | number | no |  |  | A floor on `avgTrade`. |
| `minActiveHours` | query | number | no |  |  | A floor on `activeHours`. |
| `launchpad` | query | list | no |  |  | Launchpad families, as `market.launchpads` in `GET /v1/meta/filters` lists them, each optionally chain-qualified, like `bnb:flap`; a bare `other` or `unknown` is dropped and never narrows the list, though `bnb:other` is kept, and a name outside the catalogue is ignored. |
| `dex` | query | list | no |  | paid, boost, cto | DEX signals; a token with any of them matches, and a name outside the vocabulary is ignored. |
| `fees` | query | enum | no | any | any, shared, not_shared | Whether the token's launchpad shares its fees. |
| `pair` | query | list | no |  | up to 12 items | Stock tickers the token pairs with, or `ANY-STOCK` for any stock. |
| `minMcap` | query | number | no |  | 0–1,000,000,000,000,000 | Market cap at least. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `maxMcap` | query | number | no |  | 0–1,000,000,000,000,000 | Market cap at most. Tokens with no cap yet are kept — a brand-new one is small by definition. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minLiq` | query | number | no |  | 0–1,000,000,000,000,000 | Pool depth at least — what the token can absorb before price moves. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `maxLiq` | query | number | no |  | 0–1,000,000,000,000,000 | Pool depth at most. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minLiqPct` | query | number | no |  | 0–1,000,000,000,000,000 | Depth as a share of market cap — how much of the cap there is real money behind. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minHolders` | query | number | no |  | 0–1,000,000,000,000,000 | Wallets holding the token on chain, at least, as its data provider last counted them; a token nobody counted is in no band. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minFomoHolders` | query | number | no |  | 0–1,000,000,000,000,000 | Wallets on fomo still holding a position. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minHeldPct` | query | number | no |  | 0–1,000,000,000,000,000 | Share of circulating supply sitting in fomo wallets — how much of the token the crowd here owns. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minAth` | query | number | no |  | 0–1,000,000,000,000,000 | Multiple back to the all-time high, at least — headroom above the current price. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `maxAth` | query | number | no |  | 0–1,000,000,000,000,000 | Multiple back to the high, at most — near its own top. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `maxAge` | query | number | no |  | 0–1,000,000,000,000,000 | Younger than, in hours since the token launched on chain, or first traded on our tape where that came first or no launch is dated. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minAge` | query | number | no |  | 0–1,000,000,000,000,000 | Older than, in hours since the token launched on chain, or first traded on our tape where that came first or no launch is dated. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `minCurve` | query | number | no |  | 0–1,000,000,000,000,000 | Bonding-curve progress, at least, in percent; a token that has graduated counts as 101. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `maxCurve` | query | number | no |  | 0–1,000,000,000,000,000 | Bonding-curve progress, at most, in percent; 100 keeps only tokens still on their curve. A plain number, read exactly, on the Board's day, where a token it does not list yet is left out. |
| `offset` | query | integer | no | 0 | 0–5,000 | Rows to skip. |
| `limit` | query | integer | no | 100 | 0–200 | Rows per page; 0 reads as the default, 100. |

Limits:

- Invalid keys: 30 a minute, per IP

```bash cURL
curl -s "https://api.traktor.fun/v1/traders/directory" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
```

```ts TypeScript
const response = await fetch("https://api.traktor.fun/v1/traders/directory", {
  headers: { Authorization: `Bearer ${process.env.TRAKTOR_API_KEY}` },
});
const body = await response.json();
```

```python Python
import os
import requests

response = requests.get(
    "https://api.traktor.fun/v1/traders/directory",
    headers={"Authorization": f"Bearer {os.environ['TRAKTOR_API_KEY']}"},
)
print(response.json())
```

Errors: `invalid_parameter`, `unknown_parameter`, `duplicate_query_parameter`, `route_not_found`, `data_unavailable`, `market_busy`, `market_fold_pending`, `missing_credentials`, `invalid_key`, `key_revoked`, `subscription_inactive`, `key_in_query`, `method_not_allowed`, `rate_limited`, `quota_exhausted`, `rate_limit_unavailable`, `internal_error`. Every code: https://traktor.fun/docs/errors.md

### `GET /v1/traders/{wallet}`

One wallet's page: its account where one is linked, its positions and its day, from Traktor's own store.

- URL: `https://api.traktor.fun/v1/traders/{wallet}`
- Credential: API key
- REST units: 2 units

| Parameter | In | Type | Required | Default | Bounds | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `wallet` | path | address | yes |  |  | An EVM or Solana wallet address. |

Limits:

- Invalid keys: 30 a minute, per IP

```bash cURL
curl -s "https://api.traktor.fun/v1/traders/0x2222222222222222222222222222222222222222" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
```

```ts TypeScript
const response = await fetch("https://api.traktor.fun/v1/traders/0x2222222222222222222222222222222222222222", {
  headers: { Authorization: `Bearer ${process.env.TRAKTOR_API_KEY}` },
});
const body = await response.json();
```

```python Python
import os
import requests

response = requests.get(
    "https://api.traktor.fun/v1/traders/0x2222222222222222222222222222222222222222",
    headers={"Authorization": f"Bearer {os.environ['TRAKTOR_API_KEY']}"},
)
print(response.json())
```

Errors: `invalid_parameter`, `unknown_parameter`, `duplicate_query_parameter`, `route_not_found`, `data_unavailable`, `market_busy`, `market_fold_pending`, `missing_credentials`, `invalid_key`, `key_revoked`, `subscription_inactive`, `key_in_query`, `method_not_allowed`, `rate_limited`, `quota_exhausted`, `rate_limit_unavailable`, `internal_error`. Every code: https://traktor.fun/docs/errors.md

### `GET /v1/traders/{wallet}/portfolio`

One wallet's account holdings and value, read from a data provider at most once a refresh.

- URL: `https://api.traktor.fun/v1/traders/{wallet}/portfolio`
- Credential: API key
- REST units: 10 units

| Parameter | In | Type | Required | Default | Bounds | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `wallet` | path | address | yes |  |  | An EVM or Solana wallet address. |

Limits:

- Invalid keys: 30 a minute, per IP

```bash cURL
curl -s "https://api.traktor.fun/v1/traders/0x2222222222222222222222222222222222222222/portfolio" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
```

```ts TypeScript
const response = await fetch("https://api.traktor.fun/v1/traders/0x2222222222222222222222222222222222222222/portfolio", {
  headers: { Authorization: `Bearer ${process.env.TRAKTOR_API_KEY}` },
});
const body = await response.json();
```

```python Python
import os
import requests

response = requests.get(
    "https://api.traktor.fun/v1/traders/0x2222222222222222222222222222222222222222/portfolio",
    headers={"Authorization": f"Bearer {os.environ['TRAKTOR_API_KEY']}"},
)
print(response.json())
```

Errors: `invalid_parameter`, `unknown_parameter`, `duplicate_query_parameter`, `route_not_found`, `data_unavailable`, `market_busy`, `market_fold_pending`, `missing_credentials`, `invalid_key`, `key_revoked`, `subscription_inactive`, `key_in_query`, `method_not_allowed`, `rate_limited`, `quota_exhausted`, `rate_limit_unavailable`, `internal_error`. Every code: https://traktor.fun/docs/errors.md

Each answer is the view the server last built for that question, shared with every other reader of it, and `meta.asOf` dates that build.

- The directory is rebuilt about once a minute. It lists every trader a source names, and, among the wallets that traded through the apps Traktor tracks, each chain's best traders by a year's realized profit, then every other one of them whose year Traktor holds, for that year alone. A row for one of those carries `id` `codex:<wallet>`, and where no source names the wallet its `handle` is the wallet's own address and `name` is null.
- A row listed for its year alone whose wallet traded in the last day carries that day's figures as null, never zero, as Traktor reads the day only for the traders the sources name: `volumeUsd`, `netUsd`, `buyUsd`, `sellUsd`, `trades`, `spark` and `activeHours`. It clears no screen on the day, a floor of zero or a side included, and sorts last on any of those figures.
- On any row, `buyUsd` or `sellUsd` is also null where that side traded in the window and none of those trades had a dollar figure, as far as Traktor's count of unpriced trades (a floor) shows, and where some were priced it is the priced trades' dollars alone; `netUsd` is null beside a null side, and `volumeUsd` where no trade was priced. Such a figure sorts last whichever way its column is turned, and the `buyShare` sort puts a row with a null side last, as the `avgTrade` sort does one with a null volume. A null `netUsd` clears no `side` screen and nets its trader neither way in the summary's `buyers` and `sellers`, and a null `volumeUsd` clears no `minAvgTrade` screen nor a `minVolume` above 0 (a `minVolume` of 0 is no floor where the day was read). The summary's dollars and each row's `spark` add the priced trades alone.
- The day's busiest wallets that pump.fun, Axiom, a wallet-label source or an X account names are rows too, `id` `named:<wallet>`, under that name.
- A wallet's page is read from Traktor's own store. The portfolio comes from a data provider, and a cold read can make a request there, which its units reflect. It names the account the wallet belongs to, the fomo account fomo's matcher links it to, else the fomo account whose handle a wallet label gives the wallet, and reads that account's wallet of the other kind with it.
  - A wallet a row of the all-time Leaderboard names is read alone on its own page and `account` is null: the page never names a Traktor account.
  - A labelled handle whose account Traktor does not know names that wallet alone: `account.source` is `fomo`, `handle` the fomo handle, `name` and `avatarUrl` null and `profileUrl` its fomo page.
  - Where none of those names it, the wallet's own pump.fun profile does, for that wallet alone: `account.source` is `pump`, `handle` its pump.fun username, `name` null and `profileUrl` its pump.fun page.
  - Where no pump.fun profile names it either, Axiom's KOL or pump.fun list does, for that wallet alone: `account.source` is `axiom`, `handle` the handle Axiom gives (a KOL's X handle or a pump.fun username), `name` the list's display name or null, and no `profileUrl`.

With any of the [market filter](https://traktor.fun/docs/market.md)'s token screens (`minMcap`, `launchpad`, `dex` and the rest), the directory lists only the traders whose year Traktor holds and who traded a token the screens pass in the window: `volumeUsd`, `netUsd`, `buyUsd`, `sellUsd`, `trades`, `spark`, `activeHours` and the summary count those tokens' trades alone, and `codex`, `holdings`, `firstSeenAt` and `lastTradeAt` stay the account's. A trader with no year Traktor holds, and every row listed for its year alone, is left out while one is set. The body's `generatedAt` is then the instant the trades were read to, at most two minutes before the answer was built, which `meta.asOf` dates.

Every query key and the wallet in the path are checked before the request is admitted. A key the route does not take, or a value its grammar refuses, is a `400` with no `X-Traktor-Cost`.

A view still being built, or one that failed with nothing kept, is `503 data_unavailable`, with `details.reason` `warming` or `unavailable`, and its units come back, as on the [Tokens](https://traktor.fun/docs/tokens.md) page.
