> ## 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.

# Generate Product Photography with Cherry Shot Shoots

> Learn how to create studio-quality product photography shoots via the API, including style options, quality tiers, and polling for results.

Cherry Shot Shoots turn your product images into polished, studio-quality photos — no physical set required. You choose the visual style, quality tier, and whether you want the product shown alone or styled on an AI model. The API handles the rest asynchronously: you create the shoot, then poll until the images are ready.

## How a shoot works

Shoots are **asynchronous**. When you call `POST /v1/shoots`, Cherry Shot immediately reserves the required credits and returns a shoot object with `status: pending`. The shoot then moves through a short pipeline before your images are delivered:

```
pending → analyzing → generating → completed
                                 ↘ failed
```

Poll `GET /v1/shoots/{id}` until `status` is `completed`, then read the `images` array for the finished URLs.

***

## Create a shoot

`POST /v1/shoots`

<ParamField body="product_image_urls" type="string[]" required>
  An array of 1–8 public `http(s)` URLs pointing to your product images. The **first URL is treated as the hero image** and receives the most prominent placement. All URLs must be publicly accessible at request time.
</ParamField>

<ParamField body="style" type="string" required>
  The visual treatment applied to your shoot. Must be one of:

  | Value         | Description                           |
  | ------------- | ------------------------------------- |
  | `classic`     | Clean, timeless studio look           |
  | `minimal`     | White space, editorial simplicity     |
  | `luxury`      | Rich textures, premium staging        |
  | `loud_luxury` | Bold, maximalist high-end aesthetic   |
  | `magazine`    | Editorial spreads, strong composition |
  | `editorial`   | Fashion-forward, story-driven framing |
  | `avant_garde` | Abstract, experimental styling        |
  | `element`     | Ingredient or material hero shots     |
  | `influencer`  | Lifestyle-adjacent, social-ready look |
  | `lifestyle`   | In-context, aspirational staging      |
</ParamField>

<ParamField body="mode" type="string" default="product_only">
  Controls whether the product is shot alone or placed on an AI model.

  * `product_only` — the product is the sole subject.
  * `with_model` — the product is worn or held by an AI model. Requires `model_url`.
</ParamField>

<ParamField body="model_url" type="string">
  Required when `mode` is `with_model`. Provide a public image URL of the model you want to use. Browse available presets via [`GET /v1/models`](/api-reference).
</ParamField>

<ParamField body="shots" type="integer" default="4">
  The number of output images to generate. Accepted values: `1`, `4`, or `6`.

  <Note>
    `6` shots is only available for the `classic` and `minimal` styles. For all other styles, a request for `6` is automatically clamped to `4` and the response will include `shots_adjusted: true`.
  </Note>
</ParamField>

<ParamField body="quality" type="string" default="standard">
  Output resolution and credit cost per image:

  | Value      | Credits / image | Resolution |
  | ---------- | --------------- | ---------- |
  | `standard` | 1               | Default    |
  | `pro`      | 2               | 2K         |
  | `4k`       | 4               | 4K         |
</ParamField>

<ParamField body="aspect_ratio" type="string" default="1:1">
  The output aspect ratio. Common values include `1:1`, `4:5`, `9:16`, and `16:9`. Use `4:5` or `9:16` for portrait-oriented social placements, and `16:9` for widescreen or banner use.
</ParamField>

<ParamField body="background_color" type="string">
  An optional background color hint (e.g. `"#F5F0EB"` or `"ivory"`). Supported for studio-style shoots such as `classic` and `minimal`. Has no effect on styles that use complex scene environments.
</ParamField>

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

### Example request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://kyliwpyuseadbwawnsyd.supabase.co/functions/v1/api/v1/shoots \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "product_image_urls": ["https://example.com/images/product-front.png"],
      "style": "minimal",
      "mode": "product_only",
      "shots": 4,
      "quality": "pro",
      "aspect_ratio": "1:1"
    }'
  ```

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

  response = requests.post(
      "https://kyliwpyuseadbwawnsyd.supabase.co/functions/v1/api/v1/shoots",
      headers={
          "x-api-key": "YOUR_API_KEY",
          "Content-Type": "application/json",
      },
      json={
          "product_image_urls": ["https://example.com/images/product-front.png"],
          "style": "minimal",
          "mode": "product_only",
          "shots": 4,
          "quality": "pro",
          "aspect_ratio": "1:1",
      },
  )

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

  ```javascript Node theme={null}
  const response = await fetch("https://kyliwpyuseadbwawnsyd.supabase.co/functions/v1/api/v1/shoots", {
    method: "POST",
    headers: {
      "x-api-key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      product_image_urls: ["https://example.com/images/product-front.png"],
      style: "minimal",
      mode: "product_only",
      shots: 4,
      quality: "pro",
      aspect_ratio: "1:1",
    }),
  });

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

### Response (pending)

```json theme={null}
{
  "id": "b3f1c2a4-9e87-4d21-bc03-1a2f3e4d5c6b",
  "object": "shoot",
  "status": "pending",
  "shots": 4,
  "credits_used": 8,
  "credits_remaining": 192,
  "created_at": "2026-07-01T10:00:00Z"
}
```

<Note>
  Credits are **reserved at creation time**. If the shoot later fails, credits are refunded to your balance automatically.
</Note>

***

## Poll a shoot

`GET /v1/shoots/{id}`

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

| Status       | Meaning                                       |
| ------------ | --------------------------------------------- |
| `pending`    | Shoot is queued and credits are reserved      |
| `analyzing`  | Cherry Shot is processing your product images |
| `generating` | Images are being rendered                     |
| `completed`  | All images are ready in the `images` array    |
| `failed`     | Generation failed; credits have been refunded |

<Tip>
  Poll every **3–5 seconds**. A full set of 4 images typically completes in well under a minute.
</Tip>

### Response (completed)

```json theme={null}
{
  "id": "b3f1c2a4-9e87-4d21-bc03-1a2f3e4d5c6b",
  "object": "shoot",
  "status": "completed",
  "shots": 4,
  "credits_used": 8,
  "credits_remaining": 192,
  "images": [
    {
      "url": "https://cdn.cherryshot.com/results/shot-1.png",
      "thumbnail_url": "https://cdn.cherryshot.com/results/thumb-1.png",
      "status": "fulfilled"
    },
    {
      "url": "https://cdn.cherryshot.com/results/shot-2.png",
      "thumbnail_url": "https://cdn.cherryshot.com/results/thumb-2.png",
      "status": "fulfilled"
    },
    {
      "url": "https://cdn.cherryshot.com/results/shot-3.png",
      "thumbnail_url": "https://cdn.cherryshot.com/results/thumb-3.png",
      "status": "fulfilled"
    },
    {
      "url": "https://cdn.cherryshot.com/results/shot-4.png",
      "thumbnail_url": "https://cdn.cherryshot.com/results/thumb-4.png",
      "status": "fulfilled"
    }
  ],
  "created_at": "2026-07-01T10:00:00Z"
}
```

Each entry in `images` includes a full-resolution `url` and a `thumbnail_url` suitable for previews. Individual images can have a `status` of `fulfilled` or `failed` — a shoot can complete even if one or more individual shots fail, and credits for any failed shots are returned.
