Skip to content

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.

All five take an org API token and resolve the cluster the way the limit price read 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. 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.

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

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, 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's market_read source=ladder returns this body unchanged.

What your nodes are assessed

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).

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

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 block, reported beside the three bands and never subtracted from them).