Skip to main content

Scenes

A scene belongs to an episode and contains an ordered list of scene blocks (dialog or action lines).

Endpoints overview​

MethodEndpointPermissionDescription
GET/api/scenesauthenticatedList all scenes
GET/api/scenes/episode/:episodeIdauthenticatedList scenes by episode
GET/api/scenes/:idauthenticatedGet scene by ID
POST/api/scenesscene:createCreate a scene
PUT / PATCH/api/scenes/:idscene:editUpdate a scene
PUT/api/scenes/episode/:episodeId/reorderscene:editReorder scenes in episode
DELETE/api/scenes/:idscene:deleteDelete a scene
POST/api/scenes/:id/analyze-emotional-arcscene:emotional_arc:generateAnalyze emotional arc
PATCH/api/scenes/:sceneId/assign-locationscene:location:assignAssign location to scene
POST/api/scenes/:sceneId/blocksscene:block:createAdd block
POST/api/scenes/:sceneId/action-dialogscene:block:createAdd action/dialog pair
PUT / PATCH/api/scenes/:sceneId/blocks/:blockIdscene:block:editUpdate block
PUT/api/scenes/:sceneId/blocks/reorderscene:block:editReorder blocks in scene
DELETE/api/scenes/:sceneId/blocks/:blockIdscene:block:deleteDelete block
POST/api/scenes/:sceneId/blocks/:blockId/set-start-framescene:block:editSet start frame (base64)
POST/api/scenes/:sceneId/blocks/:blockId/generate-start-framescene:block:frame:generateGenerate start frame (AI)
POST/api/scenes/:sceneId/blocks/:blockId/generate-start-frame-from-imagesscene:block:frame:generateGenerate start frame from images
POST/api/scenes/:sceneId/blocks/:blockId/generate-end-frame-from-imagesscene:block:frame:generateGenerate end frame from images
DELETE/api/scenes/:sceneId/blocks/:blockId/start-framescene:block:frame:deleteDelete start frame
DELETE/api/scenes/:sceneId/blocks/:blockId/end-framescene:block:frame:deleteDelete end frame
POST/api/scenes/:sceneId/blocks/generate-videoscene:block:video:generateGenerate video for blocks
DELETE/api/scenes/:sceneId/blocks/:blockId/videoscene:block:video:deleteDelete block video

Scene Endpoints​

List all scenes​

GET /api/scenes β€” Auth required

Response β€” 200

{
"scenes": [ /* array of scene objects */ ],
"total": 12
}

List scenes by episode​

GET /api/scenes/episode/:episodeId β€” Auth required

Response β€” 200

{
"scenes": [
{
"id": 1,
"episodeId": "ep-uuid-001",
"title": "Intro scene",
"index": 0,
"status": "draft",
"mood": "cheerful",
"titleI18n": { "uk": "Вступна сцСна", "en": "Intro scene", "es": "Escena introductoria" },
"songsCount": 0,
"actionsCount": 3,
"emotionalArc": ["joy", "surprise", "joy"],
"qualityScore": 0,
"blocks": [],
"duration": 45,
"location": null
}
],
"total": 1
}

Get scene by ID​

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

Response β€” 200 β€” single scene object (same shape as list item, with blocks array populated)

A block in the blocks array:

{
"id": "block-uuid-001",
"sceneId": "1",
"pairId": "pair-uuid",
"type": "dialog",
"text": "Hello, world!",
"characterId": "char-uuid-001",
"emotion": "joy",
"startSec": 0,
"endSec": 3.5,
"soundEffects": [
{
"id": "sound-uuid",
"name": "Fanfare",
"url": "/api/sounds/file/fanfare.mp3",
"duration": 2,
"soundStart": 0,
"soundEnd": 2,
"blockStart": 0,
"blockEnd": 2
}
],
"character": { "id": "char-uuid-001", "name": "Mia" },
"media": [],
"comments": [],
"voiceUrl": null,
"textI18n": { "uk": "ΠŸΡ€ΠΈΠ²Ρ–Ρ‚, світ!", "en": "Hello, world!", "es": "Hola, mundo!" },
"intensity": null,
"startFrameUrl": null,
"endFrameUrl": null,
"startFrameGenerationParams": null,
"endFrameGenerationParams": null,
"videoUrl": null,
"videoGenerationParams": null
}

