API Reference
Episodes
An episode is a time-bounded recording unit within a project — e.g. a robot run, an experiment session.
POST /namespaces/:slug/projects/:projectSlug/episodes
Create or update an episode. If an episode with the same name already exists, it is updated (upsert).
| Property | Value |
|---|---|
| Auth | JWT |
| DB roundtrips | 3–5 |
| # | Query | Condition |
|---|---|---|
| 1 | namespace.findUnique({ slug }) | Always |
| 2 | space.findFirst / space.create | Always (upsert) |
| 3 | node.upsert (per folder segment) | If folder provided |
| 4 | episode.findFirst({ projectId, name }) | Always |
| 5 | episode.create / episode.update | Always |
Params
| Param | Type | Description |
|---|---|---|
slug | string | Namespace slug |
projectSlug | string | Project slug |
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Episode name (unique within space) |
description | string | No | Description |
tags | string[] | No | Tags |
folder | string | No | Folder path (e.g. /experiments/batch-1) — auto-created |
writeProtected | boolean | No | Lock episode for immutability |
metadata | object | No | Arbitrary metadata |
Response 201 (created) / 200 (updated)
{
"episode": {
"id": "episode-id",
"name": "run-042",
"description": null,
"tags": [],
"projectId": "space-id",
"folderId": null,
"writeProtected": false,
"status": "running",
"metadata": null
},
"workspace": { "id": "space-id", "slug": "robotics" },
"folder": null,
"namespace": { "id": "namespace-id", "slug": "alice" }
}Errors
| Status | Condition |
|---|---|
| 400 | name is missing |
| 403 | Existing episode is write-protected |
| 404 | Nameproject not found |
| 410 | Episode was previously deleted |
GET /namespaces/:slug/projects/:projectSlug/episodes
List episodes in a project with pagination.
| Property | Value |
|---|---|
| Auth | JWT |
| DB roundtrips | 4 (3 effective latency) |
| # | Query | Condition | Parallel |
|---|---|---|---|
| 1 | namespace.findUnique({ slug }) | Always | — |
| 2 | space.findFirst({ nameprojectId, slug }) | Always | — |
| 3 | episode.findMany({ projectId }) | Always | ✓ |
| 4 | episode.count({ projectId }) | Always | ✓ |
Params
| Param | Type | Description |
|---|---|---|
slug | string | Namespace slug |
projectSlug | string | Project slug |
Query
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number (1-based) |
pageSize | number | 50 | Items per page (max 200) |
Response 200
{
"episodes": [
{
"id": "episode-id",
"name": "run-042",
"description": null,
"tags": [],
"status": "running",
"writeProtected": false,
"folderId": null,
"createdAt": "2026-04-14T...",
"updatedAt": "2026-04-14T..."
}
],
"page": 1,
"pageSize": 50,
"total": 1,
"totalPages": 1
}Errors
| Status | Condition |
|---|---|
| 404 | Nameproject not found or deleted |
| 404 | Space not found or deleted |
PATCH /namespaces/:slug/projects/:projectSlug/episodes/:episodeName
Update an episode. Write-protected episodes cannot be updated.
| Property | Value |
|---|---|
| Auth | JWT |
| DB roundtrips | 3–5 |
| # | Query | Condition |
|---|---|---|
| 1 | namespace.findUnique({ slug }) | Always |
| 2 | space.findFirst({ nameprojectId, slug }) | Always |
| 3 | episode.findFirst({ projectId, name }) | Always |
| 4 | node.upsert (per folder segment) | If folder provided |
| 5 | episode.update({ id }) | Always |
Params
| Param | Type | Description |
|---|---|---|
slug | string | Namespace slug |
projectSlug | string | Project slug |
episodeName | string | Episode name |
Body (all fields optional)
| Field | Type | Description |
|---|---|---|
name | string | New episode name |
description | string | Description |
tags | string[] | Tags |
status | string | running, completed, failed, archived |
writeProtected | boolean | Lock episode |
folder | string | Folder path — auto-created |
metadata | object | Arbitrary metadata |
Response 200
{
"id": "episode-id",
"name": "run-042",
"description": "Updated description",
"tags": ["batch-1"],
"status": "completed",
"writeProtected": true,
"folderId": "folder-id",
"metadata": null,
"createdAt": "2026-04-14T...",
"updatedAt": "2026-04-14T..."
}Errors
| Status | Condition |
|---|---|
| 403 | Episode is write-protected |
| 404 | Namespace /project / episode not found |