Shopify productVariantAppendMedia: one AI image per color variant

Link an existing Shopify image to each color variant with productVariantAppendMedia, and generate the recolored shots from one product photo with Sume.

5 min readSume
All posts

Shopify's productVariantAppendMedia mutation links media that is already on a product to specific variants, so a shopper who picks "sage green" sees the sage green photo. You pass a productId and a variantMedia list of variantId and mediaIds pairs, and Shopify links the existing media without duplicating files. Sume's part is making one recolored shot per variant from a single product photo.

Shopify facts come from the productVariantAppendMedia and fileCreate references, read 2026-10-02. Sume facts come from the Image docs and Jobs and results.

What does productVariantAppendMedia need?

Two required inputs: productId and variantMedia. It needs the write_products scope and a user permitted to append media to variants. The payload returns the product, the updated productVariants and userErrors.

The page does not say how many media items one variant may carry, or whether the media must be READY first. Treat both as open questions and wait for READY anyway, as described in our file status post.

How do I generate one image per color?

Sume image edits take reference images: the request carries input_references entries of type image_url, and the response lists Sume-hosted data[].url values. A request blocks for up to 30 seconds and returns 200; if the generation outlasts that, you get 202 with a job envelope, and the image is then read from the result endpoint.

The loop below sends one request per color. Each call is its own paid generation, so keep the prompt short, state what must not change, and review the results before you attach them. A recolor that also changes the handle shape is a wrong product photo, and shoppers will return the item.

import os, requests

H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
SOURCE = "https://example.com/mug-white-bg.jpg"
COLORS = ["matte black", "sage green", "terracotta"]

def variant_image(color):
    body = {
        "model": "openai/gpt-image-2",
        "prompt": f"Recolor the mug to {color}. Keep shape, handle and lighting identical, white background.",
        "input_references": [{"type": "image_url", "image_url": {"url": SOURCE}}],
    }
    r = requests.post("https://api.sume.com/v1/images", headers=H, json=body, timeout=60)
    r.raise_for_status()
    if r.status_code == 202:  # still running: poll result_url, do not resubmit
        return r.json()["data"]["result_url"]
    return r.json()["data"][0]["url"]

for color in COLORS:
    print(color, variant_image(color))

What can go wrong with recolors?

An image model will happily invent a color that does not match your real dye lot. Compare each output with a physical sample or the manufacturer swatch, and if it differs, generate again or shoot the variant. Marketplace and platform rules on AI imagery differ, and a mismatched color is the likeliest cause of a complaint.

  • Keep the white-background source identical across calls so only the color varies.
  • Name each generated file by SKU and color so the mapping to a variant is obvious.
  • Never retry a 202 job by submitting again; poll the same job.
  • Write alt text that names the color, for example "sage green ceramic mug, front view".

How do I keep costs predictable?

Each color is a paid generation, so a catalog with 400 products and three colors each is 1,200 images, before any retries. Set a per-run budget and stop when you hit it. Sume balances are checked on submit: an empty balance returns 402 insufficient_credits before provider work starts, per Errors and rate limits.

Start with one product, look at the results by eye, and only then scale. If the recolors keep drifting in shape, tighten the prompt rather than raising n, because more variants of a bad prompt are just more bad images. Keep the best prompt in version control alongside the SKU list so a re-run next season uses the same wording.

How do I attach them?

Upload each Sume URL with fileCreate (up to 250 files per call, see the batch limits), attach them to the product, then run productVariantAppendMedia with the variant ids. The file ids come from the fileCreate response. If you create products with productSet, Shopify's reference says its files input also works at the variant level, which can replace the append step for new products; the deprecated route is covered in the productCreateMedia post.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume