MountainSwitch

Developers

Health

Overview

GET

/v1/health

Health

Health is the strict adapter-status source of truth. Use it to inspect adapter freshness, strict live aggregation eligibility, and infrastructure health without overriding data endpoint consumer-usability fields.

Parameters

Path and query parameters are documented together so the request surface stays easy to scan.

This endpoint does not accept path or query parameters.

Example request

Use the same endpoint across all three snippets. The tabs switch only the client syntax.

cURL

curl -sS "https://api.mountainswitch.co/v1/health" \
  -H "Accept: application/json"

Example response

The example response shows the documented JSON envelope with endpoint data in data and request metadata in _meta.

200 OK application/json
{
  "data": {
    "overall": "degraded",
    "adapters": [
      {
        "adapter_id": "ca-chain-controls",
        "jurisdiction": "US-CA",
        "feed_type": "chain-controls",
        "status": "healthy",
        "live_aggregation_eligible": true,
        "last_successful_fetch": "2026-03-19T12:47:00Z",
        "last_attempted_fetch": "2026-03-19T12:47:00Z",
        "consecutive_failures": 0,
        "last_error": null,
        "record_count": 45,
        "average_latency_ms": 340,
        "processor": {
          "last_completed_cycle": "2026-03-19T12:47:00.000Z",
          "last_job_enqueued_at": "2026-03-19T12:47:00.000Z",
          "last_job_started_at": "2026-03-19T12:47:01.000Z",
          "last_job_completed_at": "2026-03-19T12:47:02.250Z",
          "last_queue_lag_ms": 1000,
          "last_job_duration_ms": 1250,
          "last_job_outcome": "success",
          "last_job_error": null
        }
      },
      {
        "adapter_id": "ca-lane-closures",
        "jurisdiction": "US-CA",
        "feed_type": "lane-closures",
        "status": "stale",
        "live_aggregation_eligible": false,
        "last_successful_fetch": "2026-03-19T12:35:00Z",
        "last_attempted_fetch": "2026-03-19T12:47:00Z",
        "consecutive_failures": 2,
        "last_error": "HTTP 503 from upstream",
        "record_count": 120,
        "average_latency_ms": 890,
        "processor": {
          "last_completed_cycle": "2026-03-19T12:35:00.000Z",
          "last_job_enqueued_at": "2026-03-19T12:47:00.000Z",
          "last_job_started_at": "2026-03-19T12:47:18.000Z",
          "last_job_completed_at": "2026-03-19T12:47:19.000Z",
          "last_queue_lag_ms": 18000,
          "last_job_duration_ms": 1000,
          "last_job_outcome": "upstream_http_failure",
          "last_job_error": "UPSTREAM_HTTP_503"
        }
      }
    ]
  },
  "_meta": {
    "request_id": "req_health_docs",
    "response_generated_at": "2026-03-19T19:47:30Z"
  }
}

Response fields

This reference stays flat on purpose so the documented fields remain easy to scan.

data.overall
"healthy" | "degraded" | "stale" | "down"
Worst status across all adapters in the response.
data.adapters
Array<object>
Registered adapters ordered by adapter_id ascending.
data.adapters[].adapter_id
string
Registered adapter identifier.
data.adapters[].jurisdiction
string
Canonical jurisdiction code owned by the adapter.
data.adapters[].feed_type
string
Registered feed type for the adapter, such as chain-controls or lane-closures.
data.adapters[].status
"healthy" | "degraded" | "stale" | "down"
Strict request-time adapter status after monotonic worsening.
data.adapters[].live_aggregation_eligible
boolean
Strict processor publish-safety bit. Data endpoints expose their own consumer live_eligible fields.
data.adapters[].last_successful_fetch
string | null
Timestamp of the last successful fetch, or null before the first success.
data.adapters[].last_attempted_fetch
string | null
Timestamp of the last attempted fetch, or null before the first attempt.
data.adapters[].consecutive_failures
number
Current consecutive failure count for the adapter.
data.adapters[].last_error
string | null
Last error string for the adapter when one exists.
data.adapters[].record_count
number
Record count reported by the adapter health snapshot.
data.adapters[].average_latency_ms
number | null
Average fetch latency in milliseconds when available.
data.adapters[].processor
object
Last processor job timing and outcome snapshot for operator troubleshooting.
data.adapters[].processor.last_queue_lag_ms
number | null
Milliseconds between cron enqueue and processor start for the last known job.
data.adapters[].processor.last_job_outcome
string | null
Stable outcome name for the last known processor job, such as success or d1_write_failure.
_meta.request_id
string
Request identifier for debugging and support workflows.
_meta.response_generated_at
string
ISO timestamp describing when the API assembled the response.

Errors

These rows keep the repo-wide rate-limit and infrastructure behavior visible without inventing endpoint-specific transport semantics.

Status Code When it happens
429 RATE_LIMIT_EXCEEDED The caller exceeded the shared API rate limit.
503 SERVICE_UNAVAILABLE D1 or another critical dependency is unavailable.

