SuperAPI AI Directory

aituber-api

Coding & development

View repository

Updated 10-15 19:53

About this skill

AITuber API

Create AI videos from a script or idea. From 15-second Shorts to 20-minute long-form content. The API handles voice narration (1,300+ voices, any language), AI-generated visuals, word-synced captions, MP4 export, and publishing to YouTube, TikTok, Instagram, Facebook, Threads, and X.

Base URL: https://app.aituber.app/api/v1 OpenAPI spec: https://app.aituber.app/api/v1/openapi.json API docs: https://aituber.app/api

Tip: The endpoint reference and credit costs below are generated from the live API definition, so they match the current API. For interactive exploration and response schemas, use the OpenAPI spec or the docs page.

Authentication

All endpoints except GET /voices require a Bearer token. Create an API key in the AITuber dashboard at https://app.aituber.app/dashboard/api-keys. Keys start with ak_.

Authorization: Bearer <AITUBER_API_KEY>

Store the key in the AITUBER_API_KEY environment variable.

Complete Workflow

AITuber supports two common flows after generation:

  • Export flow: pick voice, generate video, poll status, export, download
  • Publish flow: pick voice, generate video, poll status, list channels, publish, poll publication status

Step 1: Pick a voice

curl "https://app.aituber.app/api/v1/voices?gender=male&accent=American"

No auth required. Returns an array of voice objects. Use the id field as voiceId when generating, or omit voiceId to use the default voice.

Step 2: Generate a video

From a script (you write the narration):

curl -X POST "https://app.aituber.app/api/v1/videos/generate" \
  -H "Authorization: Bearer $AITUBER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "script": "The human brain contains roughly 86 billion neurons. Every thought, memory, and emotion is the result of electrical signals racing through this incredible network.",
    "voiceId": "VOICE_ID_FROM_STEP_1",
    "imageStyleId": "cinematic",
    "aspectRatio": "9:16"
  }'

From an idea (AI writes the script):

curl -X POST "https://app.aituber.app/api/v1/videos/generate" \
  -H "Authorization: Bearer $AITUBER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "script": "5 mind-blowing facts about black holes",
    "inputType": "idea",
    "expectedDurationSeconds": 60
  }'

Returns { "videoId": "uuid", "status": "pending" }.

Video types (all use this same endpoint):

  1. Faceless narration (images) - Default. AI images with Ken Burns animation. Just send a script or idea.
  2. Faceless narration (video clips) - AI video clips. Set mediaType: "video".
  3. Stock footage - Real stock footage matched to narration. Set mediaType: "stock".
  4. Skeleton template - Viral "what happens if..." X-ray style. Set templateId: "skeleton". The template handles mediaType and style.
  5. Character template - Character-driven stories. Set templateId: "character", inputType: "idea". Only idea mode (AI writes the script for character consistency).
  6. Article or link to video - Send a public web page instead of a script. Set inputType: "source" and source: { kind: "url", url: "https://..." }. We fetch and read the page while the video is being made, so script is not needed. expectedDurationSeconds is required.
  7. PDF to video - Send a PDF instead of a script. Upload it first with POST /uploads (purpose: "document-source", PDF only, max 25MB) to get an assetId, then set inputType: "source" and source: { kind: "document", assetId: "..." }. expectedDurationSeconds is required.

For 6 and 7, source.mode decides what happens to the text: summarize (default) writes a short narration faithful to it, read-out speaks the text word for word and treats expectedDurationSeconds as a ceiling. Add source.instructions to steer it, e.g. "focus on the cost section". If you would rather read the page or file yourself, send the text in script instead and give source.title when you know it.

For visual control in script mode, add instructions in brackets: [A dark forest at night] The wind howled through the trees. Each [bracket] tells the AI what to show for that scene.

Step 3: Poll for completion

curl "https://app.aituber.app/api/v1/videos/VIDEO_ID" \
  -H "Authorization: Bearer $AITUBER_API_KEY"

Poll every 5-10 seconds. Generation typically takes 1-3 minutes. Wait until status is completed (or failed).

Step 4: Export to MP4

curl -X POST "https://app.aituber.app/api/v1/exports" \
  -H "Authorization: Bearer $AITUBER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "videoId": "VIDEO_ID", "resolution": "1080p" }'

Exporting is free. Requires an active paid subscription. Poll GET /videos/VIDEO_ID and check exportStatus until it is completed (typically 30 seconds to 5 minutes).

Step 5: Download the MP4

