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

# Create Video Ads from Product Images with Cherry Shot

> Learn how to generate short video ads from product images using the Cherry Shot API, including duration options, resolution tiers, pricing, and polling.

Cherry Shot Videos animate one or more product images into punchy, ready-to-publish video ads. Feed in images — from a completed shoot or your own library — and get back a polished MP4 complete with motion, optional music, and a logo reveal. Like shoots, video generation is asynchronous: credits are charged up front and automatically refunded if generation fails.

## How a video works

Videos are **asynchronous**. When you call `POST /v1/videos`, Cherry Shot immediately charges the credits for the job and returns a video object with `status: pending`. Generation then proceeds in the background through the following stages:

```
pending → submitted → generating → completed
                                 ↘ failed
```

Poll `GET /v1/videos/{id}` until `status` reaches `completed`, at which point `video_url` holds the MP4 download link.

<Note>
  If generation fails for any reason, the full credit cost is refunded to your account automatically — you are never charged for a video you do not receive.
</Note>

***

## Create a video

`POST /v1/videos`

<ParamField body="image_urls" type="string[]" required>
  An array of public `http(s)` URLs of the source images to animate. The maximum number of images depends on the requested `duration`:

  | Duration     | Max images |
  | ------------ | ---------- |
  | `5` seconds  | 1          |
  | `10` seconds | 3          |
  | `15` seconds | 4          |

  Images from a completed Cherry Shot shoot work perfectly here — just pass the `url` values from the `images` array.
</ParamField>

<ParamField body="duration" type="integer" required>
  The total length of the output video in seconds. Must be `5`, `10`, or `15`.
</ParamField>

<ParamField body="resolution" type="string" required>
  Output resolution. Must be `480p`, `720p`, or `1080p`. Higher resolutions cost more credits per second — see [Pricing](#pricing) below.
</ParamField>

<ParamField body="mode" type="string" default="product_only">
  Controls the visual treatment of the ad:

  * `product_only` — focuses on the product itself; **15% cheaper** than `with_model`.
  * `with_model` — incorporates an AI model interacting with the product.
</ParamField>

<ParamField body="aspect_ratio" type="string">
  The output aspect ratio. Supported values: `21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`.

  If you omit this field, Cherry Shot automatically selects the best ratio based on the dimensions of your source images.
</ParamField>

<ParamField body="logo_url" type="string">
  Optional public URL of a logo image (PNG with transparency recommended). When provided, the logo is revealed as a branded end-card during the final moments of the ad.
</ParamField>

<ParamField body="music" type="boolean" default="true">
  Set to `false` to produce a silent video. When `true`, Cherry Shot selects a royalty-free background track appropriate for the ad's style and pacing.
</ParamField>

<ParamField body="note" type="string">
  Optional plain-text creative direction passed to the generation model. Use this to describe mood, pacing, or specific visual motifs — for example, `"fast cuts, energetic, highlight the label"`.
</ParamField>

<ParamField body="callback_url" type="string">
  Optional. Reserved for future push-delivery support. For now, poll `GET /v1/videos/{id}` to check status.
</ParamField>

### Example request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://kyliwpyuseadbwawnsyd.supabase.co/functions/v1/api/v1/videos \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "image_urls": [
        "https://cdn.cherryshot.com/results/shot-1.png",
        "https://cdn.cherryshot.com/results/shot-2.png",
        "https://cdn.cherryshot.com/results/shot-3.png"
      ],
      "duration": 10,
      "resolution": "720p",
      "mode": "product_only",
      "aspect_ratio": "9:16",
      "music": true,
      "note": "Sleek and minimal, highlight the product from multiple angles"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://kyliwpyuseadbwawnsyd.supabase.co/functions/v1/api/v1/videos",
      headers={
          "x-api-key": "YOUR_API_KEY",
          "Content-Type": "application/json",
      },
      json={
          "image_urls": [
              "https://cdn.cherryshot.com/results/shot-1.png",
              "https://cdn.cherryshot.com/results/shot-2.png",
              "https://cdn.cherryshot.com/results/shot-3.png",
          ],
          "duration": 10,
          "resolution": "720p",
          "mode": "product_only",
          "aspect_ratio": "9:16",
          "music": True,
          "note": "Sleek and minimal, highlight the product from multiple angles",
      },
  )

  video = response.json()
  print(video["id"], video["status"])
  ```

  ```javascript Node theme={null}
  const response = await fetch("https://kyliwpyuseadbwawnsyd.supabase.co/functions/v1/api/v1/videos", {
    method: "POST",
    headers: {
      "x-api-key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      image_urls: [
        "https://cdn.cherryshot.com/results/shot-1.png",
        "https://cdn.cherryshot.com/results/shot-2.png",
        "https://cdn.cherryshot.com/results/shot-3.png",
      ],
      duration: 10,
      resolution: "720p",
      mode: "product_only",
      aspect_ratio: "9:16",
      music: true,
      note: "Sleek and minimal, highlight the product from multiple angles",
    }),
  });

  const video = await response.json();
  console.log(video.id, video.status);
  ```
</CodeGroup>

### Response (pending)

```json theme={null}
{
  "id": "7a2b3c4d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
  "object": "video",
  "status": "pending",
  "credits_used": 34,
  "credits_remaining": 206
}
```

***

## Pricing

Video credits are calculated as:

```
cost = ceil(credits_per_second × duration × mode_multiplier)
```

**Credits per second by resolution:**

| Resolution | Credits / second |
| ---------- | ---------------- |
| `480p`     | 2                |
| `720p`     | 4                |
| `1080p`    | 9                |

**Mode multiplier:**

* `product_only` → **0.85×** (15% discount)
* `with_model` → **1.0×** (no multiplier)

**Example:** A 10-second `720p` video in `product_only` mode costs:

```
ceil(4 × 10 × 0.85) = ceil(34) = 34 credits
```

The same video in `with_model` mode would cost `ceil(4 × 10 × 1.0)` = **40 credits**.

***

## Poll a video

`GET /v1/videos/{id}`

Poll this endpoint to track generation progress. The `status` field moves through the following stages:

| Status       | Meaning                                            |
| ------------ | -------------------------------------------------- |
| `pending`    | Video is queued and credits are charged            |
| `submitted`  | Job has been dispatched to the generation pipeline |
| `generating` | Video frames are being rendered                    |
| `completed`  | Video is ready at `video_url`                      |
| `failed`     | Generation failed; credits have been refunded      |

When `status` is `completed`, the `video_url` field holds a direct link to the MP4 file.

<Tip>
  Video generation typically takes **several minutes**, so use a longer polling interval than you would for shoots — checking every **15–30 seconds** is a good starting point.
</Tip>

### Response (completed)

```json theme={null}
{
  "id": "7a2b3c4d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
  "object": "video",
  "status": "completed",
  "video_url": "https://cdn.cherryshot.com/videos/ad-7a2b3c4d.mp4",
  "credits_used": 34,
  "credits_remaining": 206,
  "created_at": "2026-07-01T10:05:00Z"
}
```

The `video_url` is a time-limited signed URL. Download and store the MP4 to your own storage as soon as you receive it.
