Bifrost

Videos

POST /v1/videos, polling, content download, list, and delete.

curl -X POST "$GATEWAY/v1/videos" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "video-default", "prompt": "a serene mountain landscape at sunset", "duration": 8, "aspect_ratio": "16:9", "resolution": "720p" }'

POST /v1/videos creates an async generation job and returns a local video_* id. Poll that local id with GET /v1/videos/{video_id}. Download the generated bytes with GET /v1/videos/{video_id}/content; the default variant is video.

Request parameters

There is no industry standard for video generation, so the gateway defines its own surface and stays accept-compatible with OpenAI's Sora shape:

ParameterNotes
model, promptRequired.
durationLength in seconds (integer). seconds (string or int) is the OpenAI-style alias; send one or the other.
sizeExact WIDTHxHEIGHT. Interchangeable with aspect_ratio + resolution; send one form.
aspect_ratio / resolution16:9, 9:16, ... / 480p4K. Reverse-mapped to an exact size for providers that need one.
input_referencesArray of {type: "image_url"|"audio_url"|"video_url", ...} parts. input_reference (single, image_url or file_id) is the OpenAI-style alias.
frame_imagesFirst/last frame conditioning (frame_type: "first_frame"|"last_frame") for models that support it.
seed, generate_audioForwarded only when the model profile declares support.
qualityGateway extension; validated and forwarded only when the profile declares qualities.
userGateway-side attribution only. It is stored with the job and never forwarded upstream.
extra_bodyProvider-specific passthrough merged into the upstream request body.

Every parameter is validated against the model profile before routing, so unsupported parameters fail fast with unsupported_parameter instead of a provider error mid-pool.

Reference images can be sent as data:image/... base64 URLs; large data URLs are redacted before the request body is persisted. Multipart uploads (the OpenAI SDK's file-typed input_reference) are not supported — use the JSON reference forms.

Storage

Videos use the gateway-wide object storage layer. Configure OBJECT_STORAGE_BACKEND=local for development or OBJECT_STORAGE_BACKEND=s3 for S3/R2/MinIO-compatible storage in production. The gateway stores generated video bytes for 24 hours by default (VIDEOS_ASSET_RETENTION_HOURS=24) and keeps metadata in Postgres.

Model profiles

Video-capable deployments declare catalogEntry.operations["video.generate"]. The profile controls accepted durations, sizes (with per-provider aspectRatio/resolution mappings), quality, reference support (supportsImageUrl, supportsAudioUrl, supportsVideoUrl, supportsFileId, supportsFrameImages, maxInputReferences), and supportsSeed/supportsGenerateAudio.

Adapters expose video generation through transports: videos (OpenAI-shaped Videos API), videos_async (async job API: submit /videos, poll /videos/{jobId}, download /videos/{jobId}/content), and generate_videos (Google long-running operations). Adapter defaults pick the common path; use transportOverrides when a custom compatible target needs another transport.

Lifecycle

  • GET /v1/videos lists videos visible to the caller (virtual keys see their own; the master key sees all).
  • GET /v1/videos/{video_id} refreshes upstream status when needed.
  • GET /v1/videos/{video_id}/content streams bytes from object storage and supports byte ranges (including suffix ranges).
  • DELETE /v1/videos/{video_id} deletes stored assets, marks the metadata deleted, and best-effort deletes the upstream job where the provider supports it.

A background poller advances unfinished jobs (VIDEO_JOB_POLL_INTERVAL_MS, batch size VIDEO_JOB_POLL_BATCH_SIZE) and fails jobs that exceed VIDEO_JOB_MAX_RUNTIME_MINUTES. Jobs are claimed atomically, so multiple gateway instances can poll safely.

On this page