---
title: Products
sort: 1
---

# Products

A product is a sellable thing. Variants live inside products; if you sell tea in three sizes,
that's one product with three variants.

## Object

| Field                  | Type        | Notes                                                  |
|------------------------|-------------|--------------------------------------------------------|
| `id`                   | string      | `prod_…`, ULID                                         |
| `name`                 | string      | Human-readable, ≤ 256 chars                            |
| `sku`                  | string?     | Optional, must be unique within tenant                 |
| `description`          | string?     | Markdown, ≤ 16 KiB                                     |
| `default_price_cents`  | integer     | Minor units of `currency`                              |
| `currency`             | string      | ISO 4217, e.g. `EUR`                                   |
| `inventory`            | integer     | `-1` means infinite (digital goods)                    |
| `status`               | enum        | `active`, `archived`, `draft`                          |
| `metadata`             | object      | ≤ 50 key/value pairs, string values ≤ 500 chars        |
| `created_at`           | timestamp   | RFC 3339, UTC                                          |
| `updated_at`           | timestamp   | RFC 3339, UTC                                          |

## Endpoints

| Method | Path                          | Purpose                              |
|--------|-------------------------------|--------------------------------------|
| `GET`  | `/v1/products`                | List, paginated                      |
| `POST` | `/v1/products`                | Create                               |
| `GET`  | `/v1/products/{id}`           | Retrieve                             |
| `PATCH`| `/v1/products/{id}`           | Update (partial; `null` clears)      |
| `DELETE` | `/v1/products/{id}`         | Archive (soft); use `?hard=true` to delete |
| `POST` | `/v1/products/{id}/variants`  | Add a variant                        |

## Filtering

```bash
# Active products in EUR, updated in the last day, page of 50
curl -sS "https://api.zephyrcart.io/v1/products" \
  --get \
  --data-urlencode "status=active" \
  --data-urlencode "currency=EUR" \
  --data-urlencode "updated_after=2026-05-30T00:00:00Z" \
  --data-urlencode "limit=50" \
  -H "Authorization: Bearer $ZEPHYR_API_KEY"
```

## Common errors

| Code                              | Cause                                          | Fix                                              |
|-----------------------------------|------------------------------------------------|--------------------------------------------------|
| `validation.invalid_currency`     | `currency` not ISO 4217                        | Use a valid 3-letter uppercase code              |
| `validation.sku_already_exists`   | Duplicate SKU within tenant                    | Pick a unique SKU or update the existing product |
| `inventory.negative_not_allowed`  | `inventory < 0` and product is not digital     | Pass `inventory=-1` only for digital goods       |
| `metadata.too_many_keys`          | More than 50 metadata keys                     | Consolidate or drop unused metadata              |
