# API reference — Runs

The core primitive. `POST /v1/runs` accepts a `kind` (`run | eval | verify | matrix | threshold | compare | transfer`) with kind-specific parameters mirroring the SDK.

## POST /v1/runs

Create a run (any kind)

Creates a physical evaluation job. The `kind` field selects the primitive: `run` (default), `eval`, `verify`, `matrix`, `threshold`, `compare`, or `transfer`. Episode counts accept an integer or `auto(ci=…, moe=…)`, which sizes n for a target margin of error (Wilson interval). `max_budget_usd` is a hard stop, metered live.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| kind | body | `run \| eval \| verify \| matrix \| threshold \| compare \| transfer` | no | The primitive this run executes. |
| robot | body | `string` | no | `model@firmware`; `@latest` allowed, resolved pin recorded. |
| robots | body | `array<string>` | no | For eval \| verify \| matrix. |
| environment | body | `string` | no |  |
| environments | body | `array<string>` | no | For matrix. |
| policy | body | `Policy` | no | Policy packaging. Declared contracts (`action_space`, `observation_contract`) are validated before any motor moves. |
| policies | body | `object` | no | For compare: name → policy. |
| policy_stream | body | `object` | no | For threshold: a webhook that receives checkpoint pushes. |
| task | body | `string` | no |  |
| suite | body | `string` | no | For eval. |
| publish | body | `private \| leaderboard` | no | Leaderboard publication is opt-in only. |
| scenarios | body | `object` | no | For verify: sim-flagged initial conditions (PolaRiS/Isaac/world-model formats or layout-replay specs). |
| audit_sample | body | `number` | no | For verify: fraction of random episodes run against the sim's blind spots. |
| return_ground_truth | body | `boolean` | no | For verify: ship mocap 6-DoF poses + commanded-vs-executed, formatted to recalibrate your simulator. |
| source | body | `string` | no | For transfer: embodiment the policy was trained on. |
| target | body | `object` | no | For transfer: destination embodiment. For threshold: the target object. |
| iterate_on | body | `string` | no | For threshold: commodity tier to iterate on. |
| escalate_to | body | `string` | no | For threshold: verification-tier embodiment for confirmation. |
| monthly_cap_usd | body | `number` | no | For threshold: hard monthly cap. |
| on_verified | body | `object` | no |  |
| paired | body | `boolean` | no | For compare: same initial conditions per episode pair — halves the n needed to separate two policies. |
| episodes | body | `EpisodesSpec` | no | An integer episode count, or `auto(ci=…, moe=…)` which sizes n for a target margin of error at the given confidence (Wilson interval). |
| episodes_per_cell | body | `EpisodesSpec` | no | An integer episode count, or `auto(ci=…, moe=…)` which sizes n for a target margin of error at the given confidence (Wilson interval). |
| perturbation | body | `Perturbation` | no | Seeded, versioned, replayable perturbation schedule. The schedule IS the product spec; realized perturbations are recorded in `/meta`. |
| data | body | `DataPosture` | no | Customer IP posture, explicit per run. |
| priority | body | `burst \| standard \| soak` | no | Maps to the rate-card priority tiers. |
| max_budget_usd | body | `number` | no | Hard stop, metered live. |
| interventions | body | `none \| on_stall \| scripted` | no | Intervention policy, declared before the run. Counts and timestamps ship in results, and any intervened episode is flagged in the statistics. |

Example request — kind=run — the core primitive:

```json
{
 "kind": "run",
 "robot": "g1-edu-pro@fw2.3",
 "environment": "kitchen-std@v1.2",
 "policy": {
  "type": "container",
  "image": "ghcr.io/acme/skill:v4",
  "action_space": "joint_delta_50hz",
  "observation_contract": "droid-3cam"
 },
 "task": "load_dishwasher@v2",
 "episodes": "auto(ci=0.95, moe=0.03)",
 "perturbation": {
  "layout_jitter_mm": 25,
  "lighting": [
   "3000K",
   "5600K"
  ],
  "distractors": "set-B",
  "seed": 42
 },
 "data": {
  "retention": "30d",
  "train_on_failures": false
 },
 "max_budget_usd": 4000
}
```

