# Products Manage your products and product information in your project. Use this API to create and manage [Products](/api/product-catalog-overview.md#product) and their information you want to present on your storefront. Add [Product Variants](/api/product-catalog-overview.md#product-variant) with their [Attributes](/api/product-catalog-overview.md#attribute), assets and images. In the `Classic` [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) , a [Product](/urn?urn=ctp%3Aapi%3Atype%3AProduct) can have up to **100** [Product Variants](/urn?urn=ctp%3Aapi%3Atype%3AProductVariant). In the `Modular` [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) , a Product can have up to **10000** [Variants](/api/projects/variants.md#variant), which are managed as standalone entities through the [Variants API](/api/projects/variants.md). These limits can be increased per project after we review the performance impact. Contact the [commercetools support team](https://support.commercetools.com/) and provide the region, project key, and use case. For discovering Products based on attribute values and prices on your Product Listing Page, use the [Product Search](/api/projects/product-search.md) API. For retrieving product information to be presented on your Product Detail Page, use the [Product Projection](/api/projects/productProjections.md) API or, when using the `Modular` catalog model, the [Variant Projections](/api/projects/variant-projections.md) API. Learn more about Products in our self-paced Product data modeling and Advanced Product data modeling modules. ## Representations #### Product [type definition](/api/projects/products.md?urn=ctp:api:type:Product). ##### ProductDraft If the `key` value of `ProductDraft` is modified, any Product Tailoring associated with the Product will be removed. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductDraft). ##### ProductPagedQueryResponse [type definition](/api/projects/products.md?urn=ctp:api:type:ProductPagedQueryResponse). ##### ProductReference [type definition](/api/projects/products.md?urn=ctp:api:type:ProductReference). ##### ProductKeyReference [type definition](/api/projects/products.md?urn=ctp:import:type:ProductKeyReference). ##### ProductResourceIdentifier [type definition](/api/projects/products.md?urn=ctp:api:type:ProductResourceIdentifier). ##### ProductCatalogData [type definition](/api/projects/products.md?urn=ctp:api:type:ProductCatalogData). ##### ProductData [type definition](/api/projects/products.md?urn=ctp:api:type:ProductData). ##### CategoryOrderHints JSON object where the keys are [Category](/urn?urn=ctp%3Aapi%3Atype%3ACategory) `id`, and the values are order hint values: strings representing a number between `0` and `1`, but not ending in `0`. Order hints allow controlling the order of Products and how they appear in Categories. Products without order hints have an order score below `0`. Order hints are not unique. If a subset of Products have the same value for order hint in a specific category, the behavior is undetermined. ```json title="Example:" { "1d20faef-e8e1-44f4-b1b9-3a25b68fd266": "0.1234", "ed9556d2-203f-4c80-840d-79305f341ba8": "0.5678" } ``` ##### SearchKeywords Search keywords are primarily used by [Search Term Suggestions](/api/projects/search-term-suggestions.md), but are also considered for a [full-text search](/api/projects/product-projection-search.md#full-text-search) in the Product Projection Search API. [type definition](/api/projects/products.md?urn=ctp:api:type:SearchKeywords). ##### SearchKeyword [type definition](/api/projects/products.md?urn=ctp:api:type:SearchKeyword). ###### SuggestTokenizer Defines tokens that are used for [Search Term Suggestions](/api/projects/search-term-suggestions.md). Can be differentiated by the `type` field. ###### Whitespace Tokenizer [type definition](/api/projects/products.md?urn=ctp:api:type:WhitespaceTokenizer). ##### Custom Tokenizer [type definition](/api/projects/products.md?urn=ctp:api:type:CustomTokenizer). #### ProductVariant [ProductVariant](/urn?urn=ctp%3Aapi%3Atype%3AProductVariant) is only used in the `Classic` [ProductCatalogModel](/api/projects/project.md#productcatalogmodel). When using the `Modular` catalog model, Variants are managed as standalone entities through the [Variants API](/api/projects/variants.md). In that mode, the `masterVariant` and `variants` fields in [ProductData](/api/projects/products.md#productdata) are not used to store variant data, and images and assets are managed through the [Variant endpoints](/api/projects/variants.md#update-actions). [type definition](/api/projects/products.md?urn=ctp:api:type:ProductVariant). ##### ProductVariantDraft [type definition](/api/projects/products.md?urn=ctp:api:type:ProductVariantDraft). ##### ProductVariantKeyReference [type definition](/api/projects/products.md?urn=ctp:import:type:ProductVariantKeyReference). ##### Attribute You can configure Attributes either at the variant level or at the Product level. For more information about the difference between the two, see [AttributeDefinitionDraft](/urn?urn=ctp%3Aapi%3Atype%3AAttributeDefinitionDraft). Attributes defined at the Product level are supported by [Product Search](/api/projects/product-search.md), but not by [Product Projection Search](/api/projects/product-projection-search.md). When using Attributes with [GraphQL API](/api/graphql.md) mutations, you must escape any strings in the `value` field: `"value" : "\"A value\""`. [type definition](/api/projects/products.md?urn=ctp:api:type:Attribute). ##### Image Product images can be uploaded using the [image upload endpoint](/api/projects/products.md#upload-product-image) or the Merchant Center. An uploaded image is stored in a Content Delivery Network and is available in several pre-defined sizes. If you already have an image stored on an external service, you can save the URL when creating a [new Product](/api/projects/products.md#create-product) or [adding a ProductVariant](/api/projects/products.md#add-productvariant), or you can [add it later](/api/projects/products.md#add-external-image). An image is represented in the following way: [type definition](/api/projects/products.md?urn=ctp:api:type:Image). Images in specific sizes are obtained by adding a size suffix before the filename extension: - `-thumb` (50x50) - [example](/api/downloads/252542005_1-thumb.jpg) - `-small` (150x150) - [example](/api/downloads/252542005_1-small.jpg) - `-medium` (400x400) - [example](/api/downloads/252542005_1-medium.jpg) - `-large` (700x700) - [example](/api/downloads/252542005_1-large.jpg) - `-zoom` (1400x1400) - [example](/api/downloads/252542005_1-zoom.jpg) - the original size of the uploaded image is provided without a suffix - [example](/api/downloads/252542005_1.jpg) Images will never be scaled up. If the original image is tiny, it will keep its original size, even in the "large" and "zoom" sizes. ProductVariants do not share images. To use the same set of images for multiple ProductVariants, you can implement this in your application by always showing the images of the Master Variant, regardless of the selected ProductVariant. Learn more about images in our self-paced Images and Assets module. ##### ImageDimensions [type definition](/api/projects/products.md?urn=ctp:api:type:ImageDimensions). ##### ProductVariantAvailability [ProductVariantAvailability](/urn?urn=ctp%3Aapi%3Atype%3AProductVariantAvailability) is only used in the `Classic` [ProductCatalogModel](/api/projects/project.md#productcatalogmodel). [type definition](/api/projects/products.md?urn=ctp:api:type:ProductVariantAvailability). ##### ProductVariantChannelAvailabilityMap JSON object where the keys are supply [Channel](/api/projects/channels.md) `id`, and the values are [ProductVariantChannelAvailability](/urn?urn=ctp%3Aapi%3Atype%3AProductVariantChannelAvailability). ```json title="Example:" { "cd724bd4-52fa-4d6d-b4b0-bb1560d70475": { "id": "f64af276-a1ad-4eea-a8bc-89c453742a40", "version": 3, "isOnStock": true, "restockableInDays": 10, "availableQuantity": 20 }, "f73fa437-e244-4d6f-8723-52b447427e0b": { "id": "beaa0b68-562b-4866-a42b-e61baf1043d1", "version": 5, "isOnStock": true, "restockableInDays": 5, "availableQuantity": 12 } } ``` ##### ProductVariantChannelAvailability [type definition](/api/projects/products.md?urn=ctp:api:type:ProductVariantChannelAvailability). #### ProductPriceMode [ProductPriceMode](/urn?urn=ctp%3Aapi%3Atype%3AProductPriceModeEnum) is configurable only in the `Classic` [ProductCatalogModel](/api/projects/project.md#productcatalogmodel). When using the `Modular` catalog model, the price mode is fixed to `Standalone` and cannot be changed, and only [Standalone Prices](/api/projects/standalone-prices.md) are used. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductPriceModeEnum). Regardless of the chosen Price mode, [ProductVariant](/urn?urn=ctp%3Aapi%3Atype%3AProductVariant) `prices` contains [Embedded Prices](/api/pricing-and-discounts-overview.md#embedded-prices) only. #### ScopedPrice [type definition](/api/projects/products.md?urn=ctp:api:type:ScopedPrice). ## Get Product ### Get Product by ID [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/\{id}:GET). ### Get Product by Key [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/key=\{key}:GET). ## Query Products When querying an [Attribute](/urn?urn=ctp%3Aapi%3Atype%3AAttribute), we recommend that you use the performance-optimized [Product Search](/api/projects/product-search.md) API whenever possible. For more information, see [inefficient patterns](/api/predicates/query.md#inefficient-patterns). When querying an Attribute, you must always include both the `attribute-name` and `attribute-value` details in the Query Predicate. Otherwise, a [400 Bad Request](/api/errors.md#400-bad-request) error will occur. [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products:GET). ## Query Product Selections for Product Retrieves Product Selections that contain the given Product. ### by Product ID [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/\{id}/product-selections:GET). ### by Product Key [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/key=\{key}/product-selections:GET). ## Check if Product exists ### Check if Product exists by ID [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/\{id}:HEAD). ### Check if Product exists by Key [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/key=\{key}:HEAD). ### Check if Product exists by Query Predicate [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products:HEAD). ## Create Product [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products:POST). ## Update Product ### Update Product by ID [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/\{id}:POST). ### Update Product by Key [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/key=\{key}:POST). ## Update actions #### on Product ##### Set Product Key Modifying the key will remove any Product Tailoring associated with the Product. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetKeyAction). ##### Change Product Name [type definition](/api/projects/products.md?urn=ctp:api:type:ProductChangeNameAction). ##### Set Product Description [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetDescriptionAction). ##### Change Slug [type definition](/api/projects/products.md?urn=ctp:api:type:ProductChangeSlugAction). ##### Add ProductVariant Not available for Projects with the [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) set to `Modular`. Use the [Variants API](/api/projects/variants.md) instead. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductAddVariantAction). ##### Remove ProductVariant Not available for Projects with the [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) set to `Modular`. Use the [Variants API](/api/projects/variants.md) instead. If the Product Variant contains `images` that have been [uploaded to our CDN](/api/projects/products.md#upload-product-image) and that are also used on other Product Variants, then removing the Product Variant will make the images unavailable wherever they are shared. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductRemoveVariantAction). ##### Change Master Variant Not available for Projects with the [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) set to `Modular`. Use the [Variants API](/api/projects/variants.md) instead. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductChangeMasterVariantAction). ##### Set Default Variant Only available for Projects with the [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) set to `Modular`. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetDefaultVariantAction). ##### Set PriceMode Not available for Projects with the [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) set to `Modular`. In `Modular` mode, the price mode is automatically set to `Standalone`. This action does not affect the behavior of the [Add Price](/api/projects/products.md#add-price), [Set Prices](/api/projects/products.md#set-prices), [Change Price](/api/projects/products.md#change-price), and [Remove Price](/api/projects/products.md#remove-price) update actions as they are only meant for managing [Embedded Prices](/api/pricing-and-discounts-overview.md#embedded-prices). When changing the Price mode, no migration of Prices takes place between [Embedded Prices](/api/pricing-and-discounts-overview.md#embedded-prices) and [StandalonePrices](/api/projects/standalone-prices.md#standaloneprice). [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetPriceModeAction). ##### Set Product Attribute [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetProductAttributeAction). ##### Set Attribute In All Variants [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAttributeInAllVariantsAction). ##### Add to Category [type definition](/api/projects/products.md?urn=ctp:api:type:ProductAddToCategoryAction). ##### Set Category Order Hint [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetCategoryOrderHintAction). ##### Remove from Category [type definition](/api/projects/products.md?urn=ctp:api:type:ProductRemoveFromCategoryAction). ##### Set TaxCategory [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetTaxCategoryAction). ##### Set SearchKeywords [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetSearchKeywordsAction). ##### Set Meta Title [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetMetaTitleAction). ##### Set Meta Description [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetMetaDescriptionAction). ##### Set Meta Keywords [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetMetaKeywordsAction). ##### Transition State [type definition](/api/projects/products.md?urn=ctp:api:type:ProductTransitionStateAction). #### on ProductVariant The following update actions are not available for Projects with the [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) set to `Modular`. Using them returns a [400 Bad Request](/api/errors.md#400-bad-request) error. When using the `Modular` catalog model, manage Variants through the [Variants API](/api/projects/variants.md) instead. ##### Add Price [type definition](/api/projects/products.md?urn=ctp:api:type:ProductAddPriceAction). Prices are defined with a scope (currency and optionally country, [CustomerGroup](/urn?urn=ctp%3Aapi%3Atype%3ACustomerGroup), and [Channel](/api/projects/channels.md) and/or a validity period (`validFrom` and/or `validTo`). For more information see [price selection](/api/pricing-and-discounts-overview.md#price-selection). Adding an Embedded Price is rejected: - if the product already contains an Embedded Price with the same price scope (same currency, country, customer group, channel, valid from and valid until). - if two Embedded Prices have validity periods that overlap within the same price scope. A price without validity period does not conflict with a price defined for a time period. A maximum number of **100** prices can be specified on a [ProductVariant](/urn?urn=ctp%3Aapi%3Atype%3AProductVariant). If your business case requires going beyond this limit, use [StandalonePrices](/api/projects/standalone-prices.md) instead. Nonetheless, to keep the number of Embedded Prices per Product Variant low, make use of the [price selection](/api/pricing-and-discounts-overview.md#price-selection) fallback logic. For example, you can define a single price for all countries using the `EUR` currency instead of defining prices for the individual `country` attributes. Similarly, you can define a price without a `channel` attribute to use as a base price across channels, and create additional prices with a `channel` attribute for specific channels that differ from the base price. ##### Set Prices [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetPricesAction). ##### Change Price If an [external discount](/api/projects/productDiscounts.md#productdiscountvalueexternal) was set for a Price, this action removes it unless `price.discounted` is provided. To re-apply the discount, either include it in the `price.discounted` field of this action, or use the [Set Discounted Price](/urn?urn=ctp%3Aapi%3Atype%3AProductSetDiscountedPriceAction) update action. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductChangePriceAction). ##### Remove Price [type definition](/api/projects/products.md?urn=ctp:api:type:ProductRemovePriceAction). ##### Set Attribute [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAttributeAction). ##### Set SKU [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetSkuAction). Treat the `sku` values as immutable identifiers. Plan SKU naming up front to avoid costly reassignment and background reconciliation work. ##### Set ProductVariant Key [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetProductVariantKeyAction). ##### Add External Image [type definition](/api/projects/products.md?urn=ctp:api:type:ProductAddExternalImageAction). ##### Remove Image If the image that you want to delete has been [uploaded to our CDN](/api/projects/products.md#upload-product-image) and its `url` is also used on other Product Variants, then removing the image will make it unavailable wherever it is shared. [type definition](/api/projects/products.md?urn=ctp:api:type:ProductRemoveImageAction). ##### Add Asset [type definition](/api/projects/products.md?urn=ctp:api:type:ProductAddAssetAction). ##### Remove Asset [type definition](/api/projects/products.md?urn=ctp:api:type:ProductRemoveAssetAction). ##### Change Asset Order [type definition](/api/projects/products.md?urn=ctp:api:type:ProductChangeAssetOrderAction). #### on Embedded Price ##### Set Price Custom Type [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetProductPriceCustomTypeAction). ##### Set Price CustomField [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetProductPriceCustomFieldAction). ##### Set Discounted Price [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetDiscountedPriceAction). ##### Set Price Key [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetPriceKeyAction). #### on Asset ##### Set Asset Key [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAssetKeyAction). ##### Change Asset Name [type definition](/api/projects/products.md?urn=ctp:api:type:ProductChangeAssetNameAction). ##### Set Asset Description [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAssetDescriptionAction). ##### Set Asset Tags [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAssetTagsAction). ##### Set Asset Sources [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAssetSourcesAction). ##### Set Asset Custom Type [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAssetCustomTypeAction). ##### Set Asset CustomField [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetAssetCustomFieldAction). #### on Image ##### Move Image To Position [type definition](/api/projects/products.md?urn=ctp:api:type:ProductMoveImageToPositionAction). ##### Set Image Label [type definition](/api/projects/products.md?urn=ctp:api:type:ProductSetImageLabelAction). #### on publish workflow ##### Revert Staged Changes [type definition](/api/projects/products.md?urn=ctp:api:type:ProductRevertStagedChangesAction). ##### Revert Staged Variant Changes [type definition](/api/projects/products.md?urn=ctp:api:type:ProductRevertStagedVariantChangesAction). ##### Publish [type definition](/api/projects/products.md?urn=ctp:api:type:ProductPublishAction). ###### ProductPublishScope [type definition](/api/projects/products.md?urn=ctp:api:type:ProductPublishScope). ##### Unpublish [type definition](/api/projects/products.md?urn=ctp:api:type:ProductUnpublishAction). ## Upload Product image Uploads a binary image file to a given [ProductVariant](/urn?urn=ctp%3Aapi%3Atype%3AProductVariant). After upload, the system converts the original image to several [sizes](/api/projects/products.md#image) that are available on the builtin Content Delivery Network (CDN). Supported image formats are JPEG, PNG, and GIF. The maximum file size of the image to upload is **10 MB**. Only images in **sRGB** color space are supported. When uploading images with other color spaces, like [Adobe RGB](https://www.adobe.com/digitalimag/adobergb.html), the API returns a [400 Bad Request Error](/api/errors.md#400-bad-request-1) with code `InvalidInput` and the message `Unsupported image data. Not able to identify the color model of your image.` In such case, you must fix the issue and upload the image again. If any other error response is returned, upload the image again. The [image](/api/projects/products.md#image) uploaded to the CDN is publicly available and its `url` might be shared across different Products in either the same Project or in other Projects. However, if you delete any Product Variant that contains the image or if you remove the image from any Product Variant, then the image will be deleted from the CDN and it will no longer be available at its original URL. Depending on the size of the original image, the API returns different status codes that indicate the status of the image upload at the time the API responds. If the original image is small, the API responds with `200 OK`, and if the image is larger, it responds with `202 Accepted`. - A `200 OK` response is returned when all [sizes](/api/projects/products.md#image) of the image have been successfully uploaded to the CDN. - A `202 Accepted` response is returned when the `small` size of the image has been successfully uploaded to the CDN, but the upload of the other sizes is still ongoing. These other sizes will be available soon thereafter. [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/\{id}/images:POST). The cURL example below adds an [Image](/api/projects/products.md#image) to the ProductVariant with `id` = `2`, in the staged projection of the Product specified in path parameter `{id}`: ```bash curl -X POST -H "Content-Type: image/jpeg" -H "Authorization: Bearer {token}" --upload-file "detail.jpg" "https://api.{region}.commercetools.com/{projectKey}/products/{id}/images?variant=2&filename=detail.jpg" ``` As the `filename` parameter was included (`filename=detail.jpg`), an example URL of the uploaded image is `https://{commercetools-cdn}/detail-6xAq4Efp.jpg`. File upload using [Content-Type: multipart/form-data](https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2) is currently not supported. Learn more about images in our self-paced Images and Assets module. ## Delete Product You can only delete unpublished Products. This will also remove all Product Tailoring associated with the Product. ### Delete Product by ID [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/\{id}:DELETE). ### Delete Product by Key [endpoint definition](/api/projects/products.md?urn=ctp:api:endpoint:/\{projectKey}/products/key=\{key}:DELETE). ## Related pages - [Area overview page with navigation](/api.md) - [Previous page: Attribute Groups](/api/projects/attribute-groups.md) - [Next page: Product Projections](/api/projects/productProjections.md)