> 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/markets.md).

# Markets

The `/v1/markets` family is the core of the Data API: the live market universe, per-market stats, fills, holders, activity, lifecycle events, rounds history, and the label/logo maps that make raw HIP-4 data human-readable.

Everything on this page was captured against the live API — the JSON you see is real response data.

## Two concepts you need first

### Coins come in pairs

Every HIP-4 market has **two coins**, derived from its outcome ID: `coin = #(outcome_id × 10 + side_idx)`. The **even** coin is side 0 (**Up** / side A) and the **odd** coin right after it is side 1 (**Down** / side B) — `#1540` and `#1541` are the two sides of outcome `154`. Endpoints that take a `:coin` accept **either side**:

* `GET /v1/markets/:coin/holders` returns **both** sides, split into `up` and `down`
* `GET /v1/markets/:coin/activity` merges fills from **both** sides into one feed — so you'll see the sibling coin in the rows, which is expected
* `GET /v1/markets/:coin` and `:coin/fills` are scoped to exactly the coin you pass

Coins are `#N` strings and the `#` must be URL-encoded: `/v1/markets/%231541`.

### Market classes

| `market_class` | What it is                                                                             | `underlying`/`target_price`/`expiry`/`period`                                                     |
| -------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `named`        | Event markets (e.g. *World Cup: Canada vs Morocco*) with free-text resolution criteria | empty / `0` — not price-based                                                                     |
| `priceBinary`  | "Will BTC be above $63,927 at expiry?" — one strike, recurring rounds                  | all populated (`expiry` is `YYYYMMDD-HHMM` UTC)                                                   |
| `priceBucket`  | A ladder of price buckets over the same underlying/expiry                              | populated, but the bucket threshold lives in `description` as `index:N`, `target_price` stays `0` |
| `fallback`     | The catch-all "none of the named outcomes" leg of a question group                     | empty / `0`                                                                                       |

***

## GET /v1/markets/overview

The whole active market universe with volume stats, sorted by volume descending. Unfiltered it returns every market (\~1,350 rows at the time of writing) — filter server-side.

| Query param    | Type   | Default | Description                                        |
| -------------- | ------ | ------- | -------------------------------------------------- |
| `market_class` | string | —       | exact match: `priceBinary`, `priceBucket`, `named` |
| `underlying`   | string | —       | e.g. `BTC` (price markets only)                    |
| `period`       | string | —       | e.g. `1d`                                          |

Filters AND-combine. Unknown filter values return `200` with an empty `data` array, not an error.

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/markets/overview?underlying=BTC&period=1d"
```

```json
{
  "data": [
    {
      "coin": "#1541",
      "market_class": "priceBinary",
      "underlying": "BTC",
      "period": "1d",
      "target_price": 63927,
      "market_name": "Recurring",
      "trades": 69569,
      "traders": 300,
      "volume": 3495337.60798,
      "avg_px": 0.6787103298883124
    }
  ]
}
```

| Field                | Meaning                                                   |
| -------------------- | --------------------------------------------------------- |
| `coin`               | market coin (`#N`) — this row's side of the pair          |
| `market_name`        | display name; `Recurring` for rolling price markets       |
| `trades` / `traders` | lifetime fill count / distinct wallets                    |
| `volume`             | lifetime USD notional (`Σ px·sz`)                         |
| `avg_px`             | volume-weighted average price — a probability in `(0, 1)` |
| `target_price`       | USD strike (price markets), `0` for `named`               |

**Caching:** `no-store` — live stats, always fresh.

***

## GET /v1/markets/series

Coarse rollup per market **family** (`market_class` × `underlying` × `period`) — a handful of rows, ideal for a "products" landing view. Filter with optional `market_class` / `underlying`.

```bash
curl -H "X-API-Key: $MUTE_KEY" "https://api.mute.sh/v1/markets/series?underlying=BTC"
```

```json
{
  "data": [
    {
      "market_class": "priceBinary",
      "underlying": "BTC",
      "period": "1d",
      "all_rounds_volume": 137872292.96,
      "current_round_volume": 547583.36,
      "open_interest": 160287,
      "all_rounds_trades": 2957212,
      "rounds": 64,
      "latest_expiry": "2026-07-04 06:00:00.000"
    }
  ]
}
```

| Field                                     | Meaning                                                       |
| ----------------------------------------- | ------------------------------------------------------------- |
| `all_rounds_volume` / `all_rounds_trades` | USD volume / fills across every round of the series, all time |
| `current_round_volume`                    | USD volume in the round that's live right now                 |
| `open_interest`                           | outstanding shares in the current round                       |
| `rounds`                                  | how many rounds this series has run                           |
| `latest_expiry`                           | expiry of the current round (UTC)                             |

