REST API¶
The gateway's HTTP API, generated from its own OpenAPI spec — regenerate with
uv run python scripts/gen_api_reference.py. Every endpoint authenticates
with Authorization: Bearer <bk_… key> (mint one in the console under
API keys); the base URL is https://beta.barista.sh.
Two shapes worth knowing before the list: a session that is still starting or
mid-wake answers 409 with a human-readable reason — retry shortly; and
WebSocket attach (/v1/sessions/{name}/attach) is documented in the
CLI reference rather than here, since OpenAPI does
not describe WebSockets.
Sessions¶
GET /v1/sessions¶
The tenant's sessions, each with its one-word state (bar-052). This is
the canonical list — the old /v1/fleet noun is gone.
Query parameters:
- meta (array of string) — metadata filter as key=value, repeatable; all pairs must match
- include (string) — 'meta' to carry each row's metadata without filtering
POST /v1/sessions¶
Create Session
Body:
- name (string, required)
- template (string)
- image (string) (default: busybox:latest)
- digest (string)
- command (array of string)
- env (object)
- idle_pause_s (integer)
- metadata (object)
- size (string)
DELETE /v1/sessions/{name}¶
Delete a session: destroy its instance on the node, then forget it.
deleted means the guest VM is gone — not merely that we stopped listing the
session (bar-063). When the node cannot confirm the destroy, nothing is
removed and this answers a retryable 503 instead of a lying 200.
Deleting a session that has no live instance (never materialised, or already reaped) succeeds: there is nothing to leak, so dropping the desired record is the whole of the delete.
GET /v1/sessions/{name}¶
Get Session
POST /v1/sessions/{name}/pause¶
Pause a running session, keeping its memory (on a memory-snapshot runtime). Blocks until the node's async pause operation settles.
POST /v1/sessions/{name}/resume¶
Resume a paused session (it continues from its held memory).
POST /v1/sessions/{name}/exec¶
Run a command in the session over Contract A Exec and return its output.
The interactive (PTY) attach is the streaming variant, added next.
output_truncated is always in the response and says whether stdout/stderr
are the whole of what the command produced; when it is true,
output_truncation gives the per-stream byte counts and the limit that
separated them.
Body:
- cmd (array of string, required)
- tty (boolean) (default: False)
- env (object)
- workdir (string)
- ready_timeout_s (number)
- ensure (boolean) (default: False)
- template (string)
GET /v1/sessions/{name}/logs¶
Bounded application/serial logs for the owning tenant's session.
Bytes are base64 inside SSE JSON so arbitrary workload output cannot break event framing. Lifecycle events remain on the separate journal endpoint.
Query parameters:
- tail (integer) (default: 100)
- follow (boolean) (default: False)
GET /v1/sessions/{name}/events¶
Server-Sent-Events tail of the node's events for this session — state changes, wake-fired, ttl warnings — filtered to its instance.
DELETE /v1/sessions/{name}/publish¶
Unpublish Session
POST /v1/sessions/{name}/publish¶
Publish a session to a public URL <slug>.<public_suffix>. The slug
defaults to the session name. The published endpoint is then reachable
without a key (host-based ingress), waking the session on request.
Body:
- slug (string)
DELETE /v1/sessions/{name}/proxy/{path}¶
Forward a request to the session's workload, waking it if parked.
This is the customer-visible data path — the substrate demos' kubectl
port-forward + POST, but tenant-scoped and wake-on-request: a parked
session is resumed transparently before the request is proxied.
GET /v1/sessions/{name}/proxy/{path}¶
Forward a request to the session's workload, waking it if parked.
This is the customer-visible data path — the substrate demos' kubectl
port-forward + POST, but tenant-scoped and wake-on-request: a parked
session is resumed transparently before the request is proxied.
PATCH /v1/sessions/{name}/proxy/{path}¶
Forward a request to the session's workload, waking it if parked.
This is the customer-visible data path — the substrate demos' kubectl
port-forward + POST, but tenant-scoped and wake-on-request: a parked
session is resumed transparently before the request is proxied.
POST /v1/sessions/{name}/proxy/{path}¶
Forward a request to the session's workload, waking it if parked.
This is the customer-visible data path — the substrate demos' kubectl
port-forward + POST, but tenant-scoped and wake-on-request: a parked
session is resumed transparently before the request is proxied.
PUT /v1/sessions/{name}/proxy/{path}¶
Forward a request to the session's workload, waking it if parked.
This is the customer-visible data path — the substrate demos' kubectl
port-forward + POST, but tenant-scoped and wake-on-request: a parked
session is resumed transparently before the request is proxied.
Templates¶
GET /v1/templates¶
List Templates
POST /v1/templates¶
Register Template
Body:
- name (string, required)
- image (string, required)
- digest (string)
- description (string)
GET /v1/templates/-/registries¶
The registries this fleet's nodes can pull from (bar-043) — what the
registration gate enforces, surfaced so a caller (and the console) can see
the constraint BEFORE hitting the 422. An empty list means unrestricted.
Path uses the - segment so it can never collide with a template name.
DELETE /v1/templates/{name}¶
Delete Template
GET /v1/templates/{name}¶
Get Template
API keys¶
GET /v1/apikeys¶
List Keys
POST /v1/apikeys¶
Create Key
DELETE /v1/apikeys/{key_id}¶
Revoke Key
Usage¶
GET /v1/usage¶
Current Usage