# Important concepts

## How we identify your products

Two identifiers matter, and they are not interchangeable.

**`product_reference`** is **your** reference for a product. It must be unique
within your channel and stable, because it is what we match on. Sending an
existing `product_reference` updates that product.

**`id`** is **our** numeric key, returned on every successful push. It is
required to delete a product; the delete endpoint does not accept
`product_reference`. Store the `id` values we return.

**`variant_id_text`** is your reference for a variant, unique within its
product. An unrecognised value creates a new variant.

### Which one wins

`id` takes precedence. If you send both and the `id` points at a different
product, that product is updated and the `product_reference` you sent is
ignored. For updates, send `product_reference` alone. Use `id` for deletes.

**Never send an `id` from a different environment.** An `id` issued in Sandbox
does not exist in Production, and the other way round. An unknown `id` fails
the request, and in a bulk run stops the whole run part-way, leaving
`is_running` set for up to an hour. Store the `id` values you receive per
environment, so a Sandbox `id` is never sent to Production.

## Product

The same shape everywhere: a single upsert and each element of a bulk file.

```json
{
    "product_reference": "abc123",
    "name": "Demo Product",
    "description": "This is a product",
    "condition": "NEW",
    "delivery_type": "STANDARD_SHIPPING",
    "handling_time": 3,
    "quantity_per_lot": 1,
    "tags": "electronics,gadgets",
    "vendor": "ACME Inc.",
    "images": [ ... ],
    "variants": [ ... ]
}
```

The fields are described on the [Create or update a product](../6_Products/product_upsert.md) page.

## ProductImage

A product needs at least one image to be listed. `src` must be an absolute
URL. `position` sorts the images ascending.

```json
"images": [
    {
        "src": "https://example.com/image1.jpg",
        "position": 1
    }
]
```

## Variant

Every product needs at least one variant. Price and quantity live on the
variant.

```json
"variants": [
    {
        "variant_id_text": "ab1",
        "sku": "SKU-ABC123",
        "price": 199.99,
        "quantity": 5,
        "weight": 1.23,
        "options": [ ... ]
    }
]
```

## Option

Options distinguish variants on the listing, such as size or colour. They are
grouped by `name`: three variants with the name `Size` and values `Small`,
`Medium` and `Large` give one `Size` selector with three choices.

```json
"options": [
    {
        "name": "Size",
        "value": "Large"
    }
]
```

- **One variant:** options are not required. Omit `options` or send `null`.
  The listing has no variant selector.
- **Two or more variants:** every variant needs at least one option. A variant
  without one is dropped with the message
  `no variant options (ie: size, color) provided`. The rest of the product
  still lists, and if no variant is left the listing is closed. See [What makes a product go live](../4_What%20makes%20a%20product%20go%20live/README.md).