curl "https://app.aituber.app/api/v1/exports/download?videoId=VIDEO_ID" \
  -H "Authorization: Bearer $AITUBER_API_KEY"

Returns { "url": "https://...", "videoId": "..." }. The URL is a signed temporary link that expires in 2 minutes. Download immediately.

Step 6: Publish to connected channels

Publishing requires channels to already be connected in the AITuber dashboard and an active paid subscription with the Publish feature. If the video is not exported yet, the API starts the export automatically (no need to call POST /exports first).

List channels:

curl "https://app.aituber.app/api/v1/channels" \
  -H "Authorization: Bearer $AITUBER_API_KEY"

Publish to YouTube, TikTok, Instagram, Facebook, Threads, and X in one call:

curl -X POST "https://app.aituber.app/api/v1/publications" \
  -H "Authorization: Bearer $AITUBER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "videoId": "VIDEO_ID",
    "caption": "New short is live",
    "shortCaption": "New short is live. What do you think?",
    "publishNow": true,
    "channels": [
      {
        "channelId": "YOUTUBE_CHANNEL_ID",
        "title": "5 Mind-Blowing Facts",
        "tags": ["facts", "science"],
        "categoryId": "27"
      },
      {
        "channelId": "TIKTOK_CHANNEL_ID",
        "tiktokPrivacyStatus": "public",
        "isAiGenerated": true
      },
      {
        "channelId": "INSTAGRAM_CHANNEL_ID",
        "instagramPlacement": "reels"
      },
      { "channelId": "FACEBOOK_CHANNEL_ID" },
      { "channelId": "THREADS_CHANNEL_ID" },
      { "channelId": "X_CHANNEL_ID" }
    ]
  }'

Per-platform channel settings:

  • YouTube: title, tags, categoryId, madeForKids
  • TikTok: tiktokPrivacyStatus, allowDuet, allowStitch, isAiGenerated
  • Instagram: instagramPlacement, shareToFeed
  • TikTok and X: allowComment. No other platform lets us change it.

Poll publication status:

curl "https://app.aituber.app/api/v1/publications/PUBLICATION_ID" \
  -H "Authorization: Bearer $AITUBER_API_KEY"

Poll every 10-15 seconds until the upload reaches a stable state such as published, scheduled, or failed.

Endpoints Reference

GET /voices

Returns all available AI voices for video narration, sorted by popularity. No auth required.

Param Type Required Description
gender string No Filter by voice gender. Values: "male", "female", "neutral".
accent string No Filter by accent (case-insensitive). Examples: "American", "British", "Australian", "Indian".
age string No Filter by age group. Values: "young", "middle_aged", "old".
useCase string No Filter by recommended use case (case-insensitive). Examples: "narration", "conversational", "news", "audiobook", "social_media".
language string No Filter to voices optimized for a specific language (ISO 639-1 code). Examples: "en", "es", "fr", "hi", "zh".
search string No Search voices by name or description (case-insensitive). Examples: "roger", "energetic", "calm".

GET /voices/cloned

Returns the voices you cloned in the AITuber dashboard.

GET /avatars

Returns every avatar you can use for talking-head videos: built-in avatars available to everyone, plus your own characters.

GET /elements

Returns your saved elements: people/characters, products/props, and places, plus the built-in ones.

Param Type Required Description
type character | prop | location No Filter by element type. Omit for all.

POST /elements

Saves a reusable element (a person/character, product/prop, or place) with a reference photo.

Param Type Required Description
name string Yes Element name, used to build the @handle. Letters, numbers, spaces, and hyphens work best (e.g. "Maya", "Red Bottle").
type character | prop | location Yes character = a person or mascot (also usable as an avatar), prop = an object or product, location = a place.
description string No Optional context notes (what it is, when to use it). Do NOT describe appearance; the photo decides how the element looks.
imageUrl string No Public URL of the reference photo (JPEG, PNG, or WebP, max 25MB). We download and store it. Use this OR imageAssetId.
imageAssetId string (uuid) No An asset from POST /uploads with purpose element-image. Use this OR imageUrl.

POST /uploads

Gets a media file into your AITuber library and returns an assetId you can pass to other endpoints.

