# Create project

Create a new AI-powered video project from a prompt, URL, or script.


---

### Prompt Types
| `promptType` | Description |
|  --- | --- |
| `Prompt` | A free-text description of the video topic (default) |
| `Link` | A public URL — Shuffll scrapes the content and uses it as the basis for the script |
| `Docs` | A Google Docs URL — Shuffll reads the document content |
| `Slides` | A Google Slides URL — Shuffll reads the slide content |
| `Script` | A pre-written script — AI generation is skipped, the script is used as-is |



---

### Scene Media — Fallback System
For each scene, Shuffll fills in media content using the following priority order.
If a source doesn't yield results, it automatically tries the next one.
1. **Your videos**
 (
`customTemplate.scenes[].videosToAdd`
) — Videos you explicitly provide are always used first.
2. **Stock footage**
 — Shuffll searches stock video libraries for footage matching the scene content.
3. **Workspace assets**
 — Shuffll looks in your workspace asset library for relevant clips.
4. **Image → Video animation**
 — A still image is generated (via Stability AI) and animated into a short clip.
5. **AI video generation**
 — A full video clip is generated from scratch based on the scene script.

You can override this default order using `videoSourcesPipeline`. For example, to use only workspace assets and then generate from text, set:

```json
"videoSourcesPipeline": ["workspace_assets", "generate_from_text"]
```
The same fallback logic applies to still images in scene overlays, controlled by `imagesSourcePipeline`.


---

### Missing Images (`toGenerateMissingImages`)
Scene templates can have image slots in their dynamic values. If you don't fill those slots:
- `toGenerateMissingImages: true`
 → Shuffll generates a contextually relevant image using Stability AI.
- `toGenerateMissingImages: false`
 → The slot is left empty (scene renders without the image).



---

### AI Presenter (Avatar)
Set `aiAvatarSettings.avatarId` to use an AI avatar presenter in the video. Get available avatars from `GET /auth/config/ai_avatar_options`.


---

### Webhooks
Set `webhook` to a URL that Shuffll will call when the export completes. The payload sent to your URL will be:

```json
{
  "type": "export",
  "payload": {
    "projectId": "...",
    "projectName": "...",
    "urls": { "uploadPath": "...", "dashPath": "..." },
    "additionalParams": { }
  }
}
```
Use `additionalParams` to embed any custom data (IDs, metadata) you want returned in the webhook payload.
Set `toAutoEnhance: true` and `toAutoExport: true` to fully automate the pipeline: create → enhance → export → webhook, with no polling required.


---

### After creating a project
Project creation is asynchronous. Poll `GET /auth/project/{projectId}/create/status` until the project is ready.
Enhancement runs automatically. Monitor progress with `GET /auth/project/{projectId}/edit/status/enhance`.
When enhancement is complete, trigger export with `POST /auth/project/{projectId}/edit/export`.
For explicit tenant selection, use the organization/workspace-scoped create operation. This route resolves the default workspace. language is an object with code, videoLength is numeric minutes, and omitted automation flags inherit template settings.
For an avatar presenter, set recordingType: avatar as well as aiAvatarSettings.avatarId.

Endpoint: POST /auth/project/create
Version: 1.3.0
Security: ShuffllApiKey

## Description:

  - `Prompt Types` ()
    | `promptType` | Description |
|  --- | --- |
| `Prompt` | A free-text description of the video topic (default) |
| `Link` | A public URL — Shuffll scrapes the content and uses it as the basis for the script |
| `Docs` | A Google Docs URL — Shuffll reads the document content |
| `Slides` | A Google Slides URL — Shuffll reads the slide content |
| `Script` | A pre-written script — AI generation is skipped, the script is used as-is | ---

  - `Scene Media — Fallback System` ()
    For each scene, Shuffll fills in media content using the following priority order.
If a source doesn't yield results, it automatically tries the next one. 1. **Your videos**
 (
`customTemplate.scenes[].videosToAdd`
) — Videos you explicitly provide are always used first.
2. **Stock footage**
 — Shuffll searches stock video libraries for footage matching the scene content.
