Skip to main content
The Python package wraps these. Use them directly from another language.

Authentication

Every request to the training API carries your API key:
Errors come back as {"error": "<message>"} with status 400 (a bad request), 401 (no key, or an invalid one), 404 (not found, or not yours) or 503.

Fine-tuning jobs

A job is JSON: id, status, created_at, model, dataset_name, batch_size, learning_rate, steps, finetune, lora_rank, lora_alpha, targets, cameras, name, step, loss, error, output_dir. See Fine-tuning for the fields and their limits.

Training sessions

A session is JSON: id, status (starting, ready, closed or error), created_at, its request’s fields, url, token and error. Poll it until it’s ready, then open a websocket to its url with Authorization: Bearer <token>.

The session’s websocket

Messages are msgpack, with numpy arrays as maps with binary keys: {"__ndarray__": true, "data": <bytes>, "dtype": "<f4", "shape": [...]} (OpenPI’s encoding).
  1. The server sends {"info": {"model", "action_horizon", "action_dim", "trainable_params"}}.
  2. You send requests: {"id": <int>, "op": <op>, ...arguments}.
  3. It answers each, in order: {"id", "result"} or {"id", "error"}. You may send the next before the last is answered.
data is a list of {"observation": {"image": {camera: <encoded frame>}, "state", "prompt"}, "actions", "weight"}, the frames encoded with codec (a Codec name: "LOSSLESS" for ZPNG, or "CODEC_JPEG_Q90" and the like for JPEG).

Inference

A policy server speaks OpenPI’s websocket protocol:
  1. Connect to its wss:// URL. It sends its metadata, msgpack-encoded.
  2. Send an observation: msgpack, then compressed with zstd (level 1) using Relay’s dictionary, observation.zdict. It holds OpenPI’s keys plus image_codec, the codec its frames are encoded with.
  3. It replies with {"actions", "policy_timing", "server_timing"}, or, if the request failed, a text frame with its traceback, and then closes the connection.
GET /healthz on the same host answers OK once the server is up.