# KOL, alpha and bundles

Source: https://www.scanner.net/docs/api/reference/signals

> KOL wallets and their PnL, the alpha trader leaderboard, and bundled wallets linked to an address.

Lists of known wallets and how they trade. Every route on this page is free and reads data Scanner already holds.

12 routes. Every path below is served under `https://api.scanner.net`, and every request carries the key header, so those two are not repeated per route. Shared errors and limits are in [Requests and errors](/docs/api/reference/conventions). Keys need the **Alpha, KOL and signals** endpoint group for these routes.

KOL wallets [#kol-wallets]

```http
GET /kol/wallets
```

Every KOL wallet Scanner tracks, best ranked first.

| Parameter | In    | Type    | Required | Notes                    |
| --------- | ----- | ------- | -------- | ------------------------ |
| `limit`   | query | integer | no       | 1 to 2000. Default 2000. |
| `offset`  | query | integer | no       | Default 0.               |

```bash
curl "https://api.scanner.net/kol/wallets?limit=100" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "wallets": [...], "count": 100 }`. Each wallet has `wallet_address`, `name`, `twitter_handle`, `profile_picture_url`, `kolscan_rank`, `is_featured`, `created_at` and `updated_at`.

KOL wallet [#kol-wallet]

```http
GET /kol/wallets/{address}
```

One KOL wallet.

| Parameter | In   | Type   | Required | Notes           |
| --------- | ---- | ------ | -------- | --------------- |
| `address` | path | string | yes      | Solana address. |

```bash
curl "https://api.scanner.net/kol/wallets/WALLET_ADDRESS" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "wallet": { ... } }`, with the fields listed under [KOL wallets](#kol-wallets).

| Status | Code        | When                            |
| ------ | ----------- | ------------------------------- |
| 404    | `NOT_FOUND` | The address isn't a KOL wallet. |

KOL wallets in bulk [#kol-wallets-in-bulk]

```http
POST /kol/wallets/batch
```

Which of up to 200 addresses are KOL wallets.

| Parameter   | In   | Type      | Required | Notes                                   |
| ----------- | ---- | --------- | -------- | --------------------------------------- |
| `addresses` | body | string\[] | yes      | Not empty. Only the first 200 are used. |

```bash
curl -X POST "https://api.scanner.net/kol/wallets/batch" \
  -H "x-api-key: $SCANNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"addresses":["WALLET_1","WALLET_2"]}'
```

**Response:** `{ "success": true, "wallets": [...] }`, the matching KOL wallets only, in no set order.

| Status | Code            | When                             |
| ------ | --------------- | -------------------------------- |
| 400    | `INVALID_INPUT` | `addresses` is missing or empty. |

KOL wallet scan [#kol-wallet-scan]

```http
GET /kol/wallets/{address}/scan
```

The saved wallet scan of a KOL wallet. It never starts a scan.

| Parameter | In   | Type   | Required | Notes                           |
| --------- | ---- | ------ | -------- | ------------------------------- |
| `address` | path | string | yes      | Solana address of a KOL wallet. |

```bash
curl "https://api.scanner.net/kol/wallets/WALLET_ADDRESS/scan" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "scanResult", "scannedAt", "scanDepth" }`, where `scanResult` is a [wallet scan result](/docs/api/reference/wallet-scans#solana-wallet-scan). When there is no saved scan, or the address isn't a KOL wallet, the response is `200` with `{ "success": false }`.

KOL side wallets [#kol-side-wallets]

```http
GET /kol/wallets/{address}/bundles
```

Likely side wallets: the wallets most strongly bundled with this one, at high confidence only. Works for any Solana address, not only KOL wallets.

| Parameter | In   | Type   | Required | Notes           |
| --------- | ---- | ------ | -------- | --------------- |
| `address` | path | string | yes      | Solana address. |

```bash
curl "https://api.scanner.net/kol/wallets/WALLET_ADDRESS/bundles" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "sideWallets": [...] }`, up to 50, most confident first. Each has `address`, `co_appearances`, `confidence` (80 to 96), `first_seen_at` and `last_seen_at`. For every link regardless of confidence, use [Bundled wallets](#bundled-wallets).

Featured KOL wallets [#featured-kol-wallets]

```http
GET /kol/featured
```

Featured KOL wallets, in random order.

| Parameter | In    | Type    | Required | Notes                |
| --------- | ----- | ------- | -------- | -------------------- |
| `limit`   | query | integer | no       | 1 to 50. Default 10. |

```bash
curl "https://api.scanner.net/kol/featured?limit=20" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "wallets": [...], "count": 20 }`.

KOL PnL [#kol-pnl]

```http
GET /kol/pnl
```

The latest profit and loss for every KOL wallet. No parameters and no paging.

```bash
curl "https://api.scanner.net/kol/pnl" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "pnl": [...], "count" }`. Each entry has `wallet_address`, `pnl_1d`, `pnl_7d`, `pnl_30d`, `total_realized`, `total_unrealized`, `total_pnl`, `win_percentage` and `fetched_at`.

KOL PnL history [#kol-pnl-history]

```http
GET /kol/pnl/history
```

Daily PnL snapshots for up to 5 KOL wallets, oldest first.

| Parameter   | In    | Type    | Required | Notes                             |
| ----------- | ----- | ------- | -------- | --------------------------------- |
| `addresses` | query | string  | yes      | 1 to 5 comma-separated addresses. |
| `days`      | query | integer | no       | 1 to 30. Default 30.              |

```bash
curl "https://api.scanner.net/kol/pnl/history?addresses=WALLET_1,WALLET_2&days=7" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "snapshots": [...], "count" }`. Each snapshot has `wallet_address`, `realized`, `unrealized`, `total`, `pnl_1d` and `snapshot_at`.

| Status | Code            | When                               |
| ------ | --------------- | ---------------------------------- |
| 400    | `MISSING_FIELD` | No `addresses`.                    |
| 400    | `INVALID_INPUT` | No usable address, or more than 5. |

KOL wallet PnL [#kol-wallet-pnl]

```http
GET /kol/pnl/{address}
```

The latest PnL detail for one KOL wallet.

| Parameter | In   | Type   | Required | Notes           |
| --------- | ---- | ------ | -------- | --------------- |
| `address` | path | string | yes      | Solana address. |

```bash
curl "https://api.scanner.net/kol/pnl/WALLET_ADDRESS" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "pnl": { ... } }`. `pnl` has `wallet_address`, `pnl_1d`, `pnl_7d`, `pnl_30d`, `fetched_at` and a `summary` with `realized`, `unrealized`, `total`, `totalInvested`, `averageBuyAmount`, `totalWins`, `totalLosses`, `winPercentage` and `lossPercentage`. When there is no PnL for the address, the response is `200` with `{ "success": false }`.

Alpha traders [#alpha-traders]

```http
GET /alpha/traders
```

The alpha trader leaderboard: top Solana traders ranked over 1, 7 and 30 days. No parameters and no paging, so the response is large.

```bash
curl "https://api.scanner.net/alpha/traders" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** an `AlphaTradersResponse`: `success`, `traders`, `count`, `periods` (`1d`, `7d`, `30d`), `generated_at` and `source`. Each trader has `wallet_address`, `display_name`, `twitter_handle`, `entity`, `tags`, `periods` (stats per period), `pnl_1d`/`pnl_7d`/`pnl_30d`, `roi_*` and `rank_*` per period, `win_rate`, `trades`, `volume`, `total_pnl`, `first_trade` and `last_trade`. Rows are ordered by 1-day rank, then 7-day, then 30-day.

Wallets you saved in Scanner show your saved name, with `is_saved: true`.

Alpha PnL history [#alpha-pnl-history]

```http
GET /alpha/pnl/history
```

Daily PnL for up to 5 alpha traders, oldest first.

| Parameter   | In    | Type    | Required | Notes                                                 |
| ----------- | ----- | ------- | -------- | ----------------------------------------------------- |
| `addresses` | query | string  | yes      | Comma-separated addresses. Only the first 5 are used. |
| `days`      | query | integer | no       | 1 to 30. Default 30.                                  |

```bash
curl "https://api.scanner.net/alpha/pnl/history?addresses=WALLET_1,WALLET_2&days=14" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "success": true, "snapshots": [...], "count" }`. Each snapshot has `wallet_address`, `realized`, `unrealized`, `total`, `pnl_1d`, `pnl_7d`, `pnl_30d` and `snapshot_at`. Any of the PnL fields can be `null`.

| Status | Code            | When            |
| ------ | --------------- | --------------- |
| 400    | `MISSING_FIELD` | No `addresses`. |

Bundled wallets [#bundled-wallets]

```http
GET /bundles/{address}
```

Every wallet Scanner has recorded as bundled with this address in its token scans.

| Parameter | In    | Type   | Required | Notes                                                                   |
| --------- | ----- | ------ | -------- | ----------------------------------------------------------------------- |
| `address` | path  | string | yes      | Solana address.                                                         |
| `cluster` | query | string | no       | `true` also includes wallets bundled with those wallets (a second hop). |

```bash
curl "https://api.scanner.net/bundles/WALLET_ADDRESS" \
  -H "x-api-key: $SCANNER_API_KEY"
```

**Response:** `{ "address", "bundledWallets", "totalRelationships" }`, with no `success` field. Each bundled wallet has `address`, `coAppearances`, `firstSeen` and `lastSeen`, most co-appearances first. `totalRelationships` counts the links read, up to 200 for a direct lookup.

| Status | Code              | When                  |
| ------ | ----------------- | --------------------- |
| 400    | `INVALID_ADDRESS` | Not a Solana address. |
