Editor
Edit the artifacts one video is made of: its theme config, transcript, caption pages, b-roll segments and AI scenes.
Everything the generation pipeline produced is editable through a set of
endpoints nested under /videos/{id}. They are all arrays or objects on the
video document, so each one is read and written whole rather than patched item by
item.
| Artifact | Endpoint | Exists on |
|---|---|---|
| Theme config | /videos/{id}/config | Every video |
| Transcript and caption pages | /videos/{id}/captions | Videos generated with transcribe |
| B-roll segments | /videos/{id}/brolls | Videos generated with addBRolls |
| AI scenes | /videos/{id}/scenes | type: ai only |
Reading an artifact on the wrong pipeline is a 409 wrong-video-type. The same
arrays can be read alongside the video itself with
GET /videos/{id}?include=captions,bRolls,..., which is cheaper than four calls
when you only need to look.
Read, modify, write
PUT replaces the whole array. An item you leave out of the body is deleted, so
never construct an array from scratch: GET the current one, change what you
need, and PUT the full result back.
The write path is deliberately lossy. Only the fields listed below travel on the
wire, so a caller can never point a segment at an arbitrary asset or rewrite the
editor's styling. Everything else is carried over from the stored item with the
same id: an incoming item is layered on top of the one already saved, and an
item whose id is unknown (or absent) is treated as new. Ids are minted when
absent.
That merge is what makes a read-modify-write safe and a hand-built array dangerous. Post an array of fresh objects with no ids and you will keep the timings you sent and lose every resolved file, every animation and every sound effect the user chose.
Theme config
The config holds the caption styling for one video. An empty object means the video has never been styled and renders with the editor defaults.
curl -X PATCH https://app.shortfast.com/api/v1/videos/7bQxL2mF9dR4tK1sv/config \
-H "Authorization: Bearer sf_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"captionsPrimaryColor": "#FFD400",
"captionsFontSize": 84,
"captionsVerticalPosition": 62
}'The config is the one artifact that merges rather than replaces: PATCH
shallow-merges the keys the body carries into the stored config and returns the
whole merged object, leaving omitted keys alone. Send the config object itself or
nest it under config. Unknown keys are dropped; a known key with a value
outside its enum or range is a 400; a body carrying no known config key at all
is refused rather than saved as a no-op.
DELETE /videos/{id}/config replaces the stored config with the editor defaults
and returns them.
Transcript and caption pages
captions is the word-level transcript the pipeline produced. captionsPages is
how those words are grouped into the chunks shown on screen. Both are empty until
the video has been generated with transcription on.
PUT accepts captions, captionsPages or both. Whichever half you send is
replaced wholesale; the other is left untouched.
curl -X PUT https://app.shortfast.com/api/v1/videos/7bQxL2mF9dR4tK1sv/captions \
-H "Authorization: Bearer sf_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"captionsPages": [
{ "id": "p1a2b3", "startMs": 0, "endMs": 2000 },
{ "id": "p4d5e6", "startMs": 2000, "endMs": 3620, "hidden": true }
]
}'A caption word writes id, startMs, endMs, text, punctuated_word and
confidence. A caption page writes id, startMs, endMs and hidden; its
editor decorations (emoji, audioEffect) are read-only and preserved by id.
Caps per request: 6000 caption words, 2000 pages. endMs must be at or after
startMs on every item.
B-roll segments
One segment per stretch of the video that shows footage or a generated image instead of the base video. Each segment carries both the editable brief (what it should show) and the resolved media the pipeline picked for it.
| Writable | Read-only, preserved by id |
|---|---|
id, startMs, endMs | url, type, qualityUrls |
text (the line of script it covers, 1000 characters) | animation, transition, layout, scale |
prompt (what an AI image should show, 1000 characters) | hidden, audioEffect |
keywords (search terms for stock footage, 200 characters) | |
mediaType: ai_image or stock_footage |
curl -X PUT https://app.shortfast.com/api/v1/videos/7bQxL2mF9dR4tK1sv/brolls \
-H "Authorization: Bearer sf_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"bRolls": [
{ "id": "b1a2b3", "startMs": 0, "endMs": 2400, "prompt": "A tired founder at a desk late at night", "mediaType": "ai_image" },
{ "startMs": 2400, "endMs": 5200, "keywords": "unfinished notebook", "mediaType": "stock_footage" }
]
}'The body can be a bare JSON array or wrapped as { "bRolls": [ ... ] }. Cap: 500
segments per request. The second segment above has no id, so it is created new
and starts with no media attached.
Changing what a segment should show does not re-fetch its media on its own.
Requeue generation with addBRolls: true (see Videos) to resolve new
footage for the changed briefs, or redraw one image as below.
To redraw one segment's image, call POST /videos/{id}/brolls/{brollId}/image.
It draws a new image in the video's style and charges one AI image. Pass
prompt (500 characters) to say what the scene should show; it is saved as the
segment's prompt. Without it the stored prompt is used, or the line of script
the segment covers.
curl -X POST https://app.shortfast.com/api/v1/videos/7bQxL2mF9dR4tK1sv/brolls/b1a2b3/image \
-H "Authorization: Bearer sf_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "prompt": "A tired founder asleep on a laptop at dawn, cold coffee beside the keyboard" }'Only videos whose imageStyle draws every scene can redraw one: realistic or a
fixed art style, without animateBRolls. On mixed, stock_footage and
animated videos a still would replace footage or a clip, so the call is refused
with 409 warning-invalid-input, as it is on a segment carrying a talking
presenter. The rendered video keeps the old image until you
re-render.
AI scenes
The scene list of an AI video: one entry per shot, with the prompts that drive its still and its motion, the narration spoken over it, and the media rendered so far. Unlike the other artifacts, scenes are edited one at a time.
| Call | What it does |
|---|---|
POST /videos/{id}/scenes/generate | Plans a whole scene list from the video's prompt. Charges credits and replaces whatever scenes exist |
POST /videos/{id}/scenes | Inserts one empty scene after afterSceneId, or appends when no id is given. Free: nothing is generated yet |
PATCH /videos/{id}/scenes/{sceneId} | Edits imagePrompt, animationPrompt, narration, voiceDescription or duration. Provide at least one |
DELETE /videos/{id}/scenes/{sceneId} | Removes the scene |
POST /videos/{id}/scenes/{sceneId}/image | Generates a new still and attaches it. Charges one image generation |
curl -X PATCH https://app.shortfast.com/api/v1/videos/7bQxL2mF9dR4tK1sv/scenes/n1a2b3 \
-H "Authorization: Bearer sf_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"narration": "Most founders burn out from never finishing anything.",
"duration": 7
}'duration is 3 to 20 seconds; the prompts and the narration are capped at 2000
characters each and voiceDescription at 300. A newly added scene starts as a
5 second DRAFT with empty prompts, and inherits the preceding scene's
voiceDescription so one character stays consistent. A video holds at most 50
scenes, and a 51st is a 409 limit-reached.
Every editable field is content, so editing, adding, removing a scene or
regenerating its still makes the output stale: videoUrl on the scene and
renderUrl on the video are cleared. Regenerate the still with
POST /videos/{id}/scenes/{sceneId}/image, then
re-render before publishing.
On POST .../image, pass prompt to use a different description for this run;
it is saved as the scene's imagePrompt. Without it the stored imagePrompt is
used, and a scene with neither is a 400. UGC videos reuse one character image
across every scene, so a per-scene regeneration does not apply there and is
refused with 409 warning-invalid-input.
Reference
Videos
Where the artifacts come from, and how to requeue the pipeline that fills them.
Rendering and download
Re-render after every edit, then fetch a URL that resolves.
Credits and limits
What the scene planner, the director and an AI image each charge.
API Reference
Every field of every artifact, with schemas.
Publishing
Connect a rendered video to a publishing profile, pick platforms, and read the publish state including which platforms had no account.
Credits and limits
What each feature charges in credits, the ceilings every plan enforces, and the codes an API call returns when one of them refuses the work.