**Caching:** `public, max-age=30` — refetch at most every 30 s.

***

## GET /v1/markets/settled

Per-coin settlement rollups for every market that has settled.

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

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

```json
{
  "data": [
    {
      "coin": "#6900",
      "total_settlements": 1183,
      "won_count": 1183,
      "lost_count": 0,
      "total_volume": 903839.93504,
      "total_pnl": 41530.59340797,
      "total_fee": 44.33828007,
      "unique_users": 1291,
      "first_settlement": "2026-06-28 10:37:17.981",
      "last_settlement": "2026-07-03 06:38:59.156"
    }
  ]
}
```

A coin settles entirely one way: `won_count == total_settlements` means this side (`#6900`, the Up side) won — its Down sibling `#6901` shows the mirror image (`lost_count == total_settlements`, negative `total_pnl`).

**Caching:** `public, max-age=86400, immutable` — settled data never changes; cache it hard.

***

## GET /v1/markets/meta/outcomes

The archived **outcome metadata** — names, descriptions, sides, taxonomy — for every outcome ever seen, paginated. This is the archive that survives Hyperliquid's own API expiring old markets.

| Query param   | Type           | Default | Description                                                          |
| ------------- | -------------- | ------- | -------------------------------------------------------------------- |
| `underlying`  | string         | —       | filter (price markets)                                               |
| `period`      | string         | —       | filter                                                               |
| `from` / `to` | date           | —       | `first_seen` window; accepts `YYYY-MM-DD`, ISO-8601, or unix seconds |
| `is_settled`  | `true`/`false` | —       | settled only / active only                                           |
| `limit`       | int            | `500`   | capped at 500                                                        |
| `offset`      | int            | `0`     | pagination                                                           |

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/markets/meta/outcomes?underlying=BTC&is_settled=false&limit=2"
```

```json
{
  "data": [
    {
      "outcome_id": 736,
      "name": "Recurring Named Outcome",
      "description": "index:2",
      "side_a_name": "Yes",
      "side_b_name": "No",
      "question_id": 133,
      "question_name": "Recurring",
      "market_class": "priceBucket",
      "underlying": "BTC",
      "target_price": 0,
      "expiry": "",
      "period": "1d",
      "first_seen": "2026-07-03 06:00:34.000",
      "last_seen": "2026-07-03 12:25:32.000",
      "is_settled": false,
      "logo_url": "https://app.hyperliquid.xyz/coins/BTC.svg"
    }
  ],
  "limit": 2,
  "offset": 0
}
```

| Field                           | Meaning                                                                                                                                                                                |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `outcome_id`                    | stable integer ID for the outcome (one Up/Down coin pair). Matches `outcome_id` everywhere else in the API and in Hyperliquid's `outcomeMeta`                                          |
| `description`                   | for `named`: the full resolution-criteria text. For `priceBinary`: a spec string `class:…\|underlying:…\|expiry:…\|targetPrice:…\|period:…`. For `priceBucket` sub-outcomes: `index:N` |
| `question_id` / `question_name` | groups related outcomes under one parent question (`0` / `""` = standalone)                                                                                                            |
| `first_seen` / `last_seen`      | UTC; `last_seen` advances while the market is live                                                                                                                                     |
| `logo_url`                      | ready-to-use image URL (see `/logos`)                                                                                                                                                  |

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

***

## GET /v1/markets/coin-labels

One flat map from every coin to a human-readable label. **Public — no key needed.** This is the endpoint you want when turning raw fills/webhook events into UI text.

```bash
curl "https://api.mute.sh/v1/markets/coin-labels"
```

```json
{
  "labels": {
    "#0": "BTC $78213 · 1d · Yes",
    "#6100": "World Cup: Norway vs France — Norway · Yes",
    "#4620": "World Cup: New Zealand vs Egypt — New Zealand · Yes"
  }
}
```

Covers the entire coin universe (\~1,480 entries) in one call — fetch once, cache for an hour, and stop doing per-coin lookups.

**Caching:** `public, max-age=3600`. Public routes are metered at the free anonymous bucket regardless of key — which is fine, because you should be hitting this once an hour, not per request.

***

## GET /v1/markets/logos

Bulk logo map — the image companion to `coin-labels`. **Public — no key needed.** Three maps, all absolute HTTPS URLs:

```bash
curl "https://api.mute.sh/v1/markets/logos"
```

```json
{
  "outcomes": { "0": "https://app.hyperliquid.xyz/coins/BTC.svg" },
  "questions": { "32": "https://img.mute.sh/competitions/world-cup-2026.webp" },
  "underlyings": { "BTC": "https://app.hyperliquid.xyz/coins/BTC.svg" }
}
```

* `outcomes` — keyed by **`outcome_id`** (not `#N` coin!) → outcome icon
* `questions` — keyed by `question_id` → competition/group banner
* `underlyings` — keyed by ticker → canonical asset icon (fallback when the other two miss)

