Update a product
PATCH/products/:id
Writes the name and the variant prices (there is no separate name or price route). The selling status is changed with PATCH /products/{id}/status.
Request
- Send
nameandvariants, each variant with itsprice. - The
variantsyou send are the full set to keep: an existing variant you leave out is deleted. - Identify an existing variant by
variant_id; leave it out and sendskuto add a variant. - A variant with a new
skuand novariant_idis a new variant, even when you meant to change an existing one: that existing variant is then removed, because it is not listed. - An
idkey on a variant is ignored. An unknown field is ignored. - Images are copied from the public HTTPS URLs you send.
Behaviour
- A field you do not send is kept: no
collection_id,outlet_idsorattachmentskey keeps the stored value, andnullclears it (no collection, sold at every outlet, no images;[]clearsoutlet_idsandattachmentstoo). - On an existing variant the same holds for
sku,barcode,cost,attachmentandvariant_values: a key you leave out keeps the stored value, andnullclearsbarcode,cost(to 0) andattachment. - The option values of an existing variant can be replaced with a list.
- To remove option values, send
variant_values: nullor[]on every variant that has them, andvariant_groups: [](or novariant_groupskey). The options of all variants are cleared together, so the product ends with no variant groups, asPOST /productscreates it without options. The SKU, barcode, price and cost of each variant stay. - A clear is refused with
400 VALIDATION_FAILEDonvariants[i].variant_valueswhen any variant would still have options (a variant that leavesvariant_valuesout keeps its options; a list gives options) orvariant_groupsis not empty. Nothing is changed. - A new variant has nothing stored: what it leaves out is empty or 0.
- A service product needs its Duration option on every SKU, so clearing the options of a service product fails with
400 SERVICE_DURATION_REQUIRED: onedata.fieldsentry with codeDURATION_REQUIREDonvariants[i].variant_valuesfor each SKU left without a Duration. Nothing is changed. - The category and the product details this body cannot express (description, translations) are never changed here.
- Concurrent updates: the last write wins within the legacy scalar contract.
- With Price Management enabled, real inherited-base changes and initial prices for new SKUs on an existing product also require catalog.price.edit. A scalar echo creates no price intent.
- Every target outlet must be in the current actor's grants. Explicit, missing, suspended and permanent-owned cells are protected. New and existing intents share one command and the caller's metadata/outbox transaction.
- The current local user owns the audit. MAG client metadata is retained. Compatibility responses use final permanent maxima.
Errors
A SKU that is already used answers 409.
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_FAILED | A variant has no price, or variant_values is null or [] on an existing variant that has option values while another variant keeps or gets options, or variant_groups is not empty (on variants[i].variant_values). |
| 400 | SERVICE_DURATION_REQUIRED | A service product's SKU would have no Duration option (for example its options are cleared). data.fields has code DURATION_REQUIRED on variants[i].variant_values. |
| 404 | NOT_FOUND | The product does not exist, belongs to another merchant, or is not sold at the outlet in X-Outlet-ID. |
| With the Price Management master switch off, company-wide legacy product configuration writes return 409 PRICE_ROLLOUT_PAUSED when any company outlet is prepared or was activated. No product, price, history, feed or product-change event is written. Unprepared legacy companies retain the existing compatibility semantics. |
Request
Responses
- 200
- 400
- 401
- 403
- 404
- 409
- 422
The product
Error envelope
Error envelope
Error envelope
Error envelope
Error envelope
Error envelope