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

# Variant Product Images API

> Use the Catalog Admin API to group product images by option value so the storefront shows the right images for each variation.

A configurable product often needs different images for each variation, such as one set of photos for the black version and another for the blue version. In the Admin this is done with [Dynamic Imaging](https://docs.kibocommerce.com/pages/dynamic-imaging.md). This guide shows how to set up the same image groups with the Catalog Admin API and how the storefront APIs return the right images for a selected variation.

You set everything on the base product with [Update Product](https://docs.kibocommerce.com/api-reference/products/update-product.md). Variations do not hold their own images. Instead, the base product carries three related pieces of data:

| Field | Where | Purpose |
| - | - | - |
| `isProductImageGroupSelector` | `options[]` | Marks the one option (for example, color) whose values choose the images. |
| `productImageGroups` | Top level of the product | Defines each image group and the option values it applies to. |
| `productImageGroupId` | `content.productImages[]` | Puts an image in a group. Images without a group are in the default group. |

## Before You Begin

* The product must be a configurable product with an option attribute, such as `tenant~color`, on its product type. See [Option Attributes](https://docs.kibocommerce.com/pages/option-attributes.md).
* Note the exact option values on the product. Get the product with [Get Product](https://docs.kibocommerce.com/api-reference/products/get-product.md) and read `options[].values[].value`. Image group tags must use these values exactly, including case.
* Make the images available by URL. Each image needs an `imageUrl` (or a `cmsId` for a file in the Kibo File Manager).

## Step 1: Choose the Selector Option

Set `isProductImageGroupSelector` to `true` on the option that drives the images. Only one option on a product can be the selector. Marking two options returns a validation error.

```json theme={null}
"options": [
  {
    "attributeFQN": "tenant~color",
    "isProductImageGroupSelector": true,
    "values": [
      { "value": "Black" },
      { "value": "Blue" },
      { "value": "Red" }
    ]
  },
  {
    "attributeFQN": "tenant~size",
    "values": [
      { "value": "S" },
      { "value": "M" },
      { "value": "L" }
    ]
  }
]
```

Here color chooses the images. Size does not, so every size of the black product shows the black images.

## Step 2: Define the Image Groups

Add a `productImageGroups` array. Each group has:

* `productImageGroupId`: a code you choose, such as `black`. It must be unique on the product.
* `productImageGroupTags`: the option values the group applies to. Each tag has the option's `fqn` and a `values` array.

A group can apply to more than one value. In this example, the `cool-tones` group is shown for both blue and red:

```json theme={null}
"productImageGroups": [
  {
    "productImageGroupId": "black",
    "productImageGroupTags": [
      { "fqn": "tenant~color", "values": ["Black"] }
    ]
  },
  {
    "productImageGroupId": "cool-tones",
    "productImageGroupTags": [
      { "fqn": "tenant~color", "values": ["Blue", "Red"] }
    ]
  }
]
```

Each group needs an ID and at least one tag, and each tag needs an `fqn` and a value. The `fqn` must be an option attribute on the product's product type.

## Step 3: Assign Images to Groups

In `content.productImages`, set `productImageGroupId` on each image to the group it belongs to. Leave it out (or set it to `default`) for images that belong to the base product, such as a lifestyle shot shown before the shopper picks a color.

```json theme={null}
"content": {
  "productName": "Trail Jacket",
  "productImages": [
    { "imageUrl": "https://cdn.example.com/trail-jacket-main.jpg", "altText": "Trail Jacket", "sequence": 1 },
    { "imageUrl": "https://cdn.example.com/trail-jacket-black-front.jpg", "altText": "Black, front", "sequence": 2, "productImageGroupId": "black" },
    { "imageUrl": "https://cdn.example.com/trail-jacket-black-back.jpg", "altText": "Black, back", "sequence": 3, "productImageGroupId": "black" },
    { "imageUrl": "https://cdn.example.com/trail-jacket-blue-front.jpg", "altText": "Blue, front", "sequence": 4, "productImageGroupId": "cool-tones" }
  ]
}
```

Each image entry belongs to one group. To show the same picture in two groups, add it twice with different `productImageGroupId` values, or tag one group with both option values as in Step 2.

## Full Update Product Example

Get the current product, change the three parts above, and send the whole product back:

```http theme={null}
PUT https://t1000000.sb.usc1.gcp.kibocommerce.com/api/commerce/catalog/admin/products/TRAIL-JACKET
Content-Type: application/json
```

```json theme={null}
{
  "productCode": "TRAIL-JACKET",
  "productTypeId": 7,
  "content": {
    "productName": "Trail Jacket",
    "productImages": [
      { "imageUrl": "https://cdn.example.com/trail-jacket-main.jpg", "altText": "Trail Jacket", "sequence": 1 },
      { "imageUrl": "https://cdn.example.com/trail-jacket-black-front.jpg", "altText": "Black, front", "sequence": 2, "productImageGroupId": "black" },
      { "imageUrl": "https://cdn.example.com/trail-jacket-black-back.jpg", "altText": "Black, back", "sequence": 3, "productImageGroupId": "black" },
      { "imageUrl": "https://cdn.example.com/trail-jacket-blue-front.jpg", "altText": "Blue, front", "sequence": 4, "productImageGroupId": "cool-tones" }
    ]
  },
  "options": [
    {
      "attributeFQN": "tenant~color",
      "isProductImageGroupSelector": true,
      "values": [
        { "value": "Black" },
        { "value": "Blue" },
        { "value": "Red" }
      ]
    },
    {
      "attributeFQN": "tenant~size",
      "values": [
        { "value": "S" },
        { "value": "M" },
        { "value": "L" }
      ]
    }
  ],
  "productImageGroups": [
    {
      "productImageGroupId": "black",
      "productImageGroupTags": [
        { "fqn": "tenant~color", "values": ["Black"] }
      ]
    },
    {
      "productImageGroupId": "cool-tones",
      "productImageGroupTags": [
        { "fqn": "tenant~color", "values": ["Blue", "Red"] }
      ]
    }
  ]
}
```

The example is shortened to the fields that matter here. In a real request, send back the rest of the product you retrieved (price, properties, catalogs, and so on) unchanged.

When you read the product back, images without a group show `"productImageGroupId": "default"`.

## How the Storefront Picks Images

The storefront product APIs return a filtered `productImages` list based on the selected value of the selector option:

| Request | Images returned |
| - | - |
| No selector value chosen yet, such as [Get Product](https://docs.kibocommerce.com/api-reference/storefrontproducts/get-product.md) on the base product code | Default images only |
| A selector value is chosen, through `variationProductCode` on Get Product or through [Configure Variation Product](https://docs.kibocommerce.com/api-reference/storefrontproducts/configure-variation-product.md) | Images in every group tagged with that value. Default images are not included. |
| A selector value is chosen but no group is tagged with it | Default images only |
| Get Product with `includeAllImages=true` | Default images plus the images for every available selector value |
| The product has no image groups | Default images only |

For example, a shopper who picks Blue on the configure call gets only the `cool-tones` images:

```http theme={null}
POST https://t1000000.sb.usc1.gcp.kibocommerce.com/api/commerce/catalog/storefront/products/TRAIL-JACKET/configure
Content-Type: application/json

{
  "options": [
    { "attributeFQN": "tenant~color", "value": "Blue" }
  ]
}
```

The response's `productImages` contains only `trail-jacket-blue-front.jpg`. Choosing a size alone does not change the images, because size is not the selector option.

Use `includeAllImages=true` when your product page loads all images once and switches between them in the browser as the shopper changes options. Each returned image carries its `productImageGroupId`, and the product's `productImageGroups` tells you which option values each group belongs to.

## Pitfalls

* **No selector option set.** If no option has `isProductImageGroupSelector: true`, the storefront only ever returns default images, even when groups and tags are correct.
* **Tag values do not match option values.** Tag values are compared to the option's `value` exactly. `black` does not match `Black`. Copy the values from `options[].values[].value`.
* **Base images disappear after a color is picked.** Once a selector value is chosen, default images are not returned. If you want a lifestyle shot on every color, add a copy of it to each group.
* **Sending a partial group list deletes groups.** When an update includes `productImageGroups`, any existing group missing from the list is deleted, and its images move to the default group. To leave groups as they are, leave `productImageGroups` out of the request entirely.
* **Group IDs cannot be renamed.** An update can change a group's tags, but not its ID. Sending a new ID creates a new group, and the old group is deleted if you leave it out. Point the images at the new ID in the same request.
* **Image points to a group that does not exist.** Kibo does not reject an image whose `productImageGroupId` matches no group. That image is never returned for a selected variation, and it is not a default image either.
* **Groups named `default`.** `default` is reserved for ungrouped images. A group with this ID is ignored.
* **Bulk import.** In the [Catalog template](https://docs.kibocommerce.com/pages/catalogs-template.md), the image group columns are export-only. Use the API to set image groups.

## Related Topics

* [Dynamic Imaging](https://docs.kibocommerce.com/pages/dynamic-imaging.md)
* [Option Attributes](https://docs.kibocommerce.com/pages/option-attributes.md)
* [Kibo Catalog API Developer Guide](https://docs.kibocommerce.com/developer-guides/catalog-admin-api.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.