Example request — kind=eval — versioned, citable suite:

```json
{
 "kind": "eval",
 "policy": {
  "type": "checkpoint",
  "hf": "acme/skill-v4",
  "runtime": "openpi"
 },
 "suite": "rbr-manip-core@v3",
 "robots": [
  "g1-edu-pro@fw2.3"
 ],
 "publish": "private"
}
```

Example request — kind=verify — the interlock with simulation:

```json
{
 "kind": "verify",
 "policy": {
  "type": "checkpoint",
  "hf": "acme/skill-v4",
  "runtime": "openpi"
 },
 "scenarios": {
  "format": "layout-replay",
  "source": "sim_flagged_p1.json",
  "count": 318
 },
 "robots": [
  "g1-edu-pro@fw2.3",
  "g1-edu-plus@fw2.3"
 ],
 "audit_sample": 0.1,
 "return_ground_truth": true
}
```

Example request — kind=matrix — embodiments × environments:

```json
{
 "kind": "matrix",
 "policy": {
  "type": "checkpoint",
  "hf": "acme/skill-v4",
  "runtime": "openpi"
 },
 "robots": [
  "g1-edu-pro@fw2.3",
  "g1-edu-pro@fw2.4",
  "g1-edu-plus@fw2.3",
  "aloha2-pro@fw1.1",
  "spot-arm@fw4.1",
  "tiago-pro@fw2.0",
  "fr3-bench@fw5.2",
  "stretch3@fw1.9",
  "nori-a3@fw1.0",
  "so-101@fw1.2"
 ],
 "environments": [
  "cell-a",
  "kitchen-std@v1.2",
  "warehouse-std@v2.0"
 ],
 "task": "pick_place_class3",
 "episodes_per_cell": "auto(ci=0.95, moe=0.05)"
}
```

Example request — kind=threshold — the soak-to-verify outcome contract:

```json
{
 "kind": "threshold",
 "policy_stream": {
  "webhook": "https://acme.ai/ckpt"
 },
 "target": {
  "success_rate": 0.99,
  "ci": 0.95,
  "task": "bin_pick@v1"
 },
 "iterate_on": "soak",
 "escalate_to": "g1-edu-pro@fw2.3",
 "monthly_cap_usd": 12000,
 "on_verified": {
  "webhook": "https://acme.ai/release-gate"
 }
}
```

Example request — kind=compare — paired A/B:

```json
{
 "kind": "compare",
 "policies": {
  "v3": {
   "type": "checkpoint",
   "hf": "acme/skill-v3",
   "runtime": "openpi"
  },
  "v4": {
   "type": "checkpoint",
   "hf": "acme/skill-v4",
   "runtime": "openpi"
  }
 },
 "paired": true,
 "robot": "g1-edu-pro@fw2.3",
 "task": "shelf_restock@v1"
}
```

Example request — kind=transfer — cross-embodiment gap:

```json
{
 "kind": "transfer",
 "policy": {
  "type": "checkpoint",
  "hf": "acme/skill-v4",
  "runtime": "openpi"
 },
 "source": "aloha-bimanual@fw3.1",
 "target": "g1-edu-pro@fw2.3",
 "task": "fold_towel@v2"
}
```

Example request — Task-pinned matrix with interventions declared (espresso@v1):

