# Manage variants and images

> Add, update and delete variants and images on an existing Shoplazza product, and look variants up by SKU when syncing price and stock from your system.

Add variants and images to an existing product, and look variants up by SKU — useful when syncing prices and stock from an external system.

## When to use this

Adding a size or color after a product exists, adjusting price or stock, swapping imagery, or matching your own SKUs to Shoplazza variants.

## Prerequisites

- A working public app with OAuth and token storage — follow [Develop a standalone app](/docs/app/getting-started/create-public-app/develop-app) first. Every request below carries an `Access-Token: {token}` header, using the token you saved for each shop.
- The `product` access scope granted during OAuth.
- A product that already has options (create one with `has_only_default_variant: false` — see [Create and update products](/docs/app/use-cases/product-merchandising/create-and-update-products)).

### Add a variant

Add a variant to a product that already has options. `price` and `position` are required; `option1` is the option value for the new variant.

`POST /openapi/2026-01/products/{id}/variants`

Request body:

```json5
{
  "variant": {
    "option1": "L",              // matches a value in the product's declared options
    "price": 19.9,
    "sku": "TS-L",
    "inventory_quantity": 100,
    "position": 3
  }
}
```

Response (excerpt, new variant under `data.data.variant`):

```json
{
  "code": "Success",
  "data": {
    "variant": {
      "id": "d47c9f04-ae67-4480-a092-08945767ce4a",
      "product_id": "4d3e7859-455c-4899-a296-7befe731c585",
      "title": "L",
      "option1": "L",
      "position": 3,
      "price": 19.9,
      "sku": "TS-L",
      "inventory_quantity": 100,
      "created_at": "2026-07-02T02:58:01Z",
      "updated_at": "2026-07-02T02:58:01Z"
    }
  }
}
```

Full fields: see [Create variant](/api/variant-create).

:::warning
You can only add a variant to a product that has options (`has_only_default_variant: false`). Calling this on a single-variant product fails with "At least a single variant is included in the product." Define the variants when you create the product, or restructure it first.
:::

### Update or delete a variant

`PUT /openapi/2026-01/variants/{id}`

Request body:

```json5
{
  "variant": {
    "price": 24.9 // only the fields you want to change
  }
}
```

Returns the updated variant under `data.data.variant`. Full fields: see [Update variant](/api/variant-update).

`DELETE /openapi/2026-01/products/{id}/variants/{vid}`

No request body. Deleting a variant returns no additional data. See [Delete variant](/api/variant-delete).

### Look up variants by SKU

When an external system keys on SKU, resolve it to a variant without knowing its id.

`GET /openapi/2026-01/products/sku/{sku}/variants`

Returns the list of variants matching that SKU, under `data.data.variants`. See [List variants by SKU](/api/variants-by-sku).

To update a variant directly by SKU, use `PUT /variants/sku/{sku}` — see [Update variant by SKU](/api/variant-update-by-sku).

### Add an image

Images belong to the product. Posting an image **appends** it to the gallery (it does not replace existing images). `src` is a public image URL.

`POST /openapi/2026-01/products/{id}/images`

Request body:

```json5
{
  "image": {
    "src": "https://cdn.example.com/tshirt-back.jpg" // publicly reachable image URL
  }
}
```

Response (excerpt, new image under `data.data.image`):

```json
{
  "code": "Success",
  "data": {
    "image": {
      "id": "6c7d7bad-a4fe-48c3-95e5-51a36f20622f",
      "product_id": "4d3e7859-455c-4899-a296-7befe731c585",
      "position": 2,
      "src": "//cdn.example.com/tshirt-back.jpg",
      "created_at": "2026-07-02T02:58:13Z",
      "updated_at": "2026-07-02T02:58:13Z"
    }
  }
}
```

Full fields: see [Create product image](/api/product-image-create).

To reorder, change alt text, or remove an image, use `PUT`/`DELETE /products/{id}/images/{image_id}` — see [Update product image](/api/product-image-update) and [Delete product image](/api/product-image-delete).

### List and count variants and images

List a product's variants with `GET /products/{id}/variants`, or fetch one with `GET /variants/{id}`. Images work the same way with `GET /products/{id}/images`. Each also has a count endpoint.

See [List variants](/api/variants), [Get variant](/api/variant-detail), [Count variants](/api/variant-count), [List product images](/api/product-images), [Get product image](/api/product-image-detail), and [Count product images](/api/product-image-count).

## Next steps

- [Create and update products](/docs/app/use-cases/product-merchandising/create-and-update-products)
- [Manage inventory](/docs/app/use-cases/product-merchandising/manage-inventory)