Create scene​

POST /api/scenes β€” Auth required, Permission: scene:create

Request body

{
"episodeId": "ep-uuid-001",
"title": "Intro scene",
"mood": "cheerful"
}
FieldRequiredNotes
episodeIdyesUUID of the parent episode
titleyesAuto-translated to all locales
moodnoFree-text mood description

Response β€” 201 β€” created scene object


Update scene​

PUT /api/scenes/:id or PATCH /api/scenes/:id β€” Auth required, Permission: scene:edit

Request body (all fields optional)

{
"title": "Updated Scene",
"index": 2,
"status": "approved",
"mood": "tense",
"songsCount": 1,
"actionsCount": 4,
"emotionalArc": ["fear", "hope", "relief"],
"qualityScore": 8.5,
"changedBy": "editor@example.com"
}

status values: draft | approved

Response β€” 200 β€” updated scene object


Reorder scenes in episode​

PUT /api/scenes/episode/:episodeId/reorder β€” Auth required, Permission: scene:edit

Request body

{ "sceneIds": [3, 1, 2] }

Response β€” 200 β€” array of updated scene objects in new order


Delete scene​

DELETE /api/scenes/:id β€” Auth required, Permission: scene:delete

Response β€” 204


Analyze emotional arc​

POST /api/scenes/:id/analyze-emotional-arc β€” Auth required, Permission: scene:emotional_arc:generate

Runs an LLM analysis of the scene's dialog blocks and writes the result to emotionalArc.

Response β€” 200 β€” updated scene object with emotionalArc populated


Assign location to scene​

PATCH /api/scenes/:sceneId/assign-location β€” Auth required, Permission: scene:location:assign

Request body

{ "locationId": "loc-uuid-001" }

Pass null for locationId to clear the assignment.

Response β€” 200 β€” updated scene object with location populated


Scene Blocks​

Add block​

POST /api/scenes/:sceneId/blocks β€” Auth required, Permission: scene:block:create

Request body

{
"type": "dialog",
"text": "Hello, world!",
"pairId": null,
"characterId": "char-uuid-001",
"emotion": "joy",
"startSec": 0,
"endSec": 3.5,
"soundEffects": [],
"media": []
}
FieldRequiredNotes
typeyesdialog | action
textyesBlock content; auto-translated
pairIdnoUUID linking an action+dialog pair
characterIdnoRequired for dialog blocks
emotionnoEmotion name/emoji
startSecnoTimestamp in seconds; defaults to 0
endSecnoTimestamp in seconds; defaults to 0
soundEffectsnoArray of SoundEffectRef objects
medianoArray of BlockMedia objects

Response β€” 201 β€” created block object


Add action/dialog pair​

POST /api/scenes/:sceneId/action-dialog β€” Auth required, Permission: scene:block:create

Creates an action block and a dialog block together as a pair.

Request body

{
"actionText": "The hero steps forward",
"actionStartSec": 0,
"actionEndSec": 2,
"actionSoundEffects": [],
"dialogCharacter": "char-uuid-001",
"dialogText": "I will save you!",
"dialogEmotion": "determination",
"dialogStartSec": 2,
"dialogEndSec": 5
}

Response β€” 201

{
"action": { /* block object */ },
"dialog": { /* block object */ }
}

Update block​

PUT /api/scenes/:sceneId/blocks/:blockId or PATCH /api/scenes/:sceneId/blocks/:blockId β€” Auth required, Permission: scene:block:edit

Request body (all fields optional)

{
"type": "action",
"text": "Updated text",
"pairId": "pair-uuid",
"characterId": "char-uuid-001",
"emotion": "calm",
"startSec": 1.0,
"endSec": 4.5,
"soundEffects": [],
"media": [],
"voiceUrl": "/api/voices/file/proj/ep/scene/voices/take1.mp3",
"changedBy": "editor@example.com"
}