Param Type Required Description
purpose background-video-library-upload | background-video-upload | clip-reference-image | clip-reference-video | clip-reference-audio | rebuild-still | document-source | element-image | visual-style-reference | ugc-demo | music | voice-sample | agent-attachment Yes What this file is for. Only listed purposes are accepted; each unlocks specific endpoints (see the endpoint description).
sourceUrl string No A public URL to download the file from (image purposes only). Use this OR contentType+fileSizeBytes, not both.
contentType 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 | application/pdf No The file type for a direct upload. Returns an uploadUrl to PUT the bytes to. Must match the purpose (image, video, audio, or document).
fileSizeBytes integer No The file size in bytes for a direct upload. Max depends on the purpose (25MB images, 200MB video, 50MB audio, 25MB documents).
durationSeconds number No 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 integer No For video uploads (ugc-demo): the pixel width. Recommended so the demo is framed correctly.
videoHeight integer No For video uploads (ugc-demo): the pixel height. Recommended so the demo is framed correctly.
fileName string No The name of the file, for display (document-source shows it instead of an id). Directory parts are dropped.

GET /ugc/reactions

Returns short clips of a person reacting to camera, split into system (the built-in library) and custom (reactions you generated).

POST /ugc/reactions

Generates a short clip of your character reacting to camera, using image-to-video AI.

Param Type Required Description
avatarImageUrl string No Dashboard use only. Public callers pass elementId instead; an avatarImageUrl from the public API must be an AITuber-hosted asset URL.
elementId string (uuid) No The character element to react. Get IDs from GET /elements (type character) or create one with POST /elements.
avatarId string (uuid) No Legacy avatar ID. Prefer elementId.
reactionPrompt string No Direct control over the reaction, e.g. "shocked, eyes wide, leaning back". Provide this OR hookText.
hookText string No The hook the character is reacting to. The AI turns it into a fitting expression. Provide this OR reactionPrompt.
quality good | premium No Generation quality. premium costs more and looks better.

GET /ugc/reactions/{id}

Returns a reaction you generated.

Param Type Required Description
id string (uuid) Yes Reaction ID from POST /ugc/reactions.

POST /ugc/videos

Builds a finished UGC-style hook video: a person reaction clip with your hook text on top, optionally followed by your product demo video.

Param Type Required Description
hookText string Yes The on-screen hook text (5-200 characters).
reactionId string (uuid) No A reaction clip from GET /ugc/reactions.
ugcVideoId string (uuid) No Dashboard alias for reactionId. Public callers use reactionId.
demoVideoAssetId string (uuid) No Optional product demo video, uploaded via POST /uploads (purpose ugc-demo). Plays after the reaction.
demoVideoUrl string No Dashboard use only. Public callers pass demoVideoAssetId instead.
demoDurationSeconds number No Dashboard use only. Required when demoVideoUrl is set.
demoVideoWidth integer No Dashboard use only.
demoVideoHeight integer No Dashboard use only.
hookTextPosition top | center | bottom No Where the hook text sits.
aspectRatio 9:16 | 16:9 | 1:1 No Video dimensions.
backgroundMusicId string (uuid) No Dashboard use only. Background music track ID.
backgroundMusicVolume number No Dashboard use only. Background music volume (0-100).
captionStyleId string No Caption style ID from GET /caption-styles. Default: "tiktok".
title string No Optional video title.

POST /music

Generates an original song from a text prompt using AI.

Param Type Required Description
prompt string Yes 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 boolean No Set true for a track with no vocals or lyrics.
customMode boolean No Set true to control style, title, and lyrics yourself instead of letting the AI decide from prompt.
style string No Custom mode only: the musical style, e.g. "lo-fi hip hop, mellow, jazzy piano".
title string No Custom mode only: the song title.
lyrics string No Custom mode only: the exact lyrics to sing. Ignored when instrumental is true.

GET /music

Lists tracks in your music library: songs you generated with POST /music and audio you uploaded with POST /uploads (purpose music).

GET /music/{id}

Returns a song you generated.

Param Type Required Description
id string (uuid) Yes Song ID from POST /music.

POST /music-videos

Builds a music video: your song plus AI visuals, synced captions, and an optional waveform.

