# Market analytics

Five read only routes publish what the console's Burst Capacity page
shows for a Kubernetes cluster: the price it takes to win nodes, what
the nodes you hold are assessed, and where your demand sits.

| Route | What it serves |
|---|---|
| `GET /api/k8s/market/ladder` | the price to win ladder: per job size in nodes, the minimum bid that won that many nodes at each clearing, and the newest tick's quote |
| `GET /api/k8s/market/spend` | the rate assessed on each node you hold this hour, and the sum |
| `GET /api/k8s/market/paid` | the mean rate your nodes were assessed per bucket, and how many nodes |
| `GET /api/k8s/market/bidhistory` | the limit price in force over time |
| `GET /api/k8s/market/demand` | your cluster's GPUs by band: `bidding`, `provisioning`, `scheduled`, `reserved` |

Contract: [`GET /api/k8s/openapi.json`](https://nationalcompute.com/api/k8s/openapi.json).

All five take an org API token and resolve the cluster the way the
[limit price read](https://docs.nationalcompute.com/api/k8s-bid.md) does: a token bound to a Kubernetes cluster reads its
own; an org wide token resolves when the organization holds one
Kubernetes cluster and otherwise passes `?cluster=<name>` or gets a
`409 ambiguous-cluster`. A token bound to a VM cluster is refused with
`422 bad-request`. A cluster outside your organization is a `404`, the
same as one that does not exist.

Money is **USD per node-hour** on every route, like the
[price feed](https://docs.nationalcompute.com/api/market-feed.md). Divide by the response's own
`gpus_per_node` to compare with a per GPU-hour limit price.

The windowed routes (`ladder`, `paid`, `bidhistory`, `demand`) take
`?hours=` (default 24, clamped to 1 to 8760 hours) and return `t0`
(epoch seconds of the first bucket) and `step` (bucket width in
seconds, growing with the window: `max(300, span / 400)`). The demand
window caps at 720 hours, the 30 days its store keeps. Within one
window the series share the grid: a paid bucket and a demand bucket at
the same offset from `t0` describe the same interval, and demand
carries one extra bucket at the window's end.

!!! note "Feeds arm per market"
    `enabled: false` means the feed is not armed for your cluster's
    market and the data comes empty, not an error. The limit price
    history has no market gate: the declaration is your organization's
    own record.

## The price to win ladder

```sh
curl -H "Authorization: Bearer $NC_TOKEN" \
  "https://nationalcompute.com/api/k8s/market/ladder?hours=24"
```

The ladder is the outsider's quote: for each job size `k` in whole
nodes, the minimum bid a fresh cluster with no standing position needed
to win `k` nodes at that clearing. It is the honest entry cost for a job
of `k` nodes, and it is quoted per node-hour as the whole job's total
divided by `k`.

- `sizes` lists the sizes that quoted at least once in the window;
  `price` holds one series per size, keyed by the size as a string.
- `rungs` lists every size the ladder quotes, whatever the window.
- `now` is the newest tick's quote per rung and `now_ts` that tick.
  `now[k]` is `null` where no bid at any price wins that size right
  now. Two causes: every node the job would need sits inside a
  [protection window](https://docs.nationalcompute.com/market.md#minimum-duration-protection), or the
  island has fewer nodes than the size asks for. The console shows that
  rung as **Preemption Protected**. `now` is `null` as a whole when no
  tick landed in the window.
- A `null` in a `price` series means no tick quoted that size in that
  bucket. A quote is never held forward into a later bucket.

The [MCP server](https://docs.nationalcompute.com/api/mcp.md)'s `market_read source=ladder` returns this
body unchanged.

## What your nodes are assessed

```sh
curl -H "Authorization: Bearer $NC_TOKEN" \
  https://nationalcompute.com/api/k8s/market/spend
```

`nodes` maps each node you hold to the rate the newest auction assessed
it, `total_usd_hr` is their sum, and `site_rates` is the anonymous range
assessed across the whole market that tick as `{lo, hi}` (`null` when
nothing cleared). These are the rates the meter bills for the current
hour ([billing](https://docs.nationalcompute.com/billing.md)).

`GET /api/k8s/market/paid` is the same figure over time: `price[]` is
the mean rate across your nodes per bucket and `nodes[]` the mean number
of nodes billed, both `null` where you held nothing.

## Your limit price over time { #your-bid-over-time }

`GET /api/k8s/market/bidhistory` returns `price[]`, the limit price in force
at each bucket instant, per node-hour (the limit price PUT's per GPU-hour
figure times `gpus_per_node`). It is `null` before the first declaration
and while the limit price is withdrawn.

## Your demand by band

`GET /api/k8s/market/demand` returns `bands`, four series of GPUs per
bucket: `bidding` (requests waiting on the market), `provisioning`
(granted, nodes joining), `scheduled` (running), and `reserved` (the
cluster's live [Base Load](https://docs.nationalcompute.com/market.md#base-load-capacity) block,
reported beside the three bands and never subtracted from them).
