# Market data

See what providers offer before you send a request. The public endpoints need no key and do not name providers. The live feed names providers and needs an API key.

The **book** is the set of standing offers. An **offer** is one provider's price for one model, with the deadlines that the provider promises. A **market** is all the offers for one model.

## Public endpoints

| Path                    | Description                                                                       |
| ----------------------- | --------------------------------------------------------------------------------- |
| `/v1/models`            | Models and router models with quotes now. With a key, it adds your presets.       |
| `/v1/exchange/offers`   | Each resting offer without the provider name, lowest generation rate first.       |
| `/v1/exchange/models`   | One row for each served model and kind: price range and depth.                    |
| `/v1/exchange/markets`  | Depth for each served model: independent suppliers, offer count, liquidity.       |
| `/v1/exchange/routers`  | Each router model: ranking, default cap, rules and the models that it admits now. |
| `/v1/exchange/lifetime` | Jobs settled and tokens processed since the exchange opened.                      |

All are `GET`.

```bash
curl https://router.inference.ai.exchange/v1/exchange/offers
```

`/v1/exchange/markets` takes `model` (names or patterns) and `query` (a word search).

A job pays the rate of the offer that it won. A provider can change its rates at any time. [Offer](#offer) lists the fields.

## Live feed

`GET /v1/exchange/stream` upgrades to a WebSocket and requires an API key of scope `list` or higher. Send the key in the first frame, within five seconds after you connect:

```json
{ "type": "subscribe", "credential": "sk-liquid-..." }
```

The exchange sends a `snapshot` of the book, then one frame for each change. [Frames](#frames) lists them.

- Add `"receipts": true` to receive the receipts of your own workspace.
- Add `"parts": true` to receive the book in `snapshot_part` frames of at most 50 offers. The last part is a `snapshot` frame. Without `parts`, one `snapshot` frame holds the whole book, which is more than 1 MB.

A slow market subscriber misses frames, and the feed does not send them again. The feed disconnects a slow receipts subscriber. Reconnect for a new snapshot.

The exchange pings every 30 seconds. It closes a socket that answers no ping before the next one, or that reads no frame for 10 seconds.

## Unverified deployments

The exchange lists a new deployment only after it measures it. Until then, the deployment is unverified. The exchange never chooses it for a model name, router model, basket or preset, and no public view shows it.

Only the workspace that owns the provider can buy from it, with the deployment symbol, such as `acme/gpt-oss-120b`, as the model. The receipt then has `"addressing": { "unverified": true, … }`. Any other workspace gets `model_not_found`.

## Reference

### Offer

```json
{
  "market": "gpt-oss-120b",
  "model": "gpt-oss-120b",
  "creator": "OpenAI",
  "precision": "fp8",
  "region": "us",
  "input_length_band": { "min": 0, "max": 128000 },
  "output_limit_band": { "min": 0, "max": 4096 },
  "ttft_ms": 1500,
  "completion_ms": 30000,
  "pricing": [
    { "billable": "input_text", "unit": "mtok", "usd": 0.12 },
    { "billable": "output_text", "unit": "mtok", "usd": 0.48 }
  ],
  "synthetic": false,
  "valid_until": "2026-09-21T10:15:02.412Z"
}
```

| Field                                     | Description                                                                                                                                                                                                                                      |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `market`, `model`, `creator`              | The model, and the company that made it if the provider stated it.                                                                                                                                                                               |
| `input_length_band`, `output_limit_band`  | The token limits that the deployment accepts. The exchange refuses a request outside all bands. A `null` output maximum means no output limit. Input and output must then fit in `input_length_band` together.                                   |
| `ttft_ms`, `completion_ms`                | The provider's deadlines. If it misses one, the receipt shows `missed`. You still pay.                                                                                                                                                           |
| `pricing`                                 | Every price of the offer, one line for each billable: `billable`, `unit`, `usd` and an optional `variant`. For `mtok`, `usd` is USD per million tokens. Empty on an offer with no price. See [Prompt caching](https://inference.ai.exchange/docs/caching.md) for the cache lines. |
| `kind`                                    | `image_generation`, `audio_speech`, `video_generation` or `embedding`. Absent on a chat offer.                                                                                                                                                   |
| `pricing_unit`, `image_output_tokens_max` | On an image offer priced in tokens: `pricing_unit` is `tokens`, and the cap holds `image_output_tokens_max` tokens for each image.                                                                                                               |
| `valid_until`                             | When the quote expires, unless the provider re-marks or withdraws it first.                                                                                                                                                                      |

### Market

```json
{
  "market": "gpt-oss-120b",
  "independent_providers": 3,
  "offer_rows": 5,
  "affiliation_groups": ["grp_acme"],
  "liquid": true
}
```

Affiliated accounts count as one supplier, and so do resellers of the same upstream. A market is `liquid` with three or more independent suppliers. If a request sends `exchange.rank.allow_single_supplier: false`, the exchange refuses an award when only one supplier is eligible.

### Frames

- `snapshot`: each resting offer, with provider identity. Sent once. With `parts`, `snapshot_part` frames come first.
- `offer_updated`: a provider placed or re-marked an offer.
- `offer_removed`: the offer left the book. An expiry has `reason: "expired"`.
- `provider_connected`, `provider_disconnected`: a provider session opened or closed.
- `quote_rejected`: a request found no eligible offer. It names the model, not the requester.
- `receipt_opened`, `receipt_settled`: a job of your workspace opened or settled. Only with `receipts`.
- `refused`: the exchange did not accept the credential. Sent once, before the close.