Param Type Required Description
musicId string (uuid) No A completed song from POST /music. Provide this OR musicAssetId, not both.
musicAssetId string (uuid) No A track uploaded with POST /uploads (purpose music). Provide this OR musicId, not both.
visualMode ai-images | ai-video | cover-image Yes ai-images (a new AI image every few seconds), ai-video (short AI clips), or cover-image (one still for the whole song).
visualDirection string No 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 string No Image style for ai-images/ai-video. Get IDs from GET /image-styles.
imageQuality basic | good | premium | max No Image quality for ai-images (higher costs more).
secondsPerImage number No For ai-images: how many seconds each image is shown. Fewer seconds means more images and more credits.
videoQuality basic | good | premium | max No Clip quality for ai-video (higher costs more).
coverImageAssetId string (uuid) No For cover-image mode: an image uploaded with POST /uploads (purpose element-image). Required for that mode.
aspectRatio 9:16 | 16:9 | 1:1 No Video dimensions.
captionsEnabled boolean No Show word-synced lyric captions. Automatically off for instrumental tracks.
captionStyleId string No Caption style ID from GET /caption-styles.
captionPosition top | center | bottom No Where captions sit on screen.
showWaveform boolean No Show an audio waveform animation.
musicTrimStartSeconds number No Start the video at this point in the song (seconds). Defaults to the start.
musicTrimEndSeconds number No End the video at this point in the song (seconds). Defaults to the full length.

POST /ideas

Generates a list of specific, viral-style video topic ideas for a niche or audience.

Param Type Required Description
prompt string Yes The niche, audience, or theme to brainstorm for. Example: "space facts for a faceless YouTube Shorts channel".
language string No Language for the ideas (ISO 639-1 code like "en", "es", "hi"). Default: "en".
count number No How many ideas to generate (5-15). Default: 10.
source tool_page | inline No Where the request came from, for analytics only. Dashboard use; safe to omit.
templateId string No Creation template the request came from, for analytics only. Dashboard use; safe to omit.

POST /scripts

Generates 2 distinct narration script variations for a topic, sized to your target duration.

Param Type Required Description
prompt string Yes The topic or idea to write a script about. Example: "5 mind-blowing facts about the deep ocean".
duration number Yes Target video duration in seconds (15-1200). The script length is sized so narration fits this duration.
language string No Language for the script (ISO 639-1 code like "en", "es", "hi"). Default: English.
source tool_page | inline No Where the request came from, for analytics only. Dashboard use; safe to omit.
templateId string No Creation template the request came from, for analytics only. Dashboard use; safe to omit.

GET /image-styles

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.

GET /caption-styles

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.

POST /videos/generate

Starts generating a new AI video from a script, an idea, or the text of an article or document.

