Skip to content

API overview

Habitat exposes its hardware operations through multiple interfaces. All interfaces provide equivalent access to the same underlying hardware — choose the one that fits your environment.

Interface Status Best for
REST Available Any language, curl, HTTP clients
MCP Available AI agents — drive it in natural language

REST conventions

Habitat's REST API is served by FastAPI. All endpoints accept and return JSON.

Base URL

Each Habitat device serves its API on your local network at http://<device-name>.local:8000/ — for example http://mistyforest.local:8000/. Replace mistyforest with your device's name (ask your Open Culture contact if you're unsure). All examples in these docs use the demo device mistyforest.

Authentication

Whether the API needs a token depends on how your Habitat device is provisioned:

  • Open mode — a device with no tokens issued accepts every request without credentials. Fine on a trusted local network.
  • Enforced mode — once your device has been given tokens, every request needs one; only the health checks (/healthz, /readyz) stay open.

Your Open Culture contact issues you an API token. Send it as a Bearer header on every request:

Authorization: Bearer <your-token>

A convenient pattern is to keep the token in an environment variable — Habitat's own tooling uses the name HABITAT_API_TOKEN — and reference it:

export HABITAT_API_TOKEN="<your-token>"
curl -H "Authorization: Bearer $HABITAT_API_TOKEN" \
  http://mistyforest.local:8000/pumps/

Streaming (SSE) endpoints — browsers' EventSource can't set headers, so pass the token in the query string instead: …/system/events?auth_token=<your-token>.

The MCP connector authenticates separately, through its own sign-in.

Units

  • Volumes are always in microliters (µL). Field suffix: _ul.
  • Volumes at the API and action layer are floats. Drivers convert to hardware-specific increments internally.
  • Time is reported in seconds where applicable.

Pump addresses

Pump addresses are zero-indexed integers. /pumps/{addr} expects the integer address. The pump role (dispense / aspirate) is defined in the YAML config, not inferred from the address.

Error responses

Failures come back as application/problem+json with type, title, status, and detail fields — plus structured context (addr, chip_id, step) where relevant.

Status Meaning
400 Invalid parameters, or a precondition wasn't met
404 Unknown resource (pump, job, protocol, …)
409 Conflict — a safety interlock blocked the command, or an idempotency key was reused with a different body
422 Request body failed schema validation
500 Hardware-level failure

System & configuration endpoints

Read-only status and configuration live at the root of the API.

Method Endpoint Purpose
GET /health Device identity and driver status
GET /system/status Runtime status
GET /system/metrics Per-route latency metrics
GET /system/timezone Display timezone
GET /config Full configuration snapshot (includes the port map)
GET /config/schema JSON Schema for the configuration

See Configuration for the port map the snapshot contains.

Endpoint reference

The full endpoint surface is grouped by area:

  • System — device health and status
  • Pumps — CENTRIS syringe pump control
  • Peristaltic — Pololu Tic peristaltic pumps
  • Valves — multi-position smart valves
  • Atomics — single-step primitives
  • Routines — multi-step workflows
  • Protocols — protocol library and execution
  • Schedule — event scheduling
  • Jobs — job submission and status
  • Devices — device registry and telemetry
  • Reagents — reagent registry
  • Config — device configuration
  • Entities — chips, samples, and reagents
  • Files — logs, exports, and support bundles