Back to docs

Video Generation API

Create Veo 3.1 text-to-video and image-to-video tasks with your API key, then poll the same /api/status endpoint you use for images.

Nano AI API Base URL: https://nanobnana.com

Authentication

Send your API key as a Bearer token on every request. Use the same key to create a task and to check its status. You can create keys on the API keys page of your dashboard.

http
Authorization: Bearer YOUR_API_KEY

Models and credits

Set the model field to one of the values below. Any other value is rejected with HTTP 400 and nothing is charged.

model valueModelText to video (credits)Image to video (credits)
veo3_fastVeo 3.1 Fast (default)2535
veo3Veo 3.1 Quality180180

veo3-fast is accepted as an alias of veo3_fast. If you omit model, veo3_fast is used. Image-to-video pricing applies when image_urls contains at least one URL.

Create a video task

Validates the request, charges credits and returns a task_id. The video is generated asynchronously: poll /api/status or set callback_url to receive the result.

Request bodyJSON
prompt:string

Text description of the video to generate.

model:optionalstring

veo3_fast (alias veo3-fast) or veo3. Any other value returns HTTP 400. Defaults to veo3_fast.

image_urls:optionalstring[]

Public image URLs for image-to-video. With 1 image, the video is built around that image. With 2 images, they become the first and the last frame. imageUrls (camelCase) is accepted as an alias. If both are sent, image_urls is used.

aspect_ratio:optionalstring

16:9, 9:16 or Auto. Auto crops the video to match the uploaded image. Defaults to 16:9.

translation:optionalboolean

When true, the prompt is translated into English before generation. Defaults to true.

watermark:optionalstring

Watermark text to add to the video.

callback_url:optionalstring

Public URL that receives a POST request with the final result when the task finishes.

Fields that are not supported

duration, resolution and image_url (singular) are not part of this API and are ignored. The model decides the video length. Send images as an image_urls array.

bash
curl -X POST "https://nanobnana.com/api/video/generate" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "The camera slowly pushes in as the city lights turn on at dusk",
    "model": "veo3_fast",
    "image_urls": ["https://example.com/first-frame.jpg"],
    "aspect_ratio": "16:9"
  }'
{
  "code": 200,
  "message": "success",
  "data": {
    "task_id": "veo24223f74e4f445ec9c4403b532cc328fbksv"
  }
}

Check task status

Video task IDs start with veo and end with bksv. /api/status detects them automatically and returns the video URL when the task is completed.

Query parameters
task_id:string

The task_id returned by POST /api/video/generate.

model:optionalstring

Set to veo3 to force video routing for a task_id that does not follow the veo…bksv format.

bash
curl "https://nanobnana.com/api/status?task_id=veo24223f74e4f445ec9c4403b532cc328fbksv" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "code": 200,
  "message": "success",
  "data": {
    "task_id": "veo24223f74e4f445ec9c4403b532cc328fbksv",
    "request": {
      "prompt": "The camera slowly pushes in as the city lights turn on at dusk",
      "model": "veo3_fast",
      "image_urls": [
        "https://example.com/first-frame.jpg"
      ],
      "aspect_ratio": "16:9"
    },
    "response": null,
    "status": "IN_PROGRESS",
    "status_code": 3,
    "status_text": "IN_PROGRESS",
    "consumed_credits": 35,
    "created_at": "2026-10-04 17:05:12",
    "model": "veo3"
  },
  "model": "veo3"
}

Status values

  • IN_PROGRESS · status_code: 3 — the video is still being generated. Keep polling.
  • COMPLETED · status_code: 1 — the video is ready. response contains the video URL.
  • FAILED · status_code: 2 — generation failed. error_message explains why, and the credits are refunded automatically.

Billing and refunds

  • Credits are charged when the task is created, before generation starts.
  • If the create request does not return HTTP 200, no task exists and the charged credits are refunded immediately. The response states how many credits were refunded.
  • If a created task later ends as FAILED, its credits are refunded automatically and consumed_credits in the status response becomes 0.

Polling example

Video generation usually takes a few minutes. Poll every 10 seconds while status_code is 3, and stop when it is 1 or 2.

javascript
async function waitForVideo(taskId) {
  while (true) {
    const res = await fetch(`https://nanobnana.com/api/status?task_id=${taskId}`, {
      headers: { Authorization: 'Bearer YOUR_API_KEY' }
    });
    const payload = await res.json();
    if (!res.ok) throw new Error(payload.message);

    const task = payload.data;
    if (task.status_code === 1) return task.response[0];
    if (task.status_code === 2) throw new Error(task.error_message || 'Video generation failed');

    await new Promise((resolve) => setTimeout(resolve, 10000));
  }
}

Callback

If you set callback_url, we send a POST request with this JSON body when the task completes or fails. The URL must be reachable from the public internet.

{
  "code": 200,
  "message": "success",
  "data": {
    "request": {
      "prompt": "The camera slowly pushes in as the city lights turn on at dusk",
      "model": "veo3_fast",
      "image_urls": [
        "https://example.com/first-frame.jpg"
      ],
      "aspect_ratio": "16:9"
    },
    "response": [
      "https://example.com/generated-video.mp4"
    ],
    "status": "COMPLETED",
    "created_at": "2026-10-04 17:05:12"
  }
}

Common errors

{
  "code": 400,
  "message": "prompt is required",
  "data": null
}