Resolution order for a UI: outcome icon → question banner → underlying icon.

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

***

## GET /v1/markets/events

The market **lifecycle feed**: `creation` and `settlement` events, newest first.

| Query param | Type      | Default | Description                |
| ----------- | --------- | ------- | -------------------------- |
| `type`      | string    | —       | `creation` or `settlement` |
| `limit`     | int       | `100`   | capped at 500              |
| `since`     | timestamp | —       | events at/after this time  |

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/markets/events?type=settlement&limit=2"
```

```json
{
  "data": [
    {
      "time": "2026-07-03 06:38:59.000",
      "event_type": "settlement",
      "outcome_id": 690,
      "signer": "",
      "settle_fraction": "1",
      "settle_details": "derived from settlement fills (settledOutcome unavailable)",
      "quote_token": 0,
      "market_name": "Outcome 690",
      "description": "",
      "market_class": "",
      "underlying": "",
      "target_price": 0,
      "expiry": "",
      "period": ""
    }
  ]
}
```

Field population depends on `event_type` — unused fields come back as `""`/`0`, not `null`:

* **`creation`** rows carry `market_name`, `description` (resolution text, with a trailing `metadata=category:…|subCategory:…` tag you can parse for categorization), `market_class`, and the price-market fields.
* **`settlement`** rows carry `settle_fraction` (a **string** `"0"`–`"1"`: `"1"` = this outcome won outright, `"0"` = lost, fractional = partial/push) and `settle_details` (provenance — e.g. `price:61729.7`, or a note that the result was derived from settlement fills when the canonical `settledOutcome` was unavailable). `market_name` may fall back to `Outcome {id}` when the name join misses.

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

***

## GET /v1/markets/events/latest

A polling-friendly snapshot: the single latest settlement, latest creation, and all-time counts per event type. **These are trimmed sub-shapes**, not full event rows.

```bash
curl -H "X-API-Key: $MUTE_KEY" "https://api.mute.sh/v1/markets/events/latest"
```

```json
{
  "latest_settlement": {
    "time": "2026-07-03 06:38:59.000",
    "outcome_id": 690,
    "settle_details": "derived from settlement fills (settledOutcome unavailable)"
  },
  "latest_creation": {
    "time": "2026-07-03 10:33:30.000",
    "underlying": "",
    "target_price": 0,
    "period": "",
    "description": "…FIFA World Cup Round of 16 game between Canada and Morocco…"
  },
  "counts": [
    { "event_type": "creation", "cnt": 12402 },
    { "event_type": "settlement", "cnt": 814 }
  ]
}
```

Poll this cheaply; when `latest_settlement.time` or the counts change, fetch `/v1/markets/events` for the detail.

**Caching:** `no-store`.

***

## GET /v1/markets/rounds/:underlying

Round-by-round history for **recurring `priceBinary` markets** on one underlying — each row is one round with its strike, settlement result, and trading stats. This is how you answer "how did the daily BTC market resolve each day?"

| Param         | Type   | Default | Description       |
| ------------- | ------ | ------- | ----------------- |
| `:underlying` | path   | —       | e.g. `BTC`        |
| `period`      | string | all     | filter, e.g. `1d` |
| `limit`       | int    | `50`    | capped at 200     |

```bash
curl -H "X-API-Key: $MUTE_KEY" "https://api.mute.sh/v1/markets/rounds/BTC?limit=2"
```

```json
{
  "underlying": "BTC",
  "period": "all",
  "data": [
    {
      "outcome_id": 729,
      "target_price": 61729,
      "expiry": "20260704-0600",
      "period": "1d",
      "side_a_name": "Yes",
      "side_b_name": "No",
      "settle_fraction": null,
      "settle_details": null,
      "settled_at": null,
      "trades": 15651,
      "settlement_fills": 0,
      "unique_users": 103,
      "volume": 547469.069,
      "winner_pnl": 0
    },
    {
      "outcome_id": 721,
      "target_price": 60495,
      "expiry": "20260703-0600",
      "period": "1d",
      "side_a_name": "Yes",
      "side_b_name": "No",
      "settle_fraction": "1",
      "settle_details": "price:61729.7",
      "settled_at": "2026-07-03 06:00:06.000",
      "trades": 29325,
      "settlement_fills": 146,
      "unique_users": 193,
      "volume": 1391884.535,
      "winner_pnl": 41690.748
    }
  ]
}
```

Rows are newest-expiry first; the currently-open round has `settle_fraction: null`. `settle_details` for price markets records the settlement input (`price:61729.7` — the observed price vs the `target_price` strike). The top-level `period` echoes your filter (`"all"` when omitted). `winner_pnl` is the USD paid to the winning side at settlement.

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

***

## GET /v1/markets/top-traders

PnL leaderboard over a rolling window, optionally scoped to one builder's order flow.

| Query param    | Type    | Default | Description                                                               |
| -------------- | ------- | ------- | ------------------------------------------------------------------------- |
| `limit`        | int     | `10`    | capped at 100                                                             |
| `window_hours` | int     | `24`    | clamped to 1–720 (30 days)                                                |
| `builder`      | address | —       | scope to fills routed via this builder; malformed → `400 Invalid address` |

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/markets/top-traders?limit=3&window_hours=168"
```

