A black steam locomotive rolls into a heritage platform at dusk and slows to a stop, beginning as a distant headlight glow and ending enveloped in thick white steam. Fixed platform-level camera, warm lamp reflections sliding across wet metal. Natural sound: approaching chug, one long whistle, brake squeal, the hiss of released steam. Realistic motion, no text, no logos.
Veo 3.1 Official Image-to-Video API
google/veo3.1/image-to-videoOfficial Google Veo 3.1 flagship image-to-video endpoint breathes life into still imagery. Animate single start frames or interpolate smoothly between start and end frames with synchronized native audio up to 4K.
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, submit the inputs and instructions, then retrieve the video using the task ID.
Connect to the Vidgo API
Create an API key, keep it only on your server, and send 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 in the inputs and settings for this endpoint using the request example, then save the returned task_id to query generation progress and results.
REQUEST_BODY=$(cat <<'JSON'
{
"model": "google/veo3.1/image-to-video",
"input": {
"prompt": "A black steam locomotive rolls into a heritage platform at dusk and slows to a stop, beginning as a distant headlight glow and ending enveloped in thick white steam. Fixed platform-level camera, warm lamp reflections sliding across wet metal. Natural sound: approaching chug, one long whistle, brake squeal, the hiss of released steam. Realistic motion, no text, no logos.",
"duration": 8,
"aspect_ratio": "16:9",
"sound": true,
"resolution": "720p",
"image_urls": [
"https://cdn.vidgo.ai/apis/models/google/veo-3.1-official/image-to-video/v1/01/input-start-frame.png",
"https://cdn.vidgo.ai/apis/models/google/veo-3.1-official/image-to-video/v1/01/input-end-frame.png"
],
"generation_type": "frame"
}
}
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
Query with task_id, continue for not_started/running, and stop for finished/failed. On success, read data.files[].file_url.
Track status
GET https://api.vidgo.ai/api/generate/status/{task_id}Poll status with a 2-second base interval, and increase the interval for longer tasks. Continue only while status is not_started or running, and stop once finished or failed. You can also specify callback_url in the request payload to receive webhook notifications.
not_startedrunningfinishedfailed{
"code": 200,
"data": {
"task_id": "task-unified-...",
"status": "running",
"created_time": "2026-09-17T10: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 a complete script with HTTP and business-code checks, task_id validation, polling, terminal-state handling, and a timeout boundary.
set -euo pipefail
: "${VIDGO_API_KEY:?Set VIDGO_API_KEY in your environment}"
REQUEST_BODY=$(cat <<'JSON'
{
"model": "google/veo3.1/image-to-video",
"input": {
"prompt": "A black steam locomotive rolls into a heritage platform at dusk and slows to a stop, beginning as a distant headlight glow and ending enveloped in thick white steam. Fixed platform-level camera, warm lamp reflections sliding across wet metal. Natural sound: approaching chug, one long whistle, brake squeal, the hiss of released steam. Realistic motion, no text, no logos.",
"duration": 8,
"aspect_ratio": "16:9",
"sound": true,
"resolution": "720p",
"image_urls": [
"https://cdn.vidgo.ai/apis/models/google/veo-3.1-official/image-to-video/v1/01/input-start-frame.png",
"https://cdn.vidgo.ai/apis/models/google/veo-3.1-official/image-to-video/v1/01/input-end-frame.png"
],
"generation_type": "frame"
}
}
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 the inputs for this task and configure the output.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| prompt | string | Yes | — | 1–1,000 characters after trimming. |
| image_urls | array | Yes | — | 1 or 2 public image URLs. Two images also send generation_type as frame. |
| generation_type | string | No | frame with two images | Optional. Omitted with one image; defaults to frame with two images. Explicit frame requires exactly two images. |
| duration | integer | No | 8 | 4, 6, or 8, in seconds. |
| aspect_ratio | string | No | 16:9 | auto, 16:9, or 9:16. |
| resolution | string | No | 720p | 720p / 1080p / 4k. |
| sound | boolean | No | true | true generates native audio; false returns a silent clip. |
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 ID used in the status endpoint path. |
| data.status | string | not_started, running, finished, or failed. |
| data.created_time | string | Task creation time in date-time format. |
| data.progress | integer | Task progress from 0 to 100, when included in the response. |
| data.files[] | array | All output files from a successful task, in response order. |
| data.files[].file_url | string | Public URL for a generated video. |
| data.files[].file_type | string | File type, such as video. |
| data.error_message | string | null | Failure detail when status is failed. |
Task Lifecycle
Continue querying while the status is not_started or running. End polling at finished or failed, then process the output files or error details respectively.
not_startedThe task was accepted and is waiting to begin.
runningGeneration is in progress. Continue polling the same task_id.
finishedGeneration succeeded. Read every video URL from data.files[].file_url.
failedGeneration stopped with an error. Read data.error_message and stop polling.
Polling and Errors
- AuthenticationFor a 401 response, check the Bearer API key in Authorization, update the credentials, and retry.
- ValidationFor a 400 response, use the response details to check required inputs, parameter values, and available credits, then make the indicated adjustments before submitting again.
- Network and timeoutIf a status query encounters a network error or timeout, retain the original task_id and retry the query, then handle the result according to the returned task status.
- Polling intervalPoll status with a 2-second base interval, and gradually increase the interval for longer tasks.
- Terminal statesContinue only for not_started or running. Stop immediately on finished or failed.
- Callback optionProvide callback_url at the request top level to receive the final flat task object; polling remains available if delivery fails.
Endpoint limits
| Specification | Value | Details |
|---|---|---|
| Input mode | Image plus text | A start image is required. An optional end image uses first/last-frame control. |
| Output | Video with optional native audio | The endpoint returns an asynchronous task ID; finished tasks include a video file. |
| Resolution | 720p / 1080p / 4k | Default is 720p. |
| Duration | 4 / 6 / 8 seconds | Default is 8 seconds. |
| Aspect ratio | auto / 16:9 / 9:16 | Default is 16:9. |
| Billing basis | Per second | 720p silent 24 credits/s; audio 48 credits/s. 1080p silent 24 credits/s; audio 48 credits/s. 4k silent 48 credits/s; audio 72 credits/s. |
Related Models
Veo 3.1 Official Image-to-Video API frequently asked questions
What is the Veo 3.1 Official Image-to-Video API?
Veo 3.1 Official Image-to-Video gives developers access to the official Google Veo 3.1 model family through Vidgo API. This page is the Image-to-Video endpoint for Veo 3.1 Official.
What model ID should I use?
Use google/veo3.1/image-to-video in the model field. Do not submit the page path that contains -official.
Does Veo 3.1 Official support audio?
Yes. Use the sound parameter to request audio or silent output. Audio and no-audio jobs have different per-second rates.
What image input modes are supported?
One image creates image-to-video. Two images use first/last-frame mode and send generation_type as frame.
What limitations should I know before integrating?
Prompts are limited to 1000 characters. Duration supports 4, 6, or 8 seconds. Fast and Quality Official support 720p, 1080p, and 4K.
How does async delivery work?
Submit a job to the generate endpoint and receive a task_id. Your backend can poll status by task_id or include callback_url to receive the result asynchronously.
When should I choose Lite, Fast, or Quality?
Choose Lite for low-cost iteration, Fast for balanced production jobs and 4K access, and Quality when you need the strongest output quality or premium 4K results.
When is Veo 3.1 Official not the right choice?
It is not ideal if you need one request to generate more than 8 seconds or a three-image reference workflow.