```json
{
 "kind": "matrix",
 "task": "espresso@v1",
 "policy": {
  "type": "checkpoint",
  "hf": "pi/espresso-v7",
  "runtime": "openpi",
  "inference": {
   "action_horizon": 50,
   "chunk_size": 50,
   "temp": 0
  },
  "action_space": "joint_delta_50hz",
  "observation_contract": "droid-3cam"
 },
 "robots": [
  "g1-edu-pro@fw2.3",
  "g1-edu-pro@fw2.4",
  "g1-edu-plus@fw2.3",
  "stretch3@fw1.9"
 ],
 "environments": [
  "kitchen-std@v1.2",
  "kitchen-replica@v2.0"
 ],
 "episodes_per_cell": "auto(ci=0.95, moe=0.05)",
 "interventions": "none"
}
```

Example response (201):

```json
{
 "id": "run_8842",
 "object": "run",
 "kind": "run",
 "status": "queued",
 "created": "2026-08-28T14:02:11Z",
 "robot": "g1-edu-pro@fw2.3",
 "environment": "kitchen-std@v1.2",
 "task": "load_dishwasher@v2",
 "episodes": "auto(ci=0.95, moe=0.03)",
 "priority": "standard",
 "max_budget_usd": 4000
}
```

## GET /v1/runs

List runs

Lists runs for the account, newest first.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| kind | query | `run \| eval \| verify \| matrix \| threshold \| compare \| transfer` | no | Filter by primitive kind. |
| status | query | `queued \| scheduling \| running \| completed \| failed \| stopped` | no |  |
| limit | query | `integer` | no |  |

Example response (200):

```json
{
 "object": "list",
 "url": "/v1/runs",
 "data": [
  {
   "id": "run_8842",
   "object": "run",
   "kind": "run",
   "status": "completed",
   "created": "2026-08-28T14:02:11Z",
   "robot": "g1-edu-pro@fw2.3",
   "environment": "kitchen-std@v1.2",
   "task": "load_dishwasher@v2",
   "result": {
    "n": 612,
    "success_rate": 0.874,
    "ci95": [
     0.846,
     0.898
    ],
    "interval_method": "wilson",
    "failure_clusters": {
     "grasp_slip": 41,
     "perception_miss": 22,
     "collision": 9
    },
    "robot_hours": 20.4,
    "environment_hours": 20.4,
    "cost_usd": 3812
   }
  }
 ]
}
```

## GET /v1/runs/{run_id}

Retrieve a run

Returns the run, its resolved pins (`@latest` is allowed on create, but the resolved pin is recorded), and — once completed — the result with n, rate, CI, failure clusters, both meters, and artifact links.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| run_id | path | `string` | yes |  |

Example response (200):

```json
{
 "id": "run_8842",
 "object": "run",
 "kind": "run",
 "status": "completed",
 "created": "2026-08-28T14:02:11Z",
 "completed": "2026-08-29T11:37:48Z",
 "robot": "g1-edu-pro@fw2.3",
 "environment": "kitchen-std@v1.2",
 "task": "load_dishwasher@v2",
 "policy": {
  "type": "container",
  "image": "ghcr.io/acme/skill:v4",
  "action_space": "joint_delta_50hz",
  "observation_contract": "droid-3cam"
 },
 "episodes": "auto(ci=0.95, moe=0.03)",
 "priority": "standard",
 "perturbation": {
  "layout_jitter_mm": 25,
  "lighting": [
   "3000K",
   "5600K"
  ],
  "distractors": "set-B",
  "seed": 42
 },
 "data": {
  "retention": "30d",
  "train_on_failures": false
 },
 "max_budget_usd": 4000,
 "resolved_pins": {
  "robot": "g1-edu-pro@fw2.3",
  "environment": "kitchen-std@v1.2",
  "task": "load_dishwasher@v2",
  "perturbation_rev": "set-B@v1.4"
 },
 "result": {
  "n": 612,
  "success_rate": 0.874,
  "ci95": [
   0.846,
   0.898
  ],
  "interval_method": "wilson",
  "failure_clusters": {
   "grasp_slip": 41,
   "perception_miss": 22,
   "collision": 9
  },
  "robot_hours": 20.4,
  "environment_hours": 20.4,
  "cost_usd": 3812,
  "artifacts": {
   "mcap": "https://api.roborama.com/v1/runs/run_8842/episodes?artifact=mcap",
   "video": "https://api.roborama.com/v1/runs/run_8842/episodes?artifact=video",
   "ground_truth": "https://api.roborama.com/v1/runs/run_8842/episodes?artifact=ground_truth",
   "report_pdf": "https://api.roborama.com/v1/runs/run_8842/report?format=pdf"
  }
 }
}
```

