# API reference — Tasks

Task Specs — a customer claim formalized as a declarative, versioned protocol with instrument-bound success predicates. Lifecycle: `draft → piloting → frozen@vN`. Frozen specs are immutable; changes create the next revision.

## POST /v1/tasks

Create a Task Spec

Formalize a claim as a declarative, versioned Task Spec. Every success predicate is validated at creation against the instruments available in the target environment class; a predicate that binds to no instrument fails with `contract_validation_failed`. The new spec starts in `draft`.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| name | body | `string` | yes |  |
| visibility | body | `private \| published` | no | Private tasks stay the customer's method; published tasks join the public catalogue and become cross-customer comparable. |
| initial_conditions | body | `object` | yes | Named objects with poses, tolerances, and randomization zones. Kit hardware is referenced as `kit/<name>`. |
| success_predicates | body | `array<object>` | yes | Each predicate must bind to an available instrument in the target environment class; validated at creation. |
| instructions | body | `object` | no | Instruction distribution for language-conditioned policies. Held-out paraphrases are never sampled during iteration and are reported separately. |
| stages | body | `array<object>` | no | Ordered stage predicates; per-stage rates ship in results. |
| envelope | body | `object` | no | The claim's declared boundaries. Out-of-scope declarations appear verbatim on reports. |
| baseline | body | `object` | no | Customer's internal trials — used to sanity-check the pilot and set expectations, never published. |

Example request:

```json
{
 "name": "espresso",
 "visibility": "private",
 "initial_conditions": {
  "machine": {
   "object": "kit/acme-breville",
   "pose": "P1",
   "tol_mm": 20
  },
  "cup": {
   "object": "catalogue/cup-std-08",
   "randomize": "zone-A"
  }
 },
 "success_predicates": [
  {
   "cup_on_tray": "gt.pose(cup) within tray_zone"
  },
  {
   "liquid_mass": "scale.delta between 25 and 40 g"
  },
  {
   "no_spill": "vision.spill_area < 2 cm2"
  },
  {
   "t_complete": "episode.duration < 180 s"
  }
 ],
 "instructions": {
  "sampled_per_episode": [
   "make an espresso",
   "brew me a coffee",
   "fais un espresso"
  ],
  "held_out": [
   "prepare a single shot"
  ]
 },
 "stages": [
  {
   "grasp_cup": "gt.pose(cup) in gripper"
  },
  {
   "cup_placed": "gt.pose(cup) within drip_zone"
  },
  {
   "extraction": "scale.delta > 0 within 60s"
  },
  {
   "served": "all success_predicates"
  }
 ],
 "envelope": {
  "lighting": [
   "3000K",
   "5600K"
  ],
  "distractors": "set-B",
  "out_of_scope": [
   "oat_milk"
  ]
 },
 "baseline": {
  "internal_trials": 30,
  "internal_rate": 0.87
 }
}
```

Example response (201):

```json
{
 "id": "task_espresso_01",
 "object": "task",
 "name": "espresso",
 "rev": null,
 "status": "draft",
 "visibility": "private",
 "created": "2026-08-20T09:14:02Z",
 "frozen": null,
 "signatures": []
}
```

## GET /v1/tasks

List Task Specs

All Task Specs visible to the key's account, drafts and frozen revisions alike.

Example response (200):

```json
{
 "object": "list",
 "url": "/v1/tasks",
 "data": [
  {
   "id": "task_espresso_01",
   "object": "task",
   "name": "espresso",
   "rev": "espresso@v1",
   "status": "frozen",
   "visibility": "private",
   "created": "2026-08-20T09:14:02Z",
   "frozen": "2026-08-24T16:40:11Z",
   "signatures": [
    "acct_acme",
    "roborama"
   ],
   "initial_conditions": {
    "machine": {
     "object": "kit/acme-breville",
     "pose": "P1",
     "tol_mm": 20
    },
    "cup": {
     "object": "catalogue/cup-std-08",
     "randomize": "zone-A"
    }
   },
   "success_predicates": [
    {
     "cup_on_tray": "gt.pose(cup) within tray_zone"
    },
    {
     "liquid_mass": "scale.delta between 22 and 42 g"
    },
    {
     "no_spill": "vision.spill_area < 2 cm2"
    },
    {
     "t_complete": "episode.duration < 180 s"
    }
   ],
   "instructions": {
    "sampled_per_episode": [
     "make an espresso",
     "brew me a coffee",
     "fais un espresso"
    ],
    "held_out": [
     "prepare a single shot"
    ]
   },
   "stages": [
    {
     "grasp_cup": "gt.pose(cup) in gripper"
    },
    {
     "cup_placed": "gt.pose(cup) within drip_zone"
    },
    {
     "extraction": "scale.delta > 0 within 60s"
    },
    {
     "served": "all success_predicates"
    }
   ],
   "envelope": {
    "lighting": [
     "3000K",
     "5600K"
    ],
    "distractors": "set-B",
    "out_of_scope": [
     "oat_milk"
    ]
   },
   "pilot": {
    "run_id": "run_9088",
    "robot": "g1-edu-pro@fw2.3",
    "episodes": 25,
    "amendments": 1
   }
  }
 ],
 "has_more": false
}
```

## GET /v1/tasks/{task_id}

Get a Task Spec

Fetch a Task Spec by id or by frozen revision (`espresso@v1`).

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| task_id | path | `string` | yes | Task id (`task_espresso_01`) or frozen revision (`espresso@v1`). |

Example response (200):