Param Type Required Description
thumbnail object No
thumbnail.instructions string No
script string No The content for your video. How this field is used depends on inputType. 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. 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: [A dark forest at night] The wind howled through the trees. [Glowing eyes peering from shadows] Something was watching. Each [bracketed text] tells the AI exactly what to show for that scene. The text after it is the voiceover. Put a real person, product, or place in the video (@mentions): reference a saved element by its handle, e.g. [@Maya 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. 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. Source mode (inputType: "source"): Provide the TEXT of an article, a web page, or a document. It is not the narration. The AI reads it and writes a short narration script from it, faithful to it. Max 200,000 characters. Pair with expectedDurationSeconds (required) to set the script length, and with the source object to say where the text came from. You can skip this field in source mode by sending source.url (a web page) or source.assetId (a PDF you uploaded) instead. We then fetch and read the page or the file while the video is being made, so you do not have to read it yourself. Supports any language. The voice will speak naturally in whatever language the text is written in.
inputType script | idea | source No How to interpret the script field. - script (default): Your text is the exact narration. You control every word that is spoken. - idea: You provide a topic and the AI writes an engaging narration script for you. Use expectedDurationSeconds to control the target length. - source: Here is the text of an article or a document. Write a short video script from it. The AI keeps to that text and invents nothing. expectedDurationSeconds is required, because it sets how long the script is. Send source.url or source.assetId to have us read the page or the PDF for you, or send the text yourself in script.
source object No Where the source text comes from. Only allowed with inputType: "source"; sending it with any other inputType returns a 400. Two ways to use it: send url or assetId and we read the page or the file ourselves (then script is not needed), or read the page yourself and send the text in script.
source.kind url | document No Where the text comes from: url for a web page, document for a file you uploaded.
source.url string No The web page to read. Use with kind: "url". Send this INSTEAD of script and we fetch the page while the video is being made. The page must be public; a page that needs a login cannot be read.
source.assetId string (uuid) No The uploaded PDF to read. Use with kind: "document". Send this INSTEAD of script and we read the file while the video is being made. Upload the file first to get this id.
source.mode summarize | read-out No What to do with the text. - summarize (default): the AI writes a short narration from the text, faithful to it, about expectedDurationSeconds long. - read-out: the text itself is the narration, word for word. Nothing is rewritten and no AI writing step runs. expectedDurationSeconds is the CEILING here: text longer than that is cut at a sentence end, so the video never runs past the length you asked for.
source.title string No Title of the page or the document, when you know it. Ignored when we read the page ourselves.
source.instructions string No What you want done with the source, e.g. "focus on the cost section" or "keep it upbeat". Max 600 characters.
backgroundVideoId string (uuid) No For background mode: an id from GET /background-videos. One clip repeats under the full narration; source audio is muted.
mediaType images | video | stock | background | avatar No The type of visuals for your video. Each produces a different look and feel. - 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. - 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. - stock: Automatically finds and matches real stock footage to each segment. Great for news, educational, and documentary-style content. - 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). 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 string (uuid) No 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 string No 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 string No 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. If 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). Filter 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 number No Narration speed multiplier. Range: 0.7 to 1.2. - 0.7: 30% slower. Great for educational, meditation, or non-native audiences. - 1.0 (default): Natural speed. - 1.2: 20% faster. Great for energetic, hype, or fast-paced content. Most creators use values between 0.9 and 1.1.
aspectRatio 9:16 | 16:9 | 1:1 No Video dimensions. Choose based on where you plan to publish. - 9:16 (default): Vertical/portrait. Best for YouTube Shorts, TikTok, and Instagram Reels. - 16:9: Horizontal/landscape. Best for standard YouTube videos and presentations. - 1:1: Square. Best for Instagram feed posts and LinkedIn. Not available for mediaType: "avatar".
expectedDurationSeconds number No Target video duration in seconds. Required when inputType is "idea" so the AI knows how long a script to write. Examples: 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. Max varies by template: - Default faceless template (no templateId): 1200 seconds (20 minutes) - templateId: "skeleton" or templateId: "character": 420 seconds (7 minutes) (these templates have different cost profiles and are not designed for long-form content) - templateId: "rebuild": 60 seconds (1 minute) Also required when inputType is "source", in both source modes. With source.mode: "summarize" it is the TARGET: the AI writes a script about that long. With source.mode: "read-out" it is the CEILING: the text is read word for word, and anything past that length is cut at a sentence end. Passing 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 basic | good | premium | max No Image generation quality tier. Only applies when mediaType is "images". Higher quality produces more detailed, accurate images but costs more credits per image. - basic (default): 1 credit/image. Fast generation. Good for testing and drafts. - good: 5 credits/image. Better detail and accuracy. Good for most published content. - premium: 10 credits/image. High detail, very accurate to the script. Great for professional content. - max: 20 credits/image. Maximum quality. Best for high-production content. A typical 60-second video has 15-18 images (one every 3-5 seconds), so factor that into credit calculations. Every 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 string No 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. Realistic: - photorealistic (default): Hyperrealistic photography, DSLR quality. - cinematic: 35mm film look, dramatic lighting, movie still aesthetic. - vintage-retro: 1980s VHS aesthetic, neon colors, synthwave vibes. - noir: Classic black and white film noir, dramatic shadows. Illustrated: - 3d-pixar: 3D Pixar-style cartoon, smooth rounded shapes. - anime: Japanese anime/manga style, cel-shaded, vibrant colors. - digital-art: Professional concept art, Artstation quality. - comic-book: American comic book, bold outlines, halftone shading. Artistic: - pencil-sketch: Detailed graphite pencil drawing on textured paper. - oil-painting: Classical oil painting with visible brushstrokes. - watercolor: Soft watercolor with translucent color washes. - pop-art: Andy Warhol style, bold primary colors. Modern: - kurzgesagt: Flat vector educational style (like the YouTube channel). - pixel-art: Retro 16-bit video game aesthetic. - minimalist: Clean, simple, lots of white space. - claymation: Stop-motion clay animation, Aardman-inspired. And 11 more styles. Combine with imageStyleCustom for fine-tuning.
captionStyleId string No Caption (subtitle) visual style. Captions are rendered directly onto the video with word-by-word timing sync. Built-in styles: - wrap-1 (default): Active word highlight with 2-word groups. Most popular style. - cinematic: Thin white text with one key word per phrase in a glowing italic serif. - koe: Small lowercase serif, one quiet phrase at a time. No word highlight. - pill: Black text on a white rounded box, one short phrase at a time. - hormozi: Bold uppercase with yellow highlight on black pill. Alex Hormozi inspired. - beast: Bold Bangers font with letter-spacing bounce animation. MrBeast inspired. - noah: Bold italic Oswald with colored highlight. - handwritten: Organic casual style with handwriting font. Personal and authentic. - subtitle: Clean streaming-style subtitles on a dark bar. Professional and readable. - impact: Massive bold text, one word at a time. Maximum emphasis. - pop: Playful spring animation with bouncy words. Fun and energetic. - chronicle: Ancient serif for history, mythology, and epic stories. - cyber: Futuristic neon style for sci-fi, tech, and cyberpunk content. - grit: Raw marker style for true crime, street, and intense stories. - luxe: Elegant serif for luxury, fashion, and celebrity content. - terminal: Monospace style for tech, hacker, and AI content. You can also create custom caption styles with your own fonts, colors, and animations via the AITuber dashboard. Use the custom style ID here.
captionsEnabled boolean No Whether to show captions (subtitles) on the video. Default: true. Captions 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 string No Vertical position of captions on the video. - bottom (default): Captions at the bottom of the screen. - center: Captions in the middle of the screen. - top: Captions at the top of the screen. Not supported for mediaType: "avatar" (avatar captions always use the default position).
videoQuality string No Video clip generation quality. Only applies when mediaType is "video". - basic: Fastest generation, lower visual quality. - good (default): Good balance of quality and speed. - premium: High quality video clips. Slower generation. - max: 1080p clips, the sharpest we make. Costs the most per second.
templateId string No Specialized video template that applies a specific visual format and style. Leave empty for standard faceless narration videos (the default). Available templates: - 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". - 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". - 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". - rebuild: AI Construction Timelapse. One place changing from messy or empty to finished, in a single locked shot: the camera never moves, so the viewer compares the same frame from the first second to the last. No voiceover and no captions. You hear the sounds of the work, and background music is added over the whole video. The last few seconds always show the finished place in use rather than standing empty. Duration 15-60 seconds. Works from a prompt alone, from beforeImageUrl and afterImageUrl, or from any mix. The prompt must describe a PHYSICAL PLACE that changes; a lecture, a joke, or a product review is rejected. Example idea: "A dirty canal becomes a park with paths and lights". Important: When you set a template, it handles the visual settings for you; just provide your script (or inputType: "idea" with a topic). skeleton, character, and rebuild also pin mediaType automatically. medical keeps mediaType open: send images (default) or video; sending stock returns a 400. For talking-head avatar videos, do NOT use a template: set mediaType: "avatar" with an avatarId instead.
beforeImageUrl string No Public HTTPS image URL used as the FIRST FRAME for templateId: "rebuild". The video starts on this picture and the camera stays at its angle throughout. The place does not have to exist: a photo, a drawing, or a render all work. Uploaded pictures are free and replace a still we would have generated, so they lower the credit cost. Optional. Ignored on other templates.
afterImageUrl string No Public HTTPS image URL used as the LAST FRAME for templateId: "rebuild". The video ends on this picture, at the same camera angle as the rest. Often a render or a drawing of the finished build rather than a photograph, which is fine. Uploaded pictures are free and replace a still we would have generated. Optional. Ignored on other templates.

