comecerodocs

Update a product

POST
/products/{product_id}

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.

Authorization

headerAuthorizationBearer <token>

A secret, trusted or limited token. See Authentication.

Path Parameters

product_id*string

The product id.

Query Parameters

expand?string

Comma-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?string

Comma-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?string

Comma-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?boolean

When 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.

Defaultfalse

Request Body

The fields to change.

application/json
  1. 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?string

The 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.

Lengthlength <= 30
name?string

The name of the product. Required on create.

Lengthlength <= 75
type?string

The kind of product. Required on create.

Value in"physical""digital""service""bundle"
description?|

A description of the product.

Lengthlength <= 2048
headline?|

A short line about the product.

Lengthlength <= 100
tax_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.

Items1 <= items
compare_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?boolean

True 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?boolean

Update only. True marks the product deleted and inactive; false restores it. A product cannot be created deleted.

hidden?boolean

True 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.

Formaturi
Lengthlength <= 256
related_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.

Itemsitems <= 3
subscription_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.

Itemsitems <= 10
subscription_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.

Itemsitems <= 10
inventory?|

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.

Response Body

The updated product.

application/json
  1. 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.

Value in"product"
url*string

The URL of this product in the API.

Formaturi
product_id*string

The id of the product. Always lower case. Test products end in .test.

date_created*string

When the product was created.

Formatdate-time
date_modified*string

When the product was last changed.

Formatdate-time
test*boolean

True for a test-mode product.

account_id*string

The account the product belongs to.

name*string

The name of the product. When the shopper's language has a translation, the translated name is returned.

price*number

The 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*string

The 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*string

The 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).

Value in"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?boolean

True 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?boolean

True when the product was deleted. Not returned to limited tokens.

hidden?boolean

True 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.

Formatdate-time
file?||

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*boolean

True 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*boolean

True 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.

Formaturi
related_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.

Example Request
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}'
Example Response
{  "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."    }  }}