```json
{
 "id": "task_espresso_01",
 "object": "task",
 "name": "espresso",
 "rev": "espresso@v1",
 "status": "frozen",
 "visibility": "private",
 "created": "2026-08-20T09:14:02Z",
 "frozen": "2026-08-24T16:40:11Z",
 "signatures": [
  "acct_acme",
  "roborama"
 ],
 "initial_conditions": {
  "machine": {
   "object": "kit/acme-breville",
   "pose": "P1",
   "tol_mm": 20
  },
  "cup": {
   "object": "catalogue/cup-std-08",
   "randomize": "zone-A"
  }
 },
 "success_predicates": [
  {
   "cup_on_tray": "gt.pose(cup) within tray_zone"
  },
  {
   "liquid_mass": "scale.delta between 22 and 42 g"
  },
  {
   "no_spill": "vision.spill_area < 2 cm2"
  },
  {
   "t_complete": "episode.duration < 180 s"
  }
 ],
 "instructions": {
  "sampled_per_episode": [
   "make an espresso",
   "brew me a coffee",
   "fais un espresso"
  ],
  "held_out": [
   "prepare a single shot"
  ]
 },
 "stages": [
  {
   "grasp_cup": "gt.pose(cup) in gripper"
  },
  {
   "cup_placed": "gt.pose(cup) within drip_zone"
  },
  {
   "extraction": "scale.delta > 0 within 60s"
  },
  {
   "served": "all success_predicates"
  }
 ],
 "envelope": {
  "lighting": [
   "3000K",
   "5600K"
  ],
  "distractors": "set-B",
  "out_of_scope": [
   "oat_milk"
  ]
 },
 "pilot": {
  "run_id": "run_9088",
  "robot": "g1-edu-pro@fw2.3",
  "episodes": 25,
  "amendments": 1
 }
}
```

## POST /v1/tasks/{task_id}/pilot

Run a pilot (calibration session)

A small calibration session on the named robot. The customer watches live via `stream_url`; the session moves the spec from `draft` to `piloting`. Pilot episodes calibrate the method — they are not evidence and never appear in verification reports.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| task_id | path | `string` | yes |  |
| robot | body | `string` | yes |  |
| episodes | body | `integer` | no |  |

Example request:

```json
{
 "robot": "g1-edu-pro@fw2.3",
 "episodes": 25
}
```

Example response (200):

```json
{
 "run_id": "run_9088",
 "robot": "g1-edu-pro@fw2.3",
 "episodes": 25,
 "stream_url": "wss://streams.roborama.com/cells/cell-g1-02/webrtc"
}
```

## POST /v1/tasks/{task_id}/amend

Amend a draft or piloting Task Spec

Iterate on the method while piloting. Any TaskCreate field may be amended; amendments are rejected with `task_frozen` semantics once the spec is frozen (a frozen spec is immutable — create the next revision instead).

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| task_id | path | `string` | yes |  |
| name | body | `string` | no |  |
| visibility | body | `private \| published` | no | Private tasks stay the customer's method; published tasks join the public catalogue and become cross-customer comparable. |
| initial_conditions | body | `object` | no | Named objects with poses, tolerances, and randomization zones. Kit hardware is referenced as `kit/<name>`. |
| success_predicates | body | `array<object>` | no | Each predicate must bind to an available instrument in the target environment class; validated at creation. |
| instructions | body | `object` | no | Instruction distribution for language-conditioned policies. Held-out paraphrases are never sampled during iteration and are reported separately. |
| stages | body | `array<object>` | no | Ordered stage predicates; per-stage rates ship in results. |
| envelope | body | `object` | no | The claim's declared boundaries. Out-of-scope declarations appear verbatim on reports. |
| baseline | body | `object` | no | Customer's internal trials — used to sanity-check the pilot and set expectations, never published. |

Example request:

```json
{
 "success_predicates": [
  {
   "cup_on_tray": "gt.pose(cup) within tray_zone"
  },
  {
   "liquid_mass": "scale.delta between 22 and 42 g"
  },
  {
   "no_spill": "vision.spill_area < 2 cm2"
  },
  {
   "t_complete": "episode.duration < 180 s"
  }
 ]
}
```

Example response (200):

```json
{
 "id": "task_espresso_01",
 "object": "task",
 "name": "espresso",
 "rev": null,
 "status": "piloting",
 "visibility": "private",
 "created": "2026-08-20T09:14:02Z",
 "frozen": null,
 "signatures": [],
 "pilot": {
  "run_id": "run_9088",
  "robot": "g1-edu-pro@fw2.3",
  "episodes": 25,
  "amendments": 1
 },
 "success_predicates": [
  {
   "cup_on_tray": "gt.pose(cup) within tray_zone"
  },
  {
   "liquid_mass": "scale.delta between 22 and 42 g"
  },
  {
   "no_spill": "vision.spill_area < 2 cm2"
  },
  {
   "t_complete": "episode.duration < 180 s"
  }
 ]
}
```

## POST /v1/tasks/{task_id}/freeze

Freeze the Task Spec

Freezes the current method as the next immutable revision (`espresso@v1`), mutually signed. Every verification report cites the frozen revision. Changes after a freeze create `@v2`; results across revisions are not silently comparable.

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

Example response (200):

```json
{
 "id": "task_espresso_01",
 "object": "task",
 "name": "espresso",
 "rev": "espresso@v1",
 "status": "frozen",
 "visibility": "private",
 "created": "2026-08-20T09:14:02Z",
 "frozen": "2026-08-24T16:40:11Z",
 "signatures": [
  "acct_acme",
  "roborama"
 ]
}
```
