> For the complete documentation index, see [llms.txt](https://mute-sh.gitbook.io/mute.sh/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mute-sh.gitbook.io/mute.sh/api/api-reference/builders.md).

# Builders & Leaderboard

Builders are the apps and frontends that route order flow to HIP-4 (each order can carry a builder attribution + optional builder fee). This family is the order-flow analytics surface: who routes volume, who their traders are, how well they retain them — plus the global trader leaderboard.

A worked example runs through this page: the **market-share leader** — an unlabeled builder at address `0xab5dbc…b704` — routes the most volume on HIP-4 (62.5% share) while charging near-zero fees, whereas **Tradoor** monetizes its flow (77% of all builder-fee revenue). Both facts come straight from these endpoints.

***

## GET /v1/builders

The builder directory, ranked by cumulative builder-fee revenue.

| Query param | Type | Default | Description   |
| ----------- | ---- | ------- | ------------- |
| `limit`     | int  | `100`   | capped at 500 |

```bash
curl -H "X-API-Key: $MUTE_KEY" "https://api.mute.sh/v1/builders?limit=5"
```

```json
{
  "data": [
    {
      "builder": "0x92345453ce2000642d7d4ceeae4fccc6c2e41d23",
      "builder_name": "Tradoor",
      "total_fees_usdc": 4067.075656,
      "fills": 217193,
      "volume": 8577936.93,
      "unique_traders": 53,
      "first_seen": "2026-05-04 21:20:07.784",
      "last_seen": "2026-07-05 08:26:52.096"
    }
  ],
  "limit": 5
}
```

* `builder_name` resolves from the labels registry; `""` means unlabeled (address-only).
* `fills` counts **fee-bearing** fills; `volume`/`unique_traders` cover all the builder's non-settlement flow.
* Ordering is by `total_fees_usdc` DESC — a fee-free builder with big volume ranks low here; use `/market-share?metric=volume` for the volume view.

**Caching:** `public, max-age=3600`.

## GET /v1/builders/:address

One builder's profile — same fields as a directory row.

```json
{
  "builder": "0xab5dbc057628bc18523c4cdfc0e1e2ebdbecb704",
  "builder_name": "",
  "total_fees_usdc": 0.750127,
  "fills": 235366,
  "volume": 20801014.42,
  "unique_traders": 1484,
  "first_seen": "2026-05-02 10:22:55.179",
  "last_seen": "2026-07-05 08:39:52.961"
}
```

`404 Builder <addr> not found` only when the address has zero fees **and** zero volume **and** zero traders; malformed address → `400 Invalid address`.

**Caching:** `public, max-age=3600`.

## GET /v1/builders/:address/fills

The builder's raw fill stream with **cursor pagination**, ascending by time — built for backfilling a builder's complete order-flow history.

| Query param             | Type     | Default | Description                                                          |
| ----------------------- | -------- | ------- | -------------------------------------------------------------------- |
| `cursor`                | string   | —       | opaque `{time_ms}_{tx_index}` from the previous page's `next_cursor` |
| `startTime` / `endTime` | epoch ms | —       | inclusive time bounds                                                |
| `limit`                 | int      | `500`   | 1–2000                                                               |

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/builders/0xab5dbc…b704/fills?limit=2"
```

```json
{
  "builder": "0xab5dbc057628bc18523c4cdfc0e1e2ebdbecb704",
  "fills": [
    {
      "time": "2026-05-02 10:22:55.179",
      "time_ms": 1777717375179,
      "tx_index": 175334270567059,
      "coin": "#0",
      "side": "A",
      "dir": "Sell",
      "px": 0.6,
      "sz": 32,
      "fee": 0.0192,
      "builder_fee": 0.0192,
      "user": "0x1710022f671b4032d6c7262107ba231f41f84ce8",
      "hash": "0xe037…"
    }
  ],
  "next_cursor": "1777718662186_307976157542360"
}
```

Pagination loop: request → save `next_cursor` → pass it back → repeat until `next_cursor: null` (a page shorter than `limit`). Cursors are strictly-after, so pages never overlap; a malformed cursor is a `400` telling you the expected format. `tx_index` is the fill's trade ID (`tid`) used as the tie-breaker — despite the name, it is not an EVM transaction index. Unlike the volume metrics, this raw stream **includes Settlement legs** — filter by `dir` if you only want trades.

**Caching:** `public, max-age=30` (each cursor URL is distinct, so crawls aren't cache-blocked).

## GET /v1/builders/by-user/:user

The inverse join: which builders a wallet trades through, with a `volume_share` split. Returns `{ "user": …, "data": [] }` (never 404) for wallets with no builder-attributed flow — plenty of wallets trade direct.

Each row: `builder`, `builder_name`, `fills`, `volume`, `builder_fees_usdc`, `realized_pnl`, `unique_markets`, `first_seen`/`last_seen`, and `volume_share` (0–1, relative to that wallet's builder-routed volume). Backed by a 5-minute rollup — **Caching:** `public, max-age=300`.

***

## Per-builder trader analytics

### GET /v1/builders/:address/leaderboard

The builder's own traders, ranked.

| Query param | Type | Default | Description                                                    |
| ----------- | ---- | ------- | -------------------------------------------------------------- |
| `sort`      | enum | `pnl`   | `pnl` or `volume` (anything else silently falls back to `pnl`) |
| `limit`     | int  | `50`    | 1–200                                                          |

```json
{
  "builder": "0xab5dbc…b704",
  "sort": "pnl",
  "data": [
    { "user": "0xdd144d2b6de680c9faf1ebf1b801f85ad4b4cfe3", "pnl": 27857.28, "volume": 320404.01, "fees": 0, "fills": 1980, "markets": 121 }
  ],
  "limit": 50
}
```

`pnl` includes settlement results; `volume` excludes settlement legs (pure trading). **Caching:** 30 s.

### GET /v1/builders/:address/top-traders

Same data as `leaderboard?sort=volume` with the sort fixed — the two endpoints share one query; use whichever reads better in your code. **Caching:** 30 s.

### GET /v1/builders/:address/market-share

The builder's slice of the whole pie, by `metric=volume` (default) or `metric=fees`:

```json
{ "builder": "0xab5dbc…b704", "builder_name": "", "metric": "volume",
  "builder_value": 20801014.42, "total_value": 33252740.54, "share_pct": 62.55, "rank": 1 }
```

```json
{ "metric": "fees", "builder_value": 0.75, "total_value": 5281.18, "share_pct": 0.01, "rank": 31 }
```

Same builder, both metrics — that volume-vs-fees split is the monetization story in two calls. Unknown `metric` values silently fall back to `volume` (check the echoed `metric`). **Caching:** 1 h.

### GET /v1/builders/:address/retention

Weekly cohort retention: traders are cohorted by the ISO week (Monday-keyed) of their **first** fill through this builder, then counted again in each later week they stayed active.

| Query param | Type | Default | Description                                                             |
| ----------- | ---- | ------- | ----------------------------------------------------------------------- |
| `weeks`     | int  | `12`    | cohort lookback, 1–52 (bounds cohort *start*, not the activity horizon) |

```json
{
  "builder": "0xab5dbc…b704",
  "data": [
    { "cohort_week": "2026-06-22", "activity_week": "2026-06-29", "weeks_since": 1, "cohort_size": 104, "retained": 35, "retention_pct": 33.65 }
  ]
}
```

One row per (cohort, activity-week) pair; `weeks_since: 0` rows are always 100% by definition. Pivot `cohort_week × weeks_since` for the classic retention triangle. **Caching:** 1 h.

### GET /v1/builders/compare

Side-by-side comparison, up to 5 builders:

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/builders/compare?builders=0xab5dbc…b704,0x923454…1d23"
```

```json
{
  "data": [
    { "builder": "0xab5dbc…b704", "builder_name": "", "total_fees_usdc": 0.750127, "fills": 235366, "volume": 20801014.42, "unique_traders": 1484, "market_share_pct": 0.01 },
    { "builder": "0x923454…1d23", "builder_name": "Tradoor", "total_fees_usdc": 4067.08, "fills": 217193, "volume": 8577936.93, "unique_traders": 53, "market_share_pct": 77.01 }
  ]
}
```

**`market_share_pct` is each builder's share of the global fee total, not of the compared set** — the numbers deliberately don't sum to 100%. Order follows your request; unknown builders come back as zero-rows rather than being dropped. Missing/malformed `builders` param → `400` (`"Provide builders (comma-separated, max 5)"` / `"Invalid address"`). **Caching:** 1 h.

***

## GET /v1/leaderboard

The global trader leaderboard — every wallet ranked by your chosen metric, with taxonomy and builder filters.

| Query param  | Type    | Default | Description                                                    |
| ------------ | ------- | ------- | -------------------------------------------------------------- |
| `metric`     | enum    | `pnl`   | `pnl` \| `volume` \| `roi` \| `win_rate` \| `trades` \| `wins` |
| `timeframe`  | enum    | `all`   | `24h` \| `7d` \| `30d` \| `all`                                |
| `category`   | string  | —       | e.g. `sports` — joins outcome metadata                         |
| `underlying` | string  | —       | e.g. `BTC`                                                     |
| `builder`    | address | —       | only fills routed via this builder                             |
| `limit`      | int     | `50`    | capped at 200 — ranks beyond 200 are not reachable (no offset) |

```bash
curl "https://api.mute.sh/v1/leaderboard?metric=pnl&timeframe=7d&category=sports&limit=3"
```

```json
{
  "data": [
    {
      "user": "0xd9ee2b58b061d62d8090f4cba11b5c2043b0cd0c",
      "total_trades": 17084,
      "total_settlements": 0,
      "wins": 0,
      "losses": 0,
      "total_volume": 7147023.55,
      "total_pnl": 793828.08,
      "total_fees": 0,
      "roi": 0.111071,
      "win_rate": 0,
      "first_trade": "2026-06-07 15:21:08.968",
      "last_trade": "2026-07-05 08:48:54.351",
      "markets_traded": 51
    }
  ],
  "sort": "total_pnl",
  "limit": 50,
  "metric": "total_pnl",
  "timeframe": "all",
  "filters": { "category": null, "underlying": null, "builder": null }
}
```

Reading the rows:

* The top-PnL wallet above has `total_settlements: 0` — it made \~$794k **without ever holding to resolution** (pure trading in and out). `win_rate` only measures settlement outcomes, so it's `0` for such wallets; don't render `win_rate: 0` as "never wins".
* `roi = total_pnl / total_volume`. `metric=roi` surfaces small, short-lived accounts with extreme ratios — combine with a client-side volume floor for anything user-facing.
* `total_volume` here includes settlement notional (unlike the trader-profile endpoint's volume).

Behavioral notes, verified live:

* **Unknown `metric`/`sort`/`timeframe` values never error** — they silently fall back to defaults. The response echoes the *resolved* `metric`/`timeframe`; check those to catch typos.
* Well-formed-but-unknown `builder` → `200` with empty `data`; malformed → `400 Invalid address`. Invalid `category` characters → `400 Invalid category`.
* Anonymous requests work (free-tier metering); an invalid key is still a hard `401`.
* No `Cache-Control` on this route — poll it politely.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://mute-sh.gitbook.io/mute.sh/api/api-reference/builders.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