3. **Workspace assets**
 — Shuffll looks in your workspace asset library for relevant clips.
4. **Image → Video animation**
 — A still image is generated (via Stability AI) and animated into a short clip.
5. **AI video generation**
 — A full video clip is generated from scratch based on the scene script. You can override this default order using `videoSourcesPipeline`. For example, to use only workspace assets and then generate from text, set: ```json
"videoSourcesPipeline": ["workspace_assets", "generate_from_text"]
``` The same fallback logic applies to still images in scene overlays, controlled by `imagesSourcePipeline`. ---

  - `Missing Images (toGenerateMissingImages)` ()
    Scene templates can have image slots in their dynamic values. If you don't fill those slots: - `toGenerateMissingImages: true`
 → Shuffll generates a contextually relevant image using Stability AI.
- `toGenerateMissingImages: false`
 → The slot is left empty (scene renders without the image). ---

  - `AI Presenter (Avatar)` ()
    Set `aiAvatarSettings.avatarId` to use an AI avatar presenter in the video. Get available avatars from `GET /auth/config/ai_avatar_options`. ---

  - `Webhooks` ()
    Set `webhook` to a URL that Shuffll will call when the export completes. The payload sent to your URL will be: ```json
{
  "type": "export",
  "payload": {
    "projectId": "...",
    "projectName": "...",
    "urls": { "uploadPath": "...", "dashPath": "..." },
    "additionalParams": { }
  }
}
``` Use `additionalParams` to embed any custom data (IDs, metadata) you want returned in the webhook payload. Set `toAutoEnhance: true` and `toAutoExport: true` to fully automate the pipeline: create → enhance → export → webhook, with no polling required. ---

  - `After creating a project` ()
    Project creation is asynchronous. Poll `GET /auth/project/{projectId}/create/status` until the project is ready.
Enhancement runs automatically. Monitor progress with `GET /auth/project/{projectId}/edit/status/enhance`.
When enhancement is complete, trigger export with `POST /auth/project/{projectId}/edit/export`. For explicit tenant selection, use the organization/workspace-scoped create operation. This route resolves the default workspace. language is an object with code, videoLength is numeric minutes, and omitted automation flags inherit template settings. For an avatar presenter, set recordingType: avatar as well as aiAvatarSettings.avatarId.

## Security:

  - `ShuffllApiKey` (unknown)
    apiKey in header x-api-key

## Request fields (application/json):

  - `prompt` (string, required)
    The content/topic for your video
    Example: Explore Riot Games' Innovative Player Experiences

  - `promptType` (string)
    How Shuffll should interpret the `prompt` field.
- `Prompt`
 — Free-text topic description (default)
- `Link`
 — A public URL; Shuffll scrapes the page content
- `Docs`
 — A Google Docs URL; Shuffll reads the document
- `Slides`
 — A Google Slides URL; Shuffll reads the slides
- `Script`
 — A fully written script; AI script generation is skipped
    Enum: "Prompt", "Link", "Docs", "Slides", "Script"

  - `language` (object)
    Language for script and voiceover. Use {code:"auto"} to detect from the prompt. A bare string is not supported.
    Example: {"code":"en"}

  - `language.code` (string, required)
    Example: en

  - `videoLength` (number)
    Target duration in minutes; for example 0.5 is approximately 30 seconds. Omitted values inherit template settings.
    Example: 0.5

  - `toneOfVoice` (string)
    Narration tone. Use the `id` value from `GET /auth/config/tone_of_voice`.
    Example: natural

  - `videoTagId` (string)
    Video category. Guides the AI when writing the script and selecting media.
Use the `id` value from `GET /auth/config/video_tags`. Defaults to `explainer` if omitted.
    Example: Marketing

  - `webhook` (string)
    URL to POST to when the project export completes.
