← API Reference

Film Director

Film Director

Film Director is a chat-based tool that generates a storyboard from a creative concept. The AI writes a shot-by-shot breakdown with timing, direction, and dialogue. After generation, you can refine the storyboard inline and persist it as a Filmwork project. The resulting project uses the full Filmwork pipeline for shot production, asset uploads, and roll generation.

Flow overview

StepActionCostEndpoint
1Generate storyboard1-2 creditsPOST /api/chat/stream with activeTool: "film_director"
2aGet refine suggestions (optional)1 creditPOST /api/filmwork/director/refine-suggestions
2bRefine storyboard (optional)1 creditPOST /api/filmwork/director/refine (SSE stream)
3Persist as Filmwork project0-1 creditsPOST /api/filmwork/director/persist

Persist costs 0 credits if storyboard labels are correctly formatted, 1 credit if they need AI repair.

Step 1: Generate storyboard

Request
curl -N https://narrativelion.com/api/chat/stream \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "threadId": "your-thread-uuid",
    "actionId": "unique-action-uuid",
    "event": {
      "type": "user_text",
      "payload": {
        "text": "A delivery robot navigates a cyberpunk city at night",
        "activeTool": "film_director",
        "filmDirectorVideoType": "cinematic",
        "filmDirectorTargetDurationSec": 30,
        "filmDirectorAspectRatio": "9:16",
        "filmDirectorVisualStyle": "Neon noir, rain-slicked streets",
        "filmDirectorPinnedNoteIds": ["note-uuid-1"],
        "filmDirectorInstruction": "Focus on loneliness and scale contrast"
      }
    }
  }'

Payload fields

NameTypeRequiredDescription
activeTool"film_director"RequiredMust be "film_director".
filmDirectorVideoTypeenumRequired"short" | "cinematic" | "animate"
filmDirectorTargetDurationSecnumberRequiredTotal video duration in seconds (positive).
filmDirectorAspectRatiostringRequirede.g. "9:16", "16:9", "1:1"
filmDirectorInstructionstringOptionalCreative brief. Falls back to text field if omitted.
filmDirectorVisualStylestringOptionalVisual style guidance (e.g. "Neon noir").
filmDirectorPinnedNoteIdsstring[]OptionalNote IDs to use as context (max 20). IDs must belong to the account.

SSE response

The stream emits token events with the storyboard markdown, then a complete event. The storyboard draft is in finalMessage. The filmDirectorSetup artifact echoes back the resolved setup — pass it to refine/persist calls.

SSE complete event
event: complete
data: {
  "finalMessage": "# Cyberpunk Delivery\n\n**Summary:** 1 scene, 4 shots, ~30s.\n\n**01A** (5s) — Wide establishing\nRain-soaked city street...",
  "artifacts": {
    "filmDirectorSetup": {
      "videoType": "cinematic",
      "targetDurationSec": 30,
      "aspectRatio": "9:16",
      "visualStyle": "Neon noir, rain-slicked streets",
      "pinnedNoteIds": ["note-uuid-1"],
      "instruction": "Focus on loneliness and scale contrast"
    },
    "ragSources": [
      { "noteId": "note-uuid-1", "noteTitle": "Cyberpunk Reference", "score": 0.85 }
    ]
  }
}

The draft is not saved until you call persist. The storyboard markdown in finalMessage follows the Filmwork storyboard format (**01A** (4s) — Title).

Step 2a: Get refine suggestions (optional)

Request
curl -X POST https://narrativelion.com/api/filmwork/director/refine-suggestions \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "storyboard": "<the storyboard markdown from finalMessage>",
    "setup": { "videoType": "cinematic", "targetDurationSec": 30, ... }
  }'
NameTypeRequiredDescription
storyboardstringRequiredCurrent storyboard markdown (max 50,000 chars).
setupobjectRequiredThe filmDirectorSetup object from the generate step.
Response
{
  "suggestions": [
    { "label": "Add vulnerability moment", "prompt": "Insert a close-up showing..." },
    { "label": "End on recipient reveal", "prompt": "Change the final shot to..." }
  ]
}

Step 2b: Refine storyboard (optional)

Streams a fully revised storyboard markdown (not a diff). Does not persist.

Request
curl -N -X POST https://narrativelion.com/api/filmwork/director/refine \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "currentStoryboard": "<current storyboard markdown>",
    "setup": { "videoType": "cinematic", "targetDurationSec": 30, ... },
    "refinementPrompt": "Add a close-up of the robot's face in shot 02A",
    "pinnedNoteIds": ["note-uuid-1"]
  }'
NameTypeRequiredDescription
currentStoryboardstringRequiredCurrent storyboard markdown.
setupobjectRequiredThe filmDirectorSetup object from the generate step.
refinementPromptstringRequiredWhat to change.
pinnedNoteIdsstring[]OptionalNote IDs for additional context.
SSE event stream
event: token
data: {"content":"# Cyberpunk Delivery (revised)\n\n..."}

event: complete
data: {}

Accumulate token events to get the full revised storyboard. Save it via updateNote or pass to persist.

Step 3: Persist as Filmwork project

Creates a Filmwork note + shot records from the storyboard. Labels are validated against the storyboard format. Malformed labels trigger an AI repair pass (1 credit).

Request
curl -X POST https://narrativelion.com/api/filmwork/director/persist \
  -H "Authorization: Bearer nlk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "draftMarkdown": "# Cyberpunk Delivery\n\n**01A** (5s) — Wide establishing\nRain-soaked city...",
    "setup": {
      "videoType": "cinematic",
      "targetDurationSec": 30,
      "aspectRatio": "9:16",
      "instruction": "A delivery robot navigates a cyberpunk city"
    }
  }'
NameTypeRequiredDescription
draftMarkdownstringRequiredStoryboard markdown from the generate/refine step.
setupobjectRequiredThe filmDirectorSetup object. See setup schema below.
Response
{
  "noteId": "new-filmwork-note-uuid",
  "title": "Cyberpunk Delivery",
  "generatedShots": [],
  "totalShots": 4,
  "remainingShots": 4
}
NameTypeRequiredDescription
noteIdstringRequiredNew Filmwork note UUID.
titlestringOptionalExtracted from the first heading of the storyboard.
totalShotsnumberRequiredNumber of shot labels parsed from the storyboard.
remainingShotsnumberRequiredShots not yet populated with direction/prompts.

Error codes

HTTPCodeDescription
400INVALID_STORYBOARD_FORMATNo shot labels found after AI repair attempt.
400INVALID_PINNED_NOTEA pinned note ID was not found for this account.
429QUOTA_EXCEEDEDCredit limit reached for this billing period.

Setup schema

Used in generate payload fields, refine, and persist. The filmDirectorSetup artifact from the generate step returns this exact shape.

NameTypeRequiredDescription
videoTypeenumRequired"short" | "cinematic" | "animate"
targetDurationSecnumberRequiredTotal duration in seconds (positive).
aspectRatiostringRequirede.g. "9:16", "16:9", "1:1"
instructionstringRequiredCreative brief / concept description.
visualStylestringOptionalVisual style guidance.
pinnedNoteIdsstring[]OptionalNote IDs for context (max 20). Default [].

Important notes

  • Generate uses the chat scope. Refine uses notes:read. Persist uses notes:write.
  • The storyboard uses Filmwork label format: **01A** (4s) — Title. Write correct labels to avoid the 1-credit repair cost.
  • After persisting, use Filmwork GraphQL operations to manage shots, upload assets, and generate rolls.
  • Pinned note IDs are validated on both generate and refine — invalid IDs return an error.