Skip to main content

Health & readiness

GET /api/v1/health, /health/history/{date}, /health/trends, /incidents, and the per-subnet health/uptime/percentile/incident routes — probe-derived, never hand-set. No API key.

Last updated

Every surface metagraphed tracks (an archive node, an SDK, a subnet API, a dashboard) gets checked on a live 15-minute cron sweep. Status here is never self-reported or manually set — it comes exclusively from that probe, classified ok, degraded, failed, or unknown.

GET https://api.metagraph.sh/api/v1/health

Live status

PathScopeNotes
GET /api/v1/healthRegistry-widenetuid, status, fields, limit (≤1000), cursor, sort, order.
GET /api/v1/subnets/{netuid}/healthOne subnetkind, provider, status, classification, fields, limit, cursor, sort, order.

Both are live-only — a cold store returns an explicit unknown payload, never a stale baked value and never a 404. kind scopes to a surface type (archive, subtensor-rpc, subnet-api, docs, and similar); classification narrows to the probe's own outcome (live, dead, timeout, rate-limited, wrong-chain, and similar).

curl -s 'https://api.metagraph.sh/api/v1/subnets/7/health?status=failed'

Incidents

Reconstructed from raw probe history with a gap-island SQL query, not stored as discrete rows: consecutive failing checks group into one incident when the gap between them is under 30 minutes (cadence plus one missed-run buffer), and a lone failed probe that recovers on the next tick doesn't count — only ≥2 consecutive failures (roughly 4+ minutes sustained) become a real incident.

PathScopeParams
GET /api/v1/incidentsGlobalwindow (7d|30d)
GET /api/v1/subnets/{netuid}/health/incidentsOne subnetwindow (7d|30d) — also returns a per-surface SLA (uptime ratio) alongside the incident list

A single missed probe isn't an incident

The ≥2-consecutive threshold is deliberate — roughly three-quarters of raw failure rows are a lone probe recovering on the very next 15-minute tick. Don't treat one failed check in the history endpoints below as downtime; check /incidents for what actually cleared the threshold.

PathWindow / notes
GET /api/v1/health/history/{date}date = YYYY-MM-DD. Filters: netuid, kind, provider, status, classification, fields, limit, cursor, sort, order.
GET /api/v1/health/trendsBulk 7d/30d uptime + latency trend for every subnet, fixed windows.
GET /api/v1/subnets/{netuid}/health/trendsSame, one subnet, both windows returned together.
GET /api/v1/subnets/{netuid}/health/percentilesp50/p95/p99 + avg/min/max latency per surface. window = 7d|30d. Successful checks only.
GET /api/v1/subnets/{netuid}/uptimeLong-term daily uptime from the durable rollup table (raw checks prune after 30d, this survives). window = 90d|1y. min_samples drops low-sample days.
const res = await fetch("https://api.metagraph.sh/api/v1/subnets/7/health/percentiles?window=30d");
const { data } = await res.json();

Every route on this page is mainnet-only — none accept a /{network}/ prefix. All are cached 60s and edge-cached keyed on the health cron's own last_run_at stamp, so repeated requests within the same 15-minute window are served without re-running the aggregation.

This is registry health, not a readiness probe

The bare GET /health (no /api/v1 prefix) is a different thing entirely — a lightweight liveness/readiness check for this API's own infrastructure (bindings, data-publish freshness, cron staleness), not registry content. Don't confuse the two when wiring up a monitor.