See the endpoint description for the full webhook payload format.
    Example: https://your-app.com/hooks/shuffll-export

  - `additionalParams` (object)
    Arbitrary data to embed in the webhook payload (e.g., campaign ID, user ID).
    Example: {"campaignId":"camp_123","userId":"usr_456"}

  - `toAutoEnhance` (boolean)
    Explicitly enable or disable enhancement after creation. If omitted, integration requests inherit the template’s API setting (baseline templates default to true). Set both flags explicitly for predictable automation.
    Example: true

  - `toAutoExport` (boolean)
    Explicitly enable or disable export after enhancement. If omitted, integration requests inherit the template’s API setting (baseline templates default to true). Set both flags explicitly for predictable automation.
    Example: false

  - `aiVoiceSettings` (object)
    AI voiceover configuration. Get available voices from `GET /auth/config/ai_voice_options`.

  - `aiVoiceSettings.voiceId` (string)
    Voice identifier. Use the `id` value from `GET /auth/config/ai_voice_options`.
    Example: alloy

  - `aiVoiceSettings.voiceType` (string)
    Voice provider. Must match the `voiceType` of the chosen voice.
    Enum: "open-ai", "eleven-labs", "gemini", "voicebox"

  - `aiVoiceSettings.voiceSpeed` (number)
    Playback speed multiplier (0.7–1.2). `1.0` is normal speed.
    Example: 1

  - `aiVoiceSettings.voiceInstructions` (string)
    Custom style instructions for the voice model (OpenAI voices only).
Overrides the global tone setting for fine-grained voice control.
    Example: Speak slowly and clearly, with a warm and encouraging tone.

  - `aiAvatarSettings` (object)
    Avatar configuration. Also set recordingType: avatar; avatarId alone does not select avatar mode. Retrieve options from GET /auth/config/ai_avatar_options.

  - `aiAvatarSettings.avatarId` (string)
    Avatar identifier. Use the `id` value from `GET /auth/config/ai_avatar_options`.
    Example: avatar_sarah_001

  - `aiAvatarSettings.aiVoiceId` (string)
    Override the avatar's default voice with a specific voice ID from `GET /auth/config/ai_voice_options`.
    Example: alloy

  - `videoSourcesPipeline` (array)
    Override the default order in which Shuffll sources media for each scene.
Sources are tried in order; the first one that yields results is used.
**Default order:** `["stock_footage", "workspace_assets", "generate_from_image", "generate_from_text"]`
| Value | Description |
|  --- | --- |
| `stock_footage` | Search stock video libraries |
| `workspace_assets` | Use videos from your workspace asset library |
| `generate_from_image` | Generate a still image (Stability AI) then animate it |
| `generate_from_text` | Generate a full video clip from scratch using generative AI |
    Example: ["workspace_assets","stock_footage"]

  - `imagesSourcePipeline` (array)
    Override the default order for sourcing still images used in scene overlays and graphics.
**Default order:** `["stock_footage", "generate_from_text", "workspace_assets"]`
| Value | Description |
|  --- | --- |
| `stock_footage` | Search stock image libraries |
| `generate_from_text` | Generate an image using Stability AI |
| `workspace_assets` | Use images from your workspace asset library |
    Example: ["workspace_assets","generate_from_text"]

  - `customTemplate` (object)
    Template and scene configuration.

  - `customTemplate.id` (string)
    Template ID from `GET /auth/templates`. Omit to use the default template.

  - `customTemplate.description` (string)
    Custom description used as the AI system prompt when generating video scripts.
Overrides the template's stored description regardless of `toUseTemplateDescription`.
Use this to provide brand context, tone guidelines, or audience information that shapes the entire script.
    Example: Shuffll helps marketing teams create professional videos in minutes. Tone: confident, modern, B2B-focused.

  - `customTemplate.toUseTemplateDescription` (boolean)
    When `true`, the template's stored description is used as the AI system prompt.
