HTTP endpoints (v5.2.0)
Domain-agnostic remote-call, storage, and search API for machinable.
A generic substrate for driving machinable.Interface subclasses remotely: transport (JSON control plane + binary data plane), a config/identity index with search, and an Execution lifecycle. Each interface (a Python module in the project) decides what bytes and method calls mean while machinable stays use-case-agnostic.
Conceptual model
- Interface: a materialized data node (config + identity).
InterfaceInfocarries no lifecycle status. - Execution: the only run-record with lifecycle (
is_active, timestamps). - Project: the unit a request binds to. Multiple projects (and Python interpreters) are served from one gateway.
Discovering the full contract
- REST: this OpenAPI document (
/openapi.json,/docs). - WebSocket protocol (connect / call / stream / chunk upload / chunk read / event):
GET /v1/protocolreturns a machine-readable description, since OpenAPI cannot model WebSocket frames.
Request routing (headers; query equivalents in parentheses)
X-Machinable-Project(?project=): target project, must be under the server's allowlist; defaults to the launch project.X-Machinable-User(X-Machinable-User): attributes created interfaces (created_by); defaults to the server OS user. Ignored when the request was admitted by an OIDC token, which is attributed to its verified identity.X-Machinable-Python(?python=): interpreter; a non-gateway interpreter is routed to a subprocess worker.Authorization: Bearer <token>: required when the server setsapi_tokenoroidc_issuer; the token is the sharedapi_tokenor a JWT access token from the configured OpenID Connect issuer (/docsand/openapi.jsonare exempt). A refusal is 401 withWWW-Authenticate: Bearer. WebSocket upgrades need it too (orSec-WebSocket-Protocol: bearer, <token>, answered withbearer); a socket admitted by an OIDC token is closed with code 4401 when the token expires.POST /v1/auth/tokentrades theapi_tokenfor a session token valid for at most an hour.X-Machinable-Source-Token: thesource_tokenfor source writes, besideAuthorization.
Capability map
remote_call, binary_upload, binary_read, config_search, create_by_id, mutable_label, creator_attribution, multi_project; see /v1/protocol for the surfaces that expose each.
REST endpoints
interfaces
Create/attach interfaces, invoke methods, search by config, set the mutable label, read files, and the WebSocket data plane.
GET /v1/interfaces
List Interfaces
Responses:
200Successful Response →InterfaceInfo[]
POST /v1/interfaces
Create Interface
Create (materialize) an interface, optionally with a client-supplied id.
Idempotent in uuid: creating again with the same id returns the existing instance unchanged (content-addressed dedupe).
Request body: CreateInterfaceRequest (required)
Responses:
200Successful Response →InterfaceInfo422Validation Error →HTTPValidationError
POST /v1/interfaces/ingest
Ingest Data
Index a data record from its header bundle, its data left where it is.
For a record whose files are a folder on another computer, which a run reads as its working_copy: the header (id.json, model.json, files.json, the edge log, updated_at) is written into the server's home, where the server lays it out, and indexed, so POST /v1/executions (or machinable dispatch) with uses: [uuid] finds it. Idempotent: the same header again answers created: false; another header for a uuid (or the keys of) a record the server has is refused with 409.
Request body: IngestDataRequest (required)
Responses:
200Successful Response →IngestDataResponse400Not a data record's header409The server has this record with another header422Validation Error →HTTPValidationError
POST /v1/interfaces/search
Search
Generic config search over interface instances (operators, sort, paging).
Request body: FindRequest (required)
Responses:
200Successful Response →SearchResponse422Validation Error →HTTPValidationError
POST /v1/interfaces/resolve
Resolve
Dry-run a compact version → resolved config + CLI, without materializing.
Failures return a structured 400 detail — {"message": …, "issues": [{"path", "message"}]} — so clients can attach errors to the offending config field (path is dotted, when known).
Request body: ResolveRequest (required)
Responses:
200Successful Response →ResolveResponse422Validation Error →HTTPValidationError
POST /v1/interfaces/lifecycle
Lifecycle
Content-addressed compute lifecycle for a config.
One of: draft / running / cached / failed. A config that cannot be constructed has no lifecycle to report: it answers 400 with the same field-attached issues as resolve, rather than a 500 that says only that something went wrong.
Request body: LifecycleRequest (required)
Responses:
200Successful Response →LifecycleResponse422Validation Error →HTTPValidationError
POST /v1/interfaces/call
Call Interface
Invoke a public method; failures carry a structured detail, never a bare 500.
The interface is built (and materialized) in a worker thread, with the request's context, so a slow build does not hold up the server's other requests; a module and version built before is reused while its source is unchanged.
Request body: InterfaceCallRequest (required)
Responses:
200Successful Response →object422Validation Error →HTTPValidationError
GET /v1/interfaces/{uuid}
Get Interface
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
200Successful Response →InterfaceInfo422Validation Error →HTTPValidationError
DELETE /v1/interfaces/{uuid}
Delete Interface
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
204Successful Response422Validation Error →HTTPValidationError
PATCH /v1/interfaces/{uuid}/label
Set Interface Label
Set/replace an interface's mutable label (FCFS / last-write-wins).
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Request body: SetLabelRequest (required)
Responses:
200Successful Response →InterfaceInfo422Validation Error →HTTPValidationError
GET /v1/interfaces/{uuid}/executions
List Interface Executions
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes | |
active | query | no | |
limit (integer) | query | no |
Responses:
200Successful Response →ExecutionInfo[]422Validation Error →HTTPValidationError
GET /v1/interfaces/{uuid}/provenance
Get Provenance
The provenance graph: how this interface came to be.
Recipe (config/context/derivation) plus history (executions, each with the Manifest it used), as a normalized node-link DAG. depth bounds the walk; rels (comma-separated edge labels, e.g. derivation,runs,manifest) overrides the default policy.
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes | |
depth (integer) | query | no | |
rels | query | no |
Responses:
200Successful Response →ProvenanceGraph422Validation Error →HTTPValidationError
GET /v1/interfaces/{uuid}/data
Get Data Status
Whether the run's stored data is readable now (local / remote / evicted).
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
200Successful Response →DataStatusResponse422Validation Error →HTTPValidationError
GET /v1/interfaces/{uuid}/related
Get Related
The interface's lineage neighbours (derived, uses, executions, …).
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
200Successful Response →RelatedResponse422Validation Error →HTTPValidationError
POST /v1/interfaces/{uuid}/archive
Archive Interface
Soft-archive (hide) an interface, or restore it with ?restore=true.
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes | |
restore (boolean) | query | no |
Responses:
200Successful Response →InterfaceInfo422Validation Error →HTTPValidationError
GET /v1/interfaces/{uuid}/files
List Files
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
200Successful Response →object422Validation Error →HTTPValidationError
GET /v1/interfaces/{uuid}/files/{path}
Read File
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes | |
path (string) | path | yes |
Responses:
200Successful Response422Validation Error →HTTPValidationError
executions
Dispatch runs and query Execution lifecycle status and output.
GET /v1/executions
List All Executions
| Parameter | In | Required | Description |
|---|---|---|---|
active | query | no | |
incomplete | query | no | |
pending | query | no | |
parent | query | no | |
limit (integer) | query | no |
Responses:
200Successful Response →ExecutionInfo[]422Validation Error →HTTPValidationError
POST /v1/executions
Dispatch Execution
Dispatch interfaces into an Execution, each under its context stack.
Mirrors the CLI element chain (machinable get … --launch): for each interface, the context interfaces are entered in order (and exited in reverse) so their predicates fold into the interface's identity at materialization; the interfaces are added to the Execution container, which is then dispatched. Project is the request's ambient project.
Request body: DispatchRequest (required)
Responses:
200Successful Response →ExecutionInfo422Validation Error →HTTPValidationError
GET /v1/executions/{uuid}
Get Execution
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
200Successful Response →ExecutionInfo422Validation Error →HTTPValidationError
GET /v1/executions/{uuid}/output
Get Execution Output
A bounded window of the run's output log (never the whole file).
offset reads forward from a byte position — poll with offset=size to fetch only appended bytes; tail reads the last N bytes; the default is the last limit bytes. limit is capped server-side, so a client cannot accidentally pull a multi-GB log into memory.
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes | |
offset | query | no | |
tail | query | no | |
limit (integer) | query | no |
Responses:
200Successful Response →OutputChunk422Validation Error →HTTPValidationError
POST /v1/executions/{uuid}/cancel
Cancel Execution
Best-effort cancel: write a cancelled marker into the run's directory.
A live dispatch's watcher polls for it and injects ExecutionInterrupted; a not-yet- started or already-finished run simply carries the marker (a no-op). No execution- engine coupling. The marker travels to wherever the payload is running, so a run handed to another machine is cancellable too (see :meth:Execution.cancel).
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
204Successful Response422Validation Error →HTTPValidationError
GET /v1/executions/{uuid}/results
Get Results
The run's declared results: its results.json, read from its files.
uuid is a run-record (whose results are its interface's) or the interface itself. Served without importing the interface, so a server without its code (or its Python environment) serves them. A run that saved no results: {"results": {}}.
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes |
Responses:
200Successful Response →object422Validation Error →HTTPValidationError
GET /v1/executions/{uuid}/results/{name}
Get Result
One result, as JSON: a json result's value; otherwise data.
A table's columns (rows start to stop, or row item), an array's item (?item=12: index 12 along the first axis) or items start to stop (nested lists), a ragged result's item or items. Without item or a slice, the whole result (413 past 4M values). NaN and infinities are null. Only the chunks asked for are read.
| Parameter | In | Required | Description |
|---|---|---|---|
uuid (string) | path | yes | |
name (string) | path | yes | |
item | query | no | |
start | query | no | |
stop | query | no |
Responses:
200Successful Response →object422Validation Error →HTTPValidationError
project
Discover Interface modules and reflect their Config schemas.
GET /v1/project
List Project Modules
Responses:
200Successful Response →ProjectIndex
GET /v1/project/remotes
Get Remotes
Shareable interfaces the project resolves by URL (slurm, globus, …).
Responses:
200Successful Response →RemotesResponse
GET /v1/project/{module}/widget/{asset}
Get Widget Asset
Serve a widget's ES module or stylesheet (module-level assets).
| Parameter | In | Required | Description |
|---|---|---|---|
module (string) | path | yes | |
asset (string) | path | yes |
Responses:
200Successful Response422Validation Error →HTTPValidationError
GET /v1/project/{module}
Get Module Schema
| Parameter | In | Required | Description |
|---|---|---|---|
module (string) | path | yes |
Responses:
200Successful Response →ModuleSchema422Validation Error →HTTPValidationError
GET /v1/projects
List Open Projects
List the projects the server can serve.
The default, any with live state, the allowlist roots, and any process-isolated workers currently running.
Responses:
200Successful Response →object
source
Read/write/create/rename/delete interface source files (opt-in, token-gated; confined to the project base directory).
GET /v1/source
List Source
List the editable source files under the project base directory.
Responses:
200Successful Response →SourceListResponse
GET /v1/source/{path}
Read Source
Read a file's content; the strong ETag (MD5) is also a response header.
| Parameter | In | Required | Description |
|---|---|---|---|
path (string) | path | yes |
Responses:
200Successful Response →SourceFileContent422Validation Error →HTTPValidationError
PUT /v1/source/{path}
Write Source
Create or fully overwrite a file.
Conditional writes: If-Match: "<etag>" (or *) returns 412 on a stale ETag; If-None-Match: * returns 412 if the file already exists (create-only). Editing invalidates caches made stale by the change.
| Parameter | In | Required | Description |
|---|---|---|---|
path (string) | path | yes |
Request body: SourceWriteRequest (required)
Responses:
200Successful Response →SourceWriteResponse422Validation Error →HTTPValidationError
DELETE /v1/source/{path}
Delete Source
Delete a source file and invalidate caches made stale by its removal.
| Parameter | In | Required | Description |
|---|---|---|---|
path (string) | path | yes |
Responses:
204Successful Response422Validation Error →HTTPValidationError
POST /v1/source/move
Move Source
Atomically rename/move a file within the base directory.
Handles interface renames, including converting a single-file module to a package layout (foo.py → foo/__init__.py) and back.
Request body: SourceMoveRequest (required)
Responses:
200Successful Response →SourceWriteResponse422Validation Error →HTTPValidationError
meta
Self-description: the WebSocket protocol, interface hooks, and capability map that OpenAPI cannot express.
GET /v1/protocol
Describe the WebSocket protocol and capability map
Return the non-OpenAPI half of the contract.
Includes every WebSocket frame type, the binary upload/read sequences, the interface hooks a project implements (read, emit, callable methods), cross-cutting request headers, and the capability map.
Responses:
200Successful Response →ProtocolDoc
mcp
The MCP's tools, resources (the authoring guide, examples, the inference catalog) and prompts, for callers without an MCP client.
GET /v1/mcp
Describe
The MCP's instructions, tools, resources and prompts, each with its doc.
Responses:
200Successful Response →object
GET /v1/mcp/resources
Read Resource
One resource, by its URI (guide://authoring, examples://axis).
module://<module> is a module of the request's project. Answers {"uri", "mime_type", "content"}: the content is text, or JSON for the inference catalog and a module's schema. 404 for a URI no resource serves.
| Parameter | In | Required | Description |
|---|---|---|---|
uri (string) | query | yes |
Responses:
200Successful Response →object422Validation Error →HTTPValidationError
POST /v1/mcp/prompts/{name}
Get Prompt
The text of the prompt name with arguments.
| Parameter | In | Required | Description |
|---|---|---|---|
name (string) | path | yes |
Request body: MCPArguments (required)
Responses:
200Successful Response →object422Validation Error →HTTPValidationError
POST /v1/mcp/tools/{name}
Call Tool
The tool name called with arguments: {"result": ...}, as the MCP.
The tool runs in this server (or the request's worker), in the request's project. Read-only: the source tools answer 403. A run is better dispatched with POST /v1/executions, which answers at once; the launch tool answers when its runs did.
| Parameter | In | Required | Description |
|---|---|---|---|
name (string) | path | yes |
Request body: MCPArguments (required)
Responses:
200Successful Response →object422Validation Error →HTTPValidationError
health
Server status, version, and active execution count.
GET /v1/health
Health
The server's health; a gateway's counts the runs in its workers too.
Each live worker is asked for its own health (briefly; one that does not answer counts 0), so an idle check of the gateway sees a run in any worker. A run seen by several (a shared index) is counted once.
Responses:
200Successful Response →HealthResponse
auth
POST /v1/auth/token
Mint Session Token
Mint a short-lived bearer token (at most an hour) from the api_token.
For clients that should not hold the long-lived token, such as the notebook widget. Only a request carrying the api_token itself may mint; a session token cannot extend itself, and an OIDC caller has its own short-lived token already.
Responses:
200Successful Response →SessionTokenResponse422Validation Error →HTTPValidationError