POST /v1/products creates a whole product in a single request. What you send depends on the
product type.
A simple product
For aSIMPLE_PRODUCT (or VIRTUAL_PRODUCT) there’s one variant, so put the sku, price, cost and
stock at the top level:
200000 means 2000.00. category takes a name (we create it if it
doesn’t exist) or an existing id. status has to be a status your workspace uses.
Categories
A product can belong to several categories. Sendcategories — an ordered list of category
ids or slugs, the first being the primary:
categories takes precedence over the legacy single category (send one or the other). On a
PUT, the list replaces the product’s categories and [] clears them. An unknown id or slug
returns 422 and nothing is applied. Reads return the resolved list on each product:
parent_slug lets a headless storefront build /shop/{parent_slug}/{slug} links directly. To
list a category’s products, filter the products endpoint: GET /v1/products?categories=men,kaftan
matches products in all the given categories, and a parent term also matches products in its
children.
A variable product (options + variants)
For aVARIABLE_PRODUCT, define the options and the variants. You don’t deal with option
ids — give options by name and we resolve them to your workspace options, creating an option if
it’s new and adding any values it doesn’t have yet.
- Each variant’s
attributesmust set every option, and each value must be one you listed inoptions. Send the variants you actually want — we create exactly those, not every combination. skuandpriceare required per variant;cost,stock,statusand animage(asset id) are optional.- Don’t send top-level
sku/price/stockfor a variable product — those live on the variants.
What you get back
The response is the created product, including its resolvedoptions and the variants:
attributes is keyed by option id (not name), so use the options block to map ids
back to names and values.
Updating a product
PUT /v1/products/{id} edits an existing product. Send the fields you want the product to have —
its details, media, tags, slug, and, for a non-variable product, the default variant’s
price/cost/stock/sku:
tagsreplaces the tag set — omit the field to leave tags untouched, send[]to clear them.slugonly changes when you supply one; a name change never moves it on its own.mediasadds or repositions media;remove_mediasis a list of media ids to detach.- Variable-product variants are managed through the variant endpoints, not here — this call edits the product and (for simple products) its single default variant.
Good to know
- Options grow with use. If your workspace already has a “Color” option with Red and Green and you create a product using Blue, Blue is added to that option — you don’t manage options separately.
- Names must already be valid where we say so.
status(and a variantstatus) must be values your workspace supports; we won’t invent them.categoryand option names are created on demand. - Duplicate name or sku returns
409. Validation problems (a variant missing an option, an undeclared value, a missing price) return422with a message saying which variant and field.