Ignored if `description` is also provided (explicit description always wins).
    Example: true

  - `customTemplate.flexibilityOverride` (string)
    Controls how strictly the AI follows the template scene structure.
- `rigid`
 — Scene order and types are fixed exactly as in the template
- `minor`
 — Small adaptations allowed (e.g., skipping an empty scene)
- `flexible`
 — AI can freely reorganize or adapt scenes to fit the content

Overrides the flexibility setting stored on the template.
    Enum: "rigid", "minor", "flexible"

  - `customTemplate.assets` (array)
    Media assets (images or videos) to make available for the AI to distribute across scenes.
Each asset in this list is:
1. Validated as a reachable image or video URL
2. Analyzed by AI to generate a description and usage context
3. Downloaded and stored in your workspace under the
**"Api Assets"**
 folder
4. Made available for the AI to intelligently assign to the most relevant scenes

This is the recommended way to bring your own branded media into a project without pre-assigning clips to specific scenes. For explicit scene-level placement, use `scenes[].videosToAdd` instead.

  - `customTemplate.assets.url` (string, required)
    Publicly accessible URL of the image or video asset.
    Example: https://example.com/product-launch.mp4

  - `customTemplate.assets.type` (string)
    Asset media type. If omitted, Shuffll auto-detects from the URL.
    Enum: "image", "video"

  - `customTemplate.assets.description` (string)
    Optional human-provided description of the asset. If omitted, Shuffll generates one automatically using AI.
Providing a description improves the accuracy of scene matching.
    Example: A 30-second product demo showing the dashboard onboarding flow.

  - `customTemplate.assets.direction` (string)
    Optional guidance on how the asset should be used (e.g., which scenes it fits, what mood it conveys).
    Example: Use in the opening scene to establish product credibility.

  - `customTemplate.assets.textHeaderPosition` (number)
    Suggested vertical position for text overlays on this asset (percentage from top).
    Example: 20

  - `customTemplate.videoSourcesByOrder` (array)
    Override the video media fallback pipeline when using a template.
Equivalent to the top-level `videoSourcesPipeline` field — use one or the other, not both.
If omitted, the pipeline configured on the template is used.
    Example: ["workspace_assets","stock_footage"]

  - `customTemplate.imageSourcesByOrder` (array)
    Override the image media fallback pipeline when using a template.
Equivalent to the top-level `imagesSourcePipeline` field — use one or the other, not both.
    Example: ["workspace_assets","generate_from_text"]

  - `customTemplate.fontsSettings` (object)
    Custom font configuration for the video. Overrides the template's default fonts.
Both `primary` and `secondary` must include `family` and `weight` if provided.

  - `customTemplate.fontsSettings.primary` (object)
    Primary font used for main headings and titles.

  - `customTemplate.fontsSettings.primary.family` (string)
    Example: Arimo

  - `customTemplate.fontsSettings.primary.weight` (string)
    Example: 700

  - `customTemplate.fontsSettings.secondary` (object)
    Secondary font used for subheadings and body text.

  - `customTemplate.fontsSettings.secondary.family` (string)
    Example: Arimo

  - `customTemplate.fontsSettings.secondary.weight` (string)
    Example: 400

  - `customTemplate.fontsSettings.remaining` (object | null)
    Font applied to all other text elements not covered by primary or secondary.

  - `customTemplate.fontsSettings.remaining.family` (string)

  - `customTemplate.fontsSettings.remaining.weight` (string)

  - `customTemplate.toUseTemplateFont` (boolean)
    When `true`, use the font settings stored on the template.
Ignored if `fontsSettings` is explicitly provided.
    Example: true

  - `customTemplate.preConfigs` (object)
    Global settings applied across all scenes.

  - `customTemplate.preConfigs.bgMusic` (object)
    Background music settings.

  - `customTemplate.preConfigs.bgMusic.volume` (number)
    Music volume relative to voiceover (0–1). `0.3` is a common value for subtle background music.
    Example: 0.3

  - `customTemplate.preConfigs.bgMusic.path` (string)
    Track path from `GET /auth/config/music-library` (use the `relativePath` field).
    Example: /music/upbeat-corporate.mp3

  - `customTemplate.preConfigs.toCleanAudio` (boolean)
    Automatically remove background noise from audio in user-uploaded videos.