GET /videos

Returns all videos for your organization, sorted newest first.

Param Type Required Description
limit number No Maximum number of videos to return per page. Default: 50, max: 100.
cursor string (uuid) No 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.

GET /videos/{id}

Returns details for a single video.

Param Type Required Description
id string (uuid) Yes The video ID returned from POST /generate or GET /videos.

DELETE /videos/{id}

Permanently deletes a video and its generated assets.

Param Type Required Description
id string (uuid) Yes The video ID to delete.

GET /clip-models

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.

POST /clips

Starts generating a single AI video clip (1-30 seconds) from a text prompt, an image, or both.

Param Type Required Description
title string No Optional clip title. Defaults to the start of the prompt.
modelKey string Yes The generation model to use. Get valid keys, capabilities, and per-second costs from GET /clip-models.
prompt string No What the clip should show. Required for text-to-video models; optional when animating from images.
aspectRatio auto | 16:9 | 9:16 | 4:3 | 3:4 | 1:1 | 21:9 | 3:2 | 2:3 | 9:21 | 5:4 | 4:5 No Clip dimensions. Check the model's supportedAspectRatios from GET /clip-models. Default: "16:9".
resolution string No Output resolution (e.g. "720p", "1080p"). Check the model's supportedResolutions. Higher resolutions cost more credits per second. Default: "720p".
durationSeconds integer | auto No Clip length in seconds, or "auto" for models that support automatic duration. Default: 5.
firstFrameUrl string No Public image URL to use as the first frame (image-to-video). Only for models with supportsFirstFrame.
lastFrameUrl string No Public image URL to use as the last frame. Only for models with supportsLastFrame.
referenceImageUrls array of string No Public image URLs used as style/subject references. Only for models with supportsReferenceImages; respect maxReferenceImages.
referenceVideoUrls array of string No Public video URLs used for motion, editing, or extension. Check model capabilities first.
referenceAudioUrls array of string No Public audio URLs used for voice, lip sync, rhythm, or timing. Check model capabilities first.

