fast.video API
One HTTP call turns a prompt or an image into a video: 720p, 24 fps, with sound, 5 to 15 seconds. Batch many at once, or join segments into clips up to 60 seconds.
Quickstart
1. Get a key on the home page (you get $1 of free credit). 2. Start a video. 3. Poll until it is done.
curl https://fast.video/v1/videos \
-H "Authorization: Bearer $FAST_VIDEO_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "A red fox trots through fresh snow at dawn, slow tracking shot", "duration": 5}'
{"id": "vid_3f9c1a7b2d4e6f80", "object": "video", "status": "queued", "duration": 5, "aspect_ratio": "16:9", "cost_usd": 0.045, ...}
curl https://fast.video/v1/videos/vid_3f9c1a7b2d4e6f80 -H "Authorization: Bearer $FAST_VIDEO_KEY"
# when status is "succeeded": video_url and poster_url are set
Python
import os, time, requests
H = {"Authorization": f"Bearer {os.environ['FAST_VIDEO_KEY']}"}
v = requests.post("https://fast.video/v1/videos", headers=H, json={"prompt": "Waves roll onto a black sand beach at sunset", "duration": 5}).json()
while v["status"] in ("queued", "running"):
time.sleep(3)
v = requests.get(f"https://fast.video/v1/videos/{v['id']}", headers=H).json()
print(v["video_url"])
JavaScript
const H = { Authorization: `Bearer ${process.env.FAST_VIDEO_KEY}`, "Content-Type": "application/json" };
let v = await (await fetch("https://fast.video/v1/videos", { method: "POST", headers: H, body: JSON.stringify({ prompt: "A paper boat drifts down a rainy street", duration: 5 }) })).json();
while (["queued", "running"].includes(v.status)) {
await new Promise(r => setTimeout(r, 3000));
v = await (await fetch(`https://fast.video/v1/videos/${v.id}`, { headers: H })).json();
}
console.log(v.video_url);
Build with your AI agent
Coding agents such as Claude Code, Cursor or Codex can learn the whole API from one page: fast.video/llms-full.txt. Paste this prompt to get set up, then use the Ask your agent prompt in each section for a specific job.
Read https://fast.video/llms-full.txt. Then add fast.video video generation to this project:
- read my API key from the FAST_VIDEO_KEY environment variable (never put it in code or ask me for it)
- write a small client that starts a video, waits for it (use a webhook if this app has a server, otherwise poll every 3 seconds) and saves the mp4 to [where to save]
- handle failed or blocked clips with a clear message
First thing I want to make: [describe it]
Fill in the [brackets]. Never paste your API key into a chat: set FAST_VIDEO_KEY in your environment and the code your agent writes reads it from there.
Keys
Send your key as Authorization: Bearer fv_… (or X-API-Key). Keep it on your server, never in a browser or app. Lost it? Sign in again with your email to get a new one, or rotate with POST /v1/account/rotate-key.
Videos
POST/v1/videos
| Field | Type | |
|---|---|---|
prompt | string ≤ 2400 | What happens. Optional when you send an image. |
image | string | Start frame: https URL, data: URI, or upload id upl_…. |
end_image | string | End frame (needs image). The clip moves from one picture to the other. |
duration | int 5–15 | Seconds. Default 5. |
aspect_ratio | string | 16:9 9:16 1:1 4:3 3:4. Default: matches your image, else 16:9. |
references | array, ≤ 5 | Pictures to keep in the clip: character or prop sheets, product shots. See References. Not with image. |
audio | string | A speech or music track the clip lip-syncs to (URL, data: URI or upload id); cut to duration. Not with image. |
webhook_url | https URL | We POST the finished video here. |
GET/v1/videos/{id} · GET/v1/videos?limit=20
Status goes queued → running → succeeded or failed. A finished video has video_url (mp4 with sound) and poster_url (jpg). Files are kept for 7 days: copy them to your own storage.
imageimage + prompt → 5 s with sound. Real output, one render.
image
end_imageimage + end_image: the camera moves from the first picture to the second.Ask your agent
Using the fast.video API (read https://fast.video/llms-full.txt), add a function to this project that takes [a prompt, or an image path plus a prompt] and returns the path of a saved mp4. Read the key from FAST_VIDEO_KEY, poll until the clip is done, and handle failed or blocked clips cleanly.Images
Pass an https URL, a data: URI, or upload first (JPEG, PNG or WebP, ≤ 10 MB, at least 128 px a side):
curl https://fast.video/v1/uploads -H "Authorization: Bearer $FAST_VIDEO_KEY" -F [email protected]
# {"id": "upl_9a0b…", "kind": "image", "expires_at": …} → use "image": "upl_9a0b…"
The same endpoint takes sound files (WAV, MP3 or M4A, ≤ 10 MB) and returns "kind": "audio"; use that id as audio.
References
Give up to 5 pictures in references and the clip keeps what is in them: the same character, outfit, prop or product, in a new shot that the prompt describes. Name what you want in the prompt ("the woman from the reference", "the red bottle").
{"references": ["https://example.com/maya-sheet.jpg", "https://example.com/red-scarf.jpg"],
"prompt": "The woman from the reference, wearing the red scarf, walks through a snowy market at dusk",
"duration": 8}
Add audio and the people speak or sing along to it. Put the words in the prompt too; it helps the mouths.
{"references": ["upl_4c1d…"], "audio": "upl_77e0…", "duration": 5,
"prompt": "The woman from the reference sits in a cafe and says: \"No way, you did not! Tell me everything.\" Medium close-up"}
reference
reference
audioaudio → she says the line. Tap to hear it; the voice is a test recording.References replace the start frame: a clip uses image/end_image, or references/audio, never both. The engine places the subject in a new frame of its own, so exact framing comes from start frames, and consistent characters across shots come from references.
Ask your agent
Using the fast.video API (read https://fast.video/llms-full.txt), make [3] short clips of the character in [character-sheet.jpg]: [scene 1], [scene 2], [scene 3]. Pass the sheet as references so she looks the same in every clip, and save the mp4s to [folder].Batches
Up to 20 videos in one call. Each item takes the same fields as /v1/videos.
curl https://fast.video/v1/batches -H "Authorization: Bearer $FAST_VIDEO_KEY" -H "Content-Type: application/json" -d '{
"items": [
{"image": "https://example.com/shoe-1.jpg", "prompt": "The shoe turns slowly on a plinth", "duration": 5},
{"image": "https://example.com/shoe-2.jpg", "prompt": "The shoe turns slowly on a plinth", "duration": 5}
]}'
GET/v1/batches/{id} returns every video plus counts. Status ends as succeeded, partial or failed; failed items are refunded.
Ask your agent
Using the fast.video API (read https://fast.video/llms-full.txt), turn every photo in [folder] into a 5-second clip with a slow camera push-in, in one batch call, and save each mp4 next to its photo with the same name.Long clips
POST/v1/sequences joins 5–15 s segments into one mp4 of up to 60 s. Three ways to build one:
chain: one start, many steps
Each segment starts on the exact last frame of the one before, so motion carries on. The quickest form: a total duration and one prompt.
{"mode": "chain", "image": "https://example.com/street.jpg", "duration": 30,
"prompt": "Handheld walk down a neon street at night, rain on the lens"}
Or one prompt per segment:
{"mode": "chain", "image": "https://example.com/kitchen.jpg", "segments": [
{"prompt": "A chef cracks two eggs into a hot pan", "duration": 10},
{"prompt": "She flips the omelette in one move", "duration": 10},
{"prompt": "She slides it onto a plate and smiles at the camera", "duration": 10}]}
imagereferences: same cast, many shots
Every segment is made from the same reference pictures, so the character and props stay the same from shot to shot. Segments join with cuts, like an edit. Each segment can have its own audio for dialogue.
{"mode": "references", "references": ["https://…/robot-sheet.jpg"], "segments": [
{"prompt": "The robot from the reference rolls across the workbench", "duration": 5},
{"prompt": "Close-up: the same robot holds up a tiny wrench and says \"Got it!\"", "duration": 5, "audio": "upl_91a2…"}]}
referencekeyframes: you set the pictures
Segment i runs from images[i] to images[i+1]. Three images make two segments.
{"mode": "keyframes", "images": ["https://…/sketch.jpg", "https://…/clay.jpg", "https://…/final.jpg"],
"prompt": "A smooth morph, camera holds", "segments": [{"duration": 6}, {"duration": 6}]}
1
2
3Options: join = cut (default) or crossfade; aspect_ratio; webhook_url. The result has video_url for the joined clip and segments with each part. Every segment makes its own sound, so audio can change at a join; we soften each cut.
Segments render one after another in chain mode, so a 30 s clip takes a few minutes. Use a webhook rather than polling quickly.
Ask your agent
Using the fast.video API (read https://fast.video/llms-full.txt), make a [30]-second clip that starts from [image.jpg] and follows this story: [beat 1], [beat 2], [beat 3]. Use a chain sequence with one segment per beat, then save the joined mp4 to [path].Webhooks
Add webhook_url to any create call. We POST {"type": "video.succeeded", "data": {…}} (or batch.*, sequence.*) and retry up to 4 times. Check the X-FastVideo-Signature header: sha256= + HMAC-SHA256 of the raw body with your webhook_secret from GET /v1/account.
import hmac, hashlib
ok = hmac.compare_digest(sig_header, "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest())
Ask your agent
Using the fast.video API (read https://fast.video/llms-full.txt), add a webhook endpoint at [/webhooks/fast-video] to this app. Verify the X-FastVideo-Signature header with the webhook_secret from GET /v1/account, download the finished mp4 to [our storage] and mark the job done. Pass the endpoint's public URL as webhook_url when creating videos.Errors
Errors look like {"error": {"code": "insufficient_credit", "message": "…"}}.
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_image, missing_prompt, … | Fix the request; the message says what. |
| 401 | invalid_key | Missing or revoked key. |
| 402 | insufficient_credit | Top up on your account page. |
| 422 | content_rejected | Blocked by the content filter. Not charged. |
| 429 | rate_limited, too_many_active | 120 requests a minute; 20 clips in flight. |
A video that fails while rendering ends as status: "failed" with an error, and its cost is refunded.
Pricing
One price: $0.009 per second of video, charged when you start and refunded if it fails. GET /v1/pricing returns the current number. Balance and usage: GET /v1/account.
Limits
- 720p (1264×720 landscape, 720×1264 portrait), 24 fps, AAC sound.
- 5–15 s per clip; long clips up to 60 s; batches up to 20 items; up to 5 reference pictures a clip.
- Files kept 7 days. Uploads kept 24 hours.
- Use must follow our terms and acceptable use policy; see also our privacy and refund policies. Videos are AI-generated: label them where the law requires.