{"info":{"title":"AITuber API","description":"Automate AI video creation with the AITuber API. Go from idea or script to a fully produced video with AI narration (1,300+ voices in 50+ languages), AI-generated visuals, word-synced captions, and smooth transitions. Export to MP4 or publish directly to YouTube, TikTok, Instagram, Facebook, Threads, and X.\n\n**What you can build:**\n- Automated content pipelines that generate and publish videos on a schedule\n- Video creation tools with custom UIs powered by AITuber\n- Batch video generation from spreadsheets, RSS feeds, or databases\n- Internal tools for marketing teams to produce video content at scale\n\n**Authentication:** All endpoints (except voices) require a Bearer token. Create your API key in the [AITuber dashboard](https://app.aituber.app/dashboard/api-keys). Pass it as `Authorization: Bearer ak_...`\n\n**Usage limits:** API usage is bounded by the credits on your plan; every video generation reserves credits up front. There are no separate request-rate limits today. If you plan sustained high-volume traffic, contact support first.","version":"1.0.0"},"servers":[{"url":"https://app.aituber.app/api/v1","description":"AITuber API"}],"security":[{"BearerAuth":[]}],"tags":[{"name":"Voices","description":"Browse ultra-realistic AI voices for video narration. All voices are multilingual and work across any language. Preview audio samples, filter by gender, accent, or use case, and select the perfect voice. The public catalog needs no authentication; your cloned voices do."},{"name":"Videos","description":"Generate complete AI videos from a script or idea. Choose from AI images, AI video clips, stock footage, or talking-head avatars. Poll for generation status and manage your video library."},{"name":"Tools","description":"Content helpers that run before video generation: brainstorm topic ideas for a niche and write full narration scripts from a topic."},{"name":"Styles","description":"Catalogs of the visual and caption styles you can reference when generating videos, including custom styles created in the dashboard."},{"name":"Clips","description":"Standalone AI video clips (1-15 seconds) from a text prompt or images. No narration or captions, just one raw clip. Different models offer different capabilities and costs."},{"name":"Elements","description":"Reusable people, products, and places with a real reference photo. Mention them in scripts as @handle to keep the same face or product consistent across a whole video, or use characters as avatars for talking-head videos."},{"name":"Uploads","description":"Get media files into your AITuber library, from a public URL or a direct upload. Every upload has a purpose that decides where it can be used."},{"name":"UGC","description":"UGC-style hook videos: a person reacting to camera with your hook text on top, optionally over a product demo. Pick a reaction from the library or generate one from your own character."},{"name":"Music","description":"Generate original songs from a prompt, or bring your own uploaded track, then turn either into a music video with AI visuals, synced lyric captions, and a waveform. No talking-head mode."},{"name":"Exports","description":"Render completed videos to downloadable MP4 files in Full HD quality. Exporting is free; credits are only consumed during generation."},{"name":"Subscription","description":"Check your current plan, credit balance, and billing details. Use this to verify available credits before generating videos."},{"name":"Publishing","description":"Publish completed videos to YouTube, TikTok, Instagram, Facebook, Threads, and X. Connect channels via the AITuber dashboard, then use these endpoints to publish programmatically. Requires an active paid subscription with the Publish feature (Creator plan or higher)."}],"openapi":"3.1.1","paths":{"/videos/generate":{"post":{"operationId":"scenes.generate","summary":"Create a new video","description":"Starts generating a new AI video from a script or idea. The video is created in the background and typically takes 1-3 minutes depending on length and media type.\n\n**Two ways to create a video:**\n\n**1. From a script** (you write the narration):\n```json\n{\n  \"script\": \"The human brain is the most complex organ in the body. It contains roughly 86 billion neurons, each connected to thousands of others. Every thought, memory, and emotion is the result of electrical signals racing through this incredible network.\",\n  \"voiceId\": \"nPczCjzI2devNBz1zQrb\",\n  \"imageStyleId\": \"cinematic\"\n}\n```\n\n**2. From an idea** (AI writes the script for you):\n```json\n{\n  \"script\": \"5 mind-blowing facts about black holes\",\n  \"inputType\": \"idea\",\n  \"expectedDurationSeconds\": 60\n}\n```\n\n**Workflow after calling this endpoint:**\n1. You receive a `videoId` with `status: \"pending\"`.\n2. Poll `GET /videos/{videoId}` every 5-10 seconds.\n3. When `status` changes to `completed`, the video is ready.\n4. Call `POST /exports` to render the MP4, then `GET /exports/download` to get the file.\n\n**Credit cost:** Depends on media type, duration, and quality tier. A typical 60-second video with basic quality costs about 50 credits. Check your balance with `GET /subscription` before generating.","tags":["Videos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"script":{"type":"string","minLength":1,"description":"The content for your video. How this field is used depends on `inputType`.\n\n**Script mode** (`inputType: \"script\"`, default): Provide the exact narration text. This is what the voice will speak word-for-word. Must be at least 5 words. Max 30,000 characters (enough for a 20-minute video at normal voice speed). The AI automatically splits it into visual segments and generates matching visuals.\n\n**Visual control:** By default, the AI decides what visuals to show for each part of your narration. For more control, add visual instructions in brackets before each narration segment:\n\n`[A dark forest at night] The wind howled through the trees. [Glowing eyes peering from shadows] Something was watching.`\n\nEach `[bracketed text]` tells the AI exactly what to show for that scene. The text after it is the voiceover.\n\n**Put a real person, product, or place in the video (@mentions):** reference a saved element by its handle, e.g. `[@Dhiva holding @Red-Bottle] Meet the founder who started it all.` The element's reference photo is fed to the image model so the same face or product appears consistently across the whole video. Get handles from `GET /elements`; create new elements with `POST /elements`. Rules: works with `mediaType` `images` and `video`; not with `stock`. The photo decides how the element looks; never describe its appearance in the script. Mentions are spoken as the plain name (the `@` is never read aloud), and unknown handles are treated as plain words.\n\n**Idea mode** (`inputType: \"idea\"`): Provide a short topic or concept. The AI writes a full narration script for you. Keep it under 800 characters. Pair with `expectedDurationSeconds` to control video length.\n\nSupports any language. The voice will speak naturally in whatever language the text is written in."},"inputType":{"enum":["script","idea"],"type":"string","description":"How to interpret the `script` field.\n\n- `script` (default): Your text is the exact narration. You control every word that is spoken.\n- `idea`: You provide a topic and the AI writes an engaging narration script for you. Use `expectedDurationSeconds` to control the target length."},"mediaType":{"enum":["images","video","stock","avatar"],"type":"string","description":"The type of visuals for your video. Each produces a different look and feel.\n\n- `images` (default): AI generates a unique image for each segment, displayed with smooth Ken Burns pan/zoom animation. This is the classic \"faceless narration video\" style used by top YouTube channels. Most popular and cheapest option. Control the look with `imageQuality` and `imageStyleId`.\n- `video`: AI generates short video clips for each segment. More dynamic and cinematic than images, but costs more credits. Also used internally by the `skeleton` and `character` templates.\n- `stock`: Automatically finds and matches real stock footage to each segment. Great for news, educational, and documentary-style content.\n- `avatar`: A talking-head video where an avatar speaks your script. **Requires `avatarId` (from `GET /avatars`) and `voiceId`.** Script mode only (no idea mode), max 5 minutes, aspect ratio `9:16` or `16:9`. Costs ~480 credits per minute of video plus narration, far more than other media types. Generation also takes longer (usually 3-10 minutes).\n\n**For most use cases, leave this as default (`images`) unless you are using a template.** When using `templateId`, the template automatically selects the best media type for you, so you do not need to set `mediaType` separately."},"avatarId":{"type":"string","format":"uuid","description":"**Required when `mediaType` is `\"avatar\"`.** The avatar that speaks your script. Get valid IDs from `GET /avatars` (built-in avatars plus characters created in the dashboard). Ignored for other media types."},"motionPrompt":{"type":"string","maxLength":500,"description":"Optional direction for how the avatar moves and gestures, e.g. \"excited, talking with hands, leaning toward the camera\". Only applies when `mediaType` is `\"avatar\"`."},"voiceId":{"type":"string","description":"The voice ID for narration. Browse all 1,300+ available voices and listen to previews at `GET /voices`, or use one of your cloned voices from `GET /voices/cloned`.\n\nIf omitted, defaults to \"Adam\", a deep, natural American male voice. **Exception: required when `mediaType` is `\"avatar\"`** (no default; pick a voice that fits the avatar, or use its `defaultVoiceId` from `GET /avatars`).\n\nFilter voices by gender, accent, or use case using the `GET /voices` endpoint query parameters. Use the `previewUrl` from each voice to hear a sample before selecting."},"voiceSpeed":{"type":"number","minimum":0.7,"maximum":1.2,"description":"Narration speed multiplier. Range: 0.7 to 1.2.\n\n- `0.7`: 30% slower. Great for educational, meditation, or non-native audiences.\n- `1.0` (default): Natural speed.\n- `1.2`: 20% faster. Great for energetic, hype, or fast-paced content.\n\nMost creators use values between 0.9 and 1.1."},"aspectRatio":{"enum":["9:16","16:9","1:1"],"type":"string","description":"Video dimensions. Choose based on where you plan to publish.\n\n- `9:16` (default): Vertical/portrait. Best for YouTube Shorts, TikTok, and Instagram Reels.\n- `16:9`: Horizontal/landscape. Best for standard YouTube videos and presentations.\n- `1:1`: Square. Best for Instagram feed posts and LinkedIn. Not available for `mediaType: \"avatar\"`."},"expectedDurationSeconds":{"type":"number","minimum":15,"maximum":1200,"description":"Target video duration in seconds. **Required when `inputType` is `\"idea\"`** so the AI knows how long a script to write.\n\nExamples: `30` for a 30-second Short, `60` for a 1-minute video, `180` for a 3-minute video, `600` for a 10-minute video, `1200` for a 20-minute video.\n\n**Max varies by template:**\n- Default faceless template (no `templateId`): **1200 seconds (20 minutes)**\n- `templateId: \"skeleton\"` or `templateId: \"character\"`: **420 seconds (7 minutes)** (these templates have different cost profiles and are not designed for long-form content)\n\nPassing a value above the template-specific cap returns a 400 error. Ignored when `inputType` is `\"script\"` because the duration is determined by the word count."},"imageQuality":{"enum":["basic","good","premium","max"],"type":"string","description":"Image generation quality tier. Only applies when `mediaType` is `\"images\"`. Higher quality produces more detailed, accurate images but costs more credits per image.\n\n- `basic` (default): 1 credit/image. Fast generation. Good for testing and drafts.\n- `good`: 5 credits/image. Better detail and accuracy. Good for most published content.\n- `premium`: 10 credits/image. High detail, very accurate to the script. Great for professional content.\n- `max`: 20 credits/image. Maximum quality. Best for high-production content.\n\nA typical 60-second video has 15-18 images (one every 3-5 seconds), so factor that into credit calculations.\n\nEvery tier can use the reference photo of an @mentioned saved element. Each photo used in a scene adds 3 credits to that scene, on top of the tier price above."},"imageStyleId":{"type":"string","description":"Visual art style for AI-generated images. Only applies when `mediaType` is `\"images\"`. Each style applies a consistent aesthetic across all images in your video.\n\n**Realistic:**\n- `photorealistic` (default): Hyperrealistic photography, DSLR quality.\n- `cinematic`: 35mm film look, dramatic lighting, movie still aesthetic.\n- `vintage-retro`: 1980s VHS aesthetic, neon colors, synthwave vibes.\n- `noir`: Classic black and white film noir, dramatic shadows.\n\n**Illustrated:**\n- `3d-pixar`: 3D Pixar-style cartoon, smooth rounded shapes.\n- `anime`: Japanese anime/manga style, cel-shaded, vibrant colors.\n- `digital-art`: Professional concept art, Artstation quality.\n- `comic-book`: American comic book, bold outlines, halftone shading.\n\n**Artistic:**\n- `pencil-sketch`: Detailed graphite pencil drawing on textured paper.\n- `oil-painting`: Classical oil painting with visible brushstrokes.\n- `watercolor`: Soft watercolor with translucent color washes.\n- `pop-art`: Andy Warhol style, bold primary colors.\n\n**Modern:**\n- `kurzgesagt`: Flat vector educational style (like the YouTube channel).\n- `pixel-art`: Retro 16-bit video game aesthetic.\n- `minimalist`: Clean, simple, lots of white space.\n- `claymation`: Stop-motion clay animation, Aardman-inspired.\n\nAnd 11 more styles. Combine with `imageStyleCustom` for fine-tuning."},"captionStyleId":{"type":"string","description":"Caption (subtitle) visual style. Captions are rendered directly onto the video with word-by-word timing sync.\n\n**Built-in styles:**\n- `wrap-1` (default): Active word highlight with 2-word groups. Most popular style.\n- `hormozi`: Bold uppercase with yellow highlight on black pill. Alex Hormozi inspired.\n- `beast`: Bold Bangers font with letter-spacing bounce animation. MrBeast inspired.\n- `noah`: Bold italic Oswald with colored highlight.\n- `handwritten`: Organic casual style with handwriting font. Personal and authentic.\n- `subtitle`: Clean streaming-style subtitles on a dark bar. Professional and readable.\n- `impact`: Massive bold text, one word at a time. Maximum emphasis.\n- `pop`: Playful spring animation with bouncy words. Fun and energetic.\n- `chronicle`: Ancient serif for history, mythology, and epic stories.\n- `cyber`: Futuristic neon style for sci-fi, tech, and cyberpunk content.\n- `grit`: Raw marker style for true crime, street, and intense stories.\n- `luxe`: Elegant serif for luxury, fashion, and celebrity content.\n- `terminal`: Monospace style for tech, hacker, and AI content.\n\nYou can also create custom caption styles with your own fonts, colors, and animations via the [AITuber dashboard](https://app.aituber.app/dashboard). Use the custom style ID here."},"captionsEnabled":{"type":"boolean","description":"Whether to show captions (subtitles) on the video. Default: `true`.\n\nCaptions are auto-synced word-by-word to the narration. We strongly recommend keeping captions on as they significantly boost engagement, accessibility, and watch time. Set to `false` only for music-only or ambient videos."},"captionPosition":{"type":"string","description":"Vertical position of captions on the video.\n\n- `bottom` (default): Captions at the bottom of the screen.\n- `center`: Captions in the middle of the screen.\n- `top`: Captions at the top of the screen.\n\nNot supported for `mediaType: \"avatar\"` (avatar captions always use the default position)."},"videoQuality":{"type":"string","description":"Video clip generation quality. Only applies when `mediaType` is `\"video\"`.\n\n- `basic`: Fastest generation, lower visual quality.\n- `good` (default): Good balance of quality and speed.\n- `premium`: High quality video clips. Slower generation.\n- `max`: 1080p clips, the sharpest we make. Costs the most per second."},"templateId":{"type":"string","maxLength":50,"description":"Specialized video template that applies a specific visual format and style. Leave empty for standard faceless narration videos (the default).\n\n**Available templates:**\n- `skeleton`: \"What happens if...\" style educational videos with skeleton/X-ray visuals. Uses AI video generation internally. Popular viral format on YouTube Shorts. Example script: `\"What happens if you eat only ice cream for 30 days\"`.\n- `medical`: Medical animation videos with scientifically accurate anatomy, for health education, patient explainers, and clinic content. Works with `mediaType` `images` (default) or `video` only (no stock: stock libraries carry no anatomy footage). Optional curated styles via `imageStyleId`: `medical-3d` (realistic 3D), `medical-translucent` (see-through body), `medical-xray`, `medical-darkstudio` (organ on black), `medical-cartoon` (patient-friendly), or omit for auto. Example idea: `\"How a total knee replacement works, step by step\"`.\n- `character`: Character-driven animated videos. AI generates a consistent character across all scenes and animates them. Uses AI video generation internally. Example script: `\"A robot learns what friendship means on its first day at school\"`.\n\n**Important:** When you set a template, it handles the visual settings for you; just provide your `script` (or `inputType: \"idea\"` with a topic). `skeleton` and `character` also pin `mediaType` automatically. `medical` keeps `mediaType` open: send `images` (default) or `video`; sending `stock` returns a 400.\n\nFor talking-head avatar videos, do NOT use a template: set `mediaType: \"avatar\"` with an `avatarId` instead."}},"required":["script"],"additionalProperties":{}},"examples":{"idea-to-video":{"summary":"Idea to Video (AI writes the script)","description":"Provide a topic and the AI writes an engaging narration, generates images, and produces a complete video.","value":{"script":"5 mind-blowing facts about black holes that will change how you see the universe","inputType":"idea","expectedDurationSeconds":60,"voiceId":"onwK4e9ZLuTAKqWW03F9","imageStyleId":"cinematic","aspectRatio":"9:16"}},"script-to-video":{"summary":"Script to Video (AI video clips)","description":"Provide your own narration script. Uses AI video clips instead of images for more dynamic visuals.","value":{"script":"The human brain is the most complex organ in the body. It contains roughly 86 billion neurons, each connected to thousands of others. Every thought, memory, and emotion is the result of electrical signals racing through this incredible network.","mediaType":"video","voiceId":"nPczCjzI2devNBz1zQrb","aspectRatio":"9:16"}},"skeleton-template":{"summary":"Skeleton Template (\"What happens if...\")","description":"Popular viral format showing skeleton/X-ray educational content. Just provide a topic. Template handles all visual settings.","value":{"script":"What happens if you eat only ice cream for 30 days","inputType":"idea","expectedDurationSeconds":45,"templateId":"skeleton"}},"character-template":{"summary":"Character Template (animated story)","description":"AI generates a consistent character across all scenes and animates them into a story. Works with both scripts and ideas.","value":{"script":"A tiny robot named Bolt wakes up in a junkyard with no memory. He finds a broken compass that points to a glowing mountain in the distance. Along the way, he befriends a stray cat who teaches him what courage means.","templateId":"character","voiceId":"EXAVITQu4vr4xnSDxMaL","aspectRatio":"9:16"}},"avatar-video":{"summary":"Avatar (talking head)","description":"An avatar speaks your script to the camera. Requires avatarId from GET /avatars and a voiceId. Script mode only, max 5 minutes.","value":{"script":"Hey, I am so glad you are here. Today I want to show you three simple habits that completely changed how I work.","mediaType":"avatar","avatarId":"3f2c8a1e-5b6d-4c7e-9f0a-1b2c3d4e5f6a","voiceId":"EXAVITQu4vr4xnSDxMaL","aspectRatio":"9:16","motionPrompt":"warm and friendly, natural hand gestures"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","description":"Unique video identifier. Use this to poll `GET /videos/{id}` for generation status."},"status":{"enum":["pending","processing"],"type":"string","description":"Initial status. Will be `pending` or `processing`."}},"required":["videoId","status"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/videos":{"get":{"operationId":"scenes.list","summary":"List your videos","description":"Returns all videos for your organization, sorted newest first. Use this to browse your video library, check generation statuses, or find a video to export/publish.\n\n**Polling for generation status:** After calling `POST /generate`, poll this endpoint or `GET /videos/{id}` until `status` changes from `processing` to `completed` or `failed`. Typical generation takes 1-3 minutes.","tags":["Videos"],"parameters":[{"name":"limit","in":"query","schema":{"type":"number","minimum":1,"maximum":100,"description":"Maximum number of videos to return per page. Default: 50, max: 100."},"allowEmptyValue":true,"allowReserved":true},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid","description":"Pagination cursor: the `id` of the LAST video from the previous page. Returns videos older than that one. Omit for the first page. An empty array means there are no more videos."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique video identifier. Use this to fetch details, export, or publish."},"title":{"type":"string","description":"Video title. Auto-generated from the script if not provided during creation."},"status":{"enum":["pending","processing","completed","failed"],"type":"string","description":"Current generation status.\n\n- `pending`: Video is queued for generation.\n- `processing`: Video is being generated (audio, images, composition).\n- `completed`: Video is ready to export or publish.\n- `failed`: Generation failed. Check `errorMessage` for details."},"mediaType":{"enum":["images","video","stock","avatar","byov"],"type":"string","description":"Type of visuals used in the video.\n\n- `images`: AI-generated images with Ken Burns animation (most popular).\n- `video`: AI-generated video clips.\n- `stock`: Real stock footage matched to the script.\n- `avatar`: Talking-head avatar video.\n- `byov`: Bring-your-own video clips."},"durationSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Video duration in seconds. Determined by the narration length."},"aspectRatio":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Video aspect ratio.\n\n- `9:16`: Vertical (YouTube Shorts, TikTok, Reels).\n- `16:9`: Horizontal (standard YouTube).\n- `1:1`: Square (Instagram feed)."},"imageQuality":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Image generation quality tier used. Only present for `images` media type.\n\n- `basic`: Fast, low cost.\n- `good`: Better detail.\n- `premium`: High detail.\n- `max`: Maximum quality."},"imageStyleId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Visual art style used for image generation (e.g. `photorealistic`, `anime`, `cinematic`). Only present for `images` media type."},"exportStatus":{"anyOf":[{"enum":["pending","processing","completed","failed"],"type":"string"},{"type":"null"}],"description":"Status of the latest MP4 export. `null` if the video has never been exported.\n\n- `pending`: Export is queued.\n- `processing`: MP4 is being rendered.\n- `completed`: Ready to download via `GET /exports/download?videoId={id}`.\n- `failed`: Export rendering failed. Try exporting again."},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Human-readable error message if `status` is `failed`. `null` otherwise."},"createdAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When the video was created (ISO 8601)."},"updatedAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When the video was last updated (ISO 8601)."}},"required":["id","title","status","mediaType","durationSeconds","aspectRatio","imageQuality","imageStyleId","exportStatus","errorMessage","createdAt","updatedAt"]},"description":"List of videos sorted newest first."}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/videos/{id}":{"get":{"operationId":"scenes.byId","summary":"Get a video by ID","description":"Returns details for a single video. Use this to check generation status after creating a video.\n\n**Polling pattern:** After `POST /generate`, poll this endpoint every 5-10 seconds until `status` is `completed` or `failed`. Typical generation takes 1-3 minutes depending on video length and media type.","tags":["Videos"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The video ID returned from `POST /generate` or `GET /videos`."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"anyOf":[{},{"not":{}}]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]},"delete":{"operationId":"scenes.delete","summary":"Delete a video","description":"Permanently deletes a video and its generated assets. This cannot be undone. Credits spent on generation are not refunded.","tags":["Videos"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"The video ID to delete."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/uploads":{"post":{"operationId":"uploads.create","summary":"Upload a media file","description":"Gets a media file into your AITuber library and returns an `assetId` you can pass to other endpoints. Every upload has a `purpose` that says what the file is for; the purpose decides the validation rules and where the asset can be used.\n\n**Two ways to upload:**\n\n**1. From a URL** (easiest, works from AI agents): pass `sourceUrl` and we download the file for you. Only available for small image purposes (not video).\n\n**2. Direct upload** (for local files): pass `contentType` and `fileSizeBytes` and you get back an `uploadUrl`. PUT your file bytes to that URL within 1 hour (set the same Content-Type header), then use the `assetId`.\n\n**Supported purposes:**\n- `clip-reference-image`, `clip-reference-video`, `clip-reference-audio`: input files for standalone clip generation. Images allow JPEG, PNG, or WebP up to 25MB. Videos allow MP4, MOV, or WebM up to 200MB. Audio allows MP3, WAV, M4A, AAC, OGG, or WebM up to 50MB. Direct upload only.\n- `element-image`: a reference photo for an element (a person, product, or place). JPEG, PNG, or WebP, max 25MB. URL upload allowed. Use the `assetId` in `POST /elements`.\n- `ugc-demo`: a product demo video for a UGC hook video. MP4, MOV, or WebM, max 200MB, up to 3 minutes. Direct upload only. Use the `assetId` as `demoVideoAssetId` in `POST /ugc/videos`.\n- `music`: an audio track to score a music video. MP3, WAV, M4A, or AAC, max 50MB. Direct upload only, and `durationSeconds` is REQUIRED. Use the `assetId` as `musicAssetId` in `POST /music-videos`.\n- `voice-sample`: an audio sample for voice cloning. MP3, WAV, M4A, AAC, OGG, or WebM, max 11MB. Direct upload only. Pass the `assetId` to the voice clone endpoint.\n\nUploads that are never attached to anything are deleted after 7 days.","tags":["Uploads"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"purpose":{"enum":["clip-reference-image","clip-reference-video","clip-reference-audio","element-image","ugc-demo","music","voice-sample","agent-attachment"],"type":"string","description":"What this file is for. Only listed purposes are accepted; each unlocks specific endpoints (see the endpoint description)."},"sourceUrl":{"type":"string","maxLength":2000,"description":"A public URL to download the file from (image purposes only). Use this OR contentType+fileSizeBytes, not both."},"contentType":{"enum":["image/jpeg","image/png","image/webp","video/mp4","video/quicktime","video/webm","audio/mpeg","audio/wav","audio/mp4","audio/x-m4a","audio/aac","audio/mp3","audio/wave","audio/x-wav","audio/ogg","audio/webm"],"type":"string","description":"The file type for a direct upload. Returns an `uploadUrl` to PUT the bytes to. Must match the purpose (image, video, or audio)."},"fileSizeBytes":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"The file size in bytes for a direct upload. Max depends on the purpose (25MB images, 200MB video, 50MB audio)."},"durationSeconds":{"type":"number","minimum":1,"maximum":600,"description":"For video (ugc-demo, 1-180) and audio (music, 1-600) uploads: REQUIRED. The clip or track length in seconds. Used to time the segment."},"videoWidth":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"For video uploads (ugc-demo): the pixel width. Recommended so the demo is framed correctly."},"videoHeight":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"For video uploads (ugc-demo): the pixel height. Recommended so the demo is framed correctly."}},"required":["purpose"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"assetId":{"type":"string","format":"uuid","description":"Pass this to the endpoint that consumes this purpose."},"url":{"type":"string","description":"The public URL the file will be served from."},"uploadUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only for direct uploads: PUT your file bytes here within 1 hour, with the same Content-Type you declared. `null` for URL uploads (already stored)."},"status":{"enum":["ready","awaiting_file"],"type":"string","description":"`ready`: the file is stored and the assetId is usable now. `awaiting_file`: PUT your file to `uploadUrl` first."}},"required":["assetId","url","uploadUrl","status"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/exports":{"post":{"operationId":"exports.create","summary":"Export a video to MP4","description":"Starts rendering a completed video into a downloadable MP4 file. The rendering runs in the background and typically takes 30 seconds to 5 minutes depending on video length.\n\n**Cost:** Free. All credits were already consumed during video generation.\n\n**Requires:** A prior paid subscription.\n\n**After exporting:**\n1. Poll `GET /videos/{id}` and check the `exportStatus` field until it is `completed`.\n2. Then call `GET /exports/download?videoId={id}` to get the download URL.","tags":["Exports"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","description":"The ID of the video to export. The video must have `status: completed`."},"resolution":{"enum":["1080p","4k"],"type":"string","default":"1080p","description":"Export resolution.\n\n- `1080p` (default): Full HD (1920x1080 or 1080x1920 for vertical). Fast rendering.\n- `4k`: Ultra HD (3840x2160 or 2160x3840 for vertical). Slower rendering, larger file."}},"required":["videoId"]}}}},"responses":{"200":{"description":"Export started","content":{"application/json":{"schema":{"type":"object","properties":{"exportId":{"type":"string","format":"uuid","description":"Unique export identifier. Use this to track export status."},"videoId":{"type":"string","format":"uuid","description":"The video being exported."},"status":{"enum":["pending","processing","completed","failed"],"type":"string","description":"Export rendering status.\n\n- `pending`: Export is queued.\n- `processing`: Rendering in progress.\n- `completed`: MP4 ready for download.\n- `failed`: Rendering failed."},"resolution":{"type":"string","description":"The resolution requested for this export."},"createdAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When the export was started (ISO 8601)."}},"required":["exportId","videoId","status","resolution","createdAt"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/exports/download":{"get":{"operationId":"exports.download","summary":"Get MP4 download URL","description":"Returns a temporary signed URL to download the rendered MP4 file for a video. Automatically finds the latest completed export for the given video.\n\n**URL expires in 2 minutes.** Start your download immediately after receiving the URL.\n\nYou can pass either a `videoId` (recommended, finds the latest export automatically) or an `exportId` (if you need a specific export).","tags":["Exports"],"parameters":[{"name":"videoId","in":"query","schema":{"type":"string","format":"uuid","description":"The video ID. Finds the latest completed export for this video."},"allowEmptyValue":true,"allowReserved":true},{"name":"exportId","in":"query","schema":{"type":"string","format":"uuid","description":"A specific export ID, returned from `POST /exports`. Usually not needed since `videoId` automatically finds the latest export."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Temporary signed download URL. Expires in 2 minutes."},"videoId":{"type":"string","format":"uuid","description":"The video this download is for."}},"required":["url","videoId"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/subscription":{"get":{"operationId":"billing.subscriptionSummary","summary":"Get plan and credit balance","description":"Returns your current plan and credit balance. Call this before generating videos to check you have enough credits.\n\nPaid plans add credits each billing cycle (monthly or yearly). Credits never expire.\n\n**Upgrading:** To upgrade your plan or purchase additional credits, go to https://app.aituber.app/dashboard/billing","tags":["Subscription"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","description":"Your current plan. Determines feature access and per-cycle credit allocation. Values: \"Free\", \"Hobby\", \"Creator\", \"Growth\", \"Pro\", \"Studio\", \"Agency\", \"Business\", \"Enterprise\"."},"status":{"enum":["active","canceled","past_due","trialing","free"],"type":"string","description":"Subscription status. \"active\" means your plan is fully operational. \"canceled\" means it will end at the current period. \"past_due\" means payment failed (credits still available until resolved). \"trialing\" means you are in a free trial. \"free\" means no paid subscription."},"credits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Credits available to spend right now. Check this before generating a video. If a generation request exceeds your balance, it will return a PAYMENT_REQUIRED error."},"monthlyCredits":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Credits included with your plan each billing cycle (monthly plans bill monthly; yearly plans grant the full year up front). Null on the Free plan."}},"required":["plan","status","credits","monthlyCredits"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/channels":{"get":{"operationId":"socialMedia.listChannels","summary":"List connected social media channels","description":"Returns all connected social media channels (YouTube, TikTok, Instagram, Facebook, Threads, and X) for your organization.\n\n**Note:** Channels must be connected via the AITuber dashboard (OAuth flow). This endpoint is read-only; use it to discover channel IDs for publishing.\n\n**After listing channels:**\nUse the channel `id` values when calling `POST /publications` to publish a video.","tags":["Publishing"],"parameters":[{"name":"platform","in":"query","schema":{"enum":["youtube","tiktok","instagram","facebook","threads","x","all"],"type":"string","description":"Filter by platform. Use \"all\" or omit to list all connected channels."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Channel ID. Use this when publishing."},"platform":{"enum":["youtube","tiktok","instagram","facebook","threads","x"],"type":"string","description":"Social media platform."},"platformChannelId":{"type":"string","description":"Platform-specific channel/account ID."},"channelName":{"type":"string","description":"Display name of the channel or account."},"channelUsername":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Username or handle (e.g. @username)."},"channelThumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Profile picture URL."},"subscriberCount":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Subscriber/follower count. May be null for non-YouTube platforms."},"status":{"enum":["connected","disconnected","token_expired"],"type":"string","description":"Connection status.\n\n- `connected`: Ready to publish.\n- `disconnected`: Channel was disconnected. Reconnect via dashboard.\n- `token_expired`: OAuth token expired. Reconnect via dashboard."},"connectionProvider":{"enum":["direct","managed"],"type":"string","description":"How this channel is connected. `direct` = connected with a Google account (legacy YouTube). `managed` = connected through AITuber managed publishing (current default for all platforms)."},"lastSyncedAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}],"description":"When channel data was last refreshed from the platform."},"createdAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When this connection was created or last migrated."}},"required":["id","platform","platformChannelId","channelName","channelUsername","channelThumbnailUrl","subscriberCount","status","connectionProvider","lastSyncedAt","createdAt"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/publications":{"post":{"operationId":"socialMedia.createPublications","summary":"Publish a video to social media","description":"Publishes a completed video to one or more connected social media channels (YouTube, TikTok, Instagram, Facebook, Threads, and X).\n\n**Prerequisites:**\n1. Connect channels via the AITuber dashboard (cannot be done via API).\n2. Video must have `status: completed` (check via `GET /videos/{id}`).\n3. Active paid subscription with the Publish feature (Creator plan or higher).\n\n**How it works:**\n1. If the video has not been exported to MP4 yet, an export is automatically started.\n2. Once the MP4 is ready, it is uploaded to each selected platform.\n3. Each channel gets its own publication with independent status tracking.\n\n**After publishing:**\nPoll `GET /publications/{publicationId}` for each publication ID until it reaches a terminal state.\nImmediate publishes typically end in `published` or `failed`. Scheduled publishes may enter `scheduled` first, depending on platform behavior.\nTypical time: 2-10 minutes (longer if export is needed first).\n\n**Platform-specific settings:**\nEach entry in the `channels` array can include platform-specific metadata. Only include settings relevant to the channel's platform.\n\n**Cost:** Free. Publishing does not consume credits.","tags":["Publishing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","description":"The video to publish. Must have `status: completed`."},"sceneExportId":{"type":"string","format":"uuid","description":"Optional export ID if the video has already been exported. If omitted, an export is triggered automatically."},"caption":{"type":"string","maxLength":2200,"default":"","description":"Description or long caption used for YouTube, TikTok, Instagram, and Facebook. Max 2200 characters."},"shortCaption":{"type":"string","maxLength":500,"default":"","description":"Short caption shared by X and Threads. It is kept within X's standard weighted 280-character limit. Defaults to `caption` when omitted."},"addMadeWithCaption":{"type":"boolean","default":true,"description":"Add \"Made with AITuber, the AI video generator: aituber.app\" at the end of each caption. Default: true. Each caption is shortened when needed to stay within its platform limit."},"publishNow":{"type":"boolean","default":true,"description":"Set to `true` (default) to publish immediately. Set to `false` and provide `scheduledAt` to schedule."},"scheduledAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}],"default":null,"description":"ISO 8601 datetime to schedule publication. Must be in the future. Only used when `publishNow` is `false`."},"channels":{"type":"array","minItems":1,"items":{"type":"object","properties":{"channelId":{"type":"string","format":"uuid","description":"Channel ID from `GET /channels`. Must have `status: connected`."},"title":{"type":"string","maxLength":100,"description":"Video title (YouTube). Max 100 characters. Defaults to the video title from generation."},"tags":{"type":"array","maxItems":30,"items":{"type":"string","maxLength":100},"description":"YouTube tags for search discovery. Max 30 tags, each up to 100 characters."},"categoryId":{"type":"string","description":"YouTube category ID. Default: \"22\" (People & Blogs). Common: \"24\" Entertainment, \"27\" Education, \"26\" Howto & Style, \"28\" Science & Technology, \"20\" Gaming, \"10\" Music, \"17\" Sports, \"1\" Film & Animation, \"23\" Comedy."},"madeForKids":{"type":"boolean","description":"YouTube COPPA compliance flag. Default: false."},"allowComment":{"type":"boolean","description":"Let viewers comment. Default: true. Only TikTok and X support this. TikTok turns comments off. X has no full off switch, so it limits replies to accounts you mention. Ignored on YouTube, Instagram, Facebook, and Threads."},"tiktokPrivacyStatus":{"enum":["public","friends","private"],"type":"string","description":"Privacy setting. Default: \"public\"."},"allowDuet":{"type":"boolean","description":"Allow duets. Default: true."},"allowStitch":{"type":"boolean","description":"Allow stitches. Default: true."},"isAiGenerated":{"type":"boolean","description":"Label video as AI-generated on TikTok. Default: false."},"instagramPlacement":{"enum":["reels","stories","timeline"],"type":"string","description":"Instagram: where to post. Default: \"reels\"."},"shareToFeed":{"type":"boolean","description":"Instagram: also share Reel to feed. Default: true."}},"required":["channelId"]},"description":"One or more channels to publish to. Each entry can include platform-specific settings."}},"required":["videoId","channels"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"publications":{"type":"array","items":{"type":"object","properties":{"publicationId":{"type":"string","format":"uuid","description":"Publication ID. Poll status with `GET /publications/{publicationId}`."},"channelId":{"type":"string","format":"uuid","description":"The channel this publication targets."},"status":{"enum":["exporting","uploading","scheduled","published","failed","canceled"],"type":"string","description":"Initial status for this publication.\n\n- `exporting`: Waiting for the MP4 export to finish before upload can start.\n- `uploading`: Upload task has been queued or started.\n- `scheduled`: The platform accepted a future publish time.\n- `published`: Upload completed on the platform.\n- `failed`: Something went wrong before or during upload.\n- `canceled`: The scheduled publication was canceled before going live."},"needsExport":{"type":"boolean","description":"Whether this publication is waiting for video export to complete."}},"required":["publicationId","channelId","status","needsExport"]},"description":"One publication record per channel."},"needsExport":{"type":"boolean","description":"Whether a video export had to be started. If true, adds 1-5 minutes before upload begins."}},"required":["publications","needsExport"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/publications/{publicationId}":{"get":{"operationId":"socialMedia.getPublication","summary":"Get publication status","description":"Returns the current status of a publication. Poll this after `POST /publications` to track progress.\n\n**Status flow:** Immediate publishes typically move `exporting` -> `uploading` -> `published` (or `failed` at any stage).\nScheduled publishes may move into `scheduled` first, depending on platform behavior.\n\n**Polling recommendation:** Check every 10-15 seconds until the upload reaches a stable state such as `published`, `scheduled`, or `failed`.","tags":["Publishing"],"parameters":[{"name":"publicationId","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"Publication ID from `POST /publications`."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Publication ID."},"videoId":{"type":"string","format":"uuid","description":"The video ID being published."},"channelId":{"type":"string","format":"uuid","description":"Target channel ID."},"title":{"type":"string","description":"Video title as published."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Description/caption as published."},"status":{"enum":["draft","scheduled","exporting","uploading","published","failed","canceled"],"type":"string","description":"Current publication status.\n\n- `exporting`: Video MP4 is being rendered.\n- `uploading`: Uploading to the platform.\n- `scheduled`: The platform accepted a future publish time and is waiting.\n- `published`: Upload completed on the platform. If `scheduledAt` is in the future, the platform may still be waiting to make it public.\n- `failed`: Something went wrong. Check `errorMessage`.\n- `canceled`: The scheduled publication was canceled before going live."},"platformVideoId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Video ID on the platform (e.g. YouTube video ID). Available after publishing."},"platformVideoUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Direct URL to the published video. Available after publishing."},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Error details if status is `failed`."},"scheduledAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}],"description":"When the video is scheduled to publish. Null if publishing immediately."},"publishedAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}],"description":"When the video was actually published."},"createdAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When the publication was created (ISO 8601)."}},"required":["id","videoId","channelId","title","description","status","platformVideoId","platformVideoUrl","errorMessage","scheduledAt","publishedAt","createdAt"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]},"delete":{"operationId":"socialMedia.cancelPublication","summary":"Cancel a scheduled publication","description":"Cancels a future scheduled publication before it goes live. Already live posts cannot be canceled through this endpoint.","tags":["Publishing"],"parameters":[{"name":"publicationId","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"Publication ID to cancel."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"const":true},"status":{"const":"canceled"}},"required":["success","status"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/ideas":{"post":{"operationId":"ideas.generate","summary":"Get video topic ideas for a niche","description":"Generates a list of specific, viral-style video topic ideas for a niche or audience. Use an idea as the `script` in `POST /videos/generate` with `inputType: \"idea\"`, or expand it first with `POST /scripts`.\n\n**Cost:** 2 credits per call.","tags":["Tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","minLength":3,"maxLength":500,"description":"The niche, audience, or theme to brainstorm for. Example: \"space facts for a faceless YouTube Shorts channel\"."},"language":{"type":"string","minLength":2,"maxLength":3,"default":"en","description":"Language for the ideas (ISO 639-1 code like \"en\", \"es\", \"hi\"). Default: \"en\"."},"count":{"type":"number","minimum":5,"maximum":15,"default":10,"description":"How many ideas to generate (5-15). Default: 10."},"source":{"enum":["tool_page","inline"],"type":"string","description":"Where the request came from, for analytics only. Dashboard use; safe to omit."},"templateId":{"type":"string","maxLength":50,"description":"Creation template the request came from, for analytics only. Dashboard use; safe to omit."}},"required":["prompt"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ideas":{"type":"array","items":{"type":"string"},"description":"Video topic ideas, one per entry."},"creditsUsed":{"type":"number","description":"Credits deducted for this generation."}},"required":["ideas","creditsUsed"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/scripts":{"post":{"operationId":"scripts.generate","summary":"Write a video script from a topic","description":"Generates 2 distinct narration script variations for a topic, sized to your target duration. Pick the one you like (or edit it) and pass it to `POST /videos/generate` as the `script` with `inputType: \"script\"`.\n\n**Cost:** 1 credit per minute of target duration (minimum 1 credit).","tags":["Tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","minLength":3,"maxLength":1000,"description":"The topic or idea to write a script about. Example: \"5 mind-blowing facts about the deep ocean\"."},"duration":{"type":"number","minimum":15,"maximum":1200,"description":"Target video duration in seconds (15-1200). The script length is sized so narration fits this duration."},"language":{"type":"string","description":"Language for the script (ISO 639-1 code like \"en\", \"es\", \"hi\"). Default: English."},"source":{"enum":["tool_page","inline"],"type":"string","description":"Where the request came from, for analytics only. Dashboard use; safe to omit."},"templateId":{"type":"string","maxLength":50,"description":"Creation template the request came from, for analytics only. Dashboard use; safe to omit."}},"required":["prompt","duration"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"variations":{"type":"array","items":{"type":"object","properties":{"content":{"type":"string","description":"The full narration script as one text block."}},"required":["content"]},"description":"Two distinct script variations for the topic."},"provider":{"type":"string","description":"Which AI model wrote the scripts."},"creditsUsed":{"type":"number","description":"Credits deducted for this generation."},"success":{"type":"boolean"}},"required":["variations","provider","creditsUsed","success"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/elements":{"get":{"operationId":"elements.listPublic","summary":"List your elements","description":"Returns your saved elements: people/characters, products/props, and places, plus the built-in ones. Elements carry a real reference photo.\n\n**How to use them:** mention an element in a video script as `@handle` (for example `[@Dhiva holding @Red-Bottle] Meet the founder...`) and its photo is fed to the image model, so the same face or product appears consistently across the whole video. Characters can also be used as `avatarId` for talking-head videos.\n\nCreate new elements with `POST /elements` or in the AITuber dashboard.","tags":["Elements"],"parameters":[{"name":"type","in":"query","schema":{"enum":["character","prop","location"],"type":"string","description":"Filter by element type. Omit for all."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Element ID. For characters, this is also a valid `avatarId` for avatar videos."},"name":{"type":"string","description":"Element name."},"handle":{"type":"string","description":"Mention this element in a video script as `@handle` to put it in the video."},"type":{"enum":["character","prop","location"],"type":"string","description":"`character` = a person or mascot, `prop` = an object or product, `location` = a place."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional context notes. Appearance always comes from the photo, not from this text."},"custom":{"type":"boolean","description":"True for elements you created, false for built-in ones."},"previewImageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The reference photo."}},"required":["id","name","handle","type","description","custom","previewImageUrl"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]},"post":{"operationId":"elements.createPublic","summary":"Create an element","description":"Saves a reusable element (a person/character, product/prop, or place) with a reference photo.\n\n**Photo source, one of:**\n- `imageUrl`: a public URL; we download and store it.\n- `imageAssetId`: an asset from `POST /uploads` with purpose `element-image`.\n\n**After creating:** mention it in scripts as `@handle` (returned in the response) to put it in faceless videos, or use a character's `id` as `avatarId` for talking-head videos.\n\nThe photo is the single source of truth for how the element looks. Use `description` for context (what it is, when to use it), never for appearance.","tags":["Elements"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Element name, used to build the @handle. Letters, numbers, spaces, and hyphens work best (e.g. \"Dhiva\", \"Red Bottle\")."},"type":{"enum":["character","prop","location"],"type":"string","description":"`character` = a person or mascot (also usable as an avatar), `prop` = an object or product, `location` = a place."},"description":{"type":"string","maxLength":1000,"description":"Optional context notes (what it is, when to use it). Do NOT describe appearance; the photo decides how the element looks."},"imageUrl":{"type":"string","maxLength":2000,"description":"Public URL of the reference photo (JPEG, PNG, or WebP, max 25MB). We download and store it. Use this OR imageAssetId."},"imageAssetId":{"type":"string","format":"uuid","description":"An asset from `POST /uploads` with purpose `element-image`. Use this OR imageUrl."}},"required":["name","type"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Element ID. For characters, this is also a valid `avatarId` for avatar videos."},"name":{"type":"string","description":"Element name."},"handle":{"type":"string","description":"Mention this element in a video script as `@handle` to put it in the video."},"type":{"enum":["character","prop","location"],"type":"string","description":"`character` = a person or mascot, `prop` = an object or product, `location` = a place."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional context notes. Appearance always comes from the photo, not from this text."},"custom":{"type":"boolean","description":"True for elements you created, false for built-in ones."},"previewImageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The reference photo."}},"required":["id","name","handle","type","description","custom","previewImageUrl"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/avatars":{"get":{"operationId":"elements.listAvatars","summary":"List avatars for talking-head videos","description":"Returns every avatar you can use for talking-head videos: built-in avatars available to everyone, plus your own characters.\n\nPass the `id` as `avatarId` in `POST /videos/generate` with `mediaType: \"avatar\"`. Create a new avatar with `POST /elements` (type `character`, with a photo) or in the AITuber dashboard.","tags":["Videos"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Avatar ID. Pass as `avatarId` in POST /videos/generate with `mediaType: \"avatar\"`."},"name":{"type":"string","description":"Display name."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Look description, when set."},"custom":{"type":"boolean","description":"True for avatars you created in the dashboard, false for built-in avatars."},"previewImageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The avatar reference image."},"defaultVoiceId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A voice previously paired with this avatar, when set. You can pass it as `voiceId`, or pick any voice from `GET /voices`."}},"required":["id","name","description","custom","previewImageUrl","defaultVoiceId"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/caption-styles":{"get":{"operationId":"captionStyles.listPublic","summary":"List caption styles","description":"Returns every caption style you can use as `captionStyleId` in `POST /videos/generate`: the built-in styles plus any custom styles created in the AITuber dashboard.","tags":["Styles"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Style ID. Pass as `captionStyleId` in POST /videos/generate."},"name":{"type":"string","description":"Display name."},"description":{"type":"string","description":"What the style looks like and what content it fits."},"custom":{"type":"boolean","description":"True for styles created in your dashboard, false for built-in styles."}},"required":["id","name","description","custom"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/image-styles":{"get":{"operationId":"visualStyles.listPublic","summary":"List image styles","description":"Returns every image style you can use as `imageStyleId` in `POST /videos/generate` (when `mediaType` is `images`): the built-in styles, curated template styles (ids like `medical-xray`, made for `templateId: \"medical\"`), plus any custom styles created in the AITuber dashboard.","tags":["Styles"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Style ID. Pass as `imageStyleId` in POST /videos/generate."},"name":{"type":"string","description":"Display name."},"custom":{"type":"boolean","description":"True for styles created in your dashboard, false for built-in styles."},"previewImageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sample image showing the style, when available."}},"required":["id","name","custom","previewImageUrl"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/voices":{"get":{"operationId":"voices.list","summary":"List available voices","description":"Returns all available AI voices for video narration, sorted by popularity. Use the voice `id` as the `voiceId` parameter when generating a video.\n\n**No authentication required.** This is a public endpoint.\n\n**Multilingual support:** All voices are multilingual and work across any language. Set the `language` parameter when generating a video and the voice will speak naturally in that language. The `optimizedFor` field lists languages where the voice has been specifically fine-tuned for best pronunciation and natural delivery.\n\n**Filtering:** Use query parameters to narrow down voices by gender, accent, age, or use case. Combine multiple filters to find the perfect voice.\n\n**For full details and interactive testing, refer to the [API documentation](https://app.aituber.app/api-docs).**","tags":["Voices"],"parameters":[{"name":"gender","in":"query","schema":{"type":"string","description":"Filter by voice gender. Values: \"male\", \"female\", \"neutral\"."},"allowEmptyValue":true,"allowReserved":true},{"name":"accent","in":"query","schema":{"type":"string","description":"Filter by accent (case-insensitive). Examples: \"American\", \"British\", \"Australian\", \"Indian\"."},"allowEmptyValue":true,"allowReserved":true},{"name":"age","in":"query","schema":{"type":"string","description":"Filter by age group. Values: \"young\", \"middle_aged\", \"old\"."},"allowEmptyValue":true,"allowReserved":true},{"name":"useCase","in":"query","schema":{"type":"string","description":"Filter by recommended use case (case-insensitive). Examples: \"narration\", \"conversational\", \"news\", \"audiobook\", \"social_media\"."},"allowEmptyValue":true,"allowReserved":true},{"name":"language","in":"query","schema":{"type":"string","maxLength":5,"description":"Filter to voices optimized for a specific language (ISO 639-1 code). Examples: \"en\", \"es\", \"fr\", \"hi\", \"zh\"."},"allowEmptyValue":true,"allowReserved":true},{"name":"search","in":"query","schema":{"type":"string","maxLength":100,"description":"Search voices by name or description (case-insensitive). Examples: \"roger\", \"energetic\", \"calm\"."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique voice identifier. Pass this as the `voiceId` parameter when generating a video."},"name":{"type":"string","description":"Voice name (e.g. \"Roger\", \"Sarah\", \"James\")."},"description":{"type":"string","description":"Voice characteristics and style (e.g. \"Laid-Back, Casual, Resonant\")."},"previewUrl":{"type":"string","format":"uri","description":"Audio preview URL (MP3). Play this to hear how the voice sounds before selecting it."},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Voice gender (e.g. \"male\", \"female\", \"neutral\")."},"age":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Approximate age group (e.g. \"young\", \"middle_aged\", \"old\")."},"accent":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Primary accent (e.g. \"American\", \"British\", \"Australian\", \"Indian\"). Not all voices have an accent label."},"useCase":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Recommended use case (e.g. \"narration\", \"conversational\", \"news\", \"audiobook\", \"social_media\"). This is a suggestion; any voice works for any use case."},"optimizedFor":{"type":"array","items":{"type":"string"},"description":"ISO 639-1 language codes where this voice has been specifically fine-tuned for best pronunciation and natural delivery (e.g. [\"en\", \"fr\", \"es\"])."}},"required":["id","name","description","previewUrl","gender","age","accent","useCase","optimizedFor"]},"description":"List of voices sorted by popularity (most popular first)."}}}}},"security":[]}},"/voices/cloned":{"get":{"operationId":"voices.listCloned","summary":"List your cloned voices","description":"Returns the voices you cloned in the AITuber dashboard. Use the `voiceId` value as `voiceId` in `POST /videos/generate` to narrate with your own voice. Voice cloning itself happens in the dashboard.","tags":["Voices"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Internal clone record ID."},"name":{"type":"string","description":"The name you gave this voice."},"voiceId":{"type":"string","description":"Pass this as `voiceId` in POST /videos/generate."},"previewUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Audio sample of the cloned voice, when available."},"createdAt":{"type":"string","description":"When the voice was cloned (ISO 8601)."}},"required":["id","name","voiceId","previewUrl","createdAt"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/ugc/reactions":{"get":{"operationId":"ugcReactions.listVideos","summary":"List UGC reaction clips","description":"Returns short clips of a person reacting to camera, split into `system` (the built-in library) and `custom` (reactions you generated). Pick one by `id` and use it as `reactionId` in `POST /ugc/videos` to build a finished UGC hook video. The name and tags describe the person and the reaction, so you can choose one that fits your hook. For your own reactions, check `status` (`pending`, `processing`, `completed`, or `failed`); built-in reactions are always ready.","tags":["UGC"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"system":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Reaction clip ID. Use as `reactionId` in POST /ugc/videos."},"name":{"type":"string","description":"Describes the person and reaction, e.g. \"A woman in living room giving a mild shock reaction\"."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional longer description of the clip."},"thumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Preview thumbnail URL, when available."},"durationSeconds":{"type":"number","description":"Clip length in seconds."},"tags":{"type":"array","items":{"type":"string"},"description":"Keywords for the reaction (mood, setting, gender)."},"status":{"type":"string","description":"Built-in reactions are always `completed`."},"videoUrl":{"type":"string","description":"The clip URL."}},"required":["id","name","description","thumbnailUrl","durationSeconds","tags","status","videoUrl"]},"description":"Built-in reaction clips shared across all orgs."},"custom":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Reaction clip ID. Use as `reactionId` in POST /ugc/videos."},"name":{"type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"thumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"durationSeconds":{"type":"number"},"tags":{"type":"array","items":{"type":"string"}},"status":{"type":"string","description":"`pending`, `processing`, `completed`, or `failed`. Only `completed` clips are usable."},"videoUrl":{"type":"string","description":"The clip URL (a placeholder until the reaction finishes generating)."}},"required":["id","name","description","thumbnailUrl","durationSeconds","tags","status","videoUrl"]},"description":"Reactions this org generated."}},"required":["system","custom"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]},"post":{"operationId":"ugcReactions.generateReaction","summary":"Generate a UGC reaction clip","description":"Generates a short clip of your character reacting to camera, using image-to-video AI. The character is one of your `character` elements (create one with `POST /elements`).\n\n**Flow:** create the reaction, then poll `GET /ugc/reactions/{id}` until `status` is `completed`. The finished clip also appears in `GET /ugc/reactions` and can be used as `reactionId` in `POST /ugc/videos`.\n\n**Cost:** by quality (see the response `creditsUsed`). Credits are refunded automatically if generation fails.\n\nRequires an active paid subscription.","tags":["UGC"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"avatarImageUrl":{"type":"string","format":"uri","description":"Dashboard use only. Public callers pass `elementId` instead; an avatarImageUrl from the public API must be an AITuber-hosted asset URL."},"elementId":{"type":"string","format":"uuid","description":"The character element to react. Get IDs from `GET /elements` (type `character`) or create one with `POST /elements`."},"avatarId":{"type":"string","format":"uuid","description":"Legacy avatar ID. Prefer `elementId`."},"reactionPrompt":{"type":"string","maxLength":300,"description":"Direct control over the reaction, e.g. \"shocked, eyes wide, leaning back\". Provide this OR hookText."},"hookText":{"type":"string","maxLength":200,"description":"The hook the character is reacting to. The AI turns it into a fitting expression. Provide this OR reactionPrompt."},"quality":{"enum":["good","premium"],"type":"string","default":"good","description":"Generation quality. `premium` costs more and looks better."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"reactionVideoId":{"type":"string","format":"uuid","description":"Poll `GET /ugc/reactions/{id}` until completed."},"status":{"const":"pending"},"creditsUsed":{"type":"number"},"name":{"type":"string","description":"AI-generated name for the reaction."},"tags":{"type":"array","items":{"type":"string"},"description":"AI-generated keywords for the reaction."}},"required":["reactionVideoId","status","creditsUsed","name","tags"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/ugc/videos":{"post":{"operationId":"ugcReactions.generate","summary":"Create a UGC hook video","description":"Builds a finished UGC-style hook video: a person reaction clip with your hook text on top, optionally followed by your product demo video.\n\n**Inputs:**\n- `reactionId`: a clip from `GET /ugc/reactions` (built-in or one you generated).\n- `hookText`: the on-screen hook (5-200 characters).\n- `demoVideoAssetId` (optional): a product demo video uploaded with `POST /uploads` (purpose `ugc-demo`).\n\nReturns a `videoId`. This one is ready immediately (`status: completed`); export it with `POST /exports` and download with `GET /exports/download`, or publish it.\n\n**Cost:** flat fee (see `creditsUsed`). Requires an active paid subscription.","tags":["UGC"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"hookText":{"type":"string","minLength":5,"maxLength":200,"description":"The on-screen hook text (5-200 characters)."},"reactionId":{"type":"string","format":"uuid","description":"A reaction clip from `GET /ugc/reactions`."},"ugcVideoId":{"type":"string","format":"uuid","description":"Dashboard alias for `reactionId`. Public callers use `reactionId`."},"demoVideoAssetId":{"type":"string","format":"uuid","description":"Optional product demo video, uploaded via `POST /uploads` (purpose `ugc-demo`). Plays after the reaction."},"demoVideoUrl":{"type":"string","format":"uri","description":"Dashboard use only. Public callers pass `demoVideoAssetId` instead."},"demoDurationSeconds":{"type":"number","minimum":1,"maximum":180,"description":"Dashboard use only. Required when `demoVideoUrl` is set."},"demoVideoWidth":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Dashboard use only."},"demoVideoHeight":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"exclusiveMinimum":0,"description":"Dashboard use only."},"hookTextPosition":{"enum":["top","center","bottom"],"type":"string","default":"center","description":"Where the hook text sits."},"aspectRatio":{"enum":["9:16","16:9","1:1"],"type":"string","default":"9:16","description":"Video dimensions."},"backgroundMusicId":{"type":"string","format":"uuid","description":"Dashboard use only. Background music track ID."},"backgroundMusicVolume":{"type":"number","minimum":0,"maximum":100,"description":"Dashboard use only. Background music volume (0-100)."},"captionStyleId":{"type":"string","description":"Caption style ID from `GET /caption-styles`. Default: \"tiktok\"."},"title":{"type":"string","maxLength":80,"description":"Optional video title."}},"required":["hookText"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","description":"The finished video. Export with POST /exports, download with GET /exports/download."},"status":{"const":"completed"},"creditsUsed":{"type":"number"},"durationSeconds":{"type":"number"}},"required":["videoId","status","creditsUsed","durationSeconds"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/ugc/reactions/{id}":{"get":{"operationId":"ugcReactions.getReactionStatus","summary":"Get a reaction clip","description":"Returns a reaction you generated. Poll every 10-15 seconds after `POST /ugc/reactions` until `status` is `completed` (then use `videoUrl` or the `id` as `reactionId` in `POST /ugc/videos`) or `failed` (credits are refunded automatically).","tags":["UGC"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"Reaction ID from `POST /ugc/reactions`."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"enum":["pending","processing","completed","failed"],"type":"string"},"name":{"type":"string"},"durationSeconds":{"type":"number"},"videoUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The finished clip URL when `status` is `completed`."},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Why generation failed, when `status` is `failed`."}},"required":["id","status","name","durationSeconds","videoUrl","errorMessage"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/music":{"post":{"operationId":"musicGeneration.createMusicPublic","summary":"Generate a song","description":"Generates an original song from a text prompt using AI. Use it as the soundtrack for a music video (`POST /music-videos`), or download it once ready.\n\n**Flow:** create the song, then poll `GET /music/{id}` until `status` is `completed` (usually 30-90 seconds). The finished track also appears in `GET /music` and can be used as `musicId` in `POST /music-videos`.\n\n**Modes:**\n- Simple (default): describe the song in `prompt` and the AI writes everything (style, and lyrics unless `instrumental`).\n- Custom (`customMode: true`): you control `style`, `title`, and `lyrics` directly. `prompt` is ignored for the words.\n\n**Cost:** a flat fee per song (see the response `creditsUsed`). Credits are refunded automatically if generation fails.","tags":["Music"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","minLength":1,"maxLength":5000,"description":"What the song should be about or sound like, e.g. \"an upbeat indie pop track about summer road trips\". In custom mode this is optional context; the words come from `lyrics` and the sound from `style`."},"instrumental":{"type":"boolean","default":false,"description":"Set true for a track with no vocals or lyrics."},"customMode":{"type":"boolean","default":false,"description":"Set true to control `style`, `title`, and `lyrics` yourself instead of letting the AI decide from `prompt`."},"style":{"type":"string","maxLength":1000,"description":"Custom mode only: the musical style, e.g. \"lo-fi hip hop, mellow, jazzy piano\"."},"title":{"type":"string","maxLength":200,"description":"Custom mode only: the song title."},"lyrics":{"type":"string","maxLength":5000,"description":"Custom mode only: the exact lyrics to sing. Ignored when `instrumental` is true."}},"required":["prompt"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"musicId":{"type":"string","format":"uuid","description":"Poll `GET /music/{id}` until completed, then use as `musicId` in `POST /music-videos`."},"status":{"const":"pending"},"creditsUsed":{"type":"number","description":"Credits reserved for this song. Refunded automatically if generation fails."}},"required":["musicId","status","creditsUsed"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"musicGeneration.listMusicPublic","summary":"List songs","description":"Lists tracks in your music library: songs you generated with `POST /music` and audio you uploaded with `POST /uploads` (purpose `music`). Pick one to score a music video: use a generated song as `musicId` or an uploaded track as `musicAssetId` in `POST /music-videos`.","tags":["Music"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"For generated songs, use as `musicId`; for uploaded tracks, use as `musicAssetId` in POST /music-videos."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Track title, if known."},"durationSeconds":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Track length in seconds, if known."},"status":{"enum":["pending","processing","completed","failed"],"type":"string","description":"Generated songs report progress; uploaded tracks are always `completed`."},"source":{"enum":["generated","uploaded"],"type":"string","description":"`generated` (from POST /music) or `uploaded` (from POST /uploads)."},"audioUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The audio URL when the track is ready."}},"required":["id","title","durationSeconds","status","source","audioUrl"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/music/{id}":{"get":{"operationId":"musicGeneration.getMusicPublic","summary":"Get a song","description":"Returns a song you generated. Poll every 10-15 seconds after `POST /music` until `status` is `completed` (then use `audioUrl`, or the `id` as `musicId` in `POST /music-videos`) or `failed` (credits are refunded automatically).","tags":["Music"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"Song ID from `POST /music`."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"enum":["pending","processing","completed","failed"],"type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The song title when ready."},"durationSeconds":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Track length in seconds when ready."},"audioUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The finished audio URL when `status` is `completed`."},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Why generation failed, when `status` is `failed`."}},"required":["id","status","title","durationSeconds","audioUrl","errorMessage"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/music-videos":{"post":{"operationId":"musicGeneration.createMusicVideoPublic","summary":"Create a music video","description":"Builds a music video: your song plus AI visuals, synced captions, and an optional waveform.\n\n**Pick the song (exactly one):**\n- `musicId`: a completed song from `POST /music` (see `GET /music`).\n- `musicAssetId`: a track you uploaded with `POST /uploads` (purpose `music`).\n\n**Pick the visuals with `visualMode`:**\n- `ai-images`: AI generates a new image every few seconds (set `secondsPerImage`).\n- `ai-video`: AI generates short video clips across the song.\n- `cover-image`: a single still image for the whole song (requires `coverImageAssetId`).\n\nReturns a `videoId` (a video). Poll `GET /videos/{id}` until `status` is `completed`, then export it with `POST /exports` and download with `GET /exports/download`, or publish it.\n\n**Cost:** depends on the visual mode, quality, and song length (see the response `estimatedCredits`). Credits are refunded automatically if generation fails.","tags":["Music"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"musicId":{"type":"string","format":"uuid","description":"A completed song from `POST /music`. Provide this OR `musicAssetId`, not both."},"musicAssetId":{"type":"string","format":"uuid","description":"A track uploaded with `POST /uploads` (purpose `music`). Provide this OR `musicId`, not both."},"visualMode":{"enum":["ai-images","ai-video","cover-image"],"type":"string","description":"`ai-images` (a new AI image every few seconds), `ai-video` (short AI clips), or `cover-image` (one still for the whole song)."},"visualDirection":{"type":"string","maxLength":1000,"description":"Optional art direction for the visuals, e.g. \"neon cyberpunk city at night, moody\". Mention a saved element by @handle (see `GET /elements`) to reuse it, e.g. \"@Robo-Cat on a rooftop\". Its photo is fed to the image model so it looks the same in every scene it appears in. Each mentioned element adds a reference charge per scene for `ai-images`."},"imageStyleId":{"type":"string","description":"Image style for `ai-images`/`ai-video`. Get IDs from `GET /image-styles`."},"imageQuality":{"enum":["basic","good","premium","max"],"type":"string","default":"good","description":"Image quality for `ai-images` (higher costs more)."},"secondsPerImage":{"type":"number","minimum":3,"default":4,"description":"For `ai-images`: how many seconds each image is shown. Fewer seconds means more images and more credits."},"videoQuality":{"enum":["basic","good","premium","max"],"type":"string","default":"basic","description":"Clip quality for `ai-video` (higher costs more)."},"coverImageAssetId":{"type":"string","format":"uuid","description":"For `cover-image` mode: an image uploaded with `POST /uploads` (purpose `element-image`). Required for that mode."},"aspectRatio":{"enum":["9:16","16:9","1:1"],"type":"string","default":"9:16","description":"Video dimensions."},"captionsEnabled":{"type":"boolean","default":true,"description":"Show word-synced lyric captions. Automatically off for instrumental tracks."},"captionStyleId":{"type":"string","description":"Caption style ID from `GET /caption-styles`."},"captionPosition":{"enum":["top","center","bottom"],"type":"string","description":"Where captions sit on screen."},"showWaveform":{"type":"boolean","default":true,"description":"Show an audio waveform animation."},"musicTrimStartSeconds":{"type":"number","minimum":0,"description":"Start the video at this point in the song (seconds). Defaults to the start."},"musicTrimEndSeconds":{"type":"number","exclusiveMinimum":0,"description":"End the video at this point in the song (seconds). Defaults to the full length."}},"required":["visualMode"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","description":"Poll `GET /videos/{id}`. When completed, export with POST /exports."},"status":{"const":"pending"},"estimatedCredits":{"type":"number","description":"Credits reserved. Settled to the actual cost or refunded when generation ends."}},"required":["videoId","status","estimatedCredits"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/clip-models":{"get":{"operationId":"videoClips.listModels","summary":"List clip generation models","description":"Returns the AI video models available for standalone clip generation, with their capabilities (text-to-video, image-to-video, reference images), supported aspect ratios, resolutions, duration limits, and credit cost per second by resolution. Pick a `modelKey` for `POST /clips`.","tags":["Clips"],"parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"modelKey":{"type":"string","description":"Pass this as `modelKey` in POST /clips."},"displayName":{"type":"string","description":"Human-readable model name."},"family":{"type":"string","description":"Model family grouping."},"provider":{"type":"string","description":"The AI provider behind this model."},"modelId":{"type":"string","description":"Provider-side model identifier."},"supportsTextToVideo":{"type":"boolean","description":"Can generate a clip from a text prompt alone."},"supportsImageToVideo":{"type":"boolean","description":"Can animate from a provided image."},"supportedAspectRatios":{"type":"array","items":{"type":"string"},"description":"Valid `aspectRatio` values for this model."},"supportedResolutions":{"type":"array","items":{"type":"string"},"description":"Valid `resolution` values for this model."},"minDurationSeconds":{"type":"number","description":"Minimum clip length in seconds."},"maxDurationSeconds":{"type":"number","description":"Maximum clip length in seconds."},"supportedDurationSeconds":{"type":"array","items":{"type":"number"},"description":"When non-empty, the model only supports these exact durations."},"supportsFirstFrame":{"type":"boolean","description":"Accepts `firstFrameUrl`."},"supportsLastFrame":{"type":"boolean","description":"Accepts `lastFrameUrl`."},"supportsReferenceImages":{"type":"boolean","description":"Accepts `referenceImageUrls`."},"maxReferenceImages":{"type":"number","description":"Maximum number of reference images."},"supportsReferenceVideos":{"type":"boolean"},"maxReferenceVideos":{"type":"number"},"minReferenceVideoDurationSeconds":{"type":"number"},"maxReferenceVideoDurationSeconds":{"type":"number"},"supportsReferenceAudio":{"type":"boolean"},"maxReferenceAudio":{"type":"number"},"maxReferenceAudioDurationSeconds":{"type":"number"},"referenceAudioRequiresVisual":{"type":"boolean"},"maxReferenceFiles":{"type":"number"},"supportsAutoDuration":{"type":"boolean"},"supportsAutoAspectRatio":{"type":"boolean"},"creditsPerSecondByResolution":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"},"description":"Credit cost per second of clip, keyed by resolution."}},"required":["modelKey","displayName","family","provider","modelId","supportsTextToVideo","supportsImageToVideo","supportedAspectRatios","supportedResolutions","minDurationSeconds","maxDurationSeconds","supportedDurationSeconds","supportsFirstFrame","supportsLastFrame","supportsReferenceImages","maxReferenceImages","supportsReferenceVideos","maxReferenceVideos","minReferenceVideoDurationSeconds","maxReferenceVideoDurationSeconds","supportsReferenceAudio","maxReferenceAudio","maxReferenceAudioDurationSeconds","referenceAudioRequiresVisual","maxReferenceFiles","supportsAutoDuration","supportsAutoAspectRatio","creditsPerSecondByResolution"]}}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/clips":{"post":{"operationId":"videoClips.create","summary":"Generate a standalone AI video clip","description":"Starts generating a single AI video clip (1-30 seconds) from a text prompt, an image, or both. This is different from `POST /videos/generate`: no narration, no captions, just one raw clip.\n\n**Flow:** pick a model from `GET /clip-models`, create the clip, then poll `GET /clips/{id}` until `status` is `completed` and download from `outputUrl`. Typical generation takes 1-3 minutes.\n\n**Cost:** per second of clip, by model and resolution (see `creditsPerSecondByResolution` in `GET /clip-models`). Credits are reserved when the clip starts and refunded automatically if generation fails.\n\n**Requires an active paid subscription.**","tags":["Clips"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","maxLength":200,"description":"Optional clip title. Defaults to the start of the prompt."},"modelKey":{"type":"string","description":"The generation model to use. Get valid keys, capabilities, and per-second costs from `GET /clip-models`."},"prompt":{"type":"string","maxLength":2000,"description":"What the clip should show. Required for text-to-video models; optional when animating from images."},"aspectRatio":{"enum":["auto","16:9","9:16","4:3","3:4","1:1","21:9","3:2","2:3","9:21","5:4","4:5"],"type":"string","default":"16:9","description":"Clip dimensions. Check the model's `supportedAspectRatios` from `GET /clip-models`. Default: \"16:9\"."},"resolution":{"type":"string","minLength":1,"maxLength":20,"default":"720p","description":"Output resolution (e.g. \"720p\", \"1080p\"). Check the model's `supportedResolutions`. Higher resolutions cost more credits per second. Default: \"720p\"."},"durationSeconds":{"anyOf":[{"type":"integer","minimum":1,"maximum":30},{"const":"auto"}],"default":5,"description":"Clip length in seconds, or \"auto\" for models that support automatic duration. Default: 5."},"firstFrameUrl":{"type":"string","maxLength":2000,"description":"Public image URL to use as the first frame (image-to-video). Only for models with `supportsFirstFrame`."},"lastFrameUrl":{"type":"string","maxLength":2000,"description":"Public image URL to use as the last frame. Only for models with `supportsLastFrame`."},"referenceImageUrls":{"type":"array","maxItems":30,"items":{"type":"string","maxLength":2000},"description":"Public image URLs used as style/subject references. Only for models with `supportsReferenceImages`; respect `maxReferenceImages`."},"referenceVideoUrls":{"type":"array","maxItems":10,"items":{"type":"string","maxLength":2000},"description":"Public video URLs used for motion, editing, or extension. Check model capabilities first."},"referenceAudioUrls":{"type":"array","maxItems":10,"items":{"type":"string","maxLength":2000},"description":"Public audio URLs used for voice, lip sync, rhythm, or timing. Check model capabilities first."}},"required":["modelKey"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Clip ID. Poll `GET /clips/{id}` until completed."},"status":{"const":"pending","description":"Initial status."},"estimatedCredits":{"type":"number","description":"Credits reserved for this generation."}},"required":["id","status","estimatedCredits"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"videoClips.list","summary":"List your clips","description":"Returns your standalone AI clips, newest first. For the next page, pass the `createdAt` of the last clip as `cursor`. An empty array means there are no more clips.","tags":["Clips"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Maximum clips per page (1-50). Default: 20."},"allowEmptyValue":true,"allowReserved":true},{"name":"cursor","in":"query","schema":{"type":"string","format":"date-time","description":"Pagination cursor: the `createdAt` of the last clip from the previous page. Omit for the first page."},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Clip ID."},"title":{"type":"string","description":"Clip title."},"status":{"type":"string","description":"Generation status: `pending`, `processing`, `completed`, or `failed`."},"modelKey":{"type":"string","description":"The model used."},"aspectRatio":{"type":"string","description":"Clip aspect ratio."},"createdAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When the clip was created. Use the last item's value as the next `cursor`."},"outputUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Download URL for the finished MP4 clip. `null` until completed."},"mediaAssetId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Internal media asset ID."},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Why generation failed, when `status` is `failed`."}},"required":["id","title","status","modelKey","aspectRatio","createdAt","outputUrl","mediaAssetId","errorMessage"]},"description":"Clips sorted newest first."}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}},"/clips/{id}":{"get":{"operationId":"videoClips.byId","summary":"Get a clip by ID","description":"Returns a clip with its generation status. Poll every 10-15 seconds after `POST /clips` until `status` is `completed` (then download from `outputUrl`) or `failed` (see `errorMessage`; credits are refunded automatically).","tags":["Clips"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"Clip ID from `POST /clips`."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Clip ID."},"title":{"type":"string","description":"Clip title."},"status":{"type":"string","description":"Generation status: `pending`, `processing`, `completed`, or `failed`."},"modelKey":{"type":"string","description":"The model used."},"aspectRatio":{"type":"string","description":"Clip aspect ratio."},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Output resolution."},"duration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Clip length in seconds."},"prompt":{"type":"string","description":"The text prompt used, if any."},"referenceFrames":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","description":"Image URL."},"role":{"type":"string","description":"How the image was used: `first_frame`, `last_frame`, or `reference_image`."}},"required":["url","role"]},"description":"Input images used for generation."},"outputUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Download URL for the finished MP4 clip. `null` until `status` is `completed`."},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Why generation failed, when `status` is `failed`."},"createdAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When the clip was created (ISO 8601)."}},"required":["id","title","status","modelKey","aspectRatio","resolution","duration","prompt","referenceFrames","outputUrl","errorMessage","createdAt"]}}}},"401":{"description":"401","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"UNAUTHORIZED"},"status":{"const":401},"message":{"type":"string","default":"Authentication required. Provide a valid API key or session token."},"data":{}},"required":["defined","code","status","message"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"402":{"description":"402","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAYMENT_REQUIRED"},"status":{"const":402},"message":{"type":"string","default":"Not enough credits to perform this action."},"data":{"type":"object","properties":{"creditsRequired":{"type":"number","description":"Credits needed for this operation."},"creditsAvailable":{"type":"number","description":"Credits currently available in your account. May be absent when balance is unknown."}},"required":["creditsRequired"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}},"403":{"description":"403","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"defined":{"const":true},"code":{"const":"PAID_PLAN_REQUIRED"},"status":{"const":403},"message":{"type":"string","default":"This feature requires an active paid subscription."},"data":{"type":"object","properties":{"feature":{"enum":["export","other"],"type":"string","description":"Which gate was hit. \"export\" means MP4 export and download; \"other\" covers the remaining paid-only features. API and MCP clients branch on this instead of parsing the legacy message."}},"required":["feature"]}},"required":["defined","code","status","message","data"]},{"type":"object","properties":{"defined":{"const":false},"code":{"type":"string"},"status":{"type":"number"},"message":{"type":"string"},"data":{}},"required":["defined","code","status","message"]}]}}}}},"security":[{"BearerAuth":[]}]}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key from your AITuber dashboard. Pass as: Authorization: Bearer ak_..."}}}}