The variant, not the product, is what someone actually buys. It carries its own price, its own stock state and frequently its own photograph. In apparel a single product routinely holds forty of them.
| Field | Type | Notes |
|---|---|---|
| variant_id ·always | string | Stable. |
| product_id ·always | string | Parent product. |
| options | object | The axis values: { size: 'M', colour: 'Black' }. Normalised from the seller's own option names. |
| sku | string | null | Seller's own SKU. Present on ~99% of real variant rows — the most reliable non-GTIN identifier in DTC commerce. |
| gtin | string | null | Variant-level barcode where published. Rare on public storefront catalogues. |
| weight_grams | int | null | Present on ~78% of variants. Drives shipping-cost estimation. |
| media | Media[] | Variant-specific imagery where the seller links it — about 64% of variants carry a distinct primary image. |
| availability | enum | in_stock | out_of_stock | preorder | delisted | unknown. See the nuance below. |
{
"variant_id": "var_2c81f",
"product_id": "prd_8Fk2xQ",
"options": { "colour": "Midnight Black" },
"sku": "WH1000XM5B",
"weight_grams": 250,
"availability": "in_stock",
"media": [ { "role": "primary", "url": "https://…/xm5-black-800x800.jpg" } ]
}Only about 68% of real variant rows publish a usable stock flag. The rest are silent. We return `unknown` rather than guessing `in_stock`, because an agent that treats silence as availability will confidently recommend something nobody can buy.
We observed a storefront encoding availability as an option: a 'Status' axis whose values were 'Preorder — Ships in 45 Business Days' and 'Out of Stock'. That is parsed out into `availability` rather than left as a phantom colour choice.
Variants are first-class precisely so that one unavailable size does not read as the whole product going out of stock — a mistake that makes apparel data useless.