> ## Documentation Index
> Fetch the complete documentation index at: https://docs.znapai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Gemini Video generation

## 3-Step Video Generation Workflow

### Step 1: Initiate Video Generation

Request a new video generation task by calling the `:predictLongRunning` RPC on the model.

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.znapai.com/gemini/v1beta/models/veo-3.1-generate-preview:predictLongRunning' \
  --header 'x-goog-api-key: $ZnapAI_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
      "instances": [
        {
          "prompt": "A cat playing with a ball of yarn in a sunny garden"
        }
      ],
      "parameters": {
        "durationSeconds": 4,
        "resolution": "720p",
        "aspectRatio": "16:9"
      }
    }'
  ```
</CodeGroup>

#### Response

```json theme={null}
{
  "name": "models/veo-3.1-generate-preview/operations/{OPERATION_ID}"
}
```

***

### Step 2: Poll for Completion

Using the operation ID returned from Step 1, poll the status endpoint until `"done": true` is returned.

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.znapai.com/gemini/v1beta/models/veo-3.1-generate-preview/operations/{OPERATION_ID}' \
  --header 'x-goog-api-key: $ZnapAI_API_KEY'
  ```
</CodeGroup>

#### Response (Once Completed)

```json theme={null}
{
  "name": "models/veo-3.1-generate-preview/operations/{OPERATION_ID}",
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.ai.generativelanguage.v1beta.PredictLongRunningResponse",
    "generateVideoResponse": {
      "generatedSamples": [
        {
          "video": {
            "uri": "https://generativelanguage.googleapis.com/v1beta/files/{FILE_ID}:download?alt=media"
          }
        }
      ]
    }
  }
}
```

***

### Step 3: Download Video

Substitute the Google API host (`https://generativelanguage.googleapis.com/v1beta`) with the proxy base URL (`https://api.znapai.com/gemini/v1beta`) to route the download request through ZnapAI.

<Important>
  The query parameter `?alt=media` must be included at the end of the download
  request. Without it, the API will reject the request or return file metadata
  instead of the raw video bytes.
</Important>

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.znapai.com/gemini/v1beta/files/{FILE_ID}:download?alt=media' \
  --header 'x-goog-api-key: $ZnapAI_API_KEY' \
  --output generated_video.mp4
  ```
</CodeGroup>

***

## Supported Generation Modes

| Feature                      | Parameter(s)              | Status                                                         |
| :--------------------------- | :------------------------ | :------------------------------------------------------------- |
| **Text → Video**             | `prompt`                  | ✅ Supported                                                    |
| **Image → Video**            | `image`                   | ✅ Supported                                                    |
| **First Frame & Last Frame** | `firstFrame`, `lastFrame` | ✅ Supported (only works with duration of 8 sec)                |
| **Video Extension**          | `video`                   | ✅ Supported (not on lite; input must be a Veo-generated video) |
| **Reference Images**         | `referenceImages`         | ✅ Supported (not on lite; requires 8 sec duration)             |
| **Video Duration**           | `durationSeconds`         | ✅ Supported                                                    |
| **Aspect Ratio**             | `aspectRatio`             | ✅ Supported                                                    |
| **Seed**                     | `seed`                    | ✅ Supported                                                    |
| **Negative Prompt**          | `negativePrompt`          | ⚠️ Partial                                                     |

### Model Feature Support

As tested through this proxy, `veo-3.1-generate-preview` and `veo-3.1-fast-generate-preview` behave identically for every feature below; `veo-3.1-lite-generate-preview` differs on reference images and negative prompt.

| Feature            | `veo-3.1-generate-preview` & `veo-3.1-fast-generate-preview` | `veo-3.1-lite-generate-preview`             |
| :----------------- | :----------------------------------------------------------- | :------------------------------------------ |
| Text → Video       | ✅ Supported                                                  | ✅ Supported                                 |
| Image → Video      | ✅ Supported                                                  | ✅ Supported                                 |
| First & Last Frame | ✅ Supported (`durationSeconds: 8` required)                  | ✅ Supported (`durationSeconds: 8` required) |
| Reference Images   | ✅ Supported (`durationSeconds: 8` or omitted required)       | ❌ Not supported (any duration)              |
| Video Extension    | ✅ Supported (input must be a Veo-generated video)            | ❌ Not supported                             |
| Negative Prompt    | ✅ Supported                                                  | ❌ Not supported                             |

### First & Last Frame Generation (Interpolation)

You can generate a video transition between two images (a starting state and an ending state) by providing both a first frame and a last frame:

* **First Frame:** Can be passed via `instances[0].firstFrame` or `instances[0].image`.
* **Last Frame:** Must be passed via `instances[0].lastFrame`.

The model will generate a smooth animation interpolating between the two frames based on the prompt.

<Important>
  First-to-last frame interpolation requires **exactly 8 seconds** as the
  duration (`durationSeconds: 8`). Passing any value less than 8 is unsupported.
</Important>

<Note>
  Unlike `referenceImages`, first/last frame interpolation is supported across all three model variants: `veo-3.1-generate-preview`, `veo-3.1-lite-generate-preview`, and `veo-3.1-fast-generate-preview`.
</Note>

**Example Request:**

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.znapai.com/gemini/v1beta/models/veo-3.1-generate-preview:predictLongRunning' \
  --header 'x-goog-api-key: $ZnapAI_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
      "instances": [
        {
          "prompt": "Smooth cinematic transition from a sunny orange-purple gradient scene with a yellow sun to a cool blue-green gradient scene with a red square target",
          "image": {
            "bytesBase64Encoded": "<BASE64_FIRST_FRAME_PNG>",
            "mimeType": "image/png"
          },
          "lastFrame": {
            "bytesBase64Encoded": "<BASE64_LAST_FRAME_PNG>",
            "mimeType": "image/png"
          }
        }
      ],
      "parameters": {
        "aspectRatio": "16:9",
        "durationSeconds": 8,
        "resolution": "720p"
      }
    }'
  ```
