Products
List, read, create, and update products over the API.
The Products resource lives at /api/v1/products and requires a key (or session)
with the products permission. All responses use the
standard envelope.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/products |
List products (paginated). |
GET |
/api/v1/products/filter |
Storefront-style faceted filter. |
GET |
/api/v1/products/:id |
Read one product. |
POST |
/api/v1/products |
Create a product. |
PUT |
/api/v1/products/:id |
Update a product. |
DELETE |
/api/v1/products/:id |
Soft-delete a product. |
List response
{
"success": true,
"message": "Products fetched successfully",
"data": {
"products": [ /* product objects */ ],
"pagination": { "page": 1, "limit": 20, "total": 128, "pages": 7 }
}
}
The product object
| Field | Type | Notes |
|---|---|---|
id |
string (UUID) | |
slug |
string | URL slug; unique per store. |
sku |
string | null | |
barcode |
string | null | |
price |
decimal | Base price. Monetary fields are fixed-point decimals — parse as decimal, not float. |
compareAtPrice |
decimal | null | “Was” price for a sale. |
cost |
decimal | null | Your unit cost — sensitive; only returned to permitted keys, never on the storefront. |
categoryId |
string | null | |
images |
string[] | Absolute image URLs. |
brand |
string | null | |
tags |
string[] | |
taxExempt |
boolean | |
kind |
enum | physical, and digital kinds. |
isGiftCard |
boolean | |
quantity |
int | Stock on hand (default location). |
inventoryTracked |
boolean | |
allowBackorder |
boolean | |
lowStockThreshold |
int | null | |
hasVariants |
boolean | |
isActive |
boolean | Published/visible. |
publishedAt |
datetime | null | Scheduled-publish time. |
averageRating |
float | From approved reviews only. |
ratingCount |
int | |
createdAt / updatedAt |
datetime |
Names and descriptions are localized
A product’s display text is not a flat name field — it lives in a
translations array, one entry per language:
translations: [{ "language": "en", "name": "…", "description": "…", "slug": "…", "metaTitle": "…", "metaDescription": "…" }].
Read the entry for the language you want; write the same shape on create/update.
Create
A minimal create needs a price and at least one translation:
POST /api/v1/products
{
"price": 19.90,
"translations": [
{ "language": "en", "name": "Classic Tee", "description": "100% cotton." }
],
"category": "9d9c…",
"images": ["https://…/tee.jpg"],
"quantity": 50
}
For a product with options (size/color), send the option axes under variants
and the concrete combinations under productVariants (each with its own price,
sku, and quantity). See Products & variants in the merchant docs
for the model.
Deletes are soft
DELETE marks a product deleted (freeing its slug) rather than hard-removing
it, so order history that references it stays intact.