Every operation is a standard JSON-over-HTTP request. The full endpoint
reference is below.
Endpoint reference
Habitat API — system 0.1.0
REST API for the Habitat tissue-culture automation platform by Open Culture Science. All endpoints accept and return JSON.
system
GET /system/activity
Last / Now / Next rig activity
Description
One consistent Last / Now / Next view across every actuation path.
now covers running jobs (all orchestrated work — atomics,
routines, scheduled events, cloud dispatches) plus in-flight
direct device commands; last is the most recently finished
of either (SQL-backed across restarts); next is the
earliest pending event on this rig's own schedule.
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
{"properties":{"last":{"anyOf":[{"$ref":"#/components/schemas/ActivityItem"},{"type":"null"}]},"now":{"items":{"$ref":"#/components/schemas/ActivityItem"},"type":"array","title":"Now"},"next":{"anyOf":[{"$ref":"#/components/schemas/ActivityItem"},{"type":"null"}]},"generated_at":{"type":"string","format":"date-time","title":"Generated At"}},"type":"object","required":["last","now","next","generated_at"],"title":"ActivitySnapshot","description":"Response body of ``GET /system/activity``."}
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
{"properties":{"device_name":{"type":"string","title":"Device Name","description":"Unique physical unit identifier, e.g. 'MistyForest'."},"product_line":{"type":"string","title":"Product Line","description":"Product-line string, e.g. 'Habitat'."},"version":{"type":"string","title":"Version","description":"Application semantic version."},"started_at":{"type":"string","title":"Started At","description":"UTC ISO-8601 timestamp when the process started."},"uptime_s":{"type":"number","title":"Uptime S","description":"Seconds since the process started."},"hostname":{"type":"string","title":"Hostname","description":"OS hostname of the device."},"action_log_dir":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action Log Dir","description":"ABSOLUTE directory on this host where `habitat.action` records are being written — the input the OCS rig-runner reads for the fluidics ledger. Absolute because the consumer is a DIFFERENT PROCESS: a relative path would be resolved against its working directory, not habitat's, silently naming a directory that does not exist. Null means no action handler is installed (this device writes no action records)."}},"type":"object","required":["device_name","product_line","version","started_at","uptime_s","hostname","action_log_dir"],"title":"SystemInfo","description":"Device identity and uptime metadata (``GET /system/info``)."}
GET /system/status
Status
Description
Return an aggregate health snapshot of the running system.
kinds is a dict mapping kind name to a list of per-instance
entries. In phase A.3 the list contains exactly one entry (the
kind-level summary) with instance_count=0 as a sentinel.
Phase A.5 replaces this with real per-instance data.
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
{"properties":{"device_name":{"type":"string","title":"Device Name","description":"Unique physical unit identifier."},"emergency_stop":{"type":"boolean","title":"Emergency Stop","description":"True if an emergency stop is currently active."},"drivers_initialized":{"type":"boolean","title":"Drivers Initialized","description":"True once all drivers have connected and are ready for commands."},"kinds":{"additionalProperties":{"items":{"$ref":"#/components/schemas/KindInstanceSummary"},"type":"array"},"type":"object","title":"Kinds","description":"Device-kind name → list of per-kind summary entries."},"active_jobs":{"type":"integer","title":"Active Jobs","description":"Count of jobs in the RUNNING state."},"queued_jobs":{"type":"integer","title":"Queued Jobs","description":"Count of jobs in the QUEUED state."},"scheduled_events_pending":{"type":"integer","title":"Scheduled Events Pending","description":"Count of pending scheduled events."}},"type":"object","required":["device_name","emergency_stop","drivers_initialized","kinds","active_jobs","queued_jobs","scheduled_events_pending"],"title":"SystemStatus","description":"Aggregate health snapshot (``GET /system/status``)."}
GET /system/metrics
Metrics
Description
Latency observability snapshot.
Default: the live in-process registry (per-route percentiles, in-flight,
recent slow requests) plus the SSE slow-consumer drop count. With
?history=true returns stored request_metrics rollup windows
(filterable by route template and since).
Input parameters
Parameter
In
Type
Default
Nullable
Description
history
query
boolean
False
No
limit
query
integer
200
No
route
query
No
since
query
No
Responses
Schema of the response body
{"type":"object","additionalProperties":true,"title":"Response Metrics System Metrics Get"}
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
Return a kinds-aware capability tree from DEVICE_REGISTRY.
instance_count and instances reflect live driver state when
instances_getter is wired (production app factory). In test
builds that build their own minimal app and skip the getter, both
fields fall back to empty/zero so smoke tests remain stable.
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
Redirect to FastAPI's auto-generated OpenAPI JSON document.
Responses
Schema of the response body
GET /system/events
Get System Events
Description
Stream the firehose system channel as Server-Sent Events.
StreamManager.publish fans every per-channel event out to the
system channel, so this endpoint surfaces every job lifecycle
event, every device telemetry event, and every other system-level
event in a single stream.
Honors Last-Event-ID for replay strictly after the given id
(or full buffer when the id is unknown / evicted). Treats a
missing Last-Event-ID as an empty string so first-time
connects replay the full ring buffer before going live, matching
:func:get_job_events.
?type=foo,bar restricts the stream to events whose type
matches one of the listed values; whitespace around each entry
is stripped. When type is omitted (or empty) every event is
emitted.
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
Liveness probe — always 200 if the ASGI app is reachable.
Responses
{"status":"string"}
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
{"properties":{"status":{"type":"string","title":"Status","description":"Always 'ok' when the ASGI app is reachable."}},"type":"object","required":["status"],"title":"HealthzResponse","description":"Liveness-probe body (``GET /healthz``)."}
GET /readyz
Readyz
Description
Readiness probe — 200 when drivers are initialized, 503 otherwise.
Deployment orchestrators (Kubernetes, ECS, Docker Compose
healthcheck) poll this endpoint before routing traffic.
Responses
{"status":"string","drivers_initialized":true}
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
{"properties":{"status":{"type":"string","title":"Status","description":"'ready' when drivers are initialized, else 'not_ready'."},"drivers_initialized":{"type":"boolean","title":"Drivers Initialized","description":"True once all drivers have connected and are ready for commands."}},"type":"object","required":["status","drivers_initialized"],"title":"ReadyzResponse","description":"Readiness-probe body (``GET /readyz``)."}
GET /system/ntp
Ntp
Description
Report chrony clock-sync health: leap status, offset, and stratum.
Returns {"leap_status", "offset_ms", "stratum", "issues"}. The
OCS cloud rig-runner publishes this into the rig descriptor, where the
orchestrator's preflight §4b uses it as a hard cross-host NTP gate:
an EMPTY issues list means the clock is trustworthy, and a
non-empty one makes preflight fail closed.
Always answers 200, even when chrony is missing, wedged, or
unsynchronised. Those degrade to null readings plus a populated
issues list rather than an error status, because the caller has
to read the body to learn why the gate is failing.
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
{"properties":{"leap_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Leap Status","description":"chrony leap status ('Normal' when synced); null if unavailable."},"offset_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Offset Ms","description":"Last clock offset in milliseconds; null if unavailable."},"stratum":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stratum","description":"NTP stratum; null if unavailable."},"issues":{"items":{"type":"string"},"type":"array","title":"Issues","description":"Reasons the clock isn't trustworthy; empty when synced."}},"type":"object","title":"NtpStatus","description":"chrony clock-sync snapshot (``GET /system/ntp``).\n\nAlways returned with 200. When chrony is missing, wedged, or\nunsynchronised the readings are null and ``issues`` states why."}
GET /system/timezone
Get Timezone
Description
Return the device's configured display timezone.
Logs and audit rows always store UTC timestamps for
consistency, but they also capture the display timezone that
was active when the entry was written. The GUI uses this value
to format timestamp for human readers; agents reading
/logs can format the same way or stay in UTC.
See PUT /system/timezone to change it.
Responses
{"timezone":"string"}
⚠️This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.Schema of the response body
{"properties":{"timezone":{"type":"string","title":"Timezone","description":"Display-timezone label — 'UTC', 'local', an IANA name like 'America/Los_Angeles', or a fixed offset like '+06:00'."}},"type":"object","required":["timezone"],"title":"TimezoneResponse","description":"Active display timezone (``GET /system/timezone``)."}
Schemas
AbsoluteMoveRequest
Name
Type
Description
position_increments
Absolute position in increments
position_ul
Absolute position in microliters
top_speed_ul_per_s
Optional top plunger speed in µL/s to apply before the move. When omitted, the firmware's previously-set speed is used.
Atomic parameters keyed by the names declared in the manifest.
provenance
AtomicManifest
Name
Type
Description
authored_by
string
belongs_to_routines
Array<string>
blocking
description
string
device_kind
string
emits_metrics
Array<string>
Advisory list of metric names this atomic is expected to emit. Not populated by any atomic today and not enforced or cross-checked against the telemetry layer -- agent-read-only metadata, not a live emission guarantee.
estimated_fluid_volume_ul
estimated_wear
string
Advisory relative wear estimate. Not derived from any measurement and not read by the runtime -- agent-read-only metadata for planning, not a calibrated cost model.
Advisory pointer to the atomic that would undo this one. Not populated by any atomic today and not enforced or invoked by the runtime -- agent-read-only metadata, not a guarantee a reverse operation exists or is registered.
reversible
boolean
side_effects
Array<string>
summary
string
tier
string
typical_predecessors
Array<string>
typical_successors
Array<string>
validated_on_hardware
Array<string>
version
string
CreateEventRequest
Name
Type
Description
action
string
Action type (e.g. 'feed', 'wash')
color
string
duration_min
number
notes
string
parameters
sample_id
string
Target sample ID
series_id
start_time
string
Scheduled start (ISO 8601). Stored as aware UTC: a naive timestamp is interpreted as host-local time and converted; the response echoes the canonical +00:00 string.
Optional one-shot post-init plunger gap in increments. If provided, ``set_init_gap`` is called BEFORE the Z command on this initialization only. ``None`` means use the previously-configured gap (firmware default ~1600 if never set). DANGER: see ``POST /pumps/{addr}/init-gap`` for hazard details. This path requires ``gap_increments >= 100`` (the safety floor) — there is no override field on this endpoint. Persisting a sub-floor value requires human confirmation via the HITL-gated atomics/job path (``POST /atomics/centris.initialization.set_init_gap`` async + ``POST /jobs/{id}/confirm``); do that first, then initialize without ``init_gap_increments``.
input_port
integer
Distribution-valve input port for homing. Use ``0`` (or omit) for auto-selection from the pump YAML ``port_map``: first waste role, else first port not listed in the map, else port 1. JSON may use the field name ``init_port`` as an alias.
output_port
integer
Init output port (0=default)
speed_ul_per_s
Initialization speed as a volumetric rate in µL/s. None = firmware default homing speed. The driver snaps the value to the nearest firmware-supported discrete rate internally.
ABSOLUTE directory on this host where `habitat.action` records are being written — the input the OCS rig-runner reads for the fluidics ledger. Absolute because the consumer is a DIFFERENT PROCESS: a relative path would be resolved against its working directory, not habitat's, silently naming a directory that does not exist. Null means no action handler is installed (this device writes no action records).
device_name
string
Unique physical unit identifier, e.g. 'MistyForest'.
hostname
string
OS hostname of the device.
product_line
string
Product-line string, e.g. 'Habitat'.
started_at
string
UTC ISO-8601 timestamp when the process started.
uptime_s
number
Seconds since the process started.
version
string
Application semantic version.
SystemStatus
Name
Type
Description
active_jobs
integer
Count of jobs in the RUNNING state.
device_name
string
Unique physical unit identifier.
drivers_initialized
boolean
True once all drivers have connected and are ready for commands.
emergency_stop
boolean
True if an emergency stop is currently active.
kinds
Device-kind name → list of per-kind summary entries.
queued_jobs
integer
Count of jobs in the QUEUED state.
scheduled_events_pending
integer
Count of pending scheduled events.
TestRunRoutineRequest
Name
Type
Description
params
Routine parameters. Merged on top of the routine's manifest defaults before the executor walks the steps.
TimezoneResponse
Name
Type
Description
timezone
string
Display-timezone label — 'UTC', 'local', an IANA name like 'America/Los_Angeles', or a fixed offset like '+06:00'.
ValidateProtocolRequest
Name
Type
Description
yaml_text
string
Raw YAML text of the protocol manifest to validate.
ValidateRoutineRequest
Name
Type
Description
yaml_text
string
Raw YAML text of the routine manifest to validate.