{
  "openapi": "3.1.0",
  "info": {
    "title": "agi.diy API",
    "version": "v1",
    "description": "Hosted robot policies for SO-101: lease a slot, send observations over Zenoh or agi-wire/1, receive action chunks. 1 returned action = 1 token = $0.0001 in usage credit. Camera observations do not travel over this REST API. Reference: https://api.agi.diy/docs — checked against the Worker source by web/scripts/check-docs.mjs.",
    "x-units-warning": "Current checkpoints use LeRobot normalized units (arm −100…100, gripper 0…100) whichever `semantics` label a row answers (agi-* rows: so101-normalized-v1; stock-* rows: legacy so101-degrees-gripper-percent-v1); read `units`."
  },
  "servers": [
    {
      "url": "https://api.agi.diy"
    }
  ],
  "security": [
    {
      "bearer": []
    },
    {
      "cookie": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "`agi_sk_live_…` from the dashboard. Never ship one in a public page."
      },
      "cookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "agi_session",
        "description": "Browser session after GitHub login. Cookie writes must be same-origin JSON (else 403 cross_site)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "bad_request",
              "unauthorized",
              "invalid_key",
              "insufficient_credits",
              "forbidden",
              "cross_site",
              "not_found",
              "unknown_model",
              "no_trace",
              "no_frame",
              "no_slots",
              "session_ended",
              "incompatible_features",
              "no_observations",
              "conflict",
              "payload_too_large",
              "internal",
              "upstream",
              "no_wire",
              "runner_offline",
              "relay_down",
              "hf_forbidden",
              "hub_unavailable",
              "missing_config",
              "unsupported_policy",
              "too_large",
              "unsupported_weights",
              "rate_limited"
            ],
            "description": "Stable snake_case code — branch on this, not on `message`. Bring-your-own Hub checkpoint codes (hf_forbidden, hub_unavailable, missing_config, unsupported_policy, unsupported_weights, too_large) and `rate_limited` (custom-checkpoint caps) only occur for callers using `hf:` checkpoints."
          },
          "message": {
            "type": "string",
            "description": "One human sentence."
          },
          "retry_after_s": {
            "type": "integer",
            "description": "Seconds to wait before retrying (also sent as the `Retry-After` header)."
          },
          "doc_url": {
            "type": "string",
            "format": "uri",
            "description": "Troubleshooting entry for this code: https://api.agi.diy/docs#error-<code>. Absent for runner/operator-only codes."
          },
          "param": {
            "type": "string",
            "description": "The body field at fault, on 400s only (e.g. `ttl_s`) — for a form or an SDK that wants to point at the input rather than parse `message`."
          }
        },
        "description": "Every error code has a troubleshooting entry at https://api.agi.diy/docs#error-<code> (e.g. #error-no_slots).",
        "externalDocs": {
          "url": "https://api.agi.diy/docs#errors",
          "description": "Troubleshooting, one anchor per code"
        }
      },
      "Health": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "version": {
            "type": "string",
            "description": "Short git sha of the deployed Worker, or `dev`."
          },
          "runners": {
            "type": "integer",
            "description": "Runners seen in the last 30 s."
          },
          "relay": {
            "type": "string",
            "enum": [
              "ok",
              "down",
              "unknown"
            ]
          },
          "endpoint": {
            "type": [
              "string",
              "null"
            ]
          },
          "time": {
            "type": "string",
            "format": "date-time"
          },
          "router": {
            "type": [
              "string",
              "null"
            ],
            "description": "The production Zenoh router endpoint this Worker advertises first for linked runners (`ROUTER_ENDPOINT`), or null when none is configured (D19)."
          },
          "runner_list": {
            "type": "array",
            "description": "One row per runner seen in the last 30 s.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "role": {
                  "type": "string",
                  "description": "demo (Thor) | prod (GCP)"
                },
                "endpoint": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "What a client is handed first for this runner."
                },
                "relay": {
                  "type": "string",
                  "enum": [
                    "ok",
                    "down",
                    "unknown"
                  ],
                  "description": "The runner's own probe of its public endpoint (`endpoint_ok`)."
                },
                "router": {
                  "type": "string",
                  "enum": [
                    "ok",
                    "down",
                    "unknown"
                  ],
                  "description": "The runner's probe of its bridge to the production router (`router_ok`); `down` drops the router from its leases so a client is not left waiting for a handshake that cannot complete."
                },
                "slots": {
                  "type": "integer"
                }
              }
            }
          },
          "wire": {
            "type": [
              "object",
              "null"
            ],
            "description": "Where a BROWSER is sent for the wire (the robot data plane is `router`, which is ours). {hosts[], ephemeral, note}. `ephemeral: true` means a quick-tunnel hostname that changes when the tunnel restarts — a page holding an older URL will fail to connect, so a rotation is visible here rather than only in a broken /play.",
            "properties": {
              "hosts": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "ephemeral": {
                "type": "boolean"
              },
              "note": {
                "type": "string"
              }
            }
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "login": {
            "type": "string"
          },
          "avatar_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "credits_tokens": {
            "type": "integer",
            "description": "Balance in action tokens; 1 token = $0.0001 in usage credit."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Key": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "First 20 characters, e.g. `agi_sk_live_Ksce8qli`."
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the key last authenticated a request; written at most once per 5 minutes per key, so it can lag by up to 5 minutes. null = never used (or used before this field existed)."
          }
        }
      },
      "NewKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "key": {
            "type": "string",
            "description": "The full key — returned ONLY in this response."
          },
          "prefix": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ModelInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "act/so101"
            ]
          },
          "family": {
            "type": "string"
          },
          "robot": {
            "type": [
              "string",
              "null"
            ]
          },
          "semantics": {
            "type": [
              "string",
              "null"
            ],
            "description": "The label a lease of this row would carry right now — from the highest-generation online runner serving it. Our pools say so101-normalized-v1: the vectors are LeRobot normalized units (arm -100..100, gripper 0..100), never degrees; the legacy so101-degrees-gripper-percent-v1 string survives only on `overflow` (the third-party pool) and is wrong for the data. Read `units`.",
            "examples": [
              "so101-degrees-gripper-percent-v1"
            ]
          },
          "action_horizon": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Actions per call = tokens per call (ACT 100, SmolVLA 50)."
          },
          "fps": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Rate a chunk is played back on the robot, not a request rate."
          },
          "cameras": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Camera short names the policy expects; not interchangeable across models."
          },
          "slots_free": {
            "type": "integer"
          },
          "slots_total": {
            "type": "integer"
          },
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "warming",
              "offline"
            ]
          },
          "tier": {
            "type": "string",
            "enum": [
              "flagship",
              "default",
              "third-party",
              "custom"
            ]
          },
          "provider": {
            "type": "string",
            "description": "`agi.diy` for catalog models, `you` for the `custom` row."
          },
          "accepts": {
            "type": "string",
            "description": "`custom` row only: `hf:<org>/<repo>[@<revision>]`."
          },
          "policy_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "`custom` row only: checkpoint types the runner loads (act, smolvla, diffusion)."
          },
          "size_cap_bytes": {
            "type": "integer",
            "nullable": true,
            "description": "`custom` row only: Σ weights cap."
          },
          "units": {
            "type": "string",
            "enum": [
              "so101-normalized-v1"
            ],
            "description": "The real units of the action and state vectors — the correction to the legacy `semantics` label (W2-204)."
          },
          "units_note": {
            "type": "string",
            "description": "One sentence a machine caller can act on: normalized units, not degrees, and `--robot.use_degrees=false` on a real arm."
          },
          "aliases": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Older ids that resolve to this row (act/so101 → agi-act/so101); accepted wherever a model id is."
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "description": "Render verbatim: \"default\" or \"flagship · preview\"."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Render verbatim when present, e.g. \"post-training in progress\"."
          },
          "checkpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "Our checkpoint on the Hugging Face Hub behind this row."
          },
          "license": {
            "type": [
              "string",
              "null"
            ],
            "description": "The checkpoint's licence as its card declares it; null = none declared."
          },
          "weights": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "private",
              "public",
              null
            ],
            "description": "Whether the checkpoint's weights are downloadable on the Hub yet."
          },
          "eval": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Held-out offline numbers, or the reason there are none. **A figure travels only with the span it covers**: when `span_s` (seconds of motion the scored chunk spans) is present you get the figures — `ours` vs `stock` for the defaults, `gates` {ours, act, hold_action, …} for the flagship, plus `headline` (a sentence that always names its seconds), `common_span` (one span every family can produce, so those rows are the only subtractable cross-model comparison), `ablation` and `zero_shot`. When `span_s` is absent the block carries what was measured (`dataset`, `metric`, `horizon`, `fps`, `windows`, `training`) plus a `withheld` sentence INSTEAD of the numbers — render that, never a cached figure. Two cautions the data itself states: the same `horizon` is not the same time when `fps` differs, so never compare rows whose `span_s` differs (the ranking flips between spans); and the sampling policies are unseeded, so `first_step_spread` and the `ablation` note give a run-to-run spread currently WIDER than the gaps between models — a difference inside it is not a result. `first_step` is the one figure a span cannot distort. `null` for a raw pool id and for `custom`.",
            "properties": {
              "withheld": {
                "type": "string",
                "description": "Present INSTEAD of the figures: why no number is published yet. Render it; never fall back to an older number."
              },
              "span_s": {
                "type": "number",
                "description": "Seconds of motion the scored chunk spans (horizon / fps). Figures are published only with it, and are comparable only between rows whose span_s matches."
              },
              "headline": {
                "type": "string",
                "description": "One sentence naming the figure AND its span. Render verbatim; a ranking without the seconds is not meaningful."
              },
              "common_span": {
                "type": "object",
                "additionalProperties": true,
                "description": "The same models scored over one span every family can produce (span_s, windows, one key per model plus baselines) — the only cross-model figures you may subtract."
              },
              "first_step_spread": {
                "type": "string",
                "description": "Run-to-run range of the first-step figure for an unseeded sampler. A gap smaller than this is not a result."
              },
              "zero_shot": {
                "type": "object",
                "additionalProperties": true,
                "description": "Scored on public datasets neither checkpoint trained on. Published because it is unflattering: today both of ours are far worse than repeating the last action, so no zero-shot transfer is claimed."
              }
            }
          },
          "stock_of": {
            "type": [
              "string",
              "null"
            ],
            "description": "Third-party rows only: the id of OUR row this checkpoint is the stock counterpart of (e.g. stock-act/so101 → agi-act/so101). null on every other row."
          }
        }
      },
      "Session": {
        "type": "object",
        "description": "Current SO-101 checkpoints return LeRobot NORMALIZED units (arm −100…100, gripper 0…100) despite the legacy `so101-degrees-gripper-percent-v1` semantics label. Never execute them as degrees.",
        "properties": {
          "id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "warming",
              "leased",
              "active",
              "ended"
            ],
            "description": "`warming` (custom checkpoint still loading on the runner; poll until `leased`) → `leased` → `active` (a client attached) → `ended`."
          },
          "deployment": {
            "type": "string"
          },
          "runner": {
            "type": "string"
          },
          "zenoh": {
            "type": "object",
            "properties": {
              "endpoint": {
                "type": "string"
              },
              "endpoints": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "ORDERED, best first: the production Zenoh router (`tls/zenoh.api.agi.diy:7447`) when this runner's bridge to it is up, then the runner's own public relay as a fallback. Try them in order and keep the first that connects — it is a list, not a set (W2-221). `endpoint` is `endpoints[0]`, kept for older clients."
              },
              "mode": {
                "type": "string",
                "enum": [
                  "client"
                ]
              },
              "encoding": {
                "type": "string",
                "enum": [
                  "jpeg",
                  "raw"
                ]
              }
            }
          },
          "semantics": {
            "type": [
              "string",
              "null"
            ],
            "description": "Legacy label: the current SO-101 checkpoints return LeRobot NORMALIZED values (arm joints −100…100, gripper 0…100), not degrees, despite the `so101-degrees-gripper-percent-v1` name. Convert with your robot's calibration before execution. https://api.agi.diy/docs/concepts#normalized-units",
            "examples": [
              "so101-degrees-gripper-percent-v1"
            ]
          },
          "features": {
            "type": "object",
            "additionalProperties": true,
            "description": "Observation features fixed at lease time, e.g. observation.state [6] float32 and observation.images.<camera> [480,640,3] uint8. Camera names differ per model (ACT top+wrist, SmolVLA front+wrist)."
          },
          "action_horizon": {
            "type": [
              "integer",
              "null"
            ]
          },
          "fps": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "connect_by": {
            "type": "string",
            "format": "date-time",
            "description": "created_at + 60 s; a session nobody connected to by then ends `never_connected`. `null` while a custom checkpoint is `warming`.",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "end_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "client_done",
              "expired",
              "credits",
              "runner_lost",
              "never_connected",
              "replay_failed",
              null,
              "load_failed"
            ]
          },
          "tokens_used": {
            "type": "integer"
          },
          "record": {
            "type": "boolean"
          },
          "type": {
            "type": "string",
            "enum": [
              "live",
              "replay"
            ]
          },
          "source_session_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "commands": {
            "type": "object",
            "properties": {
              "lerobot_rollout": {
                "type": "string"
              },
              "agi_rollout": {
                "type": "string"
              },
              "python": {
                "type": "string"
              }
            }
          },
          "tier": {
            "type": "string",
            "enum": [
              "flagship",
              "default",
              "custom"
            ],
            "description": "Catalog tier of the model: `default` = agi.diy's own act/smolvla capacity, `custom` = your Hub checkpoint (hf:<org>/<repo>), `flagship` = wfm/*."
          },
          "hub": {
            "type": "object",
            "nullable": true,
            "description": "Custom checkpoints only: the validated Hub repo.",
            "properties": {
              "repo": {
                "type": "string"
              },
              "revision": {
                "type": "string",
                "description": "commit sha the lease is pinned to"
              },
              "policy_type": {
                "type": "string"
              },
              "license": {
                "type": "string",
                "nullable": true,
                "description": "from the model card; null when the repo declares none"
              },
              "size_bytes": {
                "type": "integer",
                "nullable": true
              }
            }
          },
          "ready_in_s": {
            "type": "integer",
            "description": "warming only: estimated seconds until the checkpoint is ready (act ~10, smolvla ~45)."
          },
          "ready_at": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "custom checkpoints: when the runner first reported the deployment ready; connect_by counts from here."
          },
          "units": {
            "type": "string",
            "enum": [
              "so101-normalized-v1",
              "so101-degrees-gripper-percent-v1"
            ],
            "description": "The units of the action/state vectors ON THIS LEASE (W2-206). Catalog rows: so101-normalized-v1. A custom hf: checkpoint answers in ITS units, read from its own unnormaliser stats at lease time (PLAY-TTT): so101-degrees-gripper-percent-v1 = LeRobot degrees + gripper %."
          },
          "units_note": {
            "type": "string",
            "description": "One sentence a machine caller can act on; for a custom checkpoint it carries the stats read (action.min/max) and how they were read."
          },
          "units_source": {
            "type": "string",
            "enum": [
              "catalog",
              "checkpoint_stats",
              "ambiguous",
              "none"
            ],
            "description": "Where `units` came from: `catalog` (a listed row), `checkpoint_stats` (the hf: repo's policy_postprocessor_step_N_unnormalizer_processor.safetensors: an arm joint beyond ±100 = degrees, saturation at ±100 = normalised), `ambiguous` (stats inside ±100, label defaulted to normalised — verify), `none` (no stats file readable, label defaulted)."
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "ours",
              "third-party",
              "custom",
              null
            ],
            "description": "Which pool's weights answered this session: `ours` = the agi.diy checkpoint named by `checkpoint`; `third-party` = a `stock-*` row leased by its own name (a lease of our id never spills there — ours busy answers 409); `custom` = your own hf: repo; null = a slot no catalog row claims. Fixed at lease time, so an ended session still says what ran."
          },
          "checkpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "Whose weights answer this lease: the Hub repo of the checkpoint (ours: cagataydev/agi-act-so101; stock-*: the third-party repo; hf: leases: your repo). Provenance travels with the Session (W3-MODELS run 2)."
          },
          "artefact": {
            "type": [
              "string",
              "null"
            ],
            "description": "The CONVERSION of those weights that answers this lease, when the model has more than one. `checkpoint` is the trained weights; two conversions of them can score differently, and the catalog's `eval.measured_range` ends ARE those conversions — so this field says which one you got. null when the model has a single artefact."
          },
          "license": {
            "type": [
              "string",
              "null"
            ],
            "description": "Licence of that checkpoint as published; null = none declared by its author."
          },
          "provider": {
            "type": "string",
            "description": "agi.diy for our checkpoints, the author's Hub org for a stock-* row, you for hf: leases."
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "credits_tokens": {
            "type": "integer"
          },
          "tokens_used": {
            "type": "integer"
          },
          "calls": {
            "type": "integer"
          },
          "by_model": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "model": {
                  "type": "string"
                },
                "calls": {
                  "type": "integer"
                },
                "tokens": {
                  "type": "integer"
                }
              }
            }
          },
          "events": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "session_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "model": {
                  "type": "string"
                },
                "calls": {
                  "type": "integer"
                },
                "tokens": {
                  "type": "integer"
                },
                "ts": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "Stats": {
        "type": "object",
        "properties": {
          "tokens": {
            "type": "integer",
            "description": "Tokens served, all time."
          },
          "calls": {
            "type": "integer"
          },
          "models_online": {
            "type": "integer"
          },
          "sessions_active": {
            "type": "integer"
          },
          "last_call_at": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Wire": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "wss://…/w/ses_…?exp&sig — open within 120 s."
          },
          "exp": {
            "type": "integer"
          },
          "session": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "protocol": {
            "type": "string",
            "enum": [
              "agi-wire/1"
            ]
          },
          "encoding": {
            "type": "string",
            "enum": [
              "jpeg"
            ]
          }
        }
      }
    },
    "headers": {
      "XRequestId": {
        "description": "Cloudflare ray id, or a fresh uuid — the handle to quote in a bug report. Not exposed to cross-origin browser code (no access-control-expose-headers).",
        "schema": {
          "type": "string"
        }
      }
    }
  },
  "paths": {
    "/v1/health": {
      "get": {
        "operationId": "health",
        "summary": "Service health",
        "security": [],
        "responses": {
          "200": {
            "description": "Always 200 while the Worker answers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "operationId": "me",
        "summary": "The account behind the key or cookie",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Account and balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/keys": {
      "get": {
        "operationId": "listKeys",
        "summary": "List keys (revoked included, newest first)",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Keys.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Key"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createKey",
        "summary": "Create a key (browser cookie only)",
        "security": [
          {
            "cookie": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 64
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The key, shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewKey"
                }
              }
            }
          },
          "400": {
            "description": "Bad name or unknown field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_request": {
                    "value": {
                      "error": "bad_request",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "description": "Cross-site cookie write.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "cross_site": {
                    "value": {
                      "error": "cross_site",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/keys/{id}": {
      "delete": {
        "operationId": "revokeKey",
        "summary": "Revoke a key",
        "description": "The key stops authenticating immediately. Sessions already leased with it keep running until they end.",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Revoked (idempotent)."
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "No such key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "operationId": "listModels",
        "summary": "Models, free slots, actions per call",
        "security": [],
        "responses": {
          "200": {
            "description": "Models seen in the last 24 h; `state` says whether one can be leased now.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "models": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ModelInfo"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions": {
      "get": {
        "operationId": "listSessions",
        "summary": "Your sessions (newest first, max 50)",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sessions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sessions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Session"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createSession",
        "summary": "Lease one slot of a model",
        "description": "Free to lease; each returned action is billed 1 token ($0.0001) once a client calls the policy. Connect before `connect_by`.",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "model"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "examples": [
                      "act/so101"
                    ],
                    "description": " A catalog id (`act/so101`) or your own LeRobot checkpoint on the Hugging Face Hub: `hf:<org>/<repo>[@<revision>]` (act, smolvla, diffusion; root-level weight files ≤ 3 GB — training snapshots under checkpoints/ are not counted)."
                  },
                  "ttl_s": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 3600,
                    "default": 600,
                    "description": "Refused (400) outside 60..3600 — never clamped."
                  },
                  "record": {
                    "type": "boolean",
                    "default": true,
                    "description": "false = no trace; usage is still recorded."
                  },
                  "hf_token": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "Hub read token for a private/gated `hf:` repo. Used to load this lease only: sealed at rest, handed to the runner once, then erased. Never returned."
                  },
                  "cameras": {
                    "description": "Custom checkpoints only: the cameras you PHYSICALLY have — a list of the checkpoint's short camera names, or {name: [height, width]} to send frames at your native size when the policy resizes (SmolVLA `resize_imgs_with_padding`). The wire then carries exactly those cameras. Default: the cameras the checkpoint was trained with (from its train_config/dataset metadata), at their trained size. A SmolVLA checkpoint accepts any subset that covers its trained cameras — the rest is masked by the policy, never sent black; an ACT/diffusion checkpoint needs every declared camera at the declared size. `GET /v1/models/hf:<org>/<repo>` lists required / optional / resizable before you lease. Refused with 400 bad_request (param `cameras`, `required`, `optional`, `missing`/`declared`) — nothing is leased or billed.",
                    "oneOf": [
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "minItems": 1
                      },
                      {
                        "type": "object",
                        "additionalProperties": {
                          "oneOf": [
                            {
                              "type": "array",
                              "items": {
                                "type": "integer",
                                "minimum": 16,
                                "maximum": 4096
                              },
                              "minItems": 2,
                              "maxItems": 2
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Leased.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "Missing model, bad ttl_s/record, or unknown field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_request": {
                    "value": {
                      "error": "bad_request",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "402": {
            "description": "Balance ≤ 0.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_credits": {
                    "value": {
                      "error": "insufficient_credits",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "No runner serves this model id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unknown_model": {
                    "value": {
                      "error": "unknown_model",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "description": "Every slot busy, or the model is listed but offline. Retry after `retry_after_s` (15).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "no_slots": {
                    "value": {
                      "error": "no_slots",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "503": {
            "description": "Every runner serving the model reports its public endpoint unreachable (retry_after_s 60).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "relay_down": {
                    "value": {
                      "error": "relay_down",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}": {
      "get": {
        "operationId": "getSession",
        "summary": "One session",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9A-Za-z]+$"
            },
            "description": "Session id (`ses_…`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "Not your session, or no such id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "endSession",
        "summary": "End a session",
        "description": "Idempotent: an ended session is returned unchanged with its original `end_reason`.",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9A-Za-z]+$"
            },
            "description": "Session id (`ses_…`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Ended session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "Not your session, or no such id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/trace": {
      "get": {
        "operationId": "getTrace",
        "summary": "What the policy saw and answered (docs/TRACE.md)",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9A-Za-z]+$"
            },
            "description": "Session id (`ses_…`)."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Trace with events.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "Not yours, or nothing recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  },
                  "no_trace": {
                    "value": {
                      "error": "no_trace",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "503": {
            "description": "The runner's trace server is not answering.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "runner_offline": {
                    "value": {
                      "error": "runner_offline",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/trace/live": {
      "get": {
        "operationId": "traceLive",
        "summary": "Live trace as server-sent events",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9A-Za-z]+$"
            },
            "description": "Session id (`ses_…`)."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`text/event-stream`, one Event per `data:` line.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "Not yours, or nothing recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  },
                  "no_trace": {
                    "value": {
                      "error": "no_trace",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "503": {
            "description": "Trace server unreachable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "runner_offline": {
                    "value": {
                      "error": "runner_offline",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/trace/frames/{cam}/{file}": {
      "get": {
        "operationId": "traceFrame",
        "summary": "One recorded camera frame",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9A-Za-z]+$"
            },
            "description": "Session id (`ses_…`)."
          },
          {
            "name": "cam",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "\\.jpg$"
            },
            "description": "`<request_id>.jpg`"
          }
        ],
        "responses": {
          "200": {
            "description": "JPEG as it crossed the wire.",
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "No such session or frame.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  },
                  "no_trace": {
                    "value": {
                      "error": "no_trace",
                      "message": "…"
                    }
                  },
                  "no_frame": {
                    "value": {
                      "error": "no_frame",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "503": {
            "description": "Trace server unreachable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "runner_offline": {
                    "value": {
                      "error": "runner_offline",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/replay": {
      "post": {
        "operationId": "replaySession",
        "summary": "New, billed inference on a recording's observations",
        "description": "Does not move a robot. Billed like any session; outputs need not match for stochastic models. Reproducibility is PER ROW and is not expressed in this API: agi-act/so101 is deterministic; agi-wfm/so101's served deployment fixes its sampler seed (same observation -> byte-identical chunks on the served path, measured 2026-10-25), so a replay repeats; agi-smolvla/so101 sets no seed, so treat it as non-reproducible until measured. No field carries the serving seed - ModelInfo.eval.seed, if present, is the evaluation harness's seed and says nothing about serving. The spread in ModelInfo.eval belongs to the published figures, which were measured unseeded.",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9A-Za-z]+$"
            },
            "description": "Session id (`ses_…`)."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "model": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Replay session (`type: replay`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "402": {
            "description": "Balance ≤ 0.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_credits": {
                    "value": {
                      "error": "insufficient_credits",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "Not yours, no recording, or unknown model.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  },
                  "no_trace": {
                    "value": {
                      "error": "no_trace",
                      "message": "…"
                    }
                  },
                  "unknown_model": {
                    "value": {
                      "error": "unknown_model",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "description": "Cameras/state differ, empty recording, or no free slot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "incompatible_features": {
                    "value": {
                      "error": "incompatible_features",
                      "message": "…"
                    }
                  },
                  "no_observations": {
                    "value": {
                      "error": "no_observations",
                      "message": "…"
                    }
                  },
                  "no_slots": {
                    "value": {
                      "error": "no_slots",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "503": {
            "description": "The runner holding the trace is offline.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "runner_offline": {
                    "value": {
                      "error": "runner_offline",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/wire": {
      "get": {
        "operationId": "getWire",
        "summary": "Signed WebSocket URL for the browser wire (docs/WIRE.md)",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ses_[0-9A-Za-z]+$"
            },
            "description": "Session id (`ses_…`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Open `url` within 120 s.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Wire"
                }
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "Not your session, or no such id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "error": "not_found",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "description": "Session ended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "session_ended": {
                    "value": {
                      "error": "session_ended",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "503": {
            "description": "Runner has no browser gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "no_wire": {
                    "value": {
                      "error": "no_wire",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "usage",
        "summary": "Balance and tokens used per model",
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Default: 30 days ago."
          }
        ],
        "responses": {
          "200": {
            "description": "Usage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "400": {
            "description": "`since` is not ISO-8601.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_request": {
                    "value": {
                      "error": "bad_request",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "description": "No credentials (`unauthorized`) or a key that does not resolve (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "…"
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": "invalid_key",
                      "message": "…"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "operationId": "stats",
        "summary": "Public service totals (no per-user data)",
        "security": [],
        "responses": {
          "200": {
            "description": "Totals.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Stats"
                }
              }
            }
          }
        }
      }
    },
    "/v1/models/hf:{ref}": {
      "get": {
        "summary": "Plan a custom-checkpoint lease (no lease, no billing)",
        "description": "What POST /v1/sessions would do with `model: \"hf:<ref>\"`, without doing it: policy type, size against the cap, default wire `features`, and `cameras` — `rule` (`exact` for act/diffusion: every declared camera at its declared size; `subset` for smolvla: any subset covering the trained cameras, missing ones masked), `resizable`, `required`, `optional`, `default`, `placeholders` (SmolVLA `empty_camera_N` slots — never wire features), `items[]` per camera with `declared_shape`, `trained_shape`, `trained`; `trained_source` is `dataset` when train_config.json → the dataset's meta/info.json was reachable, else `none` — nothing is guessed: every declared camera is then required. Public repos need no auth; for a private repo send the Hub token as `Authorization: Bearer hf_…` (never in the URL). Same refusals as the lease: 404 unknown_model, 403 hf_forbidden, 400 missing_config / unsupported_policy / unsupported_weights / too_large, 502 hub_unavailable.",
        "tags": [],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`<org>/<repo>[@<revision>]`",
            "example": "HashtagRobotics/smolvla-tic-tac-toe-games-1-15-120k"
          }
        ],
        "responses": {
          "200": {
            "description": "The plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "repo": {
                      "type": "string"
                    },
                    "revision": {
                      "type": "string"
                    },
                    "policy_type": {
                      "type": "string"
                    },
                    "license": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "size_bytes": {
                      "type": "integer"
                    },
                    "size_cap_bytes": {
                      "type": "integer"
                    },
                    "action_horizon": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "fps": {
                      "type": "integer"
                    },
                    "ready_in_s": {
                      "type": "integer"
                    },
                    "features": {
                      "type": "object"
                    },
                    "cameras": {
                      "type": "object",
                      "properties": {
                        "rule": {
                          "type": "string",
                          "enum": [
                            "exact",
                            "subset"
                          ]
                        },
                        "resizable": {
                          "type": "boolean"
                        },
                        "trained_source": {
                          "type": "string",
                          "enum": [
                            "dataset",
                            "none"
                          ]
                        },
                        "dataset": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "required": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "optional": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "default": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "placeholders": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    },
                    "lease": {
                      "type": "object",
                      "properties": {
                        "body": {
                          "type": "object"
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "description": "unknown_model — not public on the Hub (or private without a token)",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        }
      }
    }
  },
  "x-not-in-spec": "Runner-only routes (/v1/internal/*), operator /v1/admin/stats, /auth/* login redirects and /mcp (JSON-RPC, docs/MCP.md) are documented in docs/CONTRACT.md."
}