Recommended when your `videosToAdd` clips contain ambient noise.
    Example: false

  - `customTemplate.preConfigs.aiGenerationStability` (number)
    Creativity vs. accuracy tradeoff for AI image generation (0–1).
Lower = more creative/varied; higher = closer to the prompt.
    Example: 0.5

  - `customTemplate.preConfigs.subtitles` (object)
    Subtitle appearance settings.

  - `customTemplate.preConfigs.subtitles.percentOffset` (number)
    Vertical position from the bottom as a percentage (1–100).

  - `customTemplate.preConfigs.subtitles.textSize` (number)
    Subtitle text size.
    Example: 36

  - `customTemplate.preConfigs.subtitles.strategy` (string)
    How text is revealed as it is spoken.
- `FULL_UTTERANCE`
 — Full sentence appears at once
- `WORD_BY_WORD`
 — One word at a time
- `KARAOKE`
 — Words highlight progressively
- `WORD_HIGHLIGHT`
 — Active word is highlighted
    Enum: "FULL_UTTERANCE", "WORD_BY_WORD", "KARAOKE", "WORD_HIGHLIGHT"

  - `customTemplate.preConfigs.subtitles.fontName` (string)
    Subtitle font family name from the configured font catalog.

  - `customTemplate.preConfigs.subtitles.isBold` (boolean)
    Bold subtitle text.

  - `customTemplate.preConfigs.subtitles.primaryColour` (string)
    Primary text color (hex).
    Example: #FFFFFF

  - `customTemplate.preConfigs.subtitles.secondaryColour` (string)
    Shadow/secondary text color (hex).
    Example: #000000

  - `customTemplate.preConfigs.subtitles.outlineColour` (string)
    Text outline color (hex).
    Example: #000000

  - `customTemplate.preConfigs.subtitles.styles` (object)
    Normal and active-word colors. Font and size belong to subtitles.fontName and subtitles.textSize.

  - `customTemplate.preConfigs.subtitles.styles.normal` (object)

  - `customTemplate.preConfigs.subtitles.styles.normal.primaryColour` (string)
    Text color, e.g. #FFFFFF.

  - `customTemplate.preConfigs.subtitles.styles.normal.secondaryColour` (string)
    Secondary text color.

  - `customTemplate.preConfigs.subtitles.styles.highlight` (object)

  - `customTemplate.preConfigs.subtitles.styles.highlight.primaryColour` (string)
    Active-word color, e.g. #FFD700.

  - `customTemplate.preConfigs.subtitles.styles.highlight.secondaryColour` (string)
    Secondary active-word color.

  - `customTemplate.preConfigs.subtitles.alignment` (string)
    Enum: "left", "center", "right"

  - `customTemplate.preConfigs.subtitles.marginL` (number)
    Left margin in marginUnits.

  - `customTemplate.preConfigs.subtitles.marginR` (number)
    Right margin in marginUnits.

  - `customTemplate.preConfigs.subtitles.marginUnits` (string)
    Enum: "px", "percentage"

  - `customTemplate.preConfigs.subtitles.dropShadowEffect` (object)

  - `customTemplate.preConfigs.subtitles.dropShadowEffect.enabled` (boolean)

  - `customTemplate.preConfigs.subtitles.dropShadowEffect.xshad` (number)

  - `customTemplate.preConfigs.subtitles.dropShadowEffect.yshad` (number)

  - `customTemplate.preConfigs.subtitles.dropShadowEffect.blur` (number)

  - `customTemplate.preConfigs.subtitles.dropShadowEffect.color` (string)

  - `customTemplate.preConfigs.subtitles.dropShadowEffect.shouldAffectBoxedText` (boolean)

  - `customTemplate.preConfigs.subtitles.boxHighlight` (object)

  - `customTemplate.preConfigs.subtitles.boxHighlight.enabled` (boolean)

  - `customTemplate.preConfigs.subtitles.boxHighlight.color` (string)

  - `customTemplate.preConfigs.subtitles.boxHighlight.opacity` (number)

  - `customTemplate.preConfigs.subtitles.boxHighlight.paddingX` (number)

  - `customTemplate.preConfigs.subtitles.boxHighlight.paddingY` (number)

  - `customTemplate.preConfigs.subtitles.boxHighlight.borderRadius` (number)

  - `customTemplate.preConfigs.subtitles.boxHighlight.animated` (boolean)

  - `customTemplate.preConfigs.subtitles.boxHighlight.animationDuration` (number)

  - `customTemplate.preConfigs.subtitles.boxHighlight.renderWidthScaleByFont` (object)

  - `customTemplate.scenes` (array)
    Per-scene overrides. Only include scenes you want to customize.
