Skip to main content

Episodes

An episode belongs to a project and contains scenes, creator assignments, and a lifecycle status.

Endpoints overview​

MethodEndpointPermissionDescription
GET/api/episodesauthenticatedList all episodes
GET/api/episodes/project/:projectIdauthenticatedList episodes by project
GET/api/episodes/:idauthenticatedGet episode by ID
GET/api/episodes/rolesauthenticatedGet workflow roles
GET/api/episodes/assignment-templateauthenticatedGet assignment template
PUT/api/episodes/assignment-templatetemplate:editSave assignment template
POST/api/episodesepisode:createCreate an episode
PUT / PATCH/api/episodes/:idepisode:editUpdate an episode
DELETE/api/episodes/:idepisode:deleteDelete an episode
POST/api/episodes/preview/uploadepisode:preview:uploadUpload episode preview video
GET/api/episodes/preview/file/:projectId/:episodeId/preview/:filenameauthenticatedGet preview video file
DELETE/api/episodes/preview/:projectId/:episodeIdepisode:preview:deleteDelete episode preview
POST/api/episodes/import/prepareepisode:importPrepare episode import
POST/api/episodes/importepisode:importImport episode from video
GET/api/episodes/import/:jobId/progressauthenticatedGet import job progress

Endpoints​

List all episodes​

GET /api/episodes β€” Auth required

Supports optional filters. When no params are supplied, all episodes are returned.

Query params (all optional)

ParamTypeDescription
projectIdstringFilter by project UUID
searchstringFull-text search on title
statusstringdraft | active | completed | paused
sortBystringepisodeNumber | title | createdAt | updatedAt
sortOrderstringasc | desc
limitnumberPage size
offsetnumberPage offset

Response β€” 200

{
"episodes": [
{
"id": "ep-uuid-001",
"code": "ep01",
"projectId": "proj-uuid-001",
"episodeNumber": 1,
"title": "Episode 1 β€” The Beginning",
"description": "Pilot episode",
"titleI18n": { "uk": "Π•ΠΏΡ–Π·ΠΎΠ΄ 1", "en": "Episode 1 β€” The Beginning", "es": "Episodio 1" },
"descriptionI18n": { "uk": "ΠŸΡ–Π»ΠΎΡ‚Π½ΠΈΠΉ Π΅ΠΏΡ–Π·ΠΎΠ΄", "en": "Pilot episode", "es": "Episodio piloto" },
"icon": null,
"previewUrl": null,
"targetDuration": 300,
"status": "draft",
"safety": null,
"isLocked": false,
"tasks": [
{
"taskId": "task-uuid",
"status": "to-do",
"roleId": "role-uuid",
"roleName": "Script Writer",
"roleNameI18n": { "uk": "БцСнарист", "en": "Script Writer", "es": "Guionista" },
"userId": "user-uuid",
"userEmail": "writer@example.com",
"userEnName": "Alice",
"userEnSurname": "Brown",
"userUaName": "Аліса",
"userUaSurname": "Π‘Ρ€Π°ΡƒΠ½",
"order": 1
}
],
"createdAt": "2025-01-11T09:00:00.000Z",
"updatedAt": "2025-01-11T09:00:00.000Z",
"approved": false,
"templateId": null
}
],
"total": 1,
"filtered": 1
}

List episodes by project​

GET /api/episodes/project/:projectId β€” Auth required

Response β€” 200

{
"episodes": [ /* same shape as list above */ ],
"total": 3,
"filtered": 3
}

Get episode by ID​

GET /api/episodes/:id β€” Auth required

Response β€” 200 β€” single episode object (same shape as list item)


Get workflow roles​

GET /api/episodes/roles β€” Auth required

Returns the list of roles available for episode workflow assignments.

Response β€” 200

[
{ "id": "role-uuid-1", "name": "Script Writer", "nameI18n": { "uk": "БцСнарист", "en": "Script Writer", "es": "Guionista" } },
{ "id": "role-uuid-2", "name": "Editor", "nameI18n": { "uk": "Π Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€", "en": "Editor", "es": "Editor" } }
]

Get assignment template​

GET /api/episodes/assignment-template β€” Auth required

Returns the current global assignment template used when creating new episodes.

Response β€” 200

{
"stages": [
{ "order": 1, "roleId": "role-uuid-1", "roleName": "Script Writer" },
{ "order": 2, "roleId": "role-uuid-2", "roleName": "Editor" }
]
}

Save assignment template​

PUT /api/episodes/assignment-template β€” Auth required, Permission: template:edit

Request body

{
"stages": [
{ "order": 1, "roleId": "role-uuid-1" },
{ "order": 2, "roleId": "role-uuid-2" }
]
}

Response β€” 200 β€” updated template object


Create episode​

POST /api/episodes β€” Auth required, Permission: episode:create

Request body

{
"projectId": "proj-uuid-001",
"title": "Episode 1 β€” The Beginning",
"description": "Pilot episode",
"icon": null,
"targetDuration": 300,
"templateId": "template-uuid"
}
FieldRequiredNotes
projectIdyesUUID of the parent project
titleyesAuto-translated to all locales
descriptionnoAuto-translated if provided
iconno
targetDurationnoDuration in seconds; defaults to 300
templateIdnoIf provided, template scenes/blocks are applied after creation

Response β€” 201 β€” created episode object


Update episode​

PUT /api/episodes/:id or PATCH /api/episodes/:id β€” Auth required, Permission: episode:edit

Request body (all fields optional)

{
"episodeNumber": 2,
"title": "Episode 2",
"description": "Second episode",
"icon": "πŸŽ₯",
"targetDuration": 420,
"status": "active",
"isLocked": false,
"changedBy": "editor@example.com"
}

status values: draft | active | completed | paused

Response β€” 200 β€” updated episode object


Delete episode​

DELETE /api/episodes/:id β€” Auth required, Permission: episode:delete

Response β€” 204


Upload episode preview video​

POST /api/episodes/preview/upload β€” Auth required, multipart/form-data, Permission: episode:preview:upload

Form fields:

FieldTypeRequired
filevideo fileyes
projectIdstring (UUID)yes
episodeIdstring (UUID)yes

Response β€” 201

{ "url": "/api/episodes/preview/file/proj-uuid/ep-uuid/preview/preview.mp4", "filename": "preview.mp4" }

Get episode preview file​

GET /api/episodes/preview/file/:projectId/:episodeId/preview/:filename β€” Auth required

Returns the preview video binary stream.


Delete episode preview​

DELETE /api/episodes/preview/:projectId/:episodeId β€” Auth required, Permission: episode:preview:delete

Response β€” 204


Prepare episode import​

POST /api/episodes/import/prepare β€” Auth required, Permission: episode:import

Reserves a job ID for tracking progress via SSE.

Response β€” 200

{ "jobId": "job-abc123" }

Import episode from video​

POST /api/episodes/import β€” Auth required, multipart/form-data, Permission: episode:import

Transcribes the uploaded video with ElevenLabs, then uses the LLM to generate scenes and blocks. Response is streamed via SSE.

Form fields:

FieldTypeRequired
filevideo fileyes
projectIdstring (UUID)yes
userPromptstringno
jobIdstringno β€” use one from /import/prepare

Response β€” SSE stream of progress events

{ "progress": 50, "stage": "transcribing", "jobId": "job-abc123" }
{ "progress": 100, "stage": "finalizing", "done": true, "episodeId": "ep-uuid" }

Get import job progress​

GET /api/episodes/import/:jobId/progress β€” Auth required

Reconnects to a running SSE stream for the given job.

Response β€” SSE stream (same event shape as /import)