System
Unauthenticated bootstrap for every client that must discover the
deployment before it can log in: the dashboard (OIDC parameters, PostHog,
forced feature flags) and the daytona CLI (oidc.cli_client_id, the
SSH gateway, api_url). Documented so those clients decode it through the
generated contract types (PLAN-CLI.md D19); the body is assembled once
from the environment at process start and never changes.
Runtime configuration of this deployment
application/json- response
The /config response body.
analytics_url?|Public base URL of the rlp-analytics spending service
(PLAN-ANALYTICS-SERVICE.md), set by the operator and trimmed of a
trailing slash. null when unset — or when the value is not an
http(s)://host[:port][/path] base (see analytics_base_url) — the
dashboard then shows no spending analytics. The URL itself is
published (unlike the billing service's) because the browser calls
rlp-analytics directly, with its own bearer; the dashboard passes it
through safeUrl like toolbox_url.
api_url?|Public base URL of this API when the deployment advertises one.
billing_enabled*booleanWhether the member-facing billing surface is wired (PLAN-BILLING-WALLET.md). A boolean rather than the URL because the browser never talks to rlp-billing directly (D1) — it only needs to know whether to render Billing.
build_sha*stringFull commit SHA this API was built from; unknown when unstamped.
build_time*stringRFC 3339 UTC instant the build ran, for example
2026-10-02T14:03:11Z; unknown when unstamped.
docs_url?|Public documentation site URL for this deployment.
featureFlags?null|oidc?null|posthog?null|ssh_gateway?null|toolbox_url?|Toolbox proxy base URL the browser should use. A deployment-specific browser override wins over the general proxy URL when both are set.
version*stringPlatform version this API was built as (PLAN-BUILD-IDENTITY.md): the
latest published release, for example 2.0.0-alpha.1; 0.0.0-dev for
an unstamped build. The same value GET /health reports.
curl -X GET 'https://example.com/config'{ "analytics_url": "string", "api_url": "string", "billing_enabled": true, "build_sha": "string", "build_time": "string", "docs_url": "string", "featureFlags": null, "oidc": null, "posthog": null, "ssh_gateway": null, "toolbox_url": "string", "version": "string"}API, database, and schema are up
application/json- response
GET /health liveness body. Beside the probe result it carries the build
identity of the answering process (PLAN-BUILD-IDENTITY.md): the same three
values GET /config publishes, so a stack's version can be read from the
unauthenticated probe alone.
build_sha*stringFull commit SHA this binary was built from; unknown when unstamped.
build_time*stringRFC 3339 UTC instant the build ran; unknown when unstamped.
status*stringversion*stringPlatform version this binary was built as (the latest published
release); 0.0.0-dev for an unstamped build.
curl -X GET 'https://example.com/health'{ "build_sha": "string", "build_time": "string", "status": "string", "version": "string"}JetStream answered the probe (status may still be warn on retention-drift alarms)
application/json- response
GET /health/deep readiness body: JetStream probe result plus the wedge/shed observability counters (PLAN-NATS-HYGIENE, PLAN-OVERLOAD-SHEDDING, PLAN-SELF-CORDON-DEADLOCK, PLAN-JETSTREAM-CRITICAL-ONLY).
consecutive_publish_timeouts*integerint640 <= valueconsecutive_slow_publishes*integerint640 <= valuecreate_stuck_pending_failures*integerTotal creates the create-expiry reaper (events::maintenance) has ever
deleted before they reached running. Historical field name kept so the
health surface stays stable; a nonzero rate means creates are timing out
before becoming live right now.
int640 <= valuedb*stringok | unhealthy (migration ledger missing or empty) — the same
DB/migration probe /health runs, now also covered here (found by
review, 2026-08-25: previously absent). Draining is reported only in
the outer status field, never here — this field reflects the DB
probe alone, so it stays ok even while draining if the DB itself is
fine (cubic review, 2026-08-27: the field never actually emits a
"degraded" value). Probed concurrently with nats
(PLAN-HEALTH-LIVENESS.md) — neither should wait on the other, and a
wedged one must not delay reporting the other's real state.
jobs_consumer_ack_pending*integerFleet-wide JetStream consumer health, summed across every consumer on the JOBS stream (2026-08-27): distinguishes "queue is deep because load is high" from "queue is deep because runners have stopped acking" — no other signal here made that distinction before.
int640 <= valuejobs_consumer_pending*integerint640 <= valuejobs_consumer_redelivered*integerint640 <= valuejobs_consumer_waiting*integerint640 <= valuelast_publish_ms*integerint640 <= valuemax_queued_creates*integerint640 <= valuenats*stringok when JetStream answered the bounded $JS.API.INFO probe.
otel*stringOTel pipeline state.
publish_timeouts*integerint640 <= valuequeued_creates*integerint640 <= valuereaper_herd_guard_trips*integerReaper ticks (cumulative, this process) on which the herd guard
refused to mark runners lost because EVERY online runner was stale
at once — an observer/transport outage signature, not fleet death
(issue #1205). Nonzero and climbing means the api can hear NATS but no
runner heartbeat is arriving: check the bus, the runners' NATS
connectivity, and the runner herd-guard threshold configuration.
int640 <= valuereaper_lost_mark_gate*stringWhether the reaper is currently allowed to mark runners lost from
last_seen_at staleness (issue #1205): unbound (the heartbeat lane
is not consuming — nothing refreshes last_seen_at), settling (it
(re)bound less than one stale window ago; lost-marking is suppressed
until the runners have heartbeated through the new subscription) or
armed. A process that stays unbound/settling for minutes has a
wedged or flapping runner-event lane.
redis*stringRate-limit Redis state (PLAN-AUTH-RATE-LIMITS.md §2.6):
ok | degraded (PING failed/timed out — brute-force protection is
silently off, fail-open) | unconfigured (rate-limit storage disabled
on this deployment).
Never flips the overall status — the limiter fails open by design.
retention_alarms*array<string>Managed streams whose retention config drifted from desired. Non-empty is the alarm that was missing during both retention-drift incidents.
self_cordoned_runners*integerint64shedding*booleanslow_publishes*integerint640 <= valuestatus*stringdraining (publish-watchdog trip) | unhealthy (DB/migration-ledger
probe failed) | degraded (NATS probe failed) | warn (retention
alarms present) | ok — checked in that priority order, draining and
unhealthy first since those matter most for a deploy decision.
trace_id?|Present only on a 503 (draining / bad DB / degraded NATS), same as
every ApiError body — this endpoint's success/error bodies share
one documented shape (DeepHealth) that ApiError's generic
{"error": "..."} envelope can't carry without dropping the rest of
these fields (api/AGENTS.md's ApiError section documents this as the
one narrow exception), so the trace ID is attached here directly via
the same helper error::envelope uses rather than through ApiError.
curl -X GET 'https://example.com/health/deep'{ "consecutive_publish_timeouts": 0, "consecutive_slow_publishes": 0, "create_stuck_pending_failures": 0, "db": "string", "jobs_consumer_ack_pending": 0, "jobs_consumer_pending": 0, "jobs_consumer_redelivered": 0, "jobs_consumer_waiting": 0, "last_publish_ms": 0, "max_queued_creates": 0, "nats": "string", "otel": "string", "publish_timeouts": 0, "queued_creates": 0, "reaper_herd_guard_trips": 0, "reaper_lost_mark_gate": "string", "redis": "string", "retention_alarms": [ "string" ], "self_cordoned_runners": 0, "shedding": true, "slow_publishes": 0, "status": "string", "trace_id": "string"}