Changes
Comparing empty → 160dc49.
| @@ -1,0 +1,58 @@ | ||
| 1 | +--- | |
| 2 | +title: Products | |
| 3 | +sort: 1 | |
| 4 | +--- | |
| 5 | + | |
| 6 | +# Products | |
| 7 | + | |
| 8 | +A product is a sellable thing. Variants live inside products; if you sell tea in three sizes, | |
| 9 | +that's one product with three variants. | |
| 10 | + | |
| 11 | +## Object | |
| 12 | + | |
| 13 | +| Field | Type | Notes | | |
| 14 | +|------------------------|-------------|--------------------------------------------------------| | |
| 15 | +| `id` | string | `prod_…`, ULID | | |
| 16 | +| `name` | string | Human-readable, ≤ 256 chars | | |
| 17 | +| `sku` | string? | Optional, must be unique within tenant | | |
| 18 | +| `description` | string? | Markdown, ≤ 16 KiB | | |
| 19 | +| `default_price_cents` | integer | Minor units of `currency` | | |
| 20 | +| `currency` | string | ISO 4217, e.g. `EUR` | | |
| 21 | +| `inventory` | integer | `-1` means infinite (digital goods) | | |
| 22 | +| `status` | enum | `active`, `archived`, `draft` | | |
| 23 | +| `metadata` | object | ≤ 50 key/value pairs, string values ≤ 500 chars | | |
| 24 | +| `created_at` | timestamp | RFC 3339, UTC | | |
| 25 | +| `updated_at` | timestamp | RFC 3339, UTC | | |
| 26 | + | |
| 27 | +## Endpoints | |
| 28 | + | |
| 29 | +| Method | Path | Purpose | | |
| 30 | +|--------|-------------------------------|--------------------------------------| | |
| 31 | +| `GET` | `/v1/products` | List, paginated | | |
| 32 | +| `POST` | `/v1/products` | Create | | |
| 33 | +| `GET` | `/v1/products/{id}` | Retrieve | | |
| 34 | +| `PATCH`| `/v1/products/{id}` | Update (partial; `null` clears) | | |
| 35 | +| `DELETE` | `/v1/products/{id}` | Archive (soft); use `?hard=true` to delete | | |
| 36 | +| `POST` | `/v1/products/{id}/variants` | Add a variant | | |
| 37 | + | |
| 38 | +## Filtering | |
| 39 | + | |
| 40 | +```bash | |
| 41 | +# Active products in EUR, updated in the last day, page of 50 | |
| 42 | +curl -sS "https://api.zephyrcart.io/v1/products" \ | |
| 43 | + --get \ | |
| 44 | + --data-urlencode "status=active" \ | |
| 45 | + --data-urlencode "currency=EUR" \ | |
| 46 | + --data-urlencode "updated_after=2026-05-30T00:00:00Z" \ | |
| 47 | + --data-urlencode "limit=50" \ | |
| 48 | + -H "Authorization: Bearer $ZEPHYR_API_KEY" | |
| 49 | +``` | |
| 50 | + | |
| 51 | +## Common errors | |
| 52 | + | |
| 53 | +| Code | Cause | Fix | | |
| 54 | +|-----------------------------------|------------------------------------------------|--------------------------------------------------| | |
| 55 | +| `validation.invalid_currency` | `currency` not ISO 4217 | Use a valid 3-letter uppercase code | | |
| 56 | +| `validation.sku_already_exists` | Duplicate SKU within tenant | Pick a unique SKU or update the existing product | | |
| 57 | +| `inventory.negative_not_allowed` | `inventory < 0` and product is not digital | Pass `inventory=-1` only for digital goods | | |
| 58 | +| `metadata.too_many_keys` | More than 50 metadata keys | Consolidate or drop unused metadata | | |