---
title: "List every published surface across the registry"
method: GET
path: "/api/v1/surfaces"
tags: ["surfaces"]
---

# List every published surface across the registry

`GET /api/v1/surfaces`

## Request

- Base URL: `https://api.metagraph.sh`
- URL: `https://api.metagraph.sh/api/v1/surfaces`
- Auth: none required

List curated public surfaces.

## Query parameters

- `netuid` integer
- `kind` 'archive' | 'dashboard' | 'data-artifact' | 'docs' | 'example' | 'openapi' | 'repo-registry' | 'sdk' | 'source-repo' | 'sse' | 'subnet-api' | 'subtensor-rpc' | 'subtensor-wss' | 'website'
- `provider` string
- `id` string
- `auth_required` 'true' | 'false'
- `public_safe` 'true' | 'false'
- `rate_limited` 'true' | 'false'
- `fields` string
- `limit` integer
- `cursor` integer
- `page_snapshot` string
- `sort` 'id' | 'kind' | 'name' | 'netuid' | 'provider'
- `order` 'asc' | 'desc'
- `format` 'json' | 'csv'

## Response `200`

Canonical artifact wrapped in the Metagraphed API envelope, or the transformed list as text/csv when CSV is requested.

- object
  - `data` object, required
    - `contract_version` string
    - `generated_at` string, required
    - `notes` union: Public-safe notes; may be a string or a string list depending on the adapter.
      - string
      - string[]
    - `schema_version` 1, required
    - `surfaces` Surface[], required
      - `auth` SurfaceAuth, nullable
        - `body_envelope` object: For scheme:signature with location:body -- which key of the outgoing JSON body carries the credential, and which carries the payload it signs.
          - `credential_key` string, required
          - `payload_key` string, required
        - `location` 'header' | 'query' | 'cookie' | 'body': Where the credential is sent. `body` only applies to scheme:signature, whose values are merged into the outgoing JSON request body.
        - `name` string: The single header the credential goes in.
        - `names` string[]: The header SET, for schemes that need more than one (signature schemes send hotkey + nonce + signature together). Present instead of `name`, not alongside it.
        - `scheme` 'none' | 'bearer' | 'api-key' | 'basic' | 'oauth2' | 'signature' | 'custom', required: `signature` means the request is signed per-call (a hotkey/nonce/signature header set, see `names`), not a static token.
        - `scopes_note` string: How the requirement was established -- often a live-checked 401, because a subnet's own OpenAPI frequently declares no securitySchemes at all.
        - `token_url` string
        - `value_format` string
      - `auth_required` boolean, required
      - `authority` 'community' | 'official' | 'provider-claimed' | 'registry-observed', required
      - `classification` 'live' | 'redirected' | 'auth-required' | 'dead' | 'unsafe' | 'unsupported' | 'rate-limited' | 'transient' | 'timeout' | 'content-mismatch' | 'wrong-chain' | 'unknown'
      - `curation_level` 'native' | 'candidate-discovered' | 'community-seeded' | 'machine-verified' | 'maintainer-reviewed' | 'adapter-backed'
      - `id` string, required
      - `key` string
      - `kind` 'archive' | 'dashboard' | 'data-artifact' | 'docs' | 'example' | 'openapi' | 'repo-registry' | 'sdk' | 'source-repo' | 'sse' | 'subnet-api' | 'subtensor-rpc' | 'subtensor-wss' | 'website', required
      - `last_verified_at` string, nullable
      - `method` 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE': HTTP method this surface is invoked with; absent means GET. A non-GET surface is a declared mutation (#11146): the prober never touches it (the manifest schema forbids an enabled probe on one), so it carries no probe-derived health -- reach it through call_subnet_surface's schema-gated execution.
      - `name` string
      - `netuid` integer, required
      - `notes` string
      - `probe` ProbeConfig
        - `enabled` boolean, required
        - `expect` 'json' | 'html' | 'sse' | 'any', required
        - `method` 'GET' | 'HEAD' | 'JSON-RPC' | 'WSS-RPC', required
        - `timeout_ms` integer
      - `provider` string, required
      - `public_safe` boolean, required
      - `quality_signals` SurfaceQualitySignals
        - `archived` boolean
        - `content_type_matches_kind` boolean
        - `has_default_branch` boolean
        - `has_recent_push_metadata` boolean
        - `public_safe` boolean
        - `rate_limited` boolean
        - `redirected` boolean
        - `source_tier` 'native-chain' | 'provider-claimed' | 'third-party-index' | 'community-docs'
        - `transient_failure` boolean
      - `rate_limit` SurfaceRateLimit
        - `burst` integer
        - `cost_notes` string
        - `requests` integer, required
        - `scope` 'per-key' | 'per-ip' | 'global' | 'unknown'
        - `window` string, required
      - `rate_limit_notes` string
      - `revenue` object
        - `circularity` 'external' | 'alpha-denominated' | 'team-funded' | 'unknown': Whether the money originates outside Bittensor. Absent means unknown, never external.
        - `currency` 'USD' | 'TAO' | 'ALPHA': Unit the amount field carries. Declared rather than inferred from the path: api.chutes.ai/payments/summary/tao is named for TAO and its values reconcile as USD.
        - `excludes` string[]: Fields present in the payload that are NOT external revenue and must be subtracted -- subnet-funded or unrecognised components.
        - `fields` object: Map of role -> field name in the upstream payload, e.g. {date: 'date', amount: 'total_revenue'}.
        - `grain` 'daily' | 'weekly' | 'monthly' | 'cumulative'
        - `provenance` 'chain-verified' | 'probe-derived' | 'operator-attested' | 'third-party-reported' | 'proxy-only' | 'none', required: Evidence class. Only chain-verified and probe-derived count toward a published coverage ratio; the rest are shown beside it and never summed in.
        - `role` 'external-revenue' | 'usage-proxy' | 'miner-payout' | 'not-revenue', required: What this surface actually measures. A 'stats' endpoint is guilty until proven revenue: miner payout is emission -- the denominator -- and counting it as revenue puts the denominator in the numerator.
        - `rows` string: The envelope key holding the payload `shape` describes, for a source that wraps its rows (a pagination envelope's `items`). Absent means the payload IS the rows.
        - `searched_at` string: When absence was established. Required for provenance 'none': an undated absence is not evidence.
        - `shape` 'flat-array' | 'keyed-map' | 'scalar': How the payload is arranged, so an extractor does not have to guess. flat-array: a list of records, fields.date/fields.amount naming keys within one. keyed-map: nested {period: {subkey: amount}}, where the period IS the key and there are no field names to point at. scalar: one object carrying a single total.
        - `source_url` string, uri
        - `supersedes` string[]: Surface ids this one subsumes. Declares a subset relationship so overlapping channels are not summed twice.
      - `review` object
        - `confidence` 'low' | 'medium' | 'high'
        - `review_notes` string
        - `state` 'community-submitted' | 'maintainer-reviewed' | 'rejected', required
        - `submitted_at` string
        - `submitted_by` string
      - `schema_status` 'machine-readable' | 'ui-only' | 'not-captured'
      - `schema_url` string
      - `source_urls` string[]
      - `stale` boolean, nullable: Whether this surface's verification is older than its kind's freshness TTL. NULL when the surface has never been verified (#9906): that is unverified, not fresh, and 78% of surfaces were in that state while publishing false. Same unknown-is-not-a-value convention as `exists` on /crowdloans/{id}, `leased` on /subnets/{netuid}/lease, and lane_health's `verdict: unknown`.
      - `status` 'ok' | 'degraded' | 'failed' | 'unknown'
      - `subnet_name` string
      - `subnet_slug` string
      - `url` string, required
      - `verification` object
        - `archived` boolean
        - `classification` 'live' | 'redirected' | 'auth-required' | 'dead' | 'unsafe' | 'unsupported' | 'rate-limited' | 'transient' | 'timeout' | 'content-mismatch' | 'wrong-chain' | 'unknown'
        - `confidence_score` integer
        - `content_type` string, nullable
        - `default_branch` string, nullable
        - `error` string, nullable
        - `github_api_url` string, uri
        - `homepage` string, nullable
        - `last_push_at` string, nullable
        - `latency_ms` integer, nullable
        - `method_tested` string
        - `redirect_target` string, uri, nullable
        - `status_code` integer, nullable
        - `topics` string[]
        - `verified_at` string
  - `meta` ResponseMeta, required
    - `artifact_path` string
    - `cache` 'short' | 'standard' | 'static'
    - `catalog_paging` object
      - `reason` 'catalog_changed' | 'catalog_budget_exceeded' | 'catalog_unavailable', required
    - `contract_version` string, required
    - `generated_at` string, nullable: Deterministic build content marker (epoch by default); not a wall clock. Use published_at for human-facing freshness.
    - `observed_through` string, date-time, nullable: How far the tier that answered this request has observed at all. A payload reporting no activity at or before this time is a measured absence; one whose subject is newer is outside coverage, not empty. Null when the horizon is unreadable.
    - `pagination` PaginationMeta
      - `collection` string, required
      - `cursor` integer, required
      - `limit` integer, required
      - `next_cursor` integer, nullable, required
      - `order` 'asc' | 'desc'
      - `returned` integer, required
      - `snapshot` string: Present only for page_snapshot paging. Echo as page_snapshot on subsequent pages; a changed collection or query requires a restart.
      - `sort` string, nullable
      - `total` integer, required
    - `published_at` string, date-time, nullable: Real publish time from the KV latest pointer, distinct from generated_at. Null before the first publish or when the control KV is unbound.
    - `source` string
    - `stale_contract` object: Present ONLY when the served artifact was built under an older contract than the live one (serve-time drift, #1001) — the body may predate a schema change. Mirrored on the x-metagraph-stale-contract response header for monitoring.
      - `built_under` string, required: Contract version the served artifact was built under.
      - `live` string, required: Current (live) contract version the Worker is running.
  - `ok` true, required
  - `schema_version` 1, required

## Other responses

- `304`: ETag matched and the cached response is still valid.
- `400`: Query parameters were malformed or unsupported.
- `404`: Artifact or API route was not found.
- `405`: HTTP method is not supported.
- `500`: Unexpected backend error.

---

[API](https://skmtc.dev/metagraph/apis/metagraphed-api.md) · [All operations](https://skmtc.dev/metagraph/apis/metagraphed-api/llms.txt) · [OpenAPI document](https://skmtc.dev/metagraph/apis/metagraphed-api/revisions/e29036024bb1?raw)