</CodeGroup>

### Reference Images (Subject Consistency)

You can guide the appearance of a subject (e.g. a character or object) across the generated video by providing 1–3 reference images via `instances[0].referenceImages`, each with a `referenceType` of `"asset"`.

<Important>
  `referenceImages` requires **exactly 8 seconds** as the duration (`durationSeconds: 8`), the same constraint as first/last frame interpolation. Passing any other value (e.g. `4`) causes the request to be rejected with a generic `"Your use case is currently not supported"` error — this looks like a model-support issue but is actually a duration mismatch. Omitting `durationSeconds` entirely also works.
</Important>

<Warning>
  `referenceImages` is **not supported on `veo-3.1-lite-generate-preview`**, regardless of duration — it always returns a model-specific `400` error. It works on both `veo-3.1-generate-preview` and `veo-3.1-fast-generate-preview` once `durationSeconds` is set to `8` (or omitted).
</Warning>

**Example Request:**

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.znapai.com/gemini/v1beta/models/veo-3.1-generate-preview:predictLongRunning' \
  --header 'x-goog-api-key: $ZnapAI_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
      "instances": [
        {
          "prompt": "The blue robot character from the reference image walks across a futuristic neon city street at night, looking around curiously",
          "referenceImages": [
            {
              "image": {
                "bytesBase64Encoded": "<BASE64_REFERENCE_IMAGE_PNG>",
                "mimeType": "image/png"
              },
              "referenceType": "asset"
            }
          ]
        }
      ],
      "parameters": {
        "aspectRatio": "16:9",
        "durationSeconds": 8,
        "resolution": "720p"
      }
    }'
  ```
</CodeGroup>

### Video Extension

You can extend a previously generated Veo video by 7 seconds (repeatable up to 20 times) by passing it via `instances[0].video`.

<Important>
  The input video **must be a video previously generated by Veo** (referenced via its file download URI), not an arbitrary uploaded video. Videos are retained for 2 days after generation, and referencing one for extension resets that 2-day timer.
</Important>

<Warning>
  Pass the video as `"video": {"uri": "<file-download-url>"}` — the URI returned from a prior `predictLongRunning` poll response (`response.generateVideoResponse.generatedSamples[0].video.uri`). Passing raw video bytes via `bytesBase64Encoded` (or `inlineData`) fails with `"Video URI not found in the request."` Video extension is **not supported on `veo-3.1-lite-generate-preview`**; it works on both `veo-3.1-generate-preview` and `veo-3.1-fast-generate-preview`.
</Warning>

**Example Request:**

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.znapai.com/gemini/v1beta/models/veo-3.1-generate-preview:predictLongRunning' \
  --header 'x-goog-api-key: $ZnapAI_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
      "instances": [
        {
          "prompt": "The camera continues panning across the cool blue-green gradient scene, the red square target pulses gently with light",
          "video": {
            "uri": "https://generativelanguage.googleapis.com/v1beta/files/<FILE_ID>:download?alt=media"
          }
        }
      ],
      "parameters": {
        "resolution": "720p"
      }
    }'
  ```
</CodeGroup>

#### Chaining Extensions (Extend Again)

