Check that the API is up

Two probes that take no key say whether the API serves and whether its dependencies answer, and one operation says what happens while the ledger is unreachable.

The three operations of this page say how the API itself is doing. Two of them are probes: they stand outside /v1, take no API key and answer with a plain object that is not wrapped in data. The third is an ordinary operation of /v1 and takes a key.

Which probe to call

ProbeWhat it answers
GET /health200 as soon as the API can serve a request. The state of MySQL and of Redis is in the body: ok, or down followed by the reason.
GET /ready200 when MySQL and Redis both answer, and 503 when one of them does not. The body of a 503 names that dependency in failed.

Call /ready where the status of the answer decides something, as in a load balancer or an uptime monitor. Call /health to read which release is running and what is down: its status stays 200 while a dependency is down.

When the ledger is unreachable

Slen writes every hold and every capture to its ledger. GET /v1/degraded-status says what the API does while the ledger does not answer, and what that left behind in the project of the key.

  • mode is a setting of the service, the same for every project: fail_closed or fail_open_with_cap. While the ledger is unreachable, a request that would spend is refused in either mode: 503 with the code ledger_unavailable.

  • degraded_now is true from the first call that was let through until the last of them is priced. The webhook events ledger.degraded and ledger.restored mark the start and the end of that period.

  • journal_depth counts the calls that still wait to be priced.

  • failed_depth counts the calls that could not be priced. Their cost is not in the ledger.

The healthy answer is degraded_now set to false with a journal_depth of zero.

Operations

Liveness, with the state of each dependency in the body

GET /health

  • No API key needed
  • Available in the SDK for PHP and Node.js

Answers 200 as soon as PHP can serve; a dependency that is down is named in the body, not in the status. For a strict check use GET /ready. Not authenticated.

Responses

200

The process serves

Headers

  • X-Request-Id
application/json
{
  "app": "string",
  "release": "string",
  "server": "string",
  "mysql": "string",
  "redis": "string",
  "queue": "string",
  "broadcast": "string",
  "opcache_preloaded_files": 1,
  "opcache_cached_scripts": 1
}

Readiness — whether MySQL and Redis answer

GET /ready

  • No API key needed

503 while a dependency is unreachable, so an orchestrator stops routing traffic to the instance. Not authenticated.

Responses

200

Every dependency answers

Headers

  • X-Request-Id
application/json
{
  "status": "ok",
  "failed": {
    "key": "string"
  }
}

Errors

StatusCodesWhen
503

A dependency is unreachable; failed names it

Headers

  • X-Request-Id

The body of every error is the error envelope.

Is the ledger answering, and what did fail-open let through while it was not

GET /v1/degraded-status

  • Scope: read

The degraded mode as it stands for the caller's project — an API key's own, a person's active one. Everything here is read from Redis, and the route skips the database pre-check, so the page answers while MySQL does not: it is the page somebody opens because the database is unreachable.

  • mode — what the installation does when the ledger stops answering: fail_closed (the default) refuses with 503 ledger_unavailable; fail_open_with_cap serves a direct gateway call without a hold, up to a per-minute cap per project, and writes each one down to be priced later. One setting for the installation, not per project. No route makes a direct gateway call any more, and a flow execution is never served degraded, so an outage of the ledger is refused under either mode.
  • degraded_now — the project is inside a degraded window: a call was served without the ledger. The window closes when reconciliation has priced the last such call, not when the database answers again.
  • journal_depth, failed_depth — the calls still waiting to be priced, and the ones reconciliation gave up on (they need a person).
  • last_transition_at — when the project last entered or left the window; null if it never did, or when Redis cannot be read (then degraded_now reads false as well).

Responses

200

The degraded-mode state of this project's plane

application/json
{
  "data": {
    "mode": "fail_closed",
    "degraded_now": true,
    "journal_depth": 1,
    "failed_depth": 1,
    "last_transition_at": "2026-10-02T09:30:00Z"
  }
}

Examples

Read the state of the API

The probe needs no key. release names the release that answered.

Terminal
curl https://api.slen.ai/api/health
200 OK
{
  "app": "Slen",
  "release": "1.0.8",
  "server": "octane/frankenphp",
  "mysql": "ok",
  "redis": "ok",
  "queue": "rabbitmq",
  "broadcast": "reverb",
  "opcache_preloaded_files": 1482,
  "opcache_cached_scripts": 2913
}

Ask whether the API is ready

The status of the answer is the answer: 200 here, 503 while a dependency is unreachable.

Terminal
curl https://api.slen.ai/api/ready
200 OK
{
  "status": "ok"
}

Read the state of the ledger

This answer is the healthy one: no call was let through without a hold, and none waits to be priced.

Terminal
curl https://api.slen.ai/api/v1/degraded-status \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": {
    "mode": "fail_closed",
    "degraded_now": false,
    "journal_depth": 0,
    "failed_depth": 0,
    "last_transition_at": null
  }
}

Where to go next

  • Overview — the data wrapper the two probes do not use.

  • Authentication — the key GET /v1/degraded-status takes.

  • Error codes — every code of the API, what it means and what to do about it.

  • Webhooks — how ledger.degraded and ledger.restored arrive.

Built from openapi b070e1f, sdk contract 6a2e0e0, php 4089db3, node 0fa87be