Scenes not listed here are auto-generated using the template and your workspace branding.

  - `customTemplate.scenes.id` (string)
    Scene ID from the template. Get scene IDs from `GET /auth/templates/{templateId}`.

  - `customTemplate.scenes.staticScript` (string)
    Force a fixed voiceover script for this scene, bypassing AI generation.
To render the scene with no voiceover at all, provide a single space `" "`.

  - `customTemplate.scenes.moreDetailsAboutScene` (string)
    Extra guidance for the AI when writing this scene's script.
Example: `"Open with a bold statistic about player retention."`

  - `customTemplate.scenes.toGenerateMissingImages` (boolean)
    When `true`, any image slots in this scene's template layout that are not provided in `dynamicValues` will be auto-generated using Stability AI.
When `false` (default), unfilled image slots are left empty.
    Example: true

  - `customTemplate.scenes.toUseSubtitles` (boolean)
    Enable or disable subtitles for this scene. Overrides the global subtitle setting.

  - `customTemplate.scenes.toMakeVOAsMasterInDefault` (boolean)
    Make the AI voiceover the master audio track, taking priority over any video audio.

  - `customTemplate.scenes.wordBoost` (array)
    Words to boost in speech recognition transcription for this scene.
Use this for product names, brand names, or uncommon terms that the transcription model might mis-hear.
    Example: ["Shuffll","MPEG-DASH","Riot Games"]

  - `customTemplate.scenes.customSpelling` (array)
    Custom spelling corrections for the subtitle transcript of this scene.
Each entry maps a list of heard variations (`from`) to the correct spelling (`to`).
Useful when the AI voiceover or transcription produces a slightly wrong spelling of a proper noun.

  - `customTemplate.scenes.customSpelling.from` (array, required)
    Incorrect or alternative spellings to replace.
    Example: ["Shuffel","Shufflle"]

  - `customTemplate.scenes.customSpelling.to` (string, required)
    The correct spelling.
    Example: Shuffll

  - `customTemplate.scenes.staticText` (array)
    Fixed text values to display in this scene's text elements, used when `toUseStaticText` is `true`.
Provided in order — each string maps to a text element in the scene layout.
    Example: ["Your headline here","Supporting detail line"]

  - `customTemplate.scenes.toUseStaticText` (boolean)
    When `true`, use the strings in `staticText` as the scene's on-screen text instead of AI-generated content.

  - `customTemplate.scenes.punctuationsToRemove` (array)
    Punctuation marks to strip from the subtitle text for this scene.
    Example: [",",".","!"]

  - `customTemplate.scenes.dynamicValues` (array)
    Override specific visual elements in the scene (text, colors, images, logos).
