> ## Documentation Index
> Fetch the complete documentation index at: https://docs.signa.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Health Check

> Liveness + readiness probes for monitoring Signa from your side

## Overview

Three unauthenticated endpoints power customer-side uptime monitoring:

| Endpoint            | Purpose                                                          | Latency (origin-side) |
| ------------------- | ---------------------------------------------------------------- | --------------------- |
| `GET /v1/health`    | Customer-facing liveness alias under the `/v1` prefix.           | \< 5 ms               |
| `GET /health/live`  | Container orchestrator + load balancer liveness — process is up. | \< 5 ms               |
| `GET /health/ready` | Readiness — database + cache + search index reachable.           | 50–200 ms             |

Latencies are **origin-side** (measured at the API process). End-to-end
latency from your monitoring agent adds network round-trip and CDN transit —
expect tens of milliseconds more depending on region.

`/v1/health` and `/health/live` are aliases — both return `{ "status": "ok" }`
with HTTP 200 if the API process is alive. `/health/ready` performs three
real probes and surfaces dependency status with per-dep latency.

All three skip authentication by design (`PUBLIC_PATH_RE` in the auth
middleware). They cost no API quota and produce no request log entries.

## Authentication

**None.** These endpoints are intended for customer monitoring agents
(Datadog, Pingdom, your own cron job) that should not handle API keys.

## Suggested poll interval

**60 seconds.** More frequent polling adds noise without improving signal —
internal load-balancer health checks already cover the sub-minute window from inside our network.

For Datadog Synthetics or similar SaaS monitors, 60s is also the cheapest
billing tier.

## Response: `GET /v1/health` (and `/health/live`)

```json theme={null}
{ "status": "ok" }
```

Always 200 if the process is running. If the process is down you get a
connection error or a 5xx from the load balancer instead.

## Response: `GET /health/ready`

<ResponseField name="status" type="string">
  One of:

  * `ok` — all three dependencies reachable.
  * `degraded` — non-critical dep down (cache or search index). API still
    serves most requests; some features (rate-limit cache, search) may
    error individually.
  * `unhealthy` — database unreachable. API cannot serve most requests.
    Returns HTTP 503.
  * `shutting_down` — task is draining for a graceful stop. Returns HTTP 503
    so load balancers route around it.
</ResponseField>

<ResponseField name="service" type="string">Always `"core-api"`.</ResponseField>
<ResponseField name="uptime_ms" type="integer">Process uptime in milliseconds.</ResponseField>

<ResponseField name="dependencies" type="object">
  <Expandable title="dependencies">
    <ResponseField name="postgres" type="object">
      <Expandable title="postgres">
        <ResponseField name="status" type="string">`ok` or `error`.</ResponseField>
        <ResponseField name="latency_ms" type="integer">Probe latency in ms (omitted on error).</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="valkey" type="object">
      <Expandable title="valkey">
        <ResponseField name="status" type="string">`ok` or `error`.</ResponseField>
        <ResponseField name="latency_ms" type="integer">Probe latency in ms (omitted on error).</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="opensearch" type="object">
      <Expandable title="opensearch">
        <ResponseField name="status" type="string">`ok` or `error`.</ResponseField>
        <ResponseField name="latency_ms" type="integer">Probe latency in ms (omitted on error).</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

## SLA

`/health/ready` reflects **API + DB + cache + search readiness**. It does
NOT reflect:

* Message queue health (used by event delivery) — those
  have separate Datadog dashboards customers don't see. If your watches
  stop firing alerts but `/health/ready` is `ok`, that's a sign of an
  ingestion or evaluator-side incident, not an API outage.
* Specific office-connector health (e.g. USPTO TSDR). Connector outages
  surface as stale `last_relevant_sync_run.completed_at` in the
  [watch diagnostics](/api-reference/monitoring/watches/diagnostics)
  response, not via `/health/ready`.
* Webhook receiver health. That's by definition on your side.

For office-by-office freshness, poll
[GET /v1/reference/offices](/api-reference/reference/list-offices) and
inspect each office's last successful sync run.

## Examples

<RequestExample>
  ```bash cURL theme={null}
  # Customer-facing liveness alias under /v1
  curl https://api.signa.so/v1/health
  # -> {"status":"ok"}

  # Detailed readiness — what your monitoring agent should hit every 60s
  curl https://api.signa.so/health/ready
  # -> {"status":"ok","service":"core-api","uptime_ms":12345,"dependencies":{...}}
  ```

  ```ts TypeScript theme={null}
  // No SDK helper — these are unauthenticated, hit them with fetch.
  const res = await fetch('https://api.signa.so/health/ready');
  const ready = await res.json();
  if (ready.status !== 'ok') {
    alert(`Signa API ${ready.status} — postgres=${ready.dependencies.postgres.status}`);
  }
  ```
</RequestExample>

## See also

* [Uptime monitoring guide](/guides/monitoring/uptime-monitoring) — recipes
  for Datadog, Pingdom, and DIY cron-based monitoring.
* [Troubleshooting](/guides/monitoring/troubleshooting) — what to check
  when alerts stop firing despite `/health/ready` being `ok`.
