fast.video

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.

or open them as text

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

FieldType
promptstring ≤ 2400What happens. Optional when you send an image.
imagestringStart frame: https URL, data: URI, or upload id upl_….
end_imagestringEnd frame (needs image). The clip moves from one picture to the other.
durationint 5–15Seconds. Default 5.
aspect_ratiostring16:9 9:16 1:1 4:3 3:4. Default: matches your image, else 16:9.
referencesarray, ≤ 5Pictures to keep in the clip: character or prop sheets, product shots. See References. Not with image.
audiostringA speech or music track the clip lip-syncs to (URL, data: URI or upload id); cut to duration. Not with image.
webhook_urlhttps URLWe 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.

A red fox in snow at dawnimage
image + prompt → 5 s with sound. Real output, one render.
A sneaker on a plinth, side viewimageThe same sneaker from its other sideend_image
image + 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"}
A curly-haired woman laughing in a cafereference
One reference picture → the same woman in a new scene the prompt describes (a bookshop).
A curly-haired woman in a cafereferenceWaveform of the voice trackaudio
Reference + audio → 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}]}
A woman in a red dress in a dressing roomimage
chain, two 5 s segments: the second starts on the last frame of the first. The join is at 0:05; look for it.

references: 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…"}]}
A small white cartoon robot in a workshopreference
references mode, two 5 s segments made from one picture: the same robot in both, joined with a cut.

keyframes: 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}]}
A neon street at night1The same street at dawn2The same street at midday3
keyframes: three pictures make two segments, night → dawn → day.

Options: 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": "…"}}.

HTTPcodeMeaning
400invalid_image, missing_prompt, …Fix the request; the message says what.
401invalid_keyMissing or revoked key.
402insufficient_creditTop up on your account page.
422content_rejectedBlocked by the content filter. Not charged.
429rate_limited, too_many_active120 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