GET /clips

Returns your standalone AI clips, newest first.

Param Type Required Description
limit integer No Maximum clips per page (1-50). Default: 20.
cursor datetime (ISO 8601) No Pagination cursor: the createdAt of the last clip from the previous page. Omit for the first page.

GET /clips/{id}

Returns a clip with its generation status.

Param Type Required Description
id string (uuid) Yes Clip ID from POST /clips.

POST /exports

Starts rendering a completed video into a downloadable MP4 file.

Param Type Required Description
videoId string (uuid) Yes The ID of the video to export. The video must have status: completed.
resolution 1080p | 4k No Export resolution. - 1080p (default): Full HD (1920x1080 or 1080x1920 for vertical). Fast rendering. - 4k: Ultra HD (3840x2160 or 2160x3840 for vertical). Slower rendering, larger file.

GET /exports/download

Returns a temporary signed URL to download the rendered MP4 file for a video.

Param Type Required Description
videoId string (uuid) No The video ID. Finds the latest completed export for this video.
exportId string (uuid) No A specific export ID, returned from POST /exports. Usually not needed since videoId automatically finds the latest export.

GET /channels

Returns all connected social media channels (YouTube, TikTok, Instagram, Facebook, Threads, and X) for your organization.

Param Type Required Description
platform youtube | tiktok | instagram | facebook | threads | x | all No Filter by platform. Use "all" or omit to list all connected channels.

POST /publications

Publishes a completed video to one or more connected social media channels (YouTube, TikTok, Instagram, Facebook, Threads, and X).

Param Type Required Description
videoId string (uuid) Yes The video to publish. Must have status: completed.
sceneExportId string (uuid) No Optional export ID if the video has already been exported. If omitted, an export is triggered automatically.
caption string No Description or long caption used for YouTube, TikTok, Instagram, and Facebook. Max 2200 characters.
shortCaption string No Short caption shared by X and Threads. It is kept within X's standard weighted 280-character limit. Defaults to caption when omitted.
addMadeWithCaption boolean No 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 boolean No Set to true (default) to publish immediately. Set to false and provide scheduledAt to schedule.
scheduledAt datetime (ISO 8601) No ISO 8601 datetime to schedule publication. Must be in the future. Only used when publishNow is false.
channels array of objects Yes One or more channels to publish to. Each entry can include platform-specific settings.
channels[].channelId string (uuid) Yes Channel ID from GET /channels. Must have status: connected.
channels[].title string No Video title (YouTube). Max 100 characters. Defaults to the video title from generation.
channels[].tags array of string No YouTube tags for search discovery. Max 30 tags, each up to 100 characters.
channels[].categoryId string No 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.
channels[].madeForKids boolean No YouTube COPPA compliance flag. Default: false.
channels[].allowComment boolean No 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.
channels[].tiktokPrivacyStatus public | friends | private No Privacy setting. Default: "public".
channels[].allowDuet boolean No Allow duets. Default: true.
channels[].allowStitch boolean No Allow stitches. Default: true.
channels[].isAiGenerated boolean No Label video as AI-generated on TikTok. Default: false.
channels[].instagramPlacement reels | stories | timeline No Instagram: where to post. Default: "reels".
channels[].shareToFeed boolean No Instagram: also share Reel to feed. Default: true.

GET /publications/{publicationId}

Returns the current status of a publication.

Param Type Required Description
publicationId string (uuid) Yes Publication ID from POST /publications.

DELETE /publications/{publicationId}

Cancels a future scheduled publication before it goes live.

Param Type Required Description
publicationId string (uuid) Yes Publication ID to cancel.

GET /subscription

Returns your current plan and credit balance.

GET /background-videos

List background videos No auth required.

Param Type Required Description
categorySlug string No
cursor string (uuid) No

GET /background-videos/categories

List background video categories No auth required.

POST /uploads/confirm-background-video

Confirm a background video upload No auth required.

