Create and edit content
Build compositions, edit saved media, and generate video, voice, or copy.
Choose the task you need below. All routes use the /api/v1 prefix. API access and setup apply to every task. Creation jobs need Generate permission and an active paid plan. Saved content changes need Write. Deletion needs Delete.
Accepted members of an active paid workspace can use their own API key, CLI, or MCP connection. Resources must belong to that workspace. Each operation keeps the dashboard's owner and admin checks.
A creation job returns 202 with a public job ID. Read it with GET /jobs/{jobId}. Use the public job ID from the API response. See job status and recovery and request limits.
Prepare clips, transcripts, and captions
| Task | Method and route | Required input |
|---|---|---|
| Create a clip | POST /projects/{projectId}/clips | assetId, integer startMs and endMs; optional removeAudio. |
| List clips | GET /projects/{projectId}/clips | None. |
| Prepare a transcript | POST /assets/{assetId}/transcript | Empty object {}. |
| Read a transcript | GET /assets/{assetId}/transcript | None. |
| Edit a transcript | PATCH /assets/{assetId}/transcript | transcriptId, expectedUpdatedAt, and passage IDs with replacement text. |
| List captions | GET /assets/{assetId}/captions | None. |
| Read a language | GET /assets/{assetId}/captions/{language} | None. |
| Save a language | PUT /assets/{assetId}/captions/{language} | srt text and expectedUpdatedAt; use null for a new language. |
| Delete a language | DELETE /assets/{assetId}/captions/{language} | expectedUpdatedAt. |
Transcript edits preserve word timing. They also update automatic source-language captions. A caption update failure is reported separately. Manual captions are preserved. A concurrent edit returns a revision conflict.
Read text overlay sources
Asset reads return textOverlay.enabled and textOverlay.text for the clip's saved edit. A clip with no overlay returns {"enabled": false, "text": ""}. An enabled overlay with non-empty text identifies text added by that edit.
A later edit can keep text from an earlier edit. Follow sourceAssetId with GET /assets/{assetId} to check each parent. Check at most ten parents. Keep each parent in the same project. Stop at a missing parent or a repeated ID. If a derived clip has no available original parent, treat its source as unavailable. Read thumbnails separately with GET /assets/{assetId}/media?variant=thumbnail.
Build a composition
A composition is a saved video timeline. Create one with POST /projects/{projectId}/compositions. Read it with GET /compositions/{compositionId}. List project compositions with GET /projects/{projectId}/compositions.
Use this request body for a three-second portrait clip:
{
"title": "Opening clip",
"composition": {
"version": 1,
"aspectRatio": "9:16",
"backgroundColor": "#000000",
"durationInFrames": 90,
"fps": 30,
"width": 1080,
"height": 1920,
"overlays": [
{
"id": 0,
"type": "video",
"sourceAssetId": "<READY_PROJECT_VIDEO_ASSET_UUID>",
"from": 0,
"durationInFrames": 90,
"row": 1,
"left": 0,
"top": 0,
"width": 1080,
"height": 1920,
"rotation": 0,
"isDragging": false,
"styles": {}
}
]
}
}The source must belong to this project and contain the selected three-second range. Media overlays use sourceAssetId. An audio override also uses an audio sourceAssetId. Sovran resolves media URLs and preparation data. Do not send src, preview URLs, custom font URLs, background removal data, or external CSS references.
Timeline fields
Overlay types are video, image, sound, text, shape, emoji, and caption. Common fields are id, type, from, durationInFrames, row, left, top, width, height, rotation, and isDragging. Use unique nonnegative integer IDs. Keep each overlay inside the composition duration. See the numeric composition limits.
Lower row numbers appear above higher row numbers. Use text row 0 and video row 1 to show text over video.
| Overlay | Additional fields |
|---|---|
| Text | content and styles. |
| Video | videoStartTime, speed, segments; optional layerRole: "broll". Source offsets cannot be negative. |
| Sound | startFromSound. |
| Caption | Timed captions and words; optional built-in template, such as basicBlack. Unknown template IDs are rejected. |
| Video or image | Optional transitionIn with type: "fade", "slide", or "wipe"; optional direction: "from-left", "from-right", "from-top", or "from-bottom"; positive integer durationInFrames no greater than the overlay duration. |
Save or delete
Use PUT /compositions/{compositionId} with title, composition, and the saved expectedUpdatedAt. Read the current updatedAt before a change. A revision conflict prevents an older request from overwriting a later edit.
To delete, first read GET /compositions/{compositionId}/delete-impact. Then send DELETE /compositions/{compositionId} with expectedUpdatedAt and the returned fingerprint.
Read GET /sequences/{sequenceId}/compositions for saved sequence timeline edits. To change one through the API, read its version 1 state and create a regular composition. Dashboard batch edit guards remain active.
Export a composition
- Read the composition and its current
updatedAt. - Send
POST /compositions/{compositionId}/render-estimatewithexpectedUpdatedAtandmaxOutputs. - Review the estimate and save its
planFingerprint. - Send
POST /compositions/{compositionId}/renderswith the same input and that fingerprint. - Read the returned public job until it has a terminal status.
- Read
GET /renders/{renderId}/outputswith therenderIdfrom the job result.
Each render request creates one output. Use maxOutputs: 1 for a single composition. Keep expectedUpdatedAt and exportSettings identical between the estimate and render requests. Add the estimate's planFingerprint to the render request. Repeat these steps for each draft you choose to export. The source media must be ready before the estimate or charge. Music needs a saved duration. An audio override cannot use media with no audio track. Saved video segments are converted to continuous clips before the estimate.
Optional exportSettings include outputName, resolution (1080p, 4k, vertical, or square), quality (low, medium, or high), and purpose (finished_video, hook, body, cta, or custom). A custom purpose needs customTag. Reusable footage can specify range: {startFrame, endFrame}. Finished videos use the full timeline and the render credit charge. Reusable footage uses the existing zero-credit rule.
The operation IDs are get__compositions_compositionId, post__compositions_compositionId_render_estimate, and post__compositions_compositionId_renders. Poll acceptance through get__jobs_jobId. Read each ready renderId through get__renders_renderId_outputs. Read outputs again to refresh an expired signed url; use expiresAt to check its lifetime. A signed link can expire while the saved video remains available.
Save a separate request token with each exact export request before submission. Replay that request and token after an unknown result. A changed composition requires a fresh read and estimate. Do not reuse another composition's revision or planFingerprint. A confirmed failed composition export can use post__jobs_jobId_retry with {} after its charge and refund are resolved. It keeps the frozen sources and settings. A chain permits the original export and at most two explicit retries. There is no generic composition export cancellation operation. Stopping a wait does not cancel its job.
Plan and apply AI edits
Read GET /compositions/{compositionId} for its saved revision and overlay IDs. Plans need Read and Generate permissions. Applying a plan also needs Write. All editor requests need an active paid plan and an Idempotency-Key.
Request an edit plan:
{
"prompt": "Change the opening text to Try it today.",
"expectedUpdatedAt": "<COMPOSITION_UPDATED_AT>"
}The prompt can have at most 4,000 characters. The response is 202. Read GET /jobs/{planJobId}. A completed plan has summary, riskLevel (low, medium, or high), and 1–8 steps. Each step has tool, input, label, and why. Planning does not change the composition.
Review the saved plan before you apply it.
Apply the reviewed plan:
{
"planJobId": "<PUBLIC_PLAN_JOB_UUID>",
"expectedUpdatedAt": "<COMPOSITION_UPDATED_AT>"
}The plan must be complete and match this composition and revision. The route returns a separate execution job. It saves accepted steps and media identities before work, then applies the final composition once with a revision check. A later edit returns requires_action with revision_conflict. A changed media file, voiceover script, or selected caption file returns requires_action/source_changed. A filename-only rename remains valid. Read the current composition and sources before you request another action.
For one direct edit or search, use POST /compositions/{compositionId}/ai-tools. The editor tool reference lists all tool inputs and examples. Search and caption results are saved on the job. A successful edit returns its applied results and new saved revision.
Remove a video background
Send this request body:
{
"overlayId": 0,
"expectedUpdatedAt": "<COMPOSITION_UPDATED_AT>"
}This route needs Read, Write, and Generate permissions, an active paid plan, and an Idempotency-Key. It returns 202 with a public job ID. Select one continuous, prepared project video range of at most 60 seconds. The stored source must be at most 256 MiB (268,435,456 bytes). Batch compositions and video with alpha are rejected.
Success requires an available cutout and a saved composition. Read data.outputAssetIds[0] for the cutout asset ID. Check data.mediaAvailable, data.saved, data.saveStatus, and data.compositionUpdatedAt. A revision conflict retains the cutout and leaves the later composition unchanged.
This job response shows a retained cutout that was not saved to the composition:
{
"data": {
"id": "11111111-1111-4111-8111-111111111111",
"type": "editor_background_removal",
"status": "requires_action",
"progress": 100,
"counts": { "total": 1, "succeeded": 0, "failed": 0, "pending": 0 },
"outputAssetIds": ["33333333-3333-4333-8333-333333333333"],
"mediaAvailable": true,
"saved": false,
"saveStatus": "revision_conflict",
"compositionId": "22222222-2222-4222-8222-222222222222",
"compositionUpdatedAt": "2026-10-05T10:00:00.000Z",
"error": {
"code": "revision_conflict",
"message": "The removal result needs review."
},
"createdAt": "2026-10-05T10:00:00.000Z",
"completedAt": "2026-10-05T10:00:00.000Z"
},
"requestId": "44444444-4444-4444-8444-444444444444"
}For requires_action/revision_conflict, review the cutout only when data.mediaAvailable is true. Read the current composition and its updatedAt. Apply the retained asset through a version 1 update with that current revision. A successful removal has data.saved: true and data.saveStatus: "saved". See background removal limits and recovery.
Generate copy and analyse variations
Use POST /projects/{projectId}/messaging/generate with format: "hooks", "script", or "ab_test". Use 3–12 hooks, 2–4 test groups, or one script. Scripts require personaId and angleId. Active project context is required.
Optional fields include tone, length, language, count, guidance, productHighlights, productSpecId, contextSourceIds, and a saved template { "id": "UUID", "revision": 1 }. These requests need Generate permission and an Idempotency-Key. The result is saved on the job. Save selected copy through /projects/{projectId}/messaging.
Use GET and POST /projects/{projectId}/briefs for briefs. Use /projects/{projectId}/messaging-templates for saved copy templates. Read the OpenAPI schema for their create, read, update, and delete fields.
Use POST /sequences/{sequenceId}/smart-variations with expectedUpdatedAt to analyse combinations. Use GET on the same route to list saved analyses. See analysis limits.
Generate video, edits, and voice
| Task | Create and list | Read one result |
|---|---|---|
| AI video | POST and GET /projects/{projectId}/ai-videos | GET /ai-videos/{resourceId} |
| Automatic edit | POST and GET /projects/{projectId}/auto-edits | GET /auto-edits/{resourceId} |
| Voiceover | POST and GET /projects/{projectId}/voiceovers | GET /voiceovers/{resourceId} |
| Voiceover Remix | POST /projects/{projectId}/voiceover-remixes; list with GET /projects/{projectId}/auto-edits | GET /auto-edits/{resourceId} |
| Smart Variations | POST and GET /projects/{projectId}/smart-drafts | GET /smart-drafts/{resourceId} |
| B-roll Remix | POST /projects/{projectId}/broll-remixes; list with GET /projects/{projectId}/auto-edits | GET /auto-edits/{resourceId} |
| Avatar video | POST and GET /projects/{projectId}/avatar-videos | GET /avatar-videos/{resourceId} |
Smart Variations, Video Variations, Voiceover Remix, and B-roll Remix save editable compositions. Read outputEditorProjectIds from their public job result. Read each composition with GET /compositions/{compositionId}. Render up to ten selected drafts together with the draft batch Render. Draft creation does not start an export.
A Voiceover Remix with two or three voiceovers creates one public job for each voiceover. Its acceptance returns jobId and jobIds. Poll every ID in jobIds, or pass them all to sovran jobs wait. Reading only jobId misses the drafts of the other voiceovers.
Voiceover Remix supports public job retry and named saved batch retry. Both routes resume the same saved checkpoint. B-roll Remix creation does not support generic job retry. POST /jobs/{jobId}/retry returns HTTP 409 with retry_not_allowed for B-roll jobs. Their response includes retryAllowed: false and nextAction. Replaying the exact original creation request only reads its saved acceptance. Do not submit a new creation token to restart a failed remix. Read the saved batch retry rules before a Voiceover retry. If no supported retry is available, contact Sovran support with its public job ID.
Read project footage with get__projects_projectId_assets before draft creation. Add requireTranscript=true to list only videos whose saved transcript meets the speech rules of Video Variations, Creative Copilot, and Smart Variations. Add transcriptStatus=true to see transcriptStatus on each video: ready, needs_preparation, unsupported, or unavailable. Use stored assetId values from this project. Prepare required transcripts and read their results first. Creation acceptance supplies a public jobId for get__jobs_jobId. Native history IDs identify the saved creation run. Composition IDs identify editable drafts. Render IDs identify finished exports. Keep these IDs separate.
| Flow | Setup and creation operation IDs | Accepted draft count |
|---|---|---|
| Creative Copilot | get__auto_edit_brief_templates, get__projects_projectId_auto_edit_templates, then post__projects_projectId_auto_edits | Hook variations use hookVariationCount: "auto", 3, 4, 5, or 6. Video Variations use videoVariationCount: 4, 6, or 8. Other templates use their own output rules. |
| Smart Variations | post__projects_projectId_smart_drafts_source_preview, then post__projects_projectId_smart_drafts; read the saved run with get__smart_drafts_resourceId | draftCount: 5, 10, or 20. A run can return fewer complete drafts. See Smart Variations drafts. |
| Voiceover Remix | get__projects_projectId_voiceovers, then post__projects_projectId_voiceover_remixes | 1–3 unique saved voiceovers; draftsPerVoiceover: 1, 3, or 5; at most 15 drafts. The voiceover list leaves out voiceovers removed from the saved library, which Voiceover Remix rejects. |
| B-roll Remix | get__projects_projectId_messaging_targeted for saved hooks when needed, then post__projects_projectId_broll_remixes | draftsPerHook: 1, 3, or 5; saved text can select 1–3 hook IDs. Total drafts equal hook count times drafts per hook. |
These operations create editable drafts first. Render selected drafts with the draft batch Render, or one at a time with the composition export steps. A request for two finished videos does not make 2 a valid draft-count preset. Choose a supported creation count, then select two saved drafts to render.
Creation errors
Creative Copilot, Video Variations, Audience variations, and Voiceover Remix return the reason a request was rejected. Read error.code. Fix the input and send a new request with a new token.
| Status | error.code | Next step |
|---|---|---|
404 | project_not_found, asset_not_found, voiceover_not_found | Read the project, assets, or voiceovers again. Select available resources. |
409 | transcript_required, voiceover_not_ready, voiceover_transcript_review_required, source_media_unavailable, brand_strategy_required, analysis_stale, audience_analysis_unavailable | Prepare the transcript or media, approve the voiceover transcript, or read a current audience analysis. |
422 | invalid_input, non_video_asset, transcript_too_short, must_keep_quote_missing, insufficient_sources, insufficient_hook_variations, insufficient_video_variations, insufficient_visual_sources, voiceover_duration_invalid, audience_speech_required | Change the settings or choose other footage. |
429 | audience_generation_limit | Wait for the daily audience limit to reset. |
503 | feature_unavailable, creation_unavailable | Nothing was created. Try again later with a new token. |
503 | creation_outcome_unknown | The creation was accepted but not confirmed. Read error.details.jobId before you send anything new. |
Render several drafts
The Remixes and Creative Copilot pages render up to ten selected drafts in one batch. The API uses the same batch. Send POST /projects/{projectId}/draft-render-estimate with draftIds, the composition IDs of 1 to 10 reviewed drafts in one project. Optional resolution is 1080p or 4k, and quality is high, medium, or low. The estimate returns outputCount, creditCost, and planFingerprint. Each output uses one render credit.
Send POST /projects/{projectId}/draft-renders with the same body plus planFingerprint and a new Idempotency-Key. The result has a batchId and one item per draft. Read GET /projects/{projectId}/draft-renders/{batchId} until no item is queued or rendering. A done item has a renderId. Read its file with GET /renders/{renderId}/outputs, or sovran renders download. A failed batch can be retried once every output has finished. Use POST /projects/{projectId}/draft-renders/{batchId}/retry with expectedCreditCost.
AI video
Read GET /ai-video-models before you choose a model. Requests use provider, modelId, capability, and input. The capability is t2v, i2v, or r2v. Input fields include prompt, durationSeconds, aspectRatio, resolution, negativePrompt, seed, and generateAudio. Model limits apply. Reference modes require a project referenceAssetId. External input URLs and provider metadata are rejected.
Automatic edit
Use sourceMode: "single_asset" with exactly one sourceAssetId in sourceAssetIds. For a project story, use sourceMode: "project_story", briefTemplateId: "project_story", and a brief. Optional fields include savedTemplate, targetDurationSeconds, aspectRatio, captionsEnabled, hook or video variation settings, verbalSlipsToAvoid, and mustPreserveQuotes. The OpenAPI schema lists supported presets. Saved templates use /projects/{projectId}/auto-edit-templates.
Creative Copilot templates
Read GET /auto-edit-brief-templates for the built-in single-video templates used by Creative Copilot. Each item has id, label, brief, sourceMode, and requiresBrief. Submit its id as briefTemplateId to POST /projects/{projectId}/auto-edits. An omitted brief uses that template's instructions. custom requires your instructions in brief.
Saved project templates use /projects/{projectId}/auto-edit-templates. Select one with savedTemplate: {id, revision}. Sovran loads its instructions and settings before applying defaults. Fields you send override the saved settings. Read the current revision before use. A deleted template, another project's template, or an old revision is rejected. Do not fill omitted settings with defaults if you want the stored settings.
Smart Variations
Smart Variations makes editable drafts from saved speech transcripts across project videos. It uses the same source filters and fixed section rules as Auto-arrange in the dashboard's Modular Builder. This operation is separate from sequence combination analysis.
First send POST /projects/{projectId}/smart-drafts/source-preview with sourceFilters: {} or selected campaign, creator, location, shoot date, and tag filters. This route needs Read permission only. It reads current source readiness and makes no generation request. Its result includes sources.ready, sources.processing, sources.unavailable, warnings, and source issues. Prepare missing transcripts before creating a draft.
{
"draftCount": 5,
"aspectRatio": "9:16",
"minimumDurationSeconds": 15,
"captionsEnabled": true,
"requireCta": true,
"variationPriority": "balanced",
"animatedEmphasis": { "enabled": false },
"sourceFilters": {}
}draftCount is 5, 10, or 20. Minimum duration is 15, 30, 45, or 60 seconds. Aspect ratio is 9:16, 1:1, 4:5, or 16:9. variationPriority is balanced, new_hooks, or new_bodies. A run can return fewer complete drafts than requested. The requested count does not guarantee that enough complete speech is available.
Poll the public job from the acceptance response. List Smart runs with GET /projects/{projectId}/smart-drafts. Each list item has a native id and an optional publicJobId. Read one native run with GET /smart-drafts/{resourceId}. Its outputs have editorProjectId, combinationId, rank, confidence, duration, and original selection ranges. The response returns only compositions that still exist. It contains no worker transcript checkpoint.
To keep a body and create new hooks, add lockedDraft: {jobId, combinationId, vary: "hook"}. Use the native run id and its saved output combinationId. Use vary: "body" to keep the hook and create new bodies. The retained sections use their original source ranges. Later edits to the composition do not change this reference. Include the retained source footage in the current filters. Preview checks whether the reference remains valid. A fixed section run requires a CTA and selects the priority for the changed section.
Generic job retries are not available for native Smart Variations drafts. POST /jobs/{jobId}/retry returns HTTP 409 with retry_not_allowed. The job response includes retryAllowed: false and nextAction. Contact Sovran support with its public job ID if a run fails. Replay the exact original request to read its saved acceptance. A new request token starts a new run and does not resume its saved checkpoint. Its separate saved cancel and resume controls are listed below.
Modular Builder: Arrange clips
Arrange clips in the dashboard's Modular Builder uses sequences. Create blocks with POST /projects/{projectId}/sequences. Each block contains its selected project assetIds in order. Save changes with PUT /sequences/{sequenceId}/configuration and the current revision. Read the combinations with GET /sequences/{sequenceId}/combinations.
Use POST /sequences/{sequenceId}/render-estimate, then POST /sequences/{sequenceId}/renders with the same revision and settings plus the returned fingerprint. Public sequence render requests allow at most 100 outputs. Read the public job and its finished render outputs.
A Build can match the dashboard's one-click Build:
aspectRatiosbuilds several formats, for example["9:16", "1:1"]. Each variation renders once per format, and each output uses one render credit. The first format in display order (9:16, 4:5, 1:1, 16:9) is the preview format.useSavedShortlist: truebuilds the shortlist saved in Arrange clips instead ofcombinationIds. Without a saved shortlist, every combination is selected.useProjectSettings: trueuses the project Build settings for formats, captions, caption style, resolution, quality, and frame rate. Read or change them withGETandPATCH /projects/{projectId}/settings, includingaspectRatios.
The estimate returns aspectRatios and combinationCount with outputCount and creditCost. Free samples from POST /sequences/{sequenceId}/preview-estimate use the preview format and the first combinations of the saved shortlist.
A sequence batch can contain plain combinations and compatible saved row edits. The server uses the current caller's saved combination-to-editor mappings. It checks the mapping, editor revision, saved state, and configuration fingerprint again before acceptance. Edited selections permit at most one music track and one voiceover. Changed mappings or revisions require a fresh estimate. An earlier full-editor draft without compatible row-edit context cannot use this batch path. Export other saved compositions separately. Do not send arbitrary composition IDs or timeline overrides in a sequence render request.
POST /sequences/{sequenceId}/smart-variations checks whether selected sequence combinations make a coherent story. Its results are approved or rejected combination IDs. It does not create the editable drafts of Auto-arrange. Follow the Manual and Smart sequence batch steps for its setup, saved decisions, and exports.
Video Variations
Send POST /projects/{projectId}/auto-edits with briefTemplateId: "video_variations". Select one project video in sourceAssetIds. The video needs a saved word-timed transcript with at least ten spoken words and a duration of at least five seconds. Prepare it through POST /assets/{assetId}/transcript with {} when needed. Read the transcript job before you create variations.
Choose videoVariationCount: 4, 6, or 8. Each story creates a pair: one clean draft and one draft with opening text. Four outputs therefore require two distinct stories. A short source can meet the input limits but still lack enough complete stories. Use videoVariationMinDurationsSeconds to choose supported minimum lengths. The planner selects the actual lengths from complete speech.
{
"sourceMode": "single_asset",
"sourceAssetIds": ["11111111-1111-4111-8111-111111111111"],
"briefTemplateId": "video_variations",
"videoVariationCount": 4,
"videoVariationMinDurationsSeconds": [5],
"aspectRatio": "9:16",
"captionsEnabled": true
}Replace example IDs with your own saved resources. Video Variations removes background audio before planning. The job can remain running while its speech audio is prepared. This step must be available on the host. Prepared speech audio and the source transcript are reused.
A video variation job can create one automatic child job when paired outputs are missing. Read children and outputEditorProjectIds in the parent result. The parent remains running while the child is pending. It becomes partially_succeeded if some outputs remain unavailable after the child fails.
Retry an eligible failed child with POST /jobs/{childJobId}/retry, {}, and a new Idempotency-Key. Read the returned retry job. See generation retry limits.
Audience variations
Through the API, Audience variations need a person to approve the audiences before drafts are made. In the dashboard workflow, Sovran creates one draft for each suggested audience automatically.
- Send
POST /projects/{projectId}/audience-analyseswith one project video and a campaign goal. The video can be up to 10 minutes and does not need speech. - Poll
GET /projects/{projectId}/audience-analyses/{resourceId}untilstatusisready. Each audience lists only verified evidence moments. - Show the audiences to a person. Create drafts only from the audiences they approve.
- Send
POST /projects/{projectId}/auto-editswithbriefTemplateId: "video_variations",videoVariationStrategy: "audience", theaudienceAnalysisId, and one to three approved audiences. Do not sendvideoVariationCount; each audience makes one draft.
{
"sourceAssetId": "11111111-1111-4111-8111-111111111111",
"conversionGoal": "purchase",
"notes": "Focus on parents who research before buying."
}{
"sourceMode": "single_asset",
"sourceAssetIds": ["11111111-1111-4111-8111-111111111111"],
"briefTemplateId": "video_variations",
"videoVariationStrategy": "audience",
"audienceAnalysisId": "22222222-2222-4222-8222-222222222222",
"conversionGoal": "purchase",
"targetDurationSeconds": 30,
"aspectRatio": "9:16",
"captionsEnabled": true,
"audienceBriefs": [
{ "audienceId": "a1", "name": "Research-heavy moms", "callout": "Moms who research everything" },
{ "audienceId": "a2", "name": "Night-shift nurses", "callout": "Nurses with newborns", "ctaText": "Try it tonight" }
]
}Each audience brief can add up to three callouts: on-screen lines shown between the opening callout and the call to action. A line with a momentId from the analysis starts over that moment; other lines share the free time evenly. Ready analyses suggest callouts and, when the notes give one, a ctaText for each audience. The analysis notes can be up to 3,000 characters.
Send textStyle to style the drafts' on-screen text: { "presetId": "goldenSerif" } for a built-in style, or { "savedStyleId": "…" } for a saved workspace text style. The style's entry motion is kept. textStyle works with briefTemplateId: "video_variations" and cannot be combined with animatedEmphasis.
Send keepWholeVideo: true to make every draft the whole source video with its own sound. Only the on-screen text changes, and targetDurationSeconds is ignored.
Video variations, including audience drafts, accept the same optional animatedEmphasis object as B-roll Remix. When enabled is true, the opening text hook animates in style, and audience drafts also use that style for the call to action. The font must be available in the workspace. Other templates reject animatedEmphasis.
One analysis runs per video and goal at a time. Each analysis can make at most three draft sets. Analyses and draft sets share a limit of 10 requests per person in 24 hours. A new analysis and its draft set each use one request. Draft generation needs a source video at least five seconds long. Clips without speech are muted, unless keepWholeVideo is true. The service returns 503 feature_unavailable while Audience variations is not enabled.
Voiceover
Use script (at most 1,000 characters), voiceId, language, and optional voiceType: "preset" or "clone", modelId, and style (at most 500 characters). Read GET /voices?language=English for current choices. A clone must be ready in the same workspace.
Voiceover Remix
Send POST /projects/{projectId}/voiceover-remixes to match saved project footage to one to three saved voiceovers. Read GET /projects/{projectId}/voiceovers to choose them. Use each item's id in voiceoverJobIds. This is the native voiceover ID. When present, its publicJobId is a separate ID used by GET /jobs/{jobId}. Do not put the public job ID in voiceoverJobIds.
Each selected voiceover must have status succeeded. It must belong to this project and have a duration of 5–120 seconds. Its audio, timed words, and SRT caption file must be ready. An uploaded voiceover also needs approved transcript review. A removed saved voiceover cannot start a new remix.
Select draftsPerVoiceover: 1, 3, or 5. The API accepts 1–3 unique IDs in voiceoverJobIds and at most 15 drafts per batch. Use sourceAssetIds to select project source videos. Omit that field or use [] to search all eligible project footage. Finished exports cannot serve as source footage.
{
"voiceoverJobIds": ["11111111-1111-4111-8111-111111111111"],
"sourceAssetIds": ["22222222-2222-4222-8222-222222222222"],
"draftsPerVoiceover": 1,
"aspectRatio": "9:16",
"animatedEmphasis": { "enabled": false },
"captions": {
"enabled": true,
"style": {
"templateId": "basic-white",
"language": "English",
"textDirection": "auto",
"fontFamily": "TikTok Sans",
"fontSize": 64,
"fontWeight": 700,
"textColor": "#ffffff",
"position": "bottomCenter",
"stroke": { "enabled": false, "width": 0, "color": "#000000" },
"animationStyle": "none",
"activeWordStyle": { "textColor": "#ffffff", "backgroundColor": "transparent" }
}
}
}captions.style is required even when captions.enabled is false. Optional conceptName names the batch. Optional excludeTags removes tagged source footage. Enable animatedEmphasis to add emphasis graphics with a validated font style. The remix reuses the selected voiceover audio and captions. It does not generate another voiceover.
B-roll Remix
Send POST /projects/{projectId}/broll-remixes with an ad brief and project source footage. This flow creates portrait drafts without voiceover. Choose a supported durationSeconds preset and draftsPerHook: 1, 3, or 5.
{
"brief": "Show the product in each available shot.",
"templateId": "custom",
"durationSeconds": 5,
"draftsPerHook": 1,
"sourceScope": "selected",
"sourceAssetIds": [
"11111111-1111-4111-8111-111111111111",
"22222222-2222-4222-8222-222222222222"
],
"textMode": "none",
"musicMode": "none"
}Use sourceScope: "selected" with at least one sourceAssetId. Use sourceScope: "all" to search eligible project footage. Source IDs must be unique. Finished exports cannot serve as source footage. Optional excludeTags removes tagged footage.
Choose textMode: "none" for no opening text. Use "manual" with hookText for one opening text. Use "saved" with one to three hookIds from the project's saved overlay text. Each hook must have at most 200 characters. The requested draft count is the hook count multiplied by draftsPerHook. Animated emphasis requires an opening hook.
musicMode: "none" keeps the draft silent. Use "auto" to choose background music. Optional musicBrief describes the music you want. The worker uses project music when available. It can import a library track when the subscription permits it. A music failure can leave a saved draft silent. Read the saved composition before export.
Saved remix history and cleanup
Voiceover Remix history uses get__projects_projectId_voiceover_remix_batches. Read one batch with get__projects_projectId_voiceover_remix_batches_resourceId. Use its saved batch ID as resourceId. Rename it through patch__projects_projectId_voiceover_remix_batches_resourceId with {name}. These Voiceover operations exclude B-roll Remix rows. B-roll history uses get__projects_projectId_broll_remixes. Generic get__projects_projectId_auto_edits and get__auto_edits_resourceId can still read both kinds.
Before a Voiceover retry, read the batch's retryStatus. Its state must be eligible. A public job can report retryAllowed: true when its failed native job has a saved batch and remaining retries. That field alone does not prove that cooldown and other batch checks permit a retry.
Choose one retry route per failure. Use {} and a separate saved request token for either route:
post__jobs_jobId_retryuses the original public Voiceover RemixjobId. It returns HTTP202with that same publicjobId. Poll it withget__jobs_jobId.post__projects_projectId_voiceover_remix_batches_resourceId_retryuses the saved batch ID asresourceId. It returns nativejobIds. Read the batch again to track them. Do not use these native IDs as public job IDs.
Both routes resume at most two failed native jobs per request. Each job permits at most three retries. Only one retry can be active in a project. Requests are at least one minute apart. Saved plans, voiceover audio, captions, and successful drafts are kept. B-roll jobs are excluded. Neither route creates a new public generation job. Do not call both routes for the same failure. Replay the selected route's exact request and token if its result is unknown.
Creative Copilot, Voiceover Remix, and B-roll Remix have no creation cancellation operation. The separate native Smart draft workflow has post__projects_projectId_smart_drafts_resourceId_cancel and post__projects_projectId_smart_drafts_resourceId_resume. Use a saved Smart run ID for these controls. Resume does not restart a terminal run or reset its retry budget.
To remove saved drafts, first use post__projects_projectId_draft_cleanup_impact. Then use delete__projects_projectId_draft_cleanup with the same target and returned fingerprint. A named target {batch: {kind: "voiceover_remix", id}} applies only to Voiceover Remix. It excludes B-roll. Generic {draftIds: [...]} targets and {batch: {kind: "auto_edit", id}} targets still support both kinds. Use the native job ID for an auto_edit batch. Review blockers before deletion. A changed saved result requires a new impact read.
Avatar and voice clone
Create an avatar with POST /avatars. Supply projectId, displayName, voiceCloneId, one to five imageAssetIds, consentBasis: "self" or "authorized", and consentAccepted: true. Images must be JPEG, PNG, or WebP. See avatar and voice sample limits.
Create a voice clone with POST /voice-clones. Supply projectId, displayName, the same consent fields, and sourceType. For "upload", declare filename, mimeType, and sizeBytes, then use the returned signed upload reservation. For "asset", supply a video assetId. Call POST /voice-clones/{resourceId}/run with {} after the sample is ready.
Review the voice preview. Record approval with PUT /avatars/{avatarId}/voiceovers/{voiceoverId}/approval and { "projectId": "UUID", "audioPreviewAcknowledged": true, "approved": true }. An avatar video request then uses presenterProfileId, voiceoverJobId, presenterReferenceImageId, and optional prompt or supported direction settings.
Video and voice jobs require stored media before they report success. Auto-edit jobs require a saved composition. Avatars and voice clones also report mediaAvailable. Missing output returns requires_action; media URL requests return 409 when the stored object is missing.