Veo 3.1 Video Generation API Markdown kopierenAPI for generating videos using Google Veo 3.1 with text-to-video, reference image, and first/last frame modes. Supports multi-shot long videos up to 168 seconds.
Try it online: https://nanophoto.ai/veo-3
Method Path Description POST /api/veo-3/generateGenerate a video POST /api/veo-3/check-statusCheck task status
Authorization: Bearer YOUR_API_KEY
Resolution Shots Credits 720p per shot 10 1080p 1 shot only 14 4K 1 shot only 30
Each shot generates an 8-second video clip. Multi-shot videos are concatenated automatically.
Maximum 21 shots per request (168 seconds total). 1080p and 4K are only available for single-shot generation.
Header Value Content-Typeapplication/jsonAuthorizationBearer YOUR_API_KEY
Parameter Type Required Description shotsobject[] Yes Array of shot objects (max 21) shots[].idstring Yes Unique identifier for the shot shots[].promptstring Yes Video generation prompt shots[].generationTypestring Yes TEXT_2_VIDEO, FIRST_AND_LAST_FRAMES_2_VIDEO, or REFERENCE_2_VIDEOshots[].aspectRatiostring Yes 16:9 or 9:16shots[].imageUrlsstring[] Conditional Public image URLs (see generation type requirements) resolutionstring No 720p (default), 1080p, or 4k (single shot only)
Type Description Images Required TEXT_2_VIDEOText to video None (no images allowed) FIRST_AND_LAST_FRAMES_2_VIDEOFirst/last frame to video 1-2 images REFERENCE_2_VIDEOReference image to video 1-3 images
API calls only accept imageUrls (public URLs). Base64 image upload is not supported via API.
curl -X POST "https://nanophoto.ai/api/veo-3/generate" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-raw '{
"shots": [
{
"id": "shot-1",
"prompt": "A golden retriever running on a beach at sunset, cinematic lighting",
"generationType": "TEXT_2_VIDEO",
"aspectRatio": "16:9"
}
],
"resolution": "720p"
}'
curl -X POST "https://nanophoto.ai/api/veo-3/generate" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-raw '{
"shots": [
{
"id": "shot-1",
"prompt": "The character comes alive, walking through a magical forest",
"generationType": "REFERENCE_2_VIDEO",
"aspectRatio": "16:9",
"imageUrls": ["https://static.nanophoto.ai/demo/nano-banana-pro.webp"]
}
],
"resolution": "720p"
}'
curl -X POST "https://nanophoto.ai/api/veo-3/generate" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-raw '{
"shots": [
{
"id": "shot-1",
"prompt": "Wide shot of a city skyline at dawn, golden hour lighting",
"generationType": "TEXT_2_VIDEO",
"aspectRatio": "16:9"
},
{
"id": "shot-2",
"prompt": "Close-up of a coffee cup on a windowsill, steam rising",
"generationType": "TEXT_2_VIDEO",
"aspectRatio": "16:9"
},
{
"id": "shot-3",
"prompt": "A person walking through a park, autumn leaves falling",
"generationType": "TEXT_2_VIDEO",
"aspectRatio": "16:9"
}
],
"resolution": "720p"
}'
async function generateVideo () {
// Step 1: Submit generation task
const response = await fetch ( "https://nanophoto.ai/api/veo-3/generate" , {
method: "POST" ,
headers: {
"Content-Type" : "application/json" ,
Authorization: "Bearer YOUR_API_KEY" ,
},
body: JSON . stringify ({
shots: [
{
id: "shot-1" ,
prompt: "A golden retriever running on a beach at sunset" ,
generationType: "TEXT_2_VIDEO" ,
aspectRatio: "16:9" ,
},
],
resolution: "720p" ,
}),
});
const data = await response. json ();
if (data.status === "failed" ) {
console. error ( "Generation failed:" , data.error);
return ;
}
// Step 2: Poll for status
const taskIds = data.shots. map (( shot : any ) => ({
shotId: shot.shotId,
taskId: shot.taskId,
}));
while ( true ) {
await new Promise (( resolve ) => setTimeout (resolve, 5000 )); // Wait 5s
const statusRes = await fetch (
"https://nanophoto.ai/api/veo-3/check-status" ,
{
method: "POST" ,
headers: {
"Content-Type" : "application/json" ,
Authorization: "Bearer YOUR_API_KEY" ,
},
body: JSON . stringify ({ taskIds, resolution: "720p" }),
}
);
const status = await statusRes. json ();
if (status.status === "completed" ) {
for ( const shot of status.shots) {
console. log ( `Shot ${ shot . shotId } Video URL:` , shot.videoUrl);
}
return ;
}
if (status.status === "failed" ) {
console. error ( "Generation failed:" , status.shots);
return ;
}
console. log ( "Still processing..." );
}
}
generateVideo ();
{
"status" : "processing" ,
"shots" : [
{
"shotId" : "shot-1" ,
"taskId" : "task_abc123" ,
"status" : "processing"
}
],
"creditsUsed" : 10
}
When you receive status: "processing", poll the check-status endpoint every 5-10 seconds.
{
"error" : "Insufficient credits" ,
"errorCode" : "INSUFFICIENT_CREDITS" ,
"requiredCredits" : 10
}
POST /api/veo-3/check-status
Header Value Content-Typeapplication/jsonAuthorizationBearer YOUR_API_KEY
Parameter Type Required Description taskIdsobject[] Yes Array of task ID objects from generate response taskIds[].shotIdstring Yes Shot ID taskIds[].taskIdstring Yes Task ID from generate response resolutionstring No 720p (default), 1080p, or 4k
curl -X POST "https://nanophoto.ai/api/veo-3/check-status" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-raw '{
"taskIds": [
{"shotId": "shot-1", "taskId": "task_abc123"}
],
"resolution": "720p"
}'
{
"status" : "processing" ,
"shots" : [
{
"shotId" : "shot-1" ,
"taskId" : "task_abc123" ,
"status" : "processing"
}
]
}
{
"status" : "completed" ,
"shots" : [
{
"shotId" : "shot-1" ,
"taskId" : "task_abc123" ,
"status" : "completed" ,
"videoUrl" : "https://video.nanophoto.ai/veo/..." ,
"generationTime" : 90
}
]
}
{
"status" : "failed" ,
"shots" : [
{
"shotId" : "shot-1" ,
"taskId" : "task_abc123" ,
"status" : "failed" ,
"error" : "Video generation failed"
}
]
}
Poll /api/veo-3/check-status every 5-10 seconds
Typical generation time: 2-5 minutes per shot
Multi-shot videos take longer as each shot is generated sequentially
Credits are automatically refunded if generation fails
errorCode HTTP Status Description LOGIN_REQUIRED401 Authentication required API_KEY_RATE_LIMIT_EXCEEDED429 Rate limit exceeded (100 req/hour) INSUFFICIENT_CREDITS402 Not enough credits SHOTS_REQUIRED400 Missing shots array PROMPT_REQUIRED400 Missing prompt in a shot INVALID_IMAGE_COUNT400 Wrong number of images for generation type IMAGE_URLS_REQUIRED400 API calls require imageUrls (no base64) GENERATION_FAILED500 Video generation failed TASK_IDS_REQUIRED400 Missing task IDs TASK_NOT_FOUND404 Task not found or not owned by user INTERNAL_ERROR500 Internal server error