Skip to navigation

Video Generation

Video takes much longer to make than text or images, so it runs as a job: you start it, poll until it’s done, then download the file. HyperFlowSI follows the OpenAI Videos API.

Find a video model

  • On the Models page, pick the Video type. Each model’s page shows its price per second, and the price for each resolution where it differs.
  • From the API, GET /v1/models lists the models your key can call; video models have "mode": "video".

How it works

  1. Start the job with POST /v1/videos. You get a video id straight away, with status queued.
  2. Poll GET /v1/videos/{id} until the status is completed or failed.
  3. Download the MP4 from the job’s url, or from GET /v1/videos/{id}/content.

Start a job

The samples use the OpenAI SDK set up as in the Quickstart.

curl https://ai.hyperflow.fun/v1/videos \
-H "Authorization: Bearer $HYPERFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/veo-3.1-lite-generate-001",
"prompt": "A paper boat drifting slowly across a calm lake, static camera, soft light",
"seconds": "4",
"size": "16:9"
}'

The response is the new job:

{
"id": "video_3f9c2a...",
"object": "video",
"model": "google/veo-3.1-lite-generate-001",
"status": "queued",
"progress": 0,
"seconds": "4",
"size": "16:9",
"created_at": 1782886429,
"completed_at": null,
"error": null
}

Parameters

ParameterRequiredNotes
modelYesA video model id
promptYesWhat happens in the video: subject, motion, camera, lighting
secondsYesLength in seconds, a positive whole number, such as "4". Each model has a maximum
sizeNoAspect ratio, such as 16:9 or 9:16. Each model offers its own
resolutionNoSuch as 720p or 1080p, on models priced by resolution. Without it, the model’s base price per second applies
input_referenceNoAn image to start the video from, on models that take one
last_frame, reference_imagesNoImages to end on, or to guide the look, on models that take them
seed, generate_audio, watermark, return_last_frameNoPassed to models that support them

The OpenAI SDKs don’t have resolution yet: in Python, pass extra_body={"resolution": "1080p"}; in TypeScript, add resolution: '1080p' to the parameters, cast as for size.

Any other field is removed before the request reaches the model. A seconds, size or resolution the model doesn’t offer is refused with a 400 that says what it does offer, before anything is held.

Poll for the result

GET /v1/videos/{id} returns the job. Videos usually take from about thirty seconds to a few minutes.

import time
while video.status in ("queued", "in_progress"):
time.sleep(10)
video = client.videos.retrieve(video.id)
if video.status == "failed":
print("Failed:", video.error)

The OpenAI SDKs also have client.videos.create_and_poll(...) (Python) and client.videos.createAndPoll(...) (TypeScript), which start the job and wait for it.

Statuses

StatusMeaning
queuedThe job is waiting to start
in_progressThe video is being made
completedThe video is made, paid for and ready to download
failedThe video wasn’t made. error.code says why
error.codeMeaning
video_failedThe model couldn’t make the video
video_expiredThe video wasn’t ready within an hour and was given up on. A 410 from the content endpoint uses the same code for a different reason: see Download the video
not_chargedThe charge for the video didn’t go through, so it isn’t handed over. You aren’t charged

Download the video

Once the status is completed, the job carries a link to the file:

{
"id": "video_3f9c2a...",
"status": "completed",
"progress": 100,
"completed_at": 1782886521,
"expires_at": 1782890121,
"url": "https://..."
}
  • url is a direct link to the MP4 that works until expires_at (Unix seconds). On some models that’s an hour at most; read the job again for a fresh link.
  • GET /v1/videos/{id}/content works with your key until the video expires. It sends the file, or redirects to the link, so let your client follow redirects.
curl -L https://ai.hyperflow.fun/v1/videos/video_3f9c2a.../content \
-H "Authorization: Bearer $HYPERFLOW_API_KEY" \
--output video.mp4

Asking before the video is ready returns 409 with the code video_not_ready. Videos are kept for a limited time, set per model; after that, the content endpoint returns 410 with the code video_expired. Download the videos you want to keep.

List your videos

GET /v1/videos returns your recent videos, newest first, in a data list. Add ?limit= for up to 100; the default is 20.

curl "https://ai.hyperflow.fun/v1/videos?limit=10" \
-H "Authorization: Bearer $HYPERFLOW_API_KEY"

Videos are tied to your account: any of your keys can read them, and no one else’s can. The list can leave out url; read a single video for its link.

Best practices

  • Describe motion and camera. “Slow pan left”, “static camera”, “handheld” and the lighting matter as much as the subject.
  • Start short. Try prompts at the shortest length and lowest resolution, then make the final video.
  • Poll gently. Every 10 to 30 seconds is plenty.
  • Handle failed. Check status and error on every poll.

Troubleshooting

400 when starting a job. seconds is required and must be a positive whole number within the model’s maximum, and size and resolution must be ones the model offers. The message says what the model takes.

403 when starting a job. Video can’t be made yet with a key or an account that has a spending limit. Remove both limits on API keys to make one.

The job stays queued for a long time. Hosts can be busy. Keep polling; a job not done within an hour fails with video_expired.

404 not_found on status or content. The id is wrong. Video ids start with video_.

409 video_not_ready. Wait until the status is completed before downloading.

410 video_expired. The video is past its keep time and can’t be downloaded any more.

Billing

A video is held when you start it, for the seconds you asked for at the price per second for its resolution (or the model’s base price without one). The held amount is unavailable while the job runs. Once the video is made, you’re charged for it and the rest of the hold is released. A video that fails, or is given up on after an hour, isn’t charged, and its whole hold is released.