Price feed¶
Two read-only endpoints publish what capacity clears at in your market, so you can tune your ceiling against the going rate instead of blind increments.
| Route | What it serves |
|---|---|
GET /api/market/ticks |
one row per auction tick (~30s), newest first, 7-day window — the live feed |
GET /api/market/history |
bucketed series, up to 365 days — the trend feed |
The machine-readable contract is
GET /api/market/openapi.json
— the feed's own document, since every cluster kind reads the same feed.
Both take an org API token. "Your market" is the site your cluster trades in — the feed is uniform per market: every caller in it gets the same payload, and nothing caller-specific rides it (your own position lives on the capacity read or the k8s limit price).
Picking the market. A token bound to a cluster reads that cluster's
market with no extra input. An org-wide token must pass
?cluster=<one of your clusters> (either kind) on every call — a
missing selector is a 422. This is always explicit because your
clusters can sit on different sites, and each site is its own market.
Feeds arm per market
Both responses carry an enabled flag. false means the feed is
not yet armed for your cluster's market and the data comes empty —
not an error.
The price is an index, not a quote¶
Published prices are what winners were assessed, never bids. Pricing is discriminatory per cluster, so there is no single per-tick clearing price to publish — the feed publishes statistics:
price— the volume-weighted mean clearing rate, USD per node-hour. Divide by the response's owngpus_per_nodeto compare against your per-GPU-hour ceiling.price_min/price_max(ticks only) — the spread of rates assessed that tick.priceisnullwhen nothing cleared;0.0is a real rate (an uncontended market can clear at zero).gpu_modelandgpu_vendor: the GPU class these prices are for and its maker.gpu_modelisnullwhile the platform has not set one.
An agent bidding exactly the published mean has no clearing guarantee.
Tailing the live feed¶
curl -H "Authorization: Bearer $NC_TOKEN" \
"https://nationalcompute.com/api/market/ticks?limit=50"
Rows carry id (the keyset cursor) and at. Two cursors, mutually
exclusive:
after_id=<newest id you hold>— tail live: you usually get 0–1 rows.before_id=<oldest id you hold>— page backward;next_before_idin the response is the next page's cursor (null= exhausted).
Passing both is a 422. The MCP server's market_read
source=ticks takes the same two cursors and limit, and its grid_api
get /api/market/ticks passes them through unchanged.
The trend feed¶
curl -H "Authorization: Bearer $NC_TOKEN" \
"https://nationalcompute.com/api/market/history?hours=168"
Returns t0 (epoch seconds of the first bucket), step (bucket width
in seconds — it grows with the window), and price[] (volume-weighted
mean per bucket, null where nothing cleared).
The tuning loop¶
- Read the going rate here.
- Read your position on
GET /api/vm/capacity(declared ceiling, pending, allocations). - Adjust the ceiling on the capacity PUT (or the k8s limit price). A ceiling under the going rate leaves capacity pending and can shed nodes you hold.
- Check what you actually pay on
GET /api/billing/balance: the hourly rate the meter last assessed, by kind, cluster and unit price.