Begin exactly on the first frame and finish on the last frame. One continuous 5-second locked close-up: the folded paper crane's wings slowly uncrease and lift until they match the end still. Preserve the same crane, paper color, table, window light, and camera. Native audio: dry paper flex, a faint wooden-table creak, quiet room tone. No logos, no readable text, no products, no packaging, no prices, no CTA, no advertising, no watermark, no brand marks.
FLUX 3 First Last Frame to Video API
blackforestlabs/flux-3/first-last-frame-to-videoFLUX 3 First Last Frame to Video anchors both opening and closing still frames to generate 5–20 seconds of coherent transitional video with optional synchronized native audio. Direct motion trajectories, camera movement, and audio between two precise visual compositions.
Drag and drop files, paste from clipboard, or provide a URL.
1/1 files added
Drag and drop files, paste from clipboard, or provide a URL.
1/1 files added
Examples
REST API
Quick Start
Authenticate with the API, supply opening and closing frame URLs, and retrieve video using the task ID.
Connect to the Vidgo API
Create an API key, store securely on your server, and include Authorization: Bearer VIDGO_API_KEY.
- Endpoint
- POST
https://api.vidgo.ai/api/generate/submit - Authentication
- Authorization: Bearer VIDGO_API_KEY
Submit one generation task
Fill parameters with start and end URLs in order, submit, and save task_id for progress queries.
REQUEST_BODY=$(cat <<'JSON'
{
"model": "blackforestlabs/flux-3/first-last-frame-to-video",
"input": {
"prompt": "Begin exactly on the first frame and finish on the last frame. One continuous 5-second locked close-up: the folded paper crane's wings slowly uncrease and lift until they match the end still. Preserve the same crane, paper color, table, window light, and camera. Native audio: dry paper flex, a faint wooden-table creak, quiet room tone. No logos, no readable text, no products, no packaging, no prices, no CTA, no advertising, no watermark, no brand marks.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "auto",
"sound": true,
"image_urls": [
"https://cdn.vidgo.ai/apis/models/blackforestlabs/flux-3/first-last-frame-to-video/v1/01/input-start-frame.webp",
"https://cdn.vidgo.ai/apis/models/blackforestlabs/flux-3/first-last-frame-to-video/v1/01/input-end-frame.webp"
]
}
}
JSON
)
RESPONSE=$(curl --silent --show-error --fail-with-body \
--request POST \
--url "https://api.vidgo.ai/api/generate/submit" \
--header "Authorization: Bearer $VIDGO_API_KEY" \
--header "Content-Type: application/json" \
--data "$REQUEST_BODY")
CODE=$(printf '%s' "$RESPONSE" | jq -r '.code // empty')
if [ "$CODE" != "0" ] && [ "$CODE" != "200" ]; then
printf 'API error: %s
' "$RESPONSE" >&2
exit 1
fi
printf '%s
' "$RESPONSE"Wait for the result
Poll with task_id while running, stop on finished or failed. On success, download data.files[].file_url.
Track status
GET https://api.vidgo.ai/api/generate/status/{task_id}Poll status with a 2-second base interval. Continue querying while not_started or running, and stop on finished or failed. You can also supply callback_url in the request to receive webhook notifications.
not_startedrunningfinishedfailed{
"code": 200,
"data": {
"task_id": "task-flux3-flf-...",
"status": "running",
"created_time": "2026-09-16T10:00:00Z"
}
}{
"code": 200,
"data": {
"task_id": "task-unified-...",
"status": "finished",
"files": [
{
"file_url": "https://storage.vidgo.ai/generated/video.mp4",
"file_type": "video"
}
],
"created_time": "2026-08-22T10:00:00Z",
"progress": 100,
"error_message": null
}
}Complete runnable example
Expand for an end-to-end integration script with response checks, polling loops, and error boundaries.
set -euo pipefail
: "${VIDGO_API_KEY:?Set VIDGO_API_KEY in your environment}"
REQUEST_BODY=$(cat <<'JSON'
{
"model": "blackforestlabs/flux-3/first-last-frame-to-video",
"input": {
"prompt": "Begin exactly on the first frame and finish on the last frame. One continuous 5-second locked close-up: the folded paper crane's wings slowly uncrease and lift until they match the end still. Preserve the same crane, paper color, table, window light, and camera. Native audio: dry paper flex, a faint wooden-table creak, quiet room tone. No logos, no readable text, no products, no packaging, no prices, no CTA, no advertising, no watermark, no brand marks.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "auto",
"sound": true,
"image_urls": [
"https://cdn.vidgo.ai/apis/models/blackforestlabs/flux-3/first-last-frame-to-video/v1/01/input-start-frame.webp",
"https://cdn.vidgo.ai/apis/models/blackforestlabs/flux-3/first-last-frame-to-video/v1/01/input-end-frame.webp"
]
}
}
JSON
)
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
--request POST \
--url "https://api.vidgo.ai/api/generate/submit" \
--header "Authorization: Bearer $VIDGO_API_KEY" \
--header "Content-Type: application/json" \
--data "$REQUEST_BODY")
TASK_ID=$(printf '%s' "$SUBMIT_RESPONSE" | jq -r '.data.task_id // .task_id // empty')
BUSINESS_CODE=$(printf '%s' "$SUBMIT_RESPONSE" | jq -r '.code // empty')
if [ "$BUSINESS_CODE" != "0" ] && [ "$BUSINESS_CODE" != "200" ]; then
printf 'Submit failed:
%s
' "$SUBMIT_RESPONSE" >&2
exit 1
fi
if [ -z "$TASK_ID" ]; then
printf 'Submit response did not include task_id:
%s
' "$SUBMIT_RESPONSE" >&2
exit 1
fi
START_TIME=$(date +%s)
POLL_DELAY=2
while true; do
if [ $(( $(date +%s) - START_TIME )) -ge 600 ]; then
printf 'Timed out after 600 seconds
' >&2
exit 1
fi
STATUS_RESPONSE=$(curl --silent --show-error --fail-with-body \
--url "https://api.vidgo.ai/api/generate/status/$TASK_ID" \
--header "Authorization: Bearer $VIDGO_API_KEY")
STATUS=$(printf '%s' "$STATUS_RESPONSE" | jq -r '.data.status // .status // empty')
BUSINESS_CODE=$(printf '%s' "$STATUS_RESPONSE" | jq -r '.code // empty')
if [ "$BUSINESS_CODE" != "0" ] && [ "$BUSINESS_CODE" != "200" ]; then
printf 'Status request failed:
%s
' "$STATUS_RESPONSE" >&2
exit 1
fi
case "$STATUS" in
finished)
printf '%s' "$STATUS_RESPONSE" | jq -r '(.data.files // .files // [])[]?.file_url'
break
;;
failed)
printf '%s' "$STATUS_RESPONSE" | jq -r '.data.error_message // .error_message // "Generation failed"' >&2
exit 1
;;
not_started|running)
sleep "$POLL_DELAY"
if [ "$POLL_DELAY" -lt 10 ]; then POLL_DELAY=$((POLL_DELAY + 1)); fi
;;
*)
printf 'Unexpected task status: %s
' "$STATUS" >&2
exit 1
;;
esac
doneInput parameters
The table lists available input parameters, types, and defaults. Request examples also include the required top-level model field. Prepare inputs and configure output specifications.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| prompt | string | Yes | — | Describes transition motion, camera movement, and audio between frames. |
| image_urls | string[] | Yes | — | Array of exactly 2 public image URLs. Index 0 is start frame, index 1 is end frame. |
| duration | integer | No | 5 | Output video duration in seconds from 5 to 20. |
| resolution | string | No | 720p | Output resolution, 720p or 1080p. |
| aspect_ratio | string | No | auto | Framing ratio: auto, 21:9, 2:1, 16:9, 4:3, 1:1, 3:4, or 9:16. |
| sound | boolean | No | true | Whether to generate native synchronized audio. |
Response Fields
A successful submission returns a task ID. Status queries provide progress, output files, and error details when a task fails.
| Field | Type | Description |
|---|---|---|
| code | integer | Application result code; successful responses use 0 or 200. |
| message | string | Human-readable message or error detail when present. |
| data.task_id | string | Task identifier used for querying generation status. |
| data.status | string | not_started, running, finished, or failed. |
| data.created_time | string | Task creation timestamp in date-time format. |
| data.progress | integer | Progress percentage reported from 0 to 100. |
| data.files[] | array | Array of output files generated upon task completion. |
| data.files[].file_url | string | Public URL for the generated video file. |
| data.files[].file_type | string | Output file MIME category, such as video. |
| data.error_message | string | null | Failure details when status is failed. |
Task Lifecycle
Continue querying while status is not_started or running. End polling at finished or failed, then process output files or error details respectively.
not_startedThe task was accepted and is waiting in the queue.
runningGeneration is in progress. Continue polling the task_id.
finishedGeneration succeeded. Read video URLs from data.files[].file_url.
failedGeneration failed. Read data.error_message and halt polling.
Polling and Errors
- AuthenticationOn 401 response, verify the Bearer API key in the Authorization header and retry.
- ValidationOn 400 response, verify that image_urls has exactly 2 public URLs in chronological order.
- Network and timeoutIf status polling encounters network interruptions, retain task_id and retry status queries.
- Polling intervalPoll status with a 2-second base interval, extending intervals for longer renders.
- Terminal statesContinue polling only on not_started or running. Stop immediately once finished or failed.
- Callback optionProvide callback_url in request top level to receive final task payloads via webhook.
Endpoint limits
| Specification | Value | Details |
|---|---|---|
| Input mode | 2 images (start/end) + Prompt | Ordered pair of start and end image URLs with transition prompt. |
| Output | Video with native audio | Returns asynchronous task ID yielding standard MP4 video. |
| Duration | 5–20 seconds | Integer range, default 5 seconds. |
| Resolution | 720p / 1080p | Default is 720p. |
| Aspect ratio | 8 options (including auto) | auto, 21:9, 2:1, 16:9, 4:3, 1:1, 3:4, 9:16, default auto. |
| Billing basis | Duration × Resolution rate | 34 credits/sec for 720p, 58 credits/sec for 1080p. |
Related Endpoints
FLUX 3 First Last Frame to Video API frequently asked questions
What is the FLUX 3 First Last Frame to Video API?
FLUX 3 First Last Frame to Video is a Black Forest Labs model for synthesizing continuous video transitions between two designated still frames. Using user-supplied start and end stills as fixed composition targets, it generates 5 to 20 second video clips up to 1080p resolution with optional synchronized native audio. Built with deep motion interpolation capabilities, it preserves subject identity, spatial perspective, and surface textures while computing physically coherent camera trajectories and movement between both poles. You can call it programmatically or try it from the playground above.
How are images ordered in FLUX 3 First Last Frame to Video?
The image_urls array must contain exactly two items in chronological sequence: index 0 serves as the opening frame, and index 1 serves as the closing destination frame. The model generates forward motion from the former to the latter.
How should prompts guide the transition between frames?
Prompts should focus on how the subject moves and how the camera transitions between states. For example, 'subject stands up smoothly and steps to the desk while the camera dollies right' gives the interpolation engine explicit guidance for plausible motion paths.
How do I create seamless looping animations with FLUX 3 First Last Frame to Video?
Supply the exact same image URL as both index 0 and index 1 in image_urls, and describe a continuous cyclic action in prompt (such as a 360-degree orbit or subtle atmospheric motion). The clip will conclude seamlessly where it began.
Does FLUX 3 First Last Frame to Video generate transition audio?
Yes. When sound is true, the model evaluates visual changes across both frames alongside prompt instructions to synthesize matching dynamic sound effects and ambient progression.
What duration is recommended for wide differences between frames?
If there is significant displacement or a complex posture shift between the start and end images, setting duration to 8–15 seconds gives the physics engine sufficient time to render natural acceleration and deceleration.
Which endpoint should I use to direct more than two keyframe points?
This endpoint specializes in dual-anchor interpolation. To position up to 10 keyframes along a 24 fps timeline, use the FLUX 3 Keyframes to Video endpoint for comprehensive multi-shot storyboard directing.