Response β€” 200 β€” updated block object


Reorder blocks in scene​

PUT /api/scenes/:sceneId/blocks/reorder β€” Auth required, Permission: scene:block:edit

Request body

{ "blockIds": ["block-uuid-003", "block-uuid-001", "block-uuid-002"] }

Response β€” 200 β€” array of updated block objects in new order


Delete block​

DELETE /api/scenes/:sceneId/blocks/:blockId β€” Auth required, Permission: scene:block:delete

Response β€” 204


Block Frames​

Set start frame (base64)​

POST /api/scenes/:sceneId/blocks/:blockId/set-start-frame β€” Auth required, Permission: scene:block:edit

Request body

{
"imageBase64": "<base64-encoded-image-data>",
"mimeType": "image/png"
}

Response β€” 200 β€” updated block object with startFrameUrl set


Generate start frame (AI)​

POST /api/scenes/:sceneId/blocks/:blockId/generate-start-frame β€” Auth required, Permission: scene:block:frame:generate

Request body

{
"prompt": "A cheerful girl standing in a sunny meadow",
"width": 832,
"height": 480,
"steps": 28,
"guidanceScale": 3,
"noiseLevel": 0.35,
"seed": 42
}
FieldRequiredDefault
promptyesβ€”
widthno832
heightno480
stepsno28
guidanceScaleno3
noiseLevelno0.35
seednorandom

Response β€” 200 β€” updated block object with startFrameUrl and startFrameGenerationParams


Generate start frame from images​

POST /api/scenes/:sceneId/blocks/:blockId/generate-start-frame-from-images β€” Auth required, Permission: scene:block:frame:generate

Request body

{
"prompt": "Combine these reference images into a new scene",
"image1Base64": "<base64>",
"image2Base64": "<base64>",
"image3Base64": null,
"image4Base64": null,
"image5Base64": null,
"steps": 28,
"guidanceScale": 3,
"width": 832,
"height": 480,
"seed": null
}

image1Base64 is required; image2Base64–image5Base64 are optional.

Response β€” 200 β€” updated block object with startFrameUrl set


Generate end frame from images​

POST /api/scenes/:sceneId/blocks/:blockId/generate-end-frame-from-images β€” Auth required, Permission: scene:block:frame:generate

Same request body shape as generate-start-frame-from-images.

Response β€” 200 β€” updated block object with endFrameUrl set


Delete start frame​

DELETE /api/scenes/:sceneId/blocks/:blockId/start-frame β€” Auth required, Permission: scene:block:frame:delete

Response β€” 200 β€” updated block object with startFrameUrl: null


Delete end frame​

DELETE /api/scenes/:sceneId/blocks/:blockId/end-frame β€” Auth required, Permission: scene:block:frame:delete

Response β€” 200 β€” updated block object with endFrameUrl: null


Block Video​

Generate video for blocks in scene​

POST /api/scenes/:sceneId/blocks/generate-video β€” Auth required, Permission: scene:block:video:generate

Request body

{
"blockId": "block-uuid-001",
"pairId": "pair-uuid",
"prompt": "A girl runs across a meadow in sunlight",
"imageBase64": "<start-frame-base64>",
"image2Base64": "<end-frame-base64>",
"width": 832,
"height": 480,
"duration": 5,
"frameRate": 24,
"steps": 28,
"guidance": 4.0,
"negativePrompt": "",
"useTwoStage": false,
"seed": null
}
FieldRequiredDefault
blockIdyesβ€”
promptyesβ€”
imageBase64yesStart frame
image2Base64yesEnd frame
pairIdno
widthno832
heightno480
durationno5
frameRateno24
stepsno28
guidanceno4.0
negativePromptno""
useTwoStagenofalse
seednorandom

Response β€” 200 β€” updated block object with videoUrl set


Delete block video​

DELETE /api/scenes/:sceneId/blocks/:blockId/video β€” Auth required, Permission: scene:block:video:delete

Response β€” 204