Param Type Required Description
assetId string (uuid) Yes
title string Yes

Credit Costs

Operation Cost
Image (basic) 1 credit/image
Image (good) 5 credits/image
Image (premium) 10 credits/image
Image (max) 20 credits/image
Each reference photo in a scene +3 credits
Audio narration ~30 credits/minute
AI video clips (basic) 5 credits/second (~25 per 5s clip)
AI video clips (good) 10 credits/second (~50 per 5s clip)
AI video clips (premium) 26 credits/second (~130 per 5s clip)
AI video clips (max) 30 credits/second (~150 per 5s clip)
Stock footage ~50 credits/minute
Background video 10 credits/minute, plus narration
Export to MP4 Free
Publishing Free

A typical 60-second video with basic image quality costs about 47 credits (narration + ~17 images). Before generating, check the balance with GET /subscription.

Error Handling

HTTP Status Meaning
400 Bad request (check error message for details)
401 Missing or invalid API key
402 Not enough credits. Response includes creditsRequired and creditsAvailable
403 Feature requires an active paid subscription
404 Resource not found

402 and 403 are plan or credit limits, not bugs

Nothing is lost when one of these comes back, and no credits are charged. Never report a plain failure and stop. Say in plain words what is missing, say what the plans include, and give the page where the user manages their plan and credits: https://app.aituber.app/dashboard/billing. Do not recommend a plan, compare prices, or push an upgrade. Buying happens on the website, never through the API.

402 PAYMENT_REQUIRED means the credit balance is too low. creditsRequired and creditsAvailable show the gap. Credits come with a paid plan and are added every billing cycle.

The cheaper option is always available: a shorter script, mediaType: "images" instead of "video", or imageQuality: "basic". Offer it as a choice, never as a silent downgrade.

403 PAID_PLAN_REQUIRED (message PAID_PLAN_REQUIRED_FOR_EXPORT on exports, plus data.feature = export or other) means the account has no paid plan. MP4 downloads, single AI clip generation, and UGC reaction clips are included only with one. Retry the call once a plan is active.

403 PUBLISH_FEATURE_REQUIRED means publishing is included from the Creator plan up. Publishing itself costs no credits.

There is no endpoint for buying credits or plans, on purpose. Credits never expire, and GET /subscription always returns the live plan and balance. Never invent prices, discounts, savings, or earnings figures; quote only what the API returned.

Full Example (bash)

# 1. Check credits
curl -s "https://app.aituber.app/api/v1/subscription" \
  -H "Authorization: Bearer $AITUBER_API_KEY" | jq .

# 2. Browse voices
curl -s "https://app.aituber.app/api/v1/voices?gender=female&useCase=narration" | jq '.[0:3]'

# 3. Generate video (omit voiceId to use the default voice)
VIDEO_ID=$(curl -s -X POST "https://app.aituber.app/api/v1/videos/generate" \
  -H "Authorization: Bearer $AITUBER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "script": "Did you know that octopuses have three hearts and blue blood?",
    "imageStyleId": "cinematic",
    "aspectRatio": "9:16"
  }' | jq -r '.videoId')

echo "Video ID: $VIDEO_ID"

# 4. Poll until completed
while true; do
  STATUS=$(curl -s "https://app.aituber.app/api/v1/videos/$VIDEO_ID" \
    -H "Authorization: Bearer $AITUBER_API_KEY" | jq -r '.status')
  echo "Status: $STATUS"
  if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then break; fi
  sleep 10
done

# 5. Export to MP4
curl -s -X POST "https://app.aituber.app/api/v1/exports" \
  -H "Authorization: Bearer $AITUBER_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"videoId\": \"$VIDEO_ID\"}"

# 6. Poll export status
while true; do
  EXPORT_STATUS=$(curl -s "https://app.aituber.app/api/v1/videos/$VIDEO_ID" \
    -H "Authorization: Bearer $AITUBER_API_KEY" | jq -r '.exportStatus')
  echo "Export: $EXPORT_STATUS"
  if [ "$EXPORT_STATUS" = "completed" ] || [ "$EXPORT_STATUS" = "failed" ]; then break; fi
  sleep 10
done

# 7. Download
DOWNLOAD_URL=$(curl -s "https://app.aituber.app/api/v1/exports/download?videoId=$VIDEO_ID" \
  -H "Authorization: Bearer $AITUBER_API_KEY" | jq -r '.url')

curl -L -o video.mp4 "$DOWNLOAD_URL"
echo "Downloaded: video.mp4"