## GET /v1/runs/{run_id}/episodes

List episodes for a run

Every episode carries video, an MCAP recording (channels: `/joint_states_measured`, `/joint_targets_commanded`, `/camera/*`, `/ft_wrist`, `/gt/object_poses`, `/events`, `/meta`) and a replay spec — the initial conditions, re-runnable or sim-loadable. `/meta` carries reproducibility metadata: firmware, calibration age, actuator cycle counts, thermal state, seed, and realized (not just requested) perturbations.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| run_id | path | `string` | yes |  |
| outcome | query | `success \| failure` | no | Filter by outcome. |
| cluster | query | `string` | no | Filter failures by cluster, e.g. `grasp_slip`. |

Example response (200):

```json
{
 "object": "list",
 "url": "/v1/runs/run_8842/episodes",
 "data": [
  {
   "id": "ep_17",
   "object": "episode",
   "index": 17,
   "outcome": "success",
   "duration_s": 118,
   "video_url": "https://artifacts.roborama.com/run_8842/ep_17/video.mp4",
   "mcap_url": "https://artifacts.roborama.com/run_8842/ep_17/episode.mcap",
   "replay_spec": {
    "environment": "kitchen-std@v1.2",
    "layout_seed": 42017,
    "lighting": "5600K",
    "distractors": "set-B"
   }
  }
 ]
}
```

## GET /v1/runs/{run_id}/report

Retrieve the verification report

The deployment verification report: conformance evidence with n, rate, CI, failure clusters, resolved pins, and the perturbation schedule as realized. JSON by default; `format=pdf` returns the citable PDF.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| run_id | path | `string` | yes |  |
| format | query | `json \| pdf` | no |  |

Example response (200):

```json
{
 "object": "report",
 "run_id": "run_8842",
 "kind": "verification",
 "result": {
  "n": 612,
  "success_rate": 0.874,
  "ci95": [
   0.846,
   0.898
  ],
  "interval_method": "wilson"
 },
 "resolved_pins": {
  "robot": "g1-edu-pro@fw2.3",
  "environment": "kitchen-std@v1.2",
  "task": "load_dishwasher@v2",
  "perturbation_rev": "set-B@v1.4"
 },
 "citation": "Roborama run run_8842, 2026-08-29, g1-edu-pro@fw2.3 × kitchen-std@v1.2",
 "pdf_url": "https://api.roborama.com/v1/runs/run_8842/report?format=pdf"
}
```

## POST /v1/runs/{run_id}/export

Export run data

Packages the run's episodes for training or analysis. Formats: `lerobot`, `rlds`, `mcap-bundle`. Respects the run's `data.train_on_failures` posture.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| run_id | path | `string` | yes |  |
| format | body | `lerobot \| rlds \| mcap-bundle` | yes |  |

Example request:

```json
{
 "format": "lerobot"
}
```

Example response (202):

```json
{
 "object": "export",
 "id": "exp_2214",
 "run_id": "run_8842",
 "format": "lerobot",
 "status": "preparing",
 "download_url": null
}
```

## GET /v1/runs/{run_id}/events

Watch a run (server-sent events)

Live event stream: episode ticker, status transitions, and WebRTC stream URLs for the cell. Equivalent to `run.watch()` in the SDKs.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| run_id | path | `string` | yes |  |

Example response (200):

```json
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"}


```