Get the available element types and positions from `GET /auth/templates/{templateId}`.
Common `type` values: `header`, `topic`, `cta`, `website`, `logo`, `image`, `color_fill`, `company`, `tagline`.
    Example: [{"position":0,"type":"header","value":"Innovating Player Experience"},{"position":0,"type":"logo","value":"https://example.com/logo.png"},{"position":0,"type":"website","value":"https://riotgames.com…

  - `customTemplate.scenes.dynamicValues.position` (number)
    Element position index (from the template definition).

  - `customTemplate.scenes.dynamicValues.type` (string)
    Element type (e.g., `header`, `logo`, `image`, `color_fill`).

  - `customTemplate.scenes.dynamicValues.value` (string)
    The value to set for this element.

  - `customTemplate.scenes.videosToAdd` (array)
    Videos to place in this scene. These bypass the media fallback pipeline entirely — provided videos are always used first.
Use `uploadPath` from `GET /auth/organization/{organizationId}/workspace/{workspaceId}/assets` to reference a workspace asset, or provide any publicly accessible URL.
Use `stagePositionNumber` to target a specific layout slot within the scene. Available positions come from `availableStagePositions` in `GET /auth/templates/{templateId}`.

  - `customTemplate.scenes.videosToAdd.url` (string)
    Public video URL. Use `uploadPath` from `GET /auth/organization/{organizationId}/workspace/{workspaceId}/assets` to reference a workspace asset.
    Example: https://content.shuffll.com/workspace/product-demo.mp4

  - `customTemplate.scenes.videosToAdd.stagePositionNumber` (number | null)
    Layout slot to place this video in. Corresponds to the `position` value from `availableStagePositions` in the template.
Pass `null` to use the default (highest available) position.
    Example: 100

  - `customTemplate.scenes.videosToAdd.isMaster` (boolean)
    Marks this as the primary video layer for the scene.
The master video drives timing and is synced with voiceover and subtitles.
Only one video per scene can be master. If none is marked, the longest video is chosen automatically.

  - `customTemplate.scenes.videosToAdd.isMuted` (boolean)
    Mute this video's audio (voiceover will still play over it).

  - `customTemplate.scenes.videosToAdd.toFlip` (boolean)
    Mirror the video horizontally.

  - `customTemplate.scenes.videosToAdd.toAutoTrim` (boolean | null)
    Automatically trim the video to match the scene duration.

  - `customTemplate.scenes.videosToAdd.toUseSubtitles` (boolean)
    Use this video's own subtitles/audio instead of the AI voiceover for this scene.

  - `customTemplate.scenes.videosToAdd.toGenerateSubtitles` (boolean)
    Generate subtitles by transcribing this video's audio track.
Different from `toUseSubtitles` — this transcribes the video's own speech rather than using the AI voiceover.

  - `customTemplate.toReturnAnErrorIfMissingScene` (boolean)
    When `true`, returns a `400` error if a scene ID in `scenes[]` does not exist in the template.
When `false` (default), unrecognized scenes are silently skipped.

  - `storytellingTechnique` (string)
    Storytelling structure for the script. Use the `technique` value from `GET /auth/config/storytelling_techniques`.
    Example: The Before-and-After Transformation

  - `recordingType` (string)
    Use ai-voice for generated narration; omitted values inherit the template.
    Enum: "camera", "mic", "ai-voice", "avatar"

## Request examples:

  - `Full-featured project creation with template, assets, and webhook` (unknown)

## Response 200:

  - `200` (unknown)
    Project created successfully. Returns the project ID.

## Response 200 fields (application/json):

  - `projectId` (string)
    Unique identifier for the created project
    Example: 6947b539cc95ea68854bb523

## Response 400:

  - `400` (unknown)
    Bad request.

## Response 400 fields (application/problem+json):

  - `type` (string)
    Example: object

  - `title` (string)
    Example: Validation failed

  - `message` (string)
    Example: Bad Request

## Response 401:

  - `401` (unknown)
    Unauthorized.

## Response 401 fields (application/problem+json):

  - `type` (string)
    Example: object

  - `title` (string)
    Example: Validation failed

  - `message` (string)
    Example: Bad Request

## Response 200 examples:

  - `Project created successfully` (unknown)