```json
{
  "window_hours": 168,
  "builder": null,
  "data": [
    {
      "user": "0xaddc680878f96b93189f700d17f4a9bfcf80ff54",
      "pnl": 108443.07,
      "volume": 348352.3,
      "fees": 0,
      "fills": 3740,
      "settlements": 7,
      "wins": 5,
      "losses": 2,
      "markets": 14
    }
  ]
}
```

| Field                             | Meaning                                           |
| --------------------------------- | ------------------------------------------------- |
| `pnl`                             | realized USD PnL in the window (ranking key)      |
| `volume`                          | USD notional traded in the window                 |
| `fills`                           | trade executions (Buy/Sell)                       |
| `settlements` / `wins` / `losses` | positions settled in-window and how they resolved |
| `markets`                         | distinct markets traded                           |

These are rolling-window aggregates recomputed per request — the 24h and 168h leaderboards can rank the same wallets very differently.

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

***

## GET /v1/markets/:coin

The full per-market dossier: lifetime stats, an hourly price/volume series, top traders, recent settlements, and the outcome metadata — one call powers an entire market page.

```bash
curl -H "X-API-Key: $MUTE_KEY" "https://api.mute.sh/v1/markets/%231541"
```

```json
{
  "coin": "#1541",
  "stats": {
    "total_fills": 117635,
    "unique_users": 452,
    "total_volume": 6298565.436,
    "first_trade": "2026-06-04 06:00:19.007",
    "last_trade": "2026-06-05 06:00:04.501",
    "total_settlements": 307,
    "won_settlements": 171,
    "lost_settlements": 136
  },
  "hourly": [
    {
      "hour": "2026-06-04 06:00:00",
      "trades": 2039,
      "volume": 63972.683,
      "avg_px": 0.4658957822,
      "min_px": 0.408,
      "max_px": 0.506,
      "total_fee": 0.234,
      "total_pnl": 1768.947
    }
  ],
  "top_traders": ["…up to 50, across both sides of the pair…"],
  "settlements": ["…recent settlement fills: time, user, side, px, sz, closed_pnl…"],
  "meta": {
    "outcome_id": 154,
    "name": "Recurring",
    "side_a_name": "Yes",
    "side_b_name": "No",
    "market_class": "priceBinary",
    "underlying": "BTC",
    "target_price": 63927,
    "expiry": "20260604-0600",
    "period": "1d",
    "is_settled": true,
    "settle_fraction": "…",
    "settle_details": "…",
    "settled_at": "…"
  }
}
```

* `hourly` is one bucket per hour over the market's whole life: `avg_px`/`min_px`/`max_px` are the hour's VWAP/low/high **probabilities** — this is your chart data.
* `top_traders` covers **both sides** of the coin pair.
* `meta` joins the archived outcome metadata with the settlement event, so a settled market tells you how and when it resolved.
* A **well-formed but unknown coin does not 404** — you get `200` with zeroed `stats`, epoch timestamps (`1970-01-01…`), empty arrays, and `meta: null`. A malformed coin (`notacoin`) gets `400 Invalid coin`.