To extend a video more than once, take the `uri` from the **most recent** extension's completed poll response — not the original input video — and pass that into the next extension request. The call shape is identical each time; only the `uri` and `prompt` change.

<Note>
  Confirmed working: extending an already-extended video succeeds the same way as the first extension, with no different payload shape or extra fields required. Each successful call adds another \~7 seconds and returns a new `uri` to chain from for the next call, up to 20 times total.
</Note>

**Example Request (extending an already-extended video):**

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://api.znapai.com/gemini/v1beta/models/veo-3.1-generate-preview:predictLongRunning' \
  --header 'x-goog-api-key: $ZnapAI_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
      "instances": [
        {
          "prompt": "The scene shifts further, the red square target now floats gently upward into a starry night sky",
          "video": {
            "uri": "https://generativelanguage.googleapis.com/v1beta/files/<FILE_ID_FROM_PREVIOUS_EXTENSION>:download?alt=media"
          }
        }
      ],
      "parameters": {
        "resolution": "720p"
      }
    }'
  ```
</CodeGroup>

## Parameter Specifications

### Optional Parameters

<ParamField path="instances[0].prompt" type="string">
  A text description of the video you want to generate.
</ParamField>

<ParamField path="instances[0].image" type="object">
  Input image for Image-to-Video generation. Can also be used as the starting
  (first) frame when paired with `lastFrame`.
</ParamField>

<ParamField path="instances[0].lastFrame" type="object">
  Input image to guide the ending (last) frame of the video, enabling smooth
  transition/interpolation between the first and last frames.
</ParamField>

<ParamField path="instances[0].video" type="object">
  A previously Veo-generated video to extend by 7 seconds. Must be passed as `{"uri": "<file-download-url>"}`, not as raw bytes.

  <Warning>
    Not supported on `veo-3.1-lite-generate-preview`. Supported on `veo-3.1-generate-preview` and `veo-3.1-fast-generate-preview`. See [Video Extension Validation](#video-extension-validation) below.
  </Warning>
</ParamField>

<ParamField path="instances[0].referenceImages" type="array">
  A list of 1–3 images used to guide the appearance of a subject (e.g. a character or object) across the generated video. Each entry needs a `referenceType` of `"asset"`.

  <Warning>
    Not supported on `veo-3.1-lite-generate-preview` (always rejected). Supported on `veo-3.1-generate-preview` and `veo-3.1-fast-generate-preview`, but **only when `durationSeconds` is `8`** (or omitted) — any other duration is rejected. See [Reference Images Model Support](#reference-images-model-support) below.
  </Warning>
</ParamField>

<ParamField path="parameters.durationSeconds" type="integer">
  The length of the generated video in seconds. Supported values: `4`, `6`, or `8`.

  <Note>
    If using first-to-last frame interpolation, the duration **must be set to exactly 8 seconds**; shorter durations are not supported.
  </Note>
</ParamField>

<ParamField path="parameters.aspectRatio" type="string">
  The aspect ratio of the output video. Supported values: `"16:9"`, `"9:16"`.
</ParamField>

<ParamField path="parameters.resolution" type="string">
  The resolution of the output video. E.g., `"720p"`.
</ParamField>

<ParamField path="parameters.seed" type="integer">
  A seed value to guide the randomness of generation.
</ParamField>

<ParamField path="parameters.negativePrompt" type="string">
  Description of elements you want to avoid in the video.

  <Warning>
    This parameter is **not supported** by `veo-3.1-lite-generate-preview`. Passing it will trigger a `400 Bad Request` validation error.
  </Warning>
</ParamField>

## Validation & Error Behaviour

### Negative Prompt Validation on Lite Model

Passing a `negativePrompt` parameter to the `veo-3.1-lite-generate-preview` model will result in a `400 Bad Request` error:

```json theme={null}
{
  "error": {
    "message": "{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"`negativePrompt` isn't supported by this model. Please remove it or refer to the Gemini API documentation for supported usage.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n",
    "type": "None",
    "param": "None",
    "code": "400"
  }
}
```

### Reference Images Limit

Providing more than 3 reference images will result in a validation error:

```json theme={null}
{
  "error": {
    "message": "{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"Number of reference images can not exceed 3.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n",
    "type": "None",
    "param": "None",
    "code": "400"
  }
}
```

* **Observed Behaviour:** 1–3 reference images are accepted; 4 or more reference images are rejected.

### Reference Images Model Support

`referenceImages` (schema: `image.bytesBase64Encoded` + `referenceType: "asset"`) was tested against all three model variants. The key finding: it works on the full and fast models, but **only with `durationSeconds: 8`** — passing `4` (or `6`) triggers a generic error that looks like a model-support issue but is actually a duration mismatch.

| Model                           | With `durationSeconds: 8` (or omitted) | With `durationSeconds: 4`         |
| :------------------------------ | :------------------------------------- | :-------------------------------- |
| `veo-3.1-generate-preview`      | ✅ Succeeds                             | ❌ Rejected (generic error)        |
| `veo-3.1-fast-generate-preview` | ✅ Succeeds                             | ❌ Rejected (generic error)        |
| `veo-3.1-lite-generate-preview` | ❌ Rejected (model-specific error)      | ❌ Rejected (model-specific error) |

**`veo-3.1-lite-generate-preview`** always rejects with a model-specific message, regardless of duration:

```json theme={null}
{
  "error": {
    "message": "{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"`referenceImages` isn't supported by this model. Please remove it or refer to the Gemini API documentation for supported usage.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n",
    "type": "None",
    "param": "None",
    "code": "400"
  }
}
```

**`veo-3.1-generate-preview`** and **`veo-3.1-fast-generate-preview`** reject with this generic message only when `durationSeconds` isn't `8`:

```json theme={null}
{
  "error": {
    "message": "{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"Your use case is currently not supported.  Please refer to Gemini API documentation for current model offering.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n",
    "type": "None",
    "param": "None",
    "code": "400"
  }
}
```

* **Observed Behaviour:** With `durationSeconds: 8` set (or `parameters` omitted entirely), both the full and fast models return `200` and complete generation successfully. The lite model rejects unconditionally, confirming it's a genuine capability gap rather than a duration issue.

### `inlineData` Image Encoding Rejected

Google's SDKs/REST examples wrap image bytes as `image: { inlineData: { mimeType, data } }`. This proxy does not accept that shape for any image field — use `bytesBase64Encoded` instead:

```json theme={null}
{
  "error": {
    "message": "{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"`inlineData` isn't supported by this model. Please remove it or refer to the Gemini API documentation for supported usage.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n",
    "type": "None",
    "param": "None",
    "code": "400"
  }
}
```

### Video Extension Validation

`instances[0].video` must reference a previously Veo-generated video by its file download URI — passing raw video bytes fails:

```json theme={null}
{
  "error": {
    "message": "{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"Video URI not found in the request.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n",
    "type": "None",
    "param": "None",
    "code": "400"
  }
}
```

`veo-3.1-lite-generate-preview` rejects video extension outright:

```json theme={null}
{
  "error": {
    "message": "{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"Video extension is not allowed for this model.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n",
    "type": "None",
    "param": "None",
    "code": "400"
  }
}
```

* **Observed Behaviour:** `{"video": {"uri": "<file-download-url>"}}` succeeds and completes on both `veo-3.1-generate-preview` and `veo-3.1-fast-generate-preview`. `veo-3.1-lite-generate-preview` rejects the request regardless of payload shape. Chaining a second extension off an already-extended video's `uri` was also tested and completes successfully, with an identical request shape to the first extension.

### Validation Scenarios

| Scenario                                                           | Result / Error                                                |
| :----------------------------------------------------------------- | :------------------------------------------------------------ |
| **More than 3 reference images**                                   | Rejected with correct validation error                        |
| **`referenceImages` on lite model**                                | Rejected — unsupported on this model, any duration            |
| **`referenceImages` on full/fast model with `durationSeconds: 8`** | ✅ Succeeds                                                    |
| **`referenceImages` on full/fast model with `durationSeconds: 4`** | Rejected — generic "use case not supported" error             |
| **`image` using `inlineData` encoding**                            | Rejected — proxy requires `bytesBase64Encoded`                |
| **`lastFrame` without `image`**                                    | Unsupported request                                           |
| **`lastFrame` with `durationSeconds` under 8**                     | Unsupported request (requires exactly 8 seconds)              |
| **`video` with raw bytes (not a `uri`)**                           | Rejected — `"Video URI not found in the request."`            |
| **Video extension on lite model**                                  | Rejected — `"Video extension is not allowed for this model."` |
| **`fileData` parameter**                                           | Explicitly rejected                                           |

***

## Unsupported Fields

### fileData

Passing `fileData` (such as `fileUri` or `mimeType` inside the `video` object) is explicitly unsupported:

```json theme={null}
{
  "video": {
    "fileData": {
      "mimeType": "video/mp4",
      "fileUri": "..."
    }
  }
}
```

**Response:**

```
`fileData` isn't supported by this model.
```