Notes

These notes capture the contract edges that matter most for consumers of the endpoint.

Health omits coverage and pagination fields

Health is the source of truth for adapter status, so its _meta includes only request_id and response_generated_at. It omits _meta.sources, _meta.query_coverage, and _meta.pagination entirely.

live_aggregation_eligible is authoritative

Clients must not re-derive strict live aggregation eligibility from status or last_successful_fetch. Data endpoint _meta.sources[].live_eligible is the authoritative consumer-usability field for list, summary, and destination-access responses.

Health responses are always no-store

GET /v1/health and GET /v1/health/:adapterId are never written to response KV and must always return Cache-Control: no-store.

Subsection

GET

/v1/health/:adapterId

Health by adapter

Use the single-adapter health endpoint when the caller needs one adapter's strict status, strict live aggregation eligibility, and bootstrap or missing-health fallback behavior.

Parameters

Path and query parameters are documented together so the request surface stays easy to scan.

adapterId

Path Required

string

Registered adapter identifier such as ca-chain-controls. Unknown identifiers return 404 ADAPTER_NOT_FOUND.

Example request

Use the same endpoint across all three snippets. The tabs switch only the client syntax.

cURL

curl -sS "https://api.mountainswitch.co/v1/health/ca-chain-controls" \
  -H "Accept: application/json"

Example response

The example response shows the documented JSON envelope with endpoint data in data and request metadata in _meta.

200 OK application/json
{
  "data": {
    "adapter_id": "ca-chain-controls",
    "jurisdiction": "US-CA",
    "feed_type": "chain-controls",
    "status": "healthy",
    "live_aggregation_eligible": true,
    "last_successful_fetch": "2026-03-19T12:47:00Z",
    "last_attempted_fetch": "2026-03-19T12:47:00Z",
    "consecutive_failures": 0,
    "last_error": null,
    "record_count": 45,
    "average_latency_ms": 340,
    "processor": {
      "last_completed_cycle": "2026-03-19T12:47:00.000Z",
      "last_job_enqueued_at": "2026-03-19T12:47:00.000Z",
      "last_job_started_at": "2026-03-19T12:47:01.000Z",
      "last_job_completed_at": "2026-03-19T12:47:02.250Z",
      "last_queue_lag_ms": 1000,
      "last_job_duration_ms": 1250,
      "last_job_outcome": "success",
      "last_job_error": null
    }
  },
  "_meta": {
    "request_id": "req_health_adapter_docs",
    "response_generated_at": "2026-03-19T19:47:30Z"
  }
}

Response fields

This reference stays flat on purpose so the documented fields remain easy to scan.

data.adapter_id
string
Registered adapter identifier for the returned health record.
data.jurisdiction
string
Canonical jurisdiction code owned by the adapter.
data.feed_type
string
Registered feed type for the adapter, such as chain-controls or lane-closures.
data.status
"healthy" | "degraded" | "stale" | "down"
Strict request-time adapter status.
data.live_aggregation_eligible
boolean
Strict processor publish-safety bit for the adapter.
data.last_successful_fetch
string | null
Timestamp of the last successful fetch, or null before the first success.
data.last_attempted_fetch
string | null
Timestamp of the last attempted fetch, or null before the first attempt.
data.consecutive_failures
number
Current consecutive failure count for the adapter.
data.last_error
string | null
Last error string for the adapter when one exists.
data.record_count
number
Record count reported by the adapter health snapshot.
data.average_latency_ms
number | null
Average fetch latency in milliseconds when available.
data.processor
object
Last processor job timing and outcome snapshot for operator troubleshooting.
data.processor.last_queue_lag_ms
number | null
Milliseconds between cron enqueue and processor start for the last known job.
data.processor.last_job_outcome
string | null
Stable outcome name for the last known processor job, such as success or d1_write_failure.
_meta.request_id
string
Request identifier for debugging and support workflows.
_meta.response_generated_at
string
ISO timestamp describing when the API assembled the response.

Errors

These rows keep the repo-wide rate-limit and infrastructure behavior visible without inventing endpoint-specific transport semantics.

Status Code When it happens
404 ADAPTER_NOT_FOUND The requested adapterId is not present in the registered adapter registry.
429 RATE_LIMIT_EXCEEDED The caller exceeded the shared API rate limit.
503 SERVICE_UNAVAILABLE D1 or another critical dependency is unavailable.

Notes

These notes capture the contract edges that matter most for consumers of the endpoint.

Single-adapter health uses the same fallback rules

If health:{adapterId} is missing, the API distinguishes true bootstrap from post-boot missing health using lastCompletedCycle:{adapterId}. The response is synthesized but not written back to KV.

The single-adapter shape matches one list entry

GET /v1/health/:adapterId returns the same public AdapterHealthApiSchema used inside GET /v1/health data.adapters[].

Single-adapter health is also no-store

GET /v1/health/:adapterId is not part of the query_coverage cache matrix and must always return Cache-Control: no-store.