**Caching:** adaptive — `no-store` while the market is live, `public, max-age=86400, immutable` once it has settled.

***

## GET /v1/markets/:coin/fills

Raw paginated fills for exactly the coin you pass (not the pair), newest first.

| Query param | Type | Default | Description    |
| ----------- | ---- | ------- | -------------- |
| `limit`     | int  | `100`   | capped at 1000 |
| `offset`    | int  | `0`     | pagination     |

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/markets/%231541/fills?limit=3"
```

```json
{
  "data": [
    {
      "time": "2026-06-05 06:00:04.501",
      "coin": "#1541",
      "side": "A",
      "dir": "Settlement",
      "px": 1,
      "sz": 18,
      "fee": 0,
      "closed_pnl": 7.14996,
      "user": "0x50bce915a8039e190937cff2e9ae2408d960dfab",
      "oid": 458588623748,
      "tid": 1017007576947106
    }
  ],
  "coin": "#1541",
  "limit": 3,
  "offset": 0
}
```

| Field         | Meaning                                                                                                                                                                                        |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dir`         | fill type — `Buy`/`Sell` are real trades; `Settlement` is the payout sweep at resolution; `Negate/Split/Merge Outcome` are AMM plumbing. Filter to `Buy`/`Sell` when you want betting activity |
| `px`          | price in `(0,1)`; settlement fills print `px=1` on the winning coin, `px=0` on the loser                                                                                                       |
| `sz`          | outcome shares (`px·sz` = USD notional)                                                                                                                                                        |
| `closed_pnl`  | realized USD PnL for that user on this fill                                                                                                                                                    |
| `oid` / `tid` | HyperCore order ID / globally-unique trade ID                                                                                                                                                  |

**Caching:** `no-store`.

***

## GET /v1/markets/:coin/holders

Top 15 holders **per side**, either coin of the pair accepted. Settlement fills are excluded, so this reflects positions built by real trading.

```bash
curl -H "X-API-Key: $MUTE_KEY" "https://api.mute.sh/v1/markets/%231541/holders"
```

```json
{
  "up": [
    {
      "user": "0x1e532f0cb079be639b86073d78e0f4006cecfeac",
      "trades": 6147,
      "total_shares": 1733650,
      "avg_px": 0.3491482935,
      "volume": 763200.486
    }
  ],
  "down": [
    {
      "user": "0x1e532f0cb079be639b86073d78e0f4006cecfeac",
      "trades": 6438,
      "total_shares": 1735177,
      "avg_px": 0.6362673439,
      "volume": 971063.36
    }
  ]
}
```

`up` = the even coin's holders, `down` = the odd coin's, each sorted by `total_shares` descending, fixed at 15 entries (no `limit` param). The same wallet appearing near-balanced on both sides — like the one above — is a market-maker signature.

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

***

## GET /v1/markets/:coin/activity

A merged, human-feed-style activity stream for the **whole market** — both sides of the pair combined, newest first, settlements included. This powers "recent activity" UI.

| Query param | Type | Default | Description   |
| ----------- | ---- | ------- | ------------- |
| `limit`     | int  | `20`    | capped at 200 |
| `offset`    | int  | `0`     | pagination    |

```bash
curl -H "X-API-Key: $MUTE_KEY" \
  "https://api.mute.sh/v1/markets/%231541/activity?limit=3"
```

```json
{
  "trades": [
    {
      "time": "2026-06-05 06:00:04.501",
      "coin": "#1540",
      "user": "0x477d6e891ee44022b5c63d5fc547685c7486185c",
      "dir": "Settlement",
      "px": 0,
      "sz": 100,
      "value": 0
    }
  ],
  "hasMore": true
}
```

Note the rows carry `coin: "#1540"` even though we asked for `#1541` — that's the pair merge working as designed; use the `coin` field on each row to know which side traded. `value` is the precomputed `px·sz` USD notional. `hasMore` is `true` when the page came back full — advance with `offset`.

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

***

## Conventions recap

* **Timestamps** are UTC strings `YYYY-MM-DD HH:MM:SS.mmm` (no `T`, no `Z`) in data; error envelopes use ISO-8601 with `Z`. Price-market `expiry` uses the compact `YYYYMMDD-HHMM` form.
* **Prices are probabilities** in `(0,1)`; **`px·sz` is USD**.
* **Empty ≠ error**: valid-but-unmatched queries return `200` with empty data; only malformed input returns `400`.
* **Respect `Cache-Control`** — this family spans the full range from `no-store` to `immutable`, and it's your cheapest quota lever.


---

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