Update a product
Changes a product. Send only the fields you want to change. Lists such as prices, image_ids and related_product_ids are replaced whole, not merged. The bundle rules are checked only when the request holds type: bundle, so send type with bundle_items. Fires the product.modified event. Secret and trusted tokens may call it.
AuthorizationBearer <token>A secret, trusted or limited token. See Authentication.
product_id*stringThe product id.
expand?stringComma-separated child objects to return in full instead of as a URL, for example customer,payments. Use dot notation for nested objects (items.product), up to four levels deep. A single object takes up to 12 paths; a list takes up to 2, applied to every item. Extra paths are dropped without an error. See Expanding objects.
show?stringComma-separated fields to return; all others are left out. Use dot notation for child fields (customer.email). You cannot send show and hide together (400). See Customizing output.
hide?stringComma-separated fields to leave out of the response. Use dot notation for child fields (customer.email). You cannot send show and hide together (400). See Customizing output.
formatted?booleanWhen true, the object also has a formatted child with amounts and dates as display text in the shopper's language and currency (for example $19.99 or November 7, 2026). The default is false. See Localized formatting.
falseThe fields to change.
application/json- body
The fields you can set on a product. On create, name, type and at least one price are required. On update, send only the fields you want to change; the rest keep their values.
product_id?stringThe id you want for the product. Letters, numbers, underscores, dashes and periods only. It is stored in lower case, and .test is added to a test product's id. If you leave it out, the next free number is used. Must not be in use already. Can only be set on create; on update it must match the id in the URL.
length <= 30name?stringThe name of the product. Required on create.
length <= 75type?stringThe kind of product. Required on create.
"physical""digital""service""bundle"description?|A description of the product.
length <= 2048headline?|A short line about the product.
length <= 100tax_code?|The tax code that decides how the product is taxed.
prices?array<>The price in each currency you want to set, at least one. Each price must be 0 or more and each currency may appear only once. On update, the list replaces the old one and may not be empty or null.
1 <= itemscompare_at_prices?array<>Higher "was" prices to show next to the price. Each must be greater than 0. Replaces the old list.
volume_prices?array<>Quantity tiers with their own unit price. Replaces the old list.
weight?|The weight of one unit. Send null to remove it.
active?booleanTrue to put the product on sale. The default on create is false, so send true for a product shoppers can buy. Setting it to true also clears deleted. Cannot be true when deleted is true.
deleted?booleanUpdate only. True marks the product deleted and inactive; false restores it. A product cannot be created deleted.
hidden?booleanTrue to leave the product out of the product list for shoppers while keeping it for sale by its id. The default is false.
file_id?|The file a buyer may download. It must be one of your files. Not allowed on a bundle.
license_service_id?|The license service that issues a license key when the product is bought. It must be one of your license services. Not allowed on a bundle.
subscription_plan_id?|The subscription plan to start each time the product is bought. It must be one of your plans and not deleted. Not allowed on a bundle.
image_ids?array<string>The ids of the product's images, in display order. Each must be one of your images. Repeats are removed. Replaces the old list.
video_url?|A link to a video about the product. Must be a valid URL.
urilength <= 256related_product_ids?array<string>|Up to 3 products to suggest with this one. Each must exist, be active and not be deleted. No repeats, and not the product itself. Send null or an empty list to remove them all. Read them at GET /products/{product_id}/related_products.
items <= 3subscription_change_product_ids?array<string>|Up to 10 products a subscriber to this product may switch to. Each must exist, be active, not be deleted and have the same subscription plan as this product. No repeats; the product itself is dropped. Send null to remove them all.
items <= 10subscription_term_change_product_ids?array<string>|Up to 10 products on a different subscription plan (for example yearly instead of monthly) that a subscriber may switch to. Each must exist, be active, not be deleted and have a subscription plan other than this product's. No repeats; the product itself is dropped. Send null to remove them all.
items <= 10inventory?|Turns on stock tracking for the product. Send null to stop tracking. Send current to set the stock level, or adjust_quantity_by to change it.
bundle_items?array<>Required for a bundle, with at least one item. The products the bundle holds, each once, not the bundle itself.
meta?||Your own data for the product, a string or an object, up to 2048 characters.
translations?|The product's text in other languages, keyed by a 2 to 5 character language code such as de or ja-JP. Replaces the old translations. Send null to remove them.
The updated product.
application/json- response
Something you sell: a physical item, a digital download, a service or a bundle of other products. A product with a subscription plan starts a subscription every time it is bought. Limited tokens see only active, visible products and do not get the fields marked as not returned to them.
object*"product"The object type. Always product.
"product"url*stringThe URL of this product in the API.
uriproduct_id*stringThe id of the product. Always lower case. Test products end in .test.
date_created*stringWhen the product was created.
date-timedate_modified*stringWhen the product was last changed.
date-timetest*booleanTrue for a test-mode product.
account_id*stringThe account the product belongs to.
name*stringThe name of the product. When the shopper's language has a translation, the translated name is returned.
price*numberThe unit price in currency. The currency comes from the cart_id, invoice_id or currency you send, or from the shopper's country or IP address, or else the account's default payment currency. When the product has no price in that currency, it is converted at the current exchange rate.
currency*stringThe currency of price, compare_at_price and effective_volume_prices.
compare_at_price*|A higher "was" price to show next to price, in currency, or null when the product has none.
type*stringThe kind of product. It decides how tax is worked out and what the shopper must give at checkout (a shipping address for physical goods, an email address for digital ones).
"physical""digital""service""bundle"description*|A description of the product, translated when a translation exists.
headline*|A short line about the product, translated when a translation exists.
tax_code*|The tax code that decides how the product is taxed, or null for the default.
prices*array<>The prices you set, one per currency. A price set here is always used for that currency. Other currencies are converted at the current exchange rate.
compare_at_prices?array<>The "was" prices you set, one per currency. Not returned to limited tokens.
volume_prices*array<>The quantity tiers you set, with their prices in each currency.
effective_volume_prices*array<>The quantity tiers priced in currency, starting from a tier of 1 at the regular price. Empty when the product has no tiers.
inventory*|Stock tracking for the product. Null when the product does not track stock.
bundle_items*array<>For a bundle, the products it holds. Empty for other types.
weight?|The weight of one unit, or null. Not returned to limited tokens.
active?booleanTrue when the product is for sale. Inactive products cannot be added to a cart and are not shown to shoppers. Not returned to limited tokens.
deleted?booleanTrue when the product was deleted. Not returned to limited tokens.
hidden?booleanTrue when the product is left out of the product list for shoppers. A shopper can still read it and buy it by its id. Not returned to limited tokens.
date_deleted?|When the product was deleted, or null. Not returned to limited tokens.
date-timefile?||The file a buyer may download, as a link, or the full object when you send expand=file. Null when the product has none. Left out for tokens that may not read files, such as limited tokens.
has_file*booleanTrue when the product has a file. Returned to every token.
license_service?||The license service that issues license keys for this product, as a link, or the full object when you send expand=license_service. Null when the product has none. Left out for tokens that may not read license services, such as limited tokens.
has_license_service*booleanTrue when the product has a license service. Returned to every token.
subscription_plan?||The subscription plan, as a link, or the full object when you send expand=subscription_plan. Null when the product is not a subscription.
subscription_terms*||For a subscription product, a link to its subscription terms, or the terms when you send expand=subscription_terms. Null for other products.
images*array<>The product's images, in the order you gave their ids.
video_url*|A link to a video about the product.
urirelated_products*|A link to the related products, or the list when you send expand=related_products on a single product. Inactive and deleted products are left out.
subscription_change_products*|A link to the products a subscriber may switch to on the same plan, or the list when you send expand=subscription_change_products on a single product.
subscription_term_change_products*|A link to the products a subscriber may switch to on a different plan, or the list when you send expand=subscription_term_change_products on a single product.
meta*||Your own data for the product, a string or an object, up to 2048 characters.
translations?|The product's text in other languages, keyed by language code such as de or ja-JP. Not returned to limited tokens. The translation that matches the shopper's language (from user_locale or the Accept-Language header) replaces name, headline and description.
formatted?Present only when you send formatted=true.
curl -X POST 'https://api.comecero.com/api/v1/products/string' \ -H 'Content-Type: application/json' \ -d '{ "prices": [ { "price": 44.95, "currency": "USD" } ], "hidden": true}'{ "object": "product", "url": "https://api.comecero.com/api/v1/products/widget.test", "product_id": "widget.test", "date_created": "2026-11-02T14:36:52Z", "date_modified": "2026-11-02T14:36:52Z", "test": true, "account_id": "AB1234", "name": "Widget", "price": 49.95, "currency": "USD", "compare_at_price": 59.95, "type": "physical", "description": "A simple widget for everyday use.", "headline": "The widget you will use every day", "tax_code": null, "prices": [ { "price": 49.95, "currency": "USD" }, { "price": 45.95, "currency": "EUR" } ], "compare_at_prices": [ { "price": 59.95, "currency": "USD" } ], "volume_prices": [ { "low": 10, "high": null, "prices": [ { "price": 39.95, "currency": "USD" } ] } ], "effective_volume_prices": [ { "low": 1, "high": 9, "price": 49.95, "currency": "USD", "discount_percent": 0, "discount_amount": 0 }, { "low": 10, "high": null, "price": 39.95, "currency": "USD", "discount_percent": 0.2, "discount_amount": 10 } ], "inventory": { "in_stock": true, "quantity": 120, "allow_oversells": false, "low_quantity_notification": 10 }, "bundle_items": [], "weight": { "amount": 3, "unit": "lb" }, "active": true, "deleted": false, "hidden": false, "date_deleted": null, "file": null, "has_file": false, "license_service": null, "has_license_service": false, "subscription_plan": null, "subscription_terms": null, "images": [ { "object": "image", "url": "https://api.comecero.com/api/v1/images/0099844605810ImLAMbo73", "image_id": "0099844605810ImLAMbo73", "date_created": "2026-11-02T14:36:45Z", "date_modified": "2026-11-02T14:36:45Z", "test": true, "account_id": "AB1234", "link": "https://cdn.comecero.net/AB1234/0099844605810ImLAMbo73/widget.png", "link_small": "https://cdn.comecero.net/AB1234/0099844605810ImLAMbo73/sm_widget.png", "link_medium": "https://cdn.comecero.net/AB1234/0099844605810ImLAMbo73/md_widget.png", "link_large": "https://cdn.comecero.net/AB1234/0099844605810ImLAMbo73/lg_widget.png", "link_square": "https://cdn.comecero.net/AB1234/0099844605810ImLAMbo73/sq_widget.png", "filename": "widget.png" } ], "video_url": null, "related_products": "https://api.comecero.com/api/v1/products/widget.test/related_products", "subscription_change_products": "https://api.comecero.com/api/v1/products/widget.test/subscription_change_products", "subscription_term_change_products": "https://api.comecero.com/api/v1/products/widget.test/subscription_term_change_products", "meta": null, "translations": { "de": { "name": "Widget", "headline": "Das Widget fur jeden Tag", "description": "Ein einfaches Widget fur jeden Tag." } }}Get a product GET
Returns one product, priced in one currency (see `currency`). A limited token may read any product of the account by its id, including a hidden one, but does not get the fields marked as not returned to limited tokens. Secret, trusted and limited tokens may call it.
Delete a product DELETE
Marks a product deleted and inactive. It is not erased: orders keep pointing at it, you can still read it, and you can bring it back by updating it with `deleted: false` or `active: true`. Fires the `product.deleted` event. Secret and trusted tokens may call it.