# REST

Bearer auth, JSON in and out, SSE for live events — every SDK call is one of these HTTP calls underneath.

The base URL is `https://api.roborama.com`. Authenticate with
`Authorization: Bearer $ROBORAMA_API_KEY`; send
`Content-Type: application/json` on anything with a body. Keys carry the
`rbr_live_` prefix, and a missing or invalid key is a 401 with code
`invalid_api_key`. Every example on this page is a real request you can
paste — the cURL tab on every example on this site is built the same way.

*Example: create a run*

**Python**

```python
import roborama  # reads ROBORAMA_API_KEY from the environment

run = roborama.run(
    robot="g1-edu-pro@fw2.3",
    environment="kitchen-std@v1.2",
    task="pick_place@v1",
    episodes="auto(ci=0.95, moe=0.03)",
)
print(run.result())  # n=612  rate=0.874  ci95=(0.846, 0.898)
```

**TypeScript**

```typescript
import Roborama from "@roborama/sdk"; // reads ROBORAMA_API_KEY

const roborama = new Roborama();

const run = await roborama.runs.create({
  robot: "g1-edu-pro@fw2.3",
  environment: "kitchen-std@v1.2",
  task: "pick_place@v1",
  episodes: "auto(ci=0.95, moe=0.03)",
});

console.log(await run.result()); // n=612  rate=0.874  ci95=(0.846, 0.898)
```

**cURL**

```bash
curl https://api.roborama.com/v1/runs \
  -H "Authorization: Bearer $ROBORAMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "run",
    "robot": "g1-edu-pro@fw2.3",
    "environment": "kitchen-std@v1.2",
    "task": "pick_place@v1",
    "episodes": "auto(ci=0.95, moe=0.03)"
  }'
```

**Agent (tool-use payload)**

```json
{
  "type": "tool_use",
  "name": "roborama_run",
  "input": {
    "robot": "g1-edu-pro@fw2.3",
    "environment": "kitchen-std@v1.2",
    "task": "pick_place@v1",
    "episodes": "auto(ci=0.95, moe=0.03)"
  }
}
```

## One endpoint, seven primitives

`POST /v1/runs` creates every kind of job. The `kind` field selects the
primitive — `run` (the default), `eval`, `verify`, `matrix`, `threshold`,
`compare`, or `transfer` — and the rest of the body is that primitive's
fields, as documented from [`run()`](/docs/primitives/run/) onward. The
response is a `run` object whose `status` moves through `queued`,
`scheduling`, and `running` to `completed`, `failed`, or `stopped`. Success
rates in responses always arrive with `n` and `ci95` attached; the API does
not emit a bare percentage.

## The endpoints

List endpoints take `kind`, `status`, and `limit` query parameters —
`GET /v1/runs?kind=eval` is how CI polls for suite verdicts.

| Method and path | Returns |
| --- | --- |
| `POST /v1/runs` | the created run; `kind` selects the primitive |
| `GET /v1/runs/{run_id}` | the run, its resolved pins, and once completed the result: `n`, `success_rate`, `ci95`, clusters, both meters |
| `GET /v1/runs/{run_id}/episodes` | per-episode artifacts: video, MCAP, replay spec |
| `GET /v1/runs/{run_id}/report` | the verification report (`format=pdf`) |
| `GET /v1/runs/{run_id}/events` | live server-sent events — use `curl -N` |
| `POST /v1/quote` | both meters, dollars, and `queue_eta` before you commit |
| `GET /v1/robots` | the catalogue: firmware pins, cells, duty cycle, tier |
| `GET /v1/environments` | the catalogue: revisions, instrumentation, reset class |

## Watch a run live

The events endpoint is the wire form of `run.watch()` in the SDKs: an episode
ticker plus status transitions carrying the cell's WebRTC URL, delivered as
they happen, with no polling interval to tune.

*Example: watch via SSE*

**Python**

```python
import roborama  # reads ROBORAMA_API_KEY from the environment

run = roborama.runs.get("run_8842")

for event in run.watch():   # live: episode ticker + WebRTC stream URLs
    print(event.episode, event.status)

stream = roborama.streams.get("cell-g1-04")
print(stream)
# {webrtc: "wss://streams.roborama.com/cells/cell-g1-04/webrtc",
#  mjpeg: "https://streams.roborama.com/cells/cell-g1-04/mjpeg",
#  viewer_token: "vt_7Kq2mHentXw4"}
```

**TypeScript**

```typescript
import Roborama from "@roborama/sdk"; // reads ROBORAMA_API_KEY

const roborama = new Roborama();

const run = await roborama.runs.get("run_8842");

for await (const event of run.watch()) {
  // live: episode ticker + WebRTC stream URLs
  console.log(event.episode, event.status);
}

const stream = await roborama.streams.get("cell-g1-04");
console.log(stream);
// { webrtc: "wss://streams.roborama.com/cells/cell-g1-04/webrtc",
//   mjpeg: "https://streams.roborama.com/cells/cell-g1-04/mjpeg",
//   viewer_token: "vt_7Kq2mHentXw4" }
```

**cURL**

```bash
# live event stream (server-sent events): episode ticker + status
curl -N https://api.roborama.com/v1/runs/run_8842/events \
  -H "Authorization: Bearer $ROBORAMA_API_KEY"

# cell video stream descriptor
curl https://api.roborama.com/v1/streams/cell-g1-04 \
  -H "Authorization: Bearer $ROBORAMA_API_KEY"
```

**Agent (tool-use payload)**

```json
[
  {
    "type": "tool_use",
    "name": "roborama_watch_run",
    "input": { "run_id": "run_8842" }
  },
  {
    "type": "tool_use",
    "name": "roborama_get_stream",
    "input": { "cell": "cell-g1-04" }
  }
]
```

```text
event: episode
data: {"episode": 213, "of": 612, "outcome": "success", "duration_s": 121}

event: status
data: {"status": "running", "cell": "cell-g1-04", "webrtc": "wss://streams.roborama.com/cells/cell-g1-04/webrtc"}
```

## Errors

One envelope everywhere. `code` comes from the fixed set in
[the error reference](/docs/errors/), and `doc_url` points at the matching
entry, so an error response is never a dead end:

```json
{
  "error": {
    "code": "budget_exceeded",
    "message": "max_budget_usd=500 reached after 81 episodes; run stopped, partial result kept.",
    "run_id": "run_8907",
    "doc_url": "https://roborama.com/docs/errors/#budget_exceeded"
  }
}
```

## The generated reference

The [API reference](/docs/api-reference/) is generated from
[/openapi.json](/openapi.json) — OpenAPI 3.1, with request and response
examples on every operation. If you are generating a client or handing tools
to an agent, consume the raw file; it is the same source these pages are
checked against. See also [the agent surface](/docs/sdks/agents/).
