> 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/prices-and-market-data.md).

# Prices & Market Data

Three price surfaces, three different jobs:

| Endpoint                                     | Prices of what                                                     | Backed by                            |
| -------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------ |
| `GET /v1/crypto/price-markets`               | HIP-4 **crypto price markets** (the "Bitcoin above $63.1k?" cards) | mute.sh rollups + live spot          |
| `GET /v1/markpx/:symbol{,/history,/stream}`  | the **underlying assets** (BTC, ETH, SOL, HYPE perp mark price)    | live 2 s poller + sample archive     |
| `GET /v1/market-data/:coin/{candles,l2book}` | raw Hyperliquid data for one coin                                  | proxied to HL (see coverage caveats) |

Picking a chart source: market-probability chart → [`/v1/markets/:coin`](/mute.sh/api/api-reference/markets.md#get-v1marketscoin) `hourly` (always available) or `candles` where HL has history; asset price chart → `markpx/history`; live ticker → `markpx/stream`.

***

## GET /v1/crypto/price-markets

The one-call view for a crypto price-prediction UI: every price market grouped into **one card per (asset, period, expiry)** — the binary above/below market plus its bucket-range ladder, with live spot, implied probabilities, and volume. This endpoint exists to eliminate the N+1 detail calls a client would otherwise make. Public (no key required).

| Query param      | Type   | Default  | Description                                                               |
| ---------------- | ------ | -------- | ------------------------------------------------------------------------- |
| `underlying`     | string | —        | ticker, case-insensitive; unknown tickers return `{count:0}` not an error |
| `status`         | enum   | `active` | `active` (unsettled and not yet expired) \| `settled` \| `all`            |
| `period`         | string | —        | `1d` is the only period minted today                                      |
| `onlyTradable`   | bool   | `false`  | drop expired/settled/empty groups server-side                             |
| `excludeExpired` | bool   | `false`  | drop past-expiry groups regardless of settlement                          |

```bash
curl "https://api.mute.sh/v1/crypto/price-markets?underlying=BTC"
```

```json
{
  "count": 1,
  "groups": [
    {
      "underlying": "BTC",
      "assetName": "Bitcoin",
      "assetSlug": "btc",
      "logoUrl": "https://app.hyperliquid.xyz/coins/BTC.svg",
      "period": "1d",
      "expiry": "2026-07-07T06:00:00.000Z",
      "expiryMs": 1783404000000,
      "expiryLabel": "Jul 7, 2026",
      "isCurrent": true,
      "spotPrice": 62917,
      "priceChange24hPct": null,
      "binary": [
        {
          "outcomeId": 761,
          "title": "Bitcoin price above $63.1k at Jul 7, 2026",
          "targetPrice": 63104,
          "impliedProb": 0.42,
          "coinYes": "#7610",
          "coinNo": "#7611",
          "lastPxYes": 0.42,
          "lastPxNo": 0.58,
          "volumeUsd": 586675.93,
          "volume24h": 544189.81,
          "traders": 176,
          "trades": 8622,
          "lastTradeAt": "2026-07-06T08:40:11.000Z",
          "lastTradeAgeSec": 42,
          "isSettled": false
        }
      ],
      "bucketGroups": [
        {
          "questionId": 133,
          "title": "Bitcoin price range at Jul 7, 2026",
          "buckets": [
            { "label": "< $61.8k", "lowerBound": null, "upperBound": 61800, "outcomeId": 769, "coinYes": "#7690", "prob": 0.31, "probNormalized": 0.29, "volumeUsd": 137.37, "volume24h": 137.37, "traders": 3, "trades": 9, "isSettled": false }
          ],
          "probSum": 1.0646,
          "currentBucketIndex": 1,
          "totalVolume24h": 6250.46,
          "totalTraders": 41
        }
      ],
      "totalVolume24h": 550440.27
    }
  ]
}
```

The fields that carry the product logic:

* **`isCurrent`** — `true` on exactly one group per asset+period: the nearest future expiry. That's "today's market" for a default view.
* **`impliedProb`** — the market's live probability (last Yes-side trade). It is deliberately **`null` once the market settles or expires**, while `lastPxYes`/`lastPxNo` keep the final prints (`1`/`0` after settlement) — render `impliedProb` for live quotes, `lastPxYes` for historical display, never mix them.
* **`probSum` / `probNormalized`** — bucket probabilities are independent last-trade marks, so they don't sum to exactly 1 (`1.0646` here). `probNormalized` rescales them to sum to 1 for direct chart rendering; `prob` is the raw tradable price.
* **`currentBucketIndex`** — which bucket the live spot sits in right now; pairs with `spotPrice` for a "you are here" marker.
* **`coinYes`/`coinNo`** — the tradable coins, derived arithmetically (`outcome_id×10` / `+1`); buckets only have `coinYes` (their No side isn't a separate tradable ladder leg).
* `priceChange24hPct` may be `null` when the 24 h reference sample isn't available — fall back to computing from `markpx/history`.

**Caching:** `public, max-age=15`. `status=settled` gives the full resolution archive (132 groups today) with the same shape.

***

## GET /v1/markpx/:symbol

Live perp mark price for an underlying, polled from Hyperliquid every 2 s. Symbols are tickers (`BTC`, `ETH`, `SOL`, `HYPE`) — not `#N` coins (those are `400 Invalid underlying`).

```json
{ "symbol": "BTC", "mark_px": 62917, "ts_ms": 1783327351512, "source": "live" }
```

* `source: "live"` = in-memory poller (normal case); `"hyperliquid"` = fetched on demand because the poller didn't cover the symbol.
* An unknown-but-well-formed symbol is not an error: `{ "mark_px": null, "ts_ms": null, "source": "hyperliquid" }` — check for `null`, don't rely on a `404`.

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

### GET /v1/markpx/:symbol/history

Mark-price samples at \~2 s cadence for charting.

| Query param   | Type             | Default         | Description                                                                                   |
| ------------- | ---------------- | --------------- | --------------------------------------------------------------------------------------------- |
| `from` / `to` | unix **seconds** | last hour / now | inclusive window                                                                              |
| `limit`       | int              | `5000`          | 1–10000; authoritative on the primary (archive) path — fallback paths return their own window |

```json
{
  "symbol": "BTC",
  "data": [ { "time": 1783323753, "value": 63027 }, { "time": 1783323755, "value": 63027 } ],
  "source": "clickhouse"
}
```

`source` tells you what served the request: `clickhouse` (the sample archive — normal), `live` (in-memory ring fallback), or `hyperliquid` (a single synthetic current point when nothing else was available; can also come with an empty `data` — still `200`). The default window returns \~1,800 points (\~50 KB); scope `from`/`to` to what you actually chart.

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

### GET /v1/markpx/:symbol/stream

The same feed pushed over SSE — one `data:` frame per poller tick (\~every 2 s):

```bash
curl -N "https://api.mute.sh/v1/markpx/BTC/stream?apikey=$MUTE_KEY"
```

```
: connected 2026-07-06T08:42:42.999Z

data: {"time":1783327297,"value":62910}

data: {"time":1783327299,"value":62905}
```

Frames are unnamed (`EventSource.onmessage`), payload `{time: unix seconds, value: number}`, with a \~30-point replay on connect. No `id:` field — there's no `Last-Event-ID` resume; reconnect and dedupe by `time`. Standard stream caps apply (3 concurrent per key/IP, 30-min lifetime — reconnect as routine).

***

## GET /v1/market-data/:coin/candles

OHLCV candles for one HIP-4 coin, proxied live from Hyperliquid's `candleSnapshot` (mute.sh keeps no separate candle store — `source` is always `"hyperliquid"`).

| Query param             | Type     | Default        | Description                                                                                     |
| ----------------------- | -------- | -------------- | ----------------------------------------------------------------------------------------------- |
| `interval`              | enum     | `1h`           | `1m 3m 5m 15m 30m 1h 2h 4h 8h 12h 1d 3d 1w 1M` — anything else is a `400` listing the valid set |
| `startTime` / `endTime` | epoch ms | computed / now | window is capped at 5,000 intervals back from `endTime` (silent truncation, no paging)          |

```json
{
  "coin": "#2120",
  "interval": "1d",
  "source": "hyperliquid",
  "data": [
    { "t": 1783296000000, "T": 1783382399999, "s": "#2120", "i": "1d", "o": "0.12698", "c": "0.1278", "h": "0.1288", "l": "0.1239", "v": "119542.0", "n": 84 }
  ]
}
```

Candles are Hyperliquid's raw shape: `t`/`T` open/close ms, **string** OHLC prices (probabilities), `v` volume in shares (string), `n` trade count. Zero-activity periods come back with `v: "0.0"`, `n: 0` and OHLC pinned to the last price.

**Coverage caveat — read before building:** Hyperliquid only maintains candle history for a subset of HIP-4 coins. For coins it doesn't index (currently **most** of them, including high-volume ones), the upstream errors and this route surfaces a **`502` with a plain-text body** (not the JSON error envelope). Treat `502` here as "no candle history for this coin", not an outage, and fall back to the `hourly` series on [`GET /v1/markets/:coin`](/mute.sh/api/api-reference/markets.md#get-v1marketscoin) — that one is computed from mute.sh's own fills archive and works for every coin.

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

## GET /v1/market-data/:coin/l2book

Order-book snapshot proxied from Hyperliquid's `l2Book`:

```json
{
  "coin": "#7620",
  "source": "hyperliquid",
  "time": 1783328754661,
  "levels": [
    [ { "px": "0.44105", "sz": "2668.0", "n": 1 } ],
    [ { "px": "0.455", "sz": "1000.0", "n": 1 } ]
  ]
}
```

`levels` is `[bids[], asks[]]` — up to 20 levels per side of `{px, sz, n}` (string-typed price/size, `n` = order count at that level). **Live, actively-traded coins return real two-sided depth** (binary Yes/No and bucket coins alike, verified); settled or inactive coins come back with `levels: []` rather than an error — an empty book and an upstream miss are indistinguishable in this shape, so treat `[]` as "no live book", and note `time` falls back to the proxy's timestamp when the exchange doesn't supply one.

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


---

# 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/prices-and-market-data.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.
