# Products

Manage products. Supported product types include:

* `BASIC` — standalone products
* `BUNDLE` — groups of products sold together
* `PARENT_VARIANT` — products with automatically generated variants defined by a template
* `VARIANT` — individual variants of a `PARENT_VARIANT` product
* `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.

## Searching for products

> Search a list of products.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_read\_unpublished\` scope is only required if the response should contain unpublished products.\
> \* The \`product.product\_read\_by\_vendor\` scope is only required to fetch products belonging to the vendor.\
> \
> \*\*\*<br>

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_read_by_vendor","product.product_read_unpublished"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"responses":{"products_get_response_OK_200":{"description":"Resources have been retrieved successfully.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/basicProductsArray"},{"$ref":"#/components/schemas/bundleProductsArray"},{"$ref":"#/components/schemas/parentVariantProductsArray"},{"$ref":"#/components/schemas/variantProductsArray"},{"$ref":"#/components/schemas/dynamicVariantProductsArray"}]}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"schemas":{"basicProductsArray":{"type":"array","description":"List of products of the BASIC type.","items":{"$ref":"#/components/schemas/basicProductWithId"}},"basicProductWithId":{"type":"object","description":"Products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"basicProductCreation":{"type":"object","description":"Creating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productType":{"type":"string","description":"Indicates the product type, which is immutable. Once the product type is set, it cannot be updated.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"id":{"type":"string","description":"Unique resource identifier."},"YRN":{"title":"YRN (attribute)","type":"string","description":"In YaaS, a global resource identifier is a Uniform Resource Name (URN) with a custom YaaS schema and is called a YaaS Resource Name, or YRN.\n\nIt is a unique identifier, which stores information about a resource, such as its type, ID or name of the tenant."},"productMedia":{"type":"array","uniqueItems":false,"description":"Media files attached to the product.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"yrn":{"$ref":"#/components/schemas/YRN"},"contentType":{"type":"string"},"createdAt":{"type":"string"},"uploadLink":{"type":"string"},"url":{"type":"string"},"cloudinaryUrl":{"type":"string"},"uncommittedMedia":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"customAttributes":{"type":"object"}}}},"productMetadataGet":{"type":"object","description":"Metadata for GET requests.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataWithVersion"},{"type":"object","properties":{"classificationMixins":{"type":"array","description":"List of mixin schemas used for classification.","items":{"type":"object","description":"Mixin schema.","properties":{"name":{"type":"string","description":"Name of the mixin","pattern":"^[a-zA-Z0-9_]\\S*$"},"mixinPath":{"type":"string","description":"The mixins path that should be used when defining attributes on a product. It's built based on the following pattern - `class_<sourceCategory.code>_<name>`."},"schemaUrl":{"type":"string","description":"URL of the mixin schema defined on the category level.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"usedSchemaUrl":{"type":"string","description":"If given mixin has been already used in the product, then this field contains the URL of the used mixin schema.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"obsoleteSchemaUrlUsed":{"type":"boolean","description":"Indicates whether the used mixin schema is obsolete - `usedSchemaUrl` differs from `schemaUrl`."},"required":{"type":"boolean","description":"Indicates whether the mixin is required."},"sourceCategoryId":{"type":"string","description":"Unique identifier of the category from which the mixin comes from. Can be this category ID or one of the parent categories IDs."}}}},"createdAt":{"type":"string","description":"Creation date in the ISO 8601 standard."},"modifiedAt":{"type":"string","description":"Modification date in the ISO 8601 standard."}}}]},"productMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document"}}}]},"bundleProductsArray":{"type":"array","description":"List of products of the BUNDLE type.","items":{"$ref":"#/components/schemas/bundleProductWithId"}},"bundleProductWithId":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/bundleProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"bundleProductCreation":{"type":"object","description":"Creating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"parentVariantProductsArray":{"type":"array","description":"List of products of the PARENT_VARIANT type.","items":{"$ref":"#/components/schemas/parentVariantProductWithId"}},"parentVariantProductWithId":{"type":"object","description":"Products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"parentVariantProductCreation":{"type":"object","description":"Creating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductsArray":{"type":"array","description":"List of products of the VARIANT type.","items":{"$ref":"#/components/schemas/variantProductWithId"}},"variantProductWithId":{"type":"object","description":"Products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/variantProductMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"variantProductCreation":{"type":"object","description":"Creating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"metadata":{"$ref":"#/components/schemas/variantProductMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"variantProductMetadataGet":{"type":"object","description":"Variant metadata response.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataGet"},{"$ref":"#/components/schemas/variantProductMetadataWithVersion"}]},"variantProductMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/variantProductMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document."}}}]},"dynamicVariantProductsArray":{"type":"array","description":"List of products of the DYNAMIC_VARIANT type.","items":{"$ref":"#/components/schemas/dynamicVariantProductWithId"}},"dynamicVariantProductWithId":{"type":"object","description":"Response schema for products of the DYNAMIC_VARIANT type.\n\n- **`sellable`** — not inherited from parents; must be set explicitly on each product. Root and intermediate variants are typically `false`; leaf variants are typically `true`.\n- **Root products** include a `variants` map containing all descendants with accumulated attributes.\n- **Child products** include `ownVariantAttributes` (attributes defined on this product) and `inheritedVariantAttributes` (read-only, merged from ancestors).\n- `parentVariantPath` is an ordered array of ancestor IDs from direct parent (index 0) to root (last index). Empty for root products.\n- `metadata.dynamicVariantInfo` is present only when a hierarchy integrity issue is detected.\n","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"name":{"$ref":"#/components/schemas/localizedValue"},"description":{"$ref":"#/components/schemas/localizedValue"},"productType":{"$ref":"#/components/schemas/productType"},"published":{"$ref":"#/components/schemas/published"},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly (i.e. it is a leaf in the hierarchy that a customer can add to a cart). This value is **not inherited** from parent variants — it must be set explicitly on each product. Root products and intermediate-level variants are typically `false`; leaf variants are typically `true`.\n"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy. Absent for root-level products."},"parentVariantPath":{"type":"array","description":"Ordered array of ancestor product identifiers, from the direct parent (index 0) to the root (last index). Empty for root-level products.\n","items":{"type":"string"}},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind within the hierarchy (for example, `\"H1_L1\"`)."},"ownVariantAttributes":{"$ref":"#/components/schemas/ownVariantAttributes"},"inheritedVariantAttributes":{"$ref":"#/components/schemas/inheritedVariantAttributes"},"variants":{"$ref":"#/components/schemas/variantsMap"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"vendor":{"$ref":"#/components/schemas/vendor"},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"relatedItems":{"type":"array","description":"List of items in a relationship with this product.","items":{"$ref":"#/components/schemas/relatedItem"}},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging."},"mixins":{"$ref":"#/components/schemas/productMixins"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/dynamicVariantProductMetadataGet"}},"required":["id","code","name","productType"]},"ownVariantAttributes":{"type":"object","description":"Map of variant attributes defined directly on this product. Keys are attribute identifiers (for example, `storageCapacity`). These are the attributes the caller can set by create/update requests. On responses they represent what is stored on this specific product.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"dynamicVariantAttribute":{"type":"object","description":"A single dynamic variant attribute. Combines a localized display name for the attribute itself with a typed, optionally localized value.\n","required":["value"],"properties":{"name":{"$ref":"#/components/schemas/localizedValue"},"value":{"$ref":"#/components/schemas/dynamicVariantAttributeValue"}}},"dynamicVariantAttributeValue":{"type":"object","description":"The value part of a dynamic variant attribute. Holds the canonical qualifier used for matching, an optional localized display label, and an optional unit code for measurement attributes.\n","required":["type","qualifier"],"properties":{"type":{"type":"string","description":"Data type of the qualifier value.\n","enum":["STRING","NUMBER","DECIMAL","BOOLEAN"]},"qualifier":{"description":"The canonical value used for variant matching. The JSON type must match `type`: a string for `STRING`, a number for `NUMBER` or `DECIMAL`, or a boolean for `BOOLEAN`.\n","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"name":{"$ref":"#/components/schemas/localizedValue"},"unit":{"type":"string","description":"Optional unit code for measurement attributes (for example, `\"MMT\"` for millimetres, `\"PCE\"` for pieces). Unit translations are resolved by the frontend from a separate dictionary.\n"}}},"inheritedVariantAttributes":{"type":"object","description":"Read-only map of variant attributes inherited from ancestor products in the hierarchy. These cannot be modified on this product — to change an inherited attribute, update the ancestor that owns it.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"variantsMap":{"type":"object","description":"Denormalized flat map of all descendant variants stored on the root product. Keys are variant product identifiers. In API responses each entry's `variantAttributes` contains accumulated attributes.\n","additionalProperties":{"$ref":"#/components/schemas/variantMapEntry"}},"variantMapEntry":{"type":"object","description":"A single entry in the root product's `variants` map. In API responses the `variantAttributes` field contains **accumulated** attributes — the entry's own delta attributes merged with all ancestor attributes up the chain, so storefront clients receive a ready-to-use combination without additional API calls. The `published` flag is included only when the caller has the `product.product_read_unpublished` scope.\n","properties":{"version":{"type":"integer","description":"Version of the source variant product at the time of the last recalculation."},"name":{"$ref":"#/components/schemas/localizedValue"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy."},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly."},"published":{"type":"boolean","description":"Publication state of this variant. Only included in responses when the caller has the `product.product_read_unpublished` scope; entries with `published: false` are otherwise omitted from the map.\n"},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind (for example, `\"H1_L1\"`)."},"variantAttributes":{"type":"object","description":"Accumulated variant attributes for this entry. For leaf variants this includes all ancestor attributes merged with the entry's own delta. Keys are attribute identifiers.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}}}},"dynamicVariantProductMetadataGet":{"type":"object","description":"Metadata for GET responses on DYNAMIC_VARIANT products. Extends the standard product metadata with hierarchy integrity information.","allOf":[{"$ref":"#/components/schemas/productMetadataGet"},{"type":"object","properties":{"dynamicVariantInfo":{"$ref":"#/components/schemas/dynamicVariantInfo"}}}]},"dynamicVariantInfo":{"type":"object","description":"Hierarchy integrity information populated when the variant tree has structural problems. Present only when an issue is detected.\n","properties":{"missingAncestorId":{"type":"string","description":"Identifier of an ancestor product that could not be found, indicating a broken hierarchy chain."},"cycleDetected":{"type":"boolean","description":"Indicates that a circular reference was detected in the `parentVariantId` chain."}}},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"searchProducts":{"type":"object","properties":{"q":{"type":"string","description":"A standard query parameter is used to search for specific values. \n\nSee: [Standard practises - Query parameter](https://developer.emporix.io/api-references/standard-practices/q-param)\n"}}}},"requestBodies":{"productsSearchBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/searchProducts"}}}}},"parameters":{"header_x_total_count":{"name":"X-Total-Count","in":"header","required":false,"schema":{"type":"boolean"},"description":"Flag indicating whether the total number of retrieved results should be returned."},"query_page_number":{"name":"pageNumber","in":"query","required":false,"schema":{"type":"integer"},"description":"The page number to be retrieved where the size of the pages must be specified by the pageSize parameter. The number of the first page is 1."},"query_page_size":{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","default":60},"description":"The number of documents being retrieved on the page."},"query_sort_product":{"name":"sort","in":"query","description":"List of properties used to sort the results, separated by colons.\n\nPossible values:\n* `{fieldName}`\n* `{fieldName}:asc`\n* `{fieldName}:desc`\n\n**Note:** If you want to sort the results by localized properties, the possible values are:\n  * `{fieldName}.{language}`\n  * `{fieldName}.{language}:asc`\n  * `{fieldName}.{language}:desc`\n\nBy default, the fields are sorted in ascending order.\n","schema":{"type":"string"}},"query_product_fields":{"name":"fields","in":"query","required":false,"description":"Fields to be returned in the response.\n\nWhen this parameter is passed, only the `id`, `yrn` and `{fieldName}` are retrieved for each product.\n\nYou can specify multiple fields by separating them with commas.\n","schema":{"type":"string"}},"header_accept_language":{"name":"Accept-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Accept-Language request HTTP header defines which languages the client is able to understand, and which locale variant is preferred. If empty, the default system language is assumed. It can be a priority list working as a fallback mechanism."},"query_expand_product":{"name":"expand","in":"query","required":false,"schema":{"type":"string"},"description":"Fields that should be expanded with additional information in the response body. Expressed as strings separated by commas.\n\nPossible values:\n  * `template`\n  * `parentVariant`\n"},"query_raw_value_product":{"in":"query","name":"rawValue","schema":{"type":"boolean"},"required":false,"description":"Flag indicating whether product variant(s) should include their parent variants' attribute values.\n* If set to `true`, the result contains values from both the variant and its parent variant.\n* If set to `false`, the result contains only variant values.\n"}}},"paths":{"/product/{tenant}/products/search":{"post":{"responses":{"200":{"$ref":"#/components/responses/products_get_response_OK_200"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Search a list of products.\n***\n\n**Additional scope information**\n\n* The `product.product_read_unpublished` scope is only required if the response should contain unpublished products.\n* The `product.product_read_by_vendor` scope is only required to fetch products belonging to the vendor.\n\n***\n","operationId":"POST-product-search-products","requestBody":{"$ref":"#/components/requestBodies/productsSearchBody"},"parameters":[{"$ref":"#/components/parameters/header_x_total_count"},{"$ref":"#/components/parameters/query_page_number"},{"$ref":"#/components/parameters/query_page_size"},{"$ref":"#/components/parameters/query_sort_product"},{"$ref":"#/components/parameters/query_product_fields"},{"$ref":"#/components/parameters/header_accept_language"},{"$ref":"#/components/parameters/query_expand_product"},{"$ref":"#/components/parameters/query_raw_value_product"}],"summary":"Searching for products","tags":["Products"]}}}}
```

## Retrieving all products

> Retrieves a list of products.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_read\_unpublished\` scope is only required if the response should contain unpublished products.\
> \* The \`product.product\_read\_by\_vendor\` scope is only required to fetch products belonging to the vendor.\
> \* The \`product.product\_manage\_by\_vendor\` scope is only required to manage products belonging to the vendor.\
> \
> \*\*\*<br>

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_read_by_vendor","product.product_read_unpublished","product.product_manage_by_vendor"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"responses":{"products_get_response_OK_200":{"description":"Resources have been retrieved successfully.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/basicProductsArray"},{"$ref":"#/components/schemas/bundleProductsArray"},{"$ref":"#/components/schemas/parentVariantProductsArray"},{"$ref":"#/components/schemas/variantProductsArray"},{"$ref":"#/components/schemas/dynamicVariantProductsArray"}]}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"schemas":{"basicProductsArray":{"type":"array","description":"List of products of the BASIC type.","items":{"$ref":"#/components/schemas/basicProductWithId"}},"basicProductWithId":{"type":"object","description":"Products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"basicProductCreation":{"type":"object","description":"Creating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productType":{"type":"string","description":"Indicates the product type, which is immutable. Once the product type is set, it cannot be updated.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"id":{"type":"string","description":"Unique resource identifier."},"YRN":{"title":"YRN (attribute)","type":"string","description":"In YaaS, a global resource identifier is a Uniform Resource Name (URN) with a custom YaaS schema and is called a YaaS Resource Name, or YRN.\n\nIt is a unique identifier, which stores information about a resource, such as its type, ID or name of the tenant."},"productMedia":{"type":"array","uniqueItems":false,"description":"Media files attached to the product.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"yrn":{"$ref":"#/components/schemas/YRN"},"contentType":{"type":"string"},"createdAt":{"type":"string"},"uploadLink":{"type":"string"},"url":{"type":"string"},"cloudinaryUrl":{"type":"string"},"uncommittedMedia":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"customAttributes":{"type":"object"}}}},"productMetadataGet":{"type":"object","description":"Metadata for GET requests.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataWithVersion"},{"type":"object","properties":{"classificationMixins":{"type":"array","description":"List of mixin schemas used for classification.","items":{"type":"object","description":"Mixin schema.","properties":{"name":{"type":"string","description":"Name of the mixin","pattern":"^[a-zA-Z0-9_]\\S*$"},"mixinPath":{"type":"string","description":"The mixins path that should be used when defining attributes on a product. It's built based on the following pattern - `class_<sourceCategory.code>_<name>`."},"schemaUrl":{"type":"string","description":"URL of the mixin schema defined on the category level.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"usedSchemaUrl":{"type":"string","description":"If given mixin has been already used in the product, then this field contains the URL of the used mixin schema.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"obsoleteSchemaUrlUsed":{"type":"boolean","description":"Indicates whether the used mixin schema is obsolete - `usedSchemaUrl` differs from `schemaUrl`."},"required":{"type":"boolean","description":"Indicates whether the mixin is required."},"sourceCategoryId":{"type":"string","description":"Unique identifier of the category from which the mixin comes from. Can be this category ID or one of the parent categories IDs."}}}},"createdAt":{"type":"string","description":"Creation date in the ISO 8601 standard."},"modifiedAt":{"type":"string","description":"Modification date in the ISO 8601 standard."}}}]},"productMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document"}}}]},"bundleProductsArray":{"type":"array","description":"List of products of the BUNDLE type.","items":{"$ref":"#/components/schemas/bundleProductWithId"}},"bundleProductWithId":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/bundleProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"bundleProductCreation":{"type":"object","description":"Creating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"parentVariantProductsArray":{"type":"array","description":"List of products of the PARENT_VARIANT type.","items":{"$ref":"#/components/schemas/parentVariantProductWithId"}},"parentVariantProductWithId":{"type":"object","description":"Products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"parentVariantProductCreation":{"type":"object","description":"Creating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductsArray":{"type":"array","description":"List of products of the VARIANT type.","items":{"$ref":"#/components/schemas/variantProductWithId"}},"variantProductWithId":{"type":"object","description":"Products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/variantProductMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"variantProductCreation":{"type":"object","description":"Creating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"metadata":{"$ref":"#/components/schemas/variantProductMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"variantProductMetadataGet":{"type":"object","description":"Variant metadata response.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataGet"},{"$ref":"#/components/schemas/variantProductMetadataWithVersion"}]},"variantProductMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/variantProductMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document."}}}]},"dynamicVariantProductsArray":{"type":"array","description":"List of products of the DYNAMIC_VARIANT type.","items":{"$ref":"#/components/schemas/dynamicVariantProductWithId"}},"dynamicVariantProductWithId":{"type":"object","description":"Response schema for products of the DYNAMIC_VARIANT type.\n\n- **`sellable`** — not inherited from parents; must be set explicitly on each product. Root and intermediate variants are typically `false`; leaf variants are typically `true`.\n- **Root products** include a `variants` map containing all descendants with accumulated attributes.\n- **Child products** include `ownVariantAttributes` (attributes defined on this product) and `inheritedVariantAttributes` (read-only, merged from ancestors).\n- `parentVariantPath` is an ordered array of ancestor IDs from direct parent (index 0) to root (last index). Empty for root products.\n- `metadata.dynamicVariantInfo` is present only when a hierarchy integrity issue is detected.\n","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"name":{"$ref":"#/components/schemas/localizedValue"},"description":{"$ref":"#/components/schemas/localizedValue"},"productType":{"$ref":"#/components/schemas/productType"},"published":{"$ref":"#/components/schemas/published"},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly (i.e. it is a leaf in the hierarchy that a customer can add to a cart). This value is **not inherited** from parent variants — it must be set explicitly on each product. Root products and intermediate-level variants are typically `false`; leaf variants are typically `true`.\n"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy. Absent for root-level products."},"parentVariantPath":{"type":"array","description":"Ordered array of ancestor product identifiers, from the direct parent (index 0) to the root (last index). Empty for root-level products.\n","items":{"type":"string"}},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind within the hierarchy (for example, `\"H1_L1\"`)."},"ownVariantAttributes":{"$ref":"#/components/schemas/ownVariantAttributes"},"inheritedVariantAttributes":{"$ref":"#/components/schemas/inheritedVariantAttributes"},"variants":{"$ref":"#/components/schemas/variantsMap"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"vendor":{"$ref":"#/components/schemas/vendor"},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"relatedItems":{"type":"array","description":"List of items in a relationship with this product.","items":{"$ref":"#/components/schemas/relatedItem"}},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging."},"mixins":{"$ref":"#/components/schemas/productMixins"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/dynamicVariantProductMetadataGet"}},"required":["id","code","name","productType"]},"ownVariantAttributes":{"type":"object","description":"Map of variant attributes defined directly on this product. Keys are attribute identifiers (for example, `storageCapacity`). These are the attributes the caller can set by create/update requests. On responses they represent what is stored on this specific product.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"dynamicVariantAttribute":{"type":"object","description":"A single dynamic variant attribute. Combines a localized display name for the attribute itself with a typed, optionally localized value.\n","required":["value"],"properties":{"name":{"$ref":"#/components/schemas/localizedValue"},"value":{"$ref":"#/components/schemas/dynamicVariantAttributeValue"}}},"dynamicVariantAttributeValue":{"type":"object","description":"The value part of a dynamic variant attribute. Holds the canonical qualifier used for matching, an optional localized display label, and an optional unit code for measurement attributes.\n","required":["type","qualifier"],"properties":{"type":{"type":"string","description":"Data type of the qualifier value.\n","enum":["STRING","NUMBER","DECIMAL","BOOLEAN"]},"qualifier":{"description":"The canonical value used for variant matching. The JSON type must match `type`: a string for `STRING`, a number for `NUMBER` or `DECIMAL`, or a boolean for `BOOLEAN`.\n","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"name":{"$ref":"#/components/schemas/localizedValue"},"unit":{"type":"string","description":"Optional unit code for measurement attributes (for example, `\"MMT\"` for millimetres, `\"PCE\"` for pieces). Unit translations are resolved by the frontend from a separate dictionary.\n"}}},"inheritedVariantAttributes":{"type":"object","description":"Read-only map of variant attributes inherited from ancestor products in the hierarchy. These cannot be modified on this product — to change an inherited attribute, update the ancestor that owns it.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"variantsMap":{"type":"object","description":"Denormalized flat map of all descendant variants stored on the root product. Keys are variant product identifiers. In API responses each entry's `variantAttributes` contains accumulated attributes.\n","additionalProperties":{"$ref":"#/components/schemas/variantMapEntry"}},"variantMapEntry":{"type":"object","description":"A single entry in the root product's `variants` map. In API responses the `variantAttributes` field contains **accumulated** attributes — the entry's own delta attributes merged with all ancestor attributes up the chain, so storefront clients receive a ready-to-use combination without additional API calls. The `published` flag is included only when the caller has the `product.product_read_unpublished` scope.\n","properties":{"version":{"type":"integer","description":"Version of the source variant product at the time of the last recalculation."},"name":{"$ref":"#/components/schemas/localizedValue"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy."},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly."},"published":{"type":"boolean","description":"Publication state of this variant. Only included in responses when the caller has the `product.product_read_unpublished` scope; entries with `published: false` are otherwise omitted from the map.\n"},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind (for example, `\"H1_L1\"`)."},"variantAttributes":{"type":"object","description":"Accumulated variant attributes for this entry. For leaf variants this includes all ancestor attributes merged with the entry's own delta. Keys are attribute identifiers.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}}}},"dynamicVariantProductMetadataGet":{"type":"object","description":"Metadata for GET responses on DYNAMIC_VARIANT products. Extends the standard product metadata with hierarchy integrity information.","allOf":[{"$ref":"#/components/schemas/productMetadataGet"},{"type":"object","properties":{"dynamicVariantInfo":{"$ref":"#/components/schemas/dynamicVariantInfo"}}}]},"dynamicVariantInfo":{"type":"object","description":"Hierarchy integrity information populated when the variant tree has structural problems. Present only when an issue is detected.\n","properties":{"missingAncestorId":{"type":"string","description":"Identifier of an ancestor product that could not be found, indicating a broken hierarchy chain."},"cycleDetected":{"type":"boolean","description":"Indicates that a circular reference was detected in the `parentVariantId` chain."}}},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}}},"parameters":{"header_x_total_count":{"name":"X-Total-Count","in":"header","required":false,"schema":{"type":"boolean"},"description":"Flag indicating whether the total number of retrieved results should be returned."},"query_page_number":{"name":"pageNumber","in":"query","required":false,"schema":{"type":"integer"},"description":"The page number to be retrieved where the size of the pages must be specified by the pageSize parameter. The number of the first page is 1."},"query_page_size":{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","default":60},"description":"The number of documents being retrieved on the page."},"query_sort_product":{"name":"sort","in":"query","description":"List of properties used to sort the results, separated by colons.\n\nPossible values:\n* `{fieldName}`\n* `{fieldName}:asc`\n* `{fieldName}:desc`\n\n**Note:** If you want to sort the results by localized properties, the possible values are:\n  * `{fieldName}.{language}`\n  * `{fieldName}.{language}:asc`\n  * `{fieldName}.{language}:desc`\n\nBy default, the fields are sorted in ascending order.\n","schema":{"type":"string"}},"query_q_product":{"name":"q","in":"query","description":"A standard query parameter is used to search for specific values. \n\nSee: [Standard practises - Query parameter](https://developer.emporix.io/api-references/standard-practices/q-param)\n","schema":{"type":"string"}},"query_product_fields":{"name":"fields","in":"query","required":false,"description":"Fields to be returned in the response.\n\nWhen this parameter is passed, only the `id`, `yrn` and `{fieldName}` are retrieved for each product.\n\nYou can specify multiple fields by separating them with commas.\n","schema":{"type":"string"}},"header_accept_language":{"name":"Accept-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Accept-Language request HTTP header defines which languages the client is able to understand, and which locale variant is preferred. If empty, the default system language is assumed. It can be a priority list working as a fallback mechanism."},"query_expand_product":{"name":"expand","in":"query","required":false,"schema":{"type":"string"},"description":"Fields that should be expanded with additional information in the response body. Expressed as strings separated by commas.\n\nPossible values:\n  * `template`\n  * `parentVariant`\n"},"query_raw_value_product":{"in":"query","name":"rawValue","schema":{"type":"boolean"},"required":false,"description":"Flag indicating whether product variant(s) should include their parent variants' attribute values.\n* If set to `true`, the result contains values from both the variant and its parent variant.\n* If set to `false`, the result contains only variant values.\n"}}},"paths":{"/product/{tenant}/products":{"get":{"responses":{"200":{"$ref":"#/components/responses/products_get_response_OK_200"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Retrieves a list of products.\n***\n\n**Additional scope information**\n\n* The `product.product_read_unpublished` scope is only required if the response should contain unpublished products.\n* The `product.product_read_by_vendor` scope is only required to fetch products belonging to the vendor.\n* The `product.product_manage_by_vendor` scope is only required to manage products belonging to the vendor.\n\n***\n","operationId":"GET-product-list-products","parameters":[{"$ref":"#/components/parameters/header_x_total_count"},{"$ref":"#/components/parameters/query_page_number"},{"$ref":"#/components/parameters/query_page_size"},{"$ref":"#/components/parameters/query_sort_product"},{"$ref":"#/components/parameters/query_q_product"},{"$ref":"#/components/parameters/query_product_fields"},{"$ref":"#/components/parameters/header_accept_language"},{"$ref":"#/components/parameters/query_expand_product"},{"$ref":"#/components/parameters/query_raw_value_product"}],"summary":"Retrieving all products","tags":["Products"]}}}}
```

## Creating a new product

> Creates a new product.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_manage\_by\_vendor\` scope is only required for vendor employeesto manage products belonging to the vendor.\
> \* The \`product.product\_publish\` scope is only required if you want to publish the product when creating it.\
> \
> \*\*\*

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage","product.product_manage_by_vendor","product.product_publish"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"schemas":{"resourceLocation":{"type":"object","properties":{"id":{"type":"string"},"yrn":{"$ref":"#/components/schemas/YRN"}}},"YRN":{"title":"YRN (attribute)","type":"string","description":"In YaaS, a global resource identifier is a Uniform Resource Name (URN) with a custom YaaS schema and is called a YaaS Resource Name, or YRN.\n\nIt is a unique identifier, which stores information about a resource, such as its type, ID or name of the tenant."},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"coreErrorMessageWithDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/coreErrorMessage"},{"type":"object","properties":{"details":{"type":"array","description":"Error message details.","items":{"type":"object","properties":{"field":{"type":"string"},"type":{"type":"string"},"message":{"type":"string"},"moreInfo":{"type":"string"}}}}}}]},"basicProductCreation":{"type":"object","description":"Creating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productType":{"type":"string","description":"Indicates the product type, which is immutable. Once the product type is set, it cannot be updated.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"bundleProductCreation":{"type":"object","description":"Creating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"parentVariantProductCreation":{"type":"object","description":"Creating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductCreation":{"type":"object","description":"Creating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"metadata":{"$ref":"#/components/schemas/variantProductMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"dynamicVariantProductCreation":{"type":"object","description":"Creating products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/dynamicVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"dynamicVariantProduct":{"type":"object","description":"Base schema for products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy. Omit or leave empty for root-level dynamic variant products.\n"},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind within the hierarchy (for example, `\"H1_L1\"`). Used for display and filtering purposes.\n"},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly, if it's a leaf in the hierarchy that a customer can add to a cart. This value is **not inherited** from parent variants — it must be set explicitly on each product. Root products and intermediate-level variants are typically `false`. Leaf variants are typically `true`.\n"},"ownVariantAttributes":{"$ref":"#/components/schemas/ownVariantAttributes"}},"required":["name","code"]}]},"ownVariantAttributes":{"type":"object","description":"Map of variant attributes defined directly on this product. Keys are attribute identifiers (for example, `storageCapacity`). These are the attributes the caller can set by create/update requests. On responses they represent what is stored on this specific product.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"dynamicVariantAttribute":{"type":"object","description":"A single dynamic variant attribute. Combines a localized display name for the attribute itself with a typed, optionally localized value.\n","required":["value"],"properties":{"name":{"$ref":"#/components/schemas/localizedValue"},"value":{"$ref":"#/components/schemas/dynamicVariantAttributeValue"}}},"dynamicVariantAttributeValue":{"type":"object","description":"The value part of a dynamic variant attribute. Holds the canonical qualifier used for matching, an optional localized display label, and an optional unit code for measurement attributes.\n","required":["type","qualifier"],"properties":{"type":{"type":"string","description":"Data type of the qualifier value.\n","enum":["STRING","NUMBER","DECIMAL","BOOLEAN"]},"qualifier":{"description":"The canonical value used for variant matching. The JSON type must match `type`: a string for `STRING`, a number for `NUMBER` or `DECIMAL`, or a boolean for `BOOLEAN`.\n","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"name":{"$ref":"#/components/schemas/localizedValue"},"unit":{"type":"string","description":"Optional unit code for measurement attributes (for example, `\"MMT\"` for millimetres, `\"PCE\"` for pieces). Unit translations are resolved by the frontend from a separate dictionary.\n"}}}},"responses":{"products_post_response_BadRequest_400":{"description":"Resources cannot be created due to an error.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/coreErrorMessage"}]}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_Conflict_409":{"description":"There are three possible reasons:\n1. Product with given code already exists, please choose unique code for your product\n2. Optimistic locking failed. If user sends metadata/version attribute which is outdated (someone else updated product in the time user was performing his changes). User should retrieve the latest product data and retry the request.\n3. Optimistic locking failed. User did not provide metadata/version attribute in update request, but someone else updated product while it was internally handled by product service. Resending the same request can result in successful update, but the update can override recently persisted changes.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessageWithDetails"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"requestBodies":{"productCreateBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/basicProductCreation"},{"$ref":"#/components/schemas/bundleProductCreation"},{"$ref":"#/components/schemas/parentVariantProductCreation"},{"$ref":"#/components/schemas/variantProductCreation"},{"$ref":"#/components/schemas/dynamicVariantProductCreation"}]}}}}},"parameters":{"path_tenant":{"name":"tenant","in":"path","required":true,"description":"Your Emporix tenant name.\n\n**Note**: The tenant should always be written in lowercase.\n","schema":{"pattern":"^[a-z][a-z0-9]+$","minLength":3,"maxLength":16,"type":"string"}},"header_content_language":{"name":"Content-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Content-Language request HTTP header defines a language or multiple languages of the request body.\n\n* If the `Content-Language` header is set to `*`, the localized fields should be provided as maps of translations, where the keys are language codes and values are the fields in their respective languages.\n* If the `Content-Language` header is set to a specific language, the localized fields should be provided as strings.\n* If the `Content-Language` header is empty, the endpoint interprets the localized fields as being provided in the default language or the languages defined in the Configuration Service.\n\n**Note**: You can provide the localized fields only in languages defined in the Configuration Service. In case the fields are provided in languages that are not defined in the Configuration Service, the request is rejected.\n"},"query_skip_variants_generation":{"name":"skipVariantGeneration","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"The parameter is valid only for `PARENT_VARIANT` type. If true then variants are not automatically generated for the parent variant configuration."},"query_do_index":{"name":"doIndex","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"Allows to control whether the change of the state should cause reindexing or not."},"query_skip_related_items_validation":{"name":"skipRelatedItemsValidation","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"If set to `true`, the validation that checks whether related products exist is skipped. This is useful during data loading, where related products may not yet exist and will be created later. This parameter is only respected when the `allowToSkipRelatedProductsValidation` system setting is set to `true`. Otherwise, it is disregarded."}}},"paths":{"/product/{tenant}/products":{"post":{"responses":{"201":{"description":"The resource has been successfully created.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/resourceLocation"}}}},"400":{"$ref":"#/components/responses/products_post_response_BadRequest_400"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"409":{"$ref":"#/components/responses/common_response_Conflict_409"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Creates a new product.\n***\n\n**Additional scope information**\n\n* The `product.product_manage_by_vendor` scope is only required for vendor employeesto manage products belonging to the vendor.\n* The `product.product_publish` scope is only required if you want to publish the product when creating it.\n\n***","operationId":"POST-product-create-product","requestBody":{"$ref":"#/components/requestBodies/productCreateBody"},"parameters":[{"$ref":"#/components/parameters/path_tenant"},{"$ref":"#/components/parameters/header_content_language"},{"$ref":"#/components/parameters/query_skip_variants_generation"},{"$ref":"#/components/parameters/query_do_index"},{"$ref":"#/components/parameters/query_skip_related_items_validation"}],"summary":"Creating a new product","tags":["Products"]}}}}
```

## Creating multiple products

> Creates products in a bulk. The maximum batch size is 200.\
> \
> Response for a particular product is returned at the same position (index) at which that price is located in the request body.\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_manage\_by\_vendor\` scope is only required for vendor employees to manage products belonging to the vendor.\
> \* The \`product.product\_publish\` scope is only required if you want to publish the product when creating it.\
> \
> \*\*\*

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage","product.product_manage_by_vendor","product.product_publish"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"responses":{"products_create_in_bulk_response":{"description":"Example response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/bulkResponse"}}},"application/xml":{"schema":{"type":"object","properties":{}}}}},"products_post_response_BadRequest_400":{"description":"Resources cannot be created due to an error.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/coreErrorMessage"}]}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_Conflict_409":{"description":"There are three possible reasons:\n1. Product with given code already exists, please choose unique code for your product\n2. Optimistic locking failed. If user sends metadata/version attribute which is outdated (someone else updated product in the time user was performing his changes). User should retrieve the latest product data and retry the request.\n3. Optimistic locking failed. User did not provide metadata/version attribute in update request, but someone else updated product while it was internally handled by product service. Resending the same request can result in successful update, but the update can override recently persisted changes.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessageWithDetails"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"schemas":{"bulkResponse":{"title":"bulkResponse","type":"object","properties":{"index":{"type":"integer","description":"Index of the processed product, matching the price position in request body.\n"},"id":{"type":"string","description":"Product unique identifier."},"code":{"type":"integer","description":"HTTP Status Code."},"errorCode":{"type":"string","description":"Error specific errorCode."},"status":{"type":"string","description":"HTTP Status description."},"message":{"type":"string","description":"Error message."},"details":{"type":"array","description":"Error message details.","items":{"type":"string"}}}},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"coreErrorMessageWithDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/coreErrorMessage"},{"type":"object","properties":{"details":{"type":"array","description":"Error message details.","items":{"type":"object","properties":{"field":{"type":"string"},"type":{"type":"string"},"message":{"type":"string"},"moreInfo":{"type":"string"}}}}}}]},"basicProductCreation":{"type":"object","description":"Creating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productType":{"type":"string","description":"Indicates the product type, which is immutable. Once the product type is set, it cannot be updated.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"bundleProductCreation":{"type":"object","description":"Creating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"parentVariantProductCreation":{"type":"object","description":"Creating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductCreation":{"type":"object","description":"Creating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"metadata":{"$ref":"#/components/schemas/variantProductMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"dynamicVariantProductCreation":{"type":"object","description":"Creating products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/dynamicVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"dynamicVariantProduct":{"type":"object","description":"Base schema for products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy. Omit or leave empty for root-level dynamic variant products.\n"},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind within the hierarchy (for example, `\"H1_L1\"`). Used for display and filtering purposes.\n"},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly, if it's a leaf in the hierarchy that a customer can add to a cart. This value is **not inherited** from parent variants — it must be set explicitly on each product. Root products and intermediate-level variants are typically `false`. Leaf variants are typically `true`.\n"},"ownVariantAttributes":{"$ref":"#/components/schemas/ownVariantAttributes"}},"required":["name","code"]}]},"ownVariantAttributes":{"type":"object","description":"Map of variant attributes defined directly on this product. Keys are attribute identifiers (for example, `storageCapacity`). These are the attributes the caller can set by create/update requests. On responses they represent what is stored on this specific product.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"dynamicVariantAttribute":{"type":"object","description":"A single dynamic variant attribute. Combines a localized display name for the attribute itself with a typed, optionally localized value.\n","required":["value"],"properties":{"name":{"$ref":"#/components/schemas/localizedValue"},"value":{"$ref":"#/components/schemas/dynamicVariantAttributeValue"}}},"dynamicVariantAttributeValue":{"type":"object","description":"The value part of a dynamic variant attribute. Holds the canonical qualifier used for matching, an optional localized display label, and an optional unit code for measurement attributes.\n","required":["type","qualifier"],"properties":{"type":{"type":"string","description":"Data type of the qualifier value.\n","enum":["STRING","NUMBER","DECIMAL","BOOLEAN"]},"qualifier":{"description":"The canonical value used for variant matching. The JSON type must match `type`: a string for `STRING`, a number for `NUMBER` or `DECIMAL`, or a boolean for `BOOLEAN`.\n","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"name":{"$ref":"#/components/schemas/localizedValue"},"unit":{"type":"string","description":"Optional unit code for measurement attributes (for example, `\"MMT\"` for millimetres, `\"PCE\"` for pieces). Unit translations are resolved by the frontend from a separate dictionary.\n"}}}},"requestBodies":{"productBulkCreateBody":{"content":{"application/json":{"schema":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/basicProductCreation"},{"$ref":"#/components/schemas/bundleProductCreation"},{"$ref":"#/components/schemas/parentVariantProductCreation"},{"$ref":"#/components/schemas/variantProductCreation"},{"$ref":"#/components/schemas/dynamicVariantProductCreation"}]}}}},"description":"A list of product create requests"}},"parameters":{"header_content_language":{"name":"Content-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Content-Language request HTTP header defines a language or multiple languages of the request body.\n\n* If the `Content-Language` header is set to `*`, the localized fields should be provided as maps of translations, where the keys are language codes and values are the fields in their respective languages.\n* If the `Content-Language` header is set to a specific language, the localized fields should be provided as strings.\n* If the `Content-Language` header is empty, the endpoint interprets the localized fields as being provided in the default language or the languages defined in the Configuration Service.\n\n**Note**: You can provide the localized fields only in languages defined in the Configuration Service. In case the fields are provided in languages that are not defined in the Configuration Service, the request is rejected.\n"},"query_skip_variants_generation":{"name":"skipVariantGeneration","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"The parameter is valid only for `PARENT_VARIANT` type. If true then variants are not automatically generated for the parent variant configuration."},"query_do_index":{"name":"doIndex","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"Allows to control whether the change of the state should cause reindexing or not."},"query_skip_related_items_validation":{"name":"skipRelatedItemsValidation","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"If set to `true`, the validation that checks whether related products exist is skipped. This is useful during data loading, where related products may not yet exist and will be created later. This parameter is only respected when the `allowToSkipRelatedProductsValidation` system setting is set to `true`. Otherwise, it is disregarded."}}},"paths":{"/product/{tenant}/products/bulk":{"post":{"summary":"Creating multiple products","operationId":"POST-product-create-bulk-products","responses":{"207":{"$ref":"#/components/responses/products_create_in_bulk_response"},"400":{"$ref":"#/components/responses/products_post_response_BadRequest_400"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"404":{"$ref":"#/components/responses/common_response_Conflict_409"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"tags":["Products"],"description":"Creates products in a bulk. The maximum batch size is 200.\n\nResponse for a particular product is returned at the same position (index) at which that price is located in the request body.\n\n**Additional scope information**\n\n* The `product.product_manage_by_vendor` scope is only required for vendor employees to manage products belonging to the vendor.\n* The `product.product_publish` scope is only required if you want to publish the product when creating it.\n\n***","requestBody":{"$ref":"#/components/requestBodies/productBulkCreateBody"},"parameters":[{"$ref":"#/components/parameters/header_content_language"},{"$ref":"#/components/parameters/query_skip_variants_generation"},{"$ref":"#/components/parameters/query_do_index"},{"$ref":"#/components/parameters/query_skip_related_items_validation"}]}}}}
```

## Upserting multiple products

> Updates or creates products in a bulk. The maximum batch size is 200.\
> \
> Response for a particular product is returned at the same position (index) at which it is located in the request body.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_manage\_by\_vendor\` scope is only required for vendor employees to manage products belonging to the vendor.\
> \* The \`product.product\_publish\` scope is only required if you want to publish the product when updating it.\
> \* The \`product.product\_unpublish\` scope is only required if you want to unpublish the product when updating it.\
> \
> \*\*\*

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage","product.product_manage_by_vendor","product.product_publish","product.product_unpublish"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"responses":{"products_update_in_bulk_response":{"description":"Example response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/bulkResponse"}}}}},"common_response_BadRequest_400":{"description":"Bad request due to validation, incorrect parameters, etc.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"schemas":{"bulkResponse":{"title":"bulkResponse","type":"object","properties":{"index":{"type":"integer","description":"Index of the processed product, matching the price position in request body.\n"},"id":{"type":"string","description":"Product unique identifier."},"code":{"type":"integer","description":"HTTP Status Code."},"errorCode":{"type":"string","description":"Error specific errorCode."},"status":{"type":"string","description":"HTTP Status description."},"message":{"type":"string","description":"Error message."},"details":{"type":"array","description":"Error message details.","items":{"type":"string"}}}},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"basicProductBulkUpdate":{"type":"object","description":"Updating products of the BASIC type in bulk.","allOf":[{"$ref":"#/components/schemas/basicProductUpdate"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"}},"required":["id"]}]},"basicProductUpdate":{"type":"object","description":"Updating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document"}}}]},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"id":{"type":"string","description":"Unique resource identifier."},"bundleProductBulkUpdate":{"type":"object","description":"Updating products of the BUNDLE type in bulk.","allOf":[{"$ref":"#/components/schemas/bundleProductUpdate"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"}},"required":["id"]}]},"bundleProductUpdate":{"type":"object","description":"Updating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"parentVariantProductBulkUpdate":{"type":"object","description":"Updating products of the PARENT_VARIANT type in bulk.","allOf":[{"$ref":"#/components/schemas/parentVariantProductUpdate"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"}},"required":["id"]}]},"parentVariantProductUpdate":{"type":"object","description":"Updating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductBulkUpdate":{"type":"object","description":"Updating products of the VARIANT type in bulk.","allOf":[{"$ref":"#/components/schemas/variantProductUpdate"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"}},"required":["id"]}]},"variantProductUpdate":{"type":"object","description":"Updating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/variantProductMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product. This property is taken into account only for insert operations."}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/variantProductMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document."}}}]},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"dynamicVariantProductBulkUpdate":{"type":"object","description":"Updating products of the DYNAMIC_VARIANT type in bulk.","allOf":[{"$ref":"#/components/schemas/dynamicVariantProductUpdate"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"}},"required":["id"]}]},"dynamicVariantProductUpdate":{"type":"object","description":"Updating products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/dynamicVariantProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}}}]},"dynamicVariantProduct":{"type":"object","description":"Base schema for products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy. Omit or leave empty for root-level dynamic variant products.\n"},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind within the hierarchy (for example, `\"H1_L1\"`). Used for display and filtering purposes.\n"},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly, if it's a leaf in the hierarchy that a customer can add to a cart. This value is **not inherited** from parent variants — it must be set explicitly on each product. Root products and intermediate-level variants are typically `false`. Leaf variants are typically `true`.\n"},"ownVariantAttributes":{"$ref":"#/components/schemas/ownVariantAttributes"}},"required":["name","code"]}]},"ownVariantAttributes":{"type":"object","description":"Map of variant attributes defined directly on this product. Keys are attribute identifiers (for example, `storageCapacity`). These are the attributes the caller can set by create/update requests. On responses they represent what is stored on this specific product.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"dynamicVariantAttribute":{"type":"object","description":"A single dynamic variant attribute. Combines a localized display name for the attribute itself with a typed, optionally localized value.\n","required":["value"],"properties":{"name":{"$ref":"#/components/schemas/localizedValue"},"value":{"$ref":"#/components/schemas/dynamicVariantAttributeValue"}}},"dynamicVariantAttributeValue":{"type":"object","description":"The value part of a dynamic variant attribute. Holds the canonical qualifier used for matching, an optional localized display label, and an optional unit code for measurement attributes.\n","required":["type","qualifier"],"properties":{"type":{"type":"string","description":"Data type of the qualifier value.\n","enum":["STRING","NUMBER","DECIMAL","BOOLEAN"]},"qualifier":{"description":"The canonical value used for variant matching. The JSON type must match `type`: a string for `STRING`, a number for `NUMBER` or `DECIMAL`, or a boolean for `BOOLEAN`.\n","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"name":{"$ref":"#/components/schemas/localizedValue"},"unit":{"type":"string","description":"Optional unit code for measurement attributes (for example, `\"MMT\"` for millimetres, `\"PCE\"` for pieces). Unit translations are resolved by the frontend from a separate dictionary.\n"}}}},"requestBodies":{"productBulkUpdateBody":{"content":{"application/json":{"schema":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/basicProductBulkUpdate"},{"$ref":"#/components/schemas/bundleProductBulkUpdate"},{"$ref":"#/components/schemas/parentVariantProductBulkUpdate"},{"$ref":"#/components/schemas/variantProductBulkUpdate"},{"$ref":"#/components/schemas/dynamicVariantProductBulkUpdate"}]}}}}}},"parameters":{"header_content_language":{"name":"Content-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Content-Language request HTTP header defines a language or multiple languages of the request body.\n\n* If the `Content-Language` header is set to `*`, the localized fields should be provided as maps of translations, where the keys are language codes and values are the fields in their respective languages.\n* If the `Content-Language` header is set to a specific language, the localized fields should be provided as strings.\n* If the `Content-Language` header is empty, the endpoint interprets the localized fields as being provided in the default language or the languages defined in the Configuration Service.\n\n**Note**: You can provide the localized fields only in languages defined in the Configuration Service. In case the fields are provided in languages that are not defined in the Configuration Service, the request is rejected.\n"},"query_skip_variants_generation":{"name":"skipVariantGeneration","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"The parameter is valid only for `PARENT_VARIANT` type. If true then variants are not automatically generated for the parent variant configuration."},"query_do_index":{"name":"doIndex","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"Allows to control whether the change of the state should cause reindexing or not."},"query_skip_related_items_validation":{"name":"skipRelatedItemsValidation","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"If set to `true`, the validation that checks whether related products exist is skipped. This is useful during data loading, where related products may not yet exist and will be created later. This parameter is only respected when the `allowToSkipRelatedProductsValidation` system setting is set to `true`. Otherwise, it is disregarded."}}},"paths":{"/product/{tenant}/products/bulk":{"put":{"responses":{"207":{"$ref":"#/components/responses/products_update_in_bulk_response"},"400":{"$ref":"#/components/responses/common_response_BadRequest_400"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Updates or creates products in a bulk. The maximum batch size is 200.\n\nResponse for a particular product is returned at the same position (index) at which it is located in the request body.\n***\n\n**Additional scope information**\n\n* The `product.product_manage_by_vendor` scope is only required for vendor employees to manage products belonging to the vendor.\n* The `product.product_publish` scope is only required if you want to publish the product when updating it.\n* The `product.product_unpublish` scope is only required if you want to unpublish the product when updating it.\n\n***","operationId":"PUT-product-update-bulk-products","requestBody":{"$ref":"#/components/requestBodies/productBulkUpdateBody"},"parameters":[{"$ref":"#/components/parameters/header_content_language"},{"$ref":"#/components/parameters/query_skip_variants_generation"},{"$ref":"#/components/parameters/query_do_index"},{"$ref":"#/components/parameters/query_skip_related_items_validation"}],"summary":"Upserting multiple products","tags":["Products"]}}}}
```

## Triggering dynamic variant recalculation

> Triggers asynchronous recalculation of the variant tree for one or more \`DYNAMIC\_VARIANT\` products. Accepts up to 1000 product IDs at any hierarchy level — the system automatically resolves the root for each ID and creates one recalculation job per unique root product.\
> \
> This endpoint is intended to be called \*\*after\*\* a batch of products has been fully ingested, not per individual product write. For single product writes, the variant tree is updated synchronously inline.\
> \
> If a recalculation job for a given root is already \`PENDING\` or \`PROCESSING\`, the corresponding IDs are returned in \`skippedProductIds\` and the existing job is referenced in the \`jobs\` list.

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"schemas":{"dynamicVariantRecalculationRequest":{"type":"object","description":"Request body for triggering dynamic variant recalculation. Accepts up to 1000 product IDs at any level of the hierarchy — the system resolves the root for each ID automatically. Intended to be called after a batch of products has been fully ingested, not per individual product write.\n","required":["productIds"],"properties":{"productIds":{"type":"array","description":"List of product IDs (variants at any hierarchy level) for which recalculation should be triggered. The system groups IDs by their root product and creates one job per unique root.\n","minItems":1,"maxItems":1000,"items":{"type":"string"}}}},"dynamicVariantRecalculationResponse":{"type":"object","description":"Response returned when recalculation is triggered. Contains one job per unique root product resolved from the submitted IDs, plus any IDs that were skipped (for example, because a job for that root is already PENDING or PROCESSING).\n","properties":{"jobs":{"type":"array","description":"List of recalculation jobs created or referenced for each unique root product.","items":{"$ref":"#/components/schemas/dynamicVariantRecalculationJobResponse"}},"skippedProductIds":{"type":"array","description":"Product IDs that were not processed because a recalculation job for their root is already active (PENDING or PROCESSING). The existing job ID is available in the `jobs` list.\n","items":{"type":"string"}}}},"dynamicVariantRecalculationJobResponse":{"type":"object","description":"Represents a single dynamic variant recalculation job. One job is created per unique root product. Jobs remain queryable until automatically removed approximately 30 days after reaching a terminal state.\n","properties":{"id":{"type":"string","description":"Unique identifier of the recalculation job."},"parentRoot":{"type":"string","description":"Identifier of the root product whose variant tree is being recalculated."},"requestedByIds":{"type":"array","description":"List of product IDs that were submitted in the recalculation request and resolved to this root.","items":{"type":"string"}},"status":{"$ref":"#/components/schemas/dynamicVariantRecalculationJobStatus"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the job was created."},"processingStartedAt":{"type":"string","format":"date-time","description":"Timestamp when a subscriber picked up the job and started processing. Null while the job is still PENDING."},"finishedAt":{"type":"string","format":"date-time","description":"Timestamp when the job reached a terminal state (FINISHED, FAILED, or FAILED_PERMANENT)."},"error":{"type":"string","description":"Error message if the job failed. Null for successful jobs."},"attempts":{"type":"integer","description":"Number of processing attempts made for this job. Incremented on each delivery from the pub/sub subscription."}}},"dynamicVariantRecalculationJobStatus":{"type":"string","description":"Current status of a dynamic variant recalculation job.","enum":["PENDING","PROCESSING","FINISHED","FAILED","FAILED_PERMANENT"]},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}}},"responses":{"products_post_response_BadRequest_400":{"description":"Resources cannot be created due to an error.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/coreErrorMessage"}]}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}}},"paths":{"/product/{tenant}/products/recalculate":{"post":{"summary":"Triggering dynamic variant recalculation","operationId":"POST-product-trigger-dynamic-variant-recalculation","tags":["Products"],"description":"Triggers asynchronous recalculation of the variant tree for one or more `DYNAMIC_VARIANT` products. Accepts up to 1000 product IDs at any hierarchy level — the system automatically resolves the root for each ID and creates one recalculation job per unique root product.\n\nThis endpoint is intended to be called **after** a batch of products has been fully ingested, not per individual product write. For single product writes, the variant tree is updated synchronously inline.\n\nIf a recalculation job for a given root is already `PENDING` or `PROCESSING`, the corresponding IDs are returned in `skippedProductIds` and the existing job is referenced in the `jobs` list.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/dynamicVariantRecalculationRequest"}}}},"responses":{"202":{"description":"Recalculation jobs accepted. One job is created per unique root product resolved from the submitted IDs.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/dynamicVariantRecalculationResponse"}}}},"400":{"$ref":"#/components/responses/products_post_response_BadRequest_400"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}}}}}}
```

## Listing recalculation jobs

> Retrieves a list of dynamic variant recalculation jobs for the tenant. Optionally filtered by job status.\
> \
> Jobs are retained for approximately 30 days after reaching a terminal state (\`FINISHED\`, \`FAILED\`, or \`FAILED\_PERMANENT\`) and are then automatically removed by a TTL index.

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"schemas":{"dynamicVariantRecalculationJobStatus":{"type":"string","description":"Current status of a dynamic variant recalculation job.","enum":["PENDING","PROCESSING","FINISHED","FAILED","FAILED_PERMANENT"]},"dynamicVariantRecalculationJobResponse":{"type":"object","description":"Represents a single dynamic variant recalculation job. One job is created per unique root product. Jobs remain queryable until automatically removed approximately 30 days after reaching a terminal state.\n","properties":{"id":{"type":"string","description":"Unique identifier of the recalculation job."},"parentRoot":{"type":"string","description":"Identifier of the root product whose variant tree is being recalculated."},"requestedByIds":{"type":"array","description":"List of product IDs that were submitted in the recalculation request and resolved to this root.","items":{"type":"string"}},"status":{"$ref":"#/components/schemas/dynamicVariantRecalculationJobStatus"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the job was created."},"processingStartedAt":{"type":"string","format":"date-time","description":"Timestamp when a subscriber picked up the job and started processing. Null while the job is still PENDING."},"finishedAt":{"type":"string","format":"date-time","description":"Timestamp when the job reached a terminal state (FINISHED, FAILED, or FAILED_PERMANENT)."},"error":{"type":"string","description":"Error message if the job failed. Null for successful jobs."},"attempts":{"type":"integer","description":"Number of processing attempts made for this job. Incremented on each delivery from the pub/sub subscription."}}},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}}},"responses":{"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}}},"paths":{"/product/{tenant}/products/recalculate/jobs":{"get":{"summary":"Listing recalculation jobs","operationId":"GET-product-list-recalculation-jobs","tags":["Products"],"description":"Retrieves a list of dynamic variant recalculation jobs for the tenant. Optionally filtered by job status.\n\nJobs are retained for approximately 30 days after reaching a terminal state (`FINISHED`, `FAILED`, or `FAILED_PERMANENT`) and are then automatically removed by a TTL index.","parameters":[{"name":"status","in":"query","required":false,"description":"Filter jobs by status. If omitted, all jobs are returned.","schema":{"$ref":"#/components/schemas/dynamicVariantRecalculationJobStatus"}}],"responses":{"200":{"description":"Jobs retrieved successfully.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/dynamicVariantRecalculationJobResponse"}}}}},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}}}}}}
```

## Retrieving a recalculation job

> Retrieves the current status and details of a specific dynamic variant recalculation job. Use this endpoint to poll for job completion after triggering recalculation.

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"schemas":{"dynamicVariantRecalculationJobResponse":{"type":"object","description":"Represents a single dynamic variant recalculation job. One job is created per unique root product. Jobs remain queryable until automatically removed approximately 30 days after reaching a terminal state.\n","properties":{"id":{"type":"string","description":"Unique identifier of the recalculation job."},"parentRoot":{"type":"string","description":"Identifier of the root product whose variant tree is being recalculated."},"requestedByIds":{"type":"array","description":"List of product IDs that were submitted in the recalculation request and resolved to this root.","items":{"type":"string"}},"status":{"$ref":"#/components/schemas/dynamicVariantRecalculationJobStatus"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the job was created."},"processingStartedAt":{"type":"string","format":"date-time","description":"Timestamp when a subscriber picked up the job and started processing. Null while the job is still PENDING."},"finishedAt":{"type":"string","format":"date-time","description":"Timestamp when the job reached a terminal state (FINISHED, FAILED, or FAILED_PERMANENT)."},"error":{"type":"string","description":"Error message if the job failed. Null for successful jobs."},"attempts":{"type":"integer","description":"Number of processing attempts made for this job. Incremented on each delivery from the pub/sub subscription."}}},"dynamicVariantRecalculationJobStatus":{"type":"string","description":"Current status of a dynamic variant recalculation job.","enum":["PENDING","PROCESSING","FINISHED","FAILED","FAILED_PERMANENT"]},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"productErrorMessage":{"allOf":[{"$ref":"#/components/schemas/coreErrorMessage"},{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the product."}}}]}},"responses":{"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"product_NotFound_404":{"description":"Resource has not been found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/productErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}}},"paths":{"/product/{tenant}/products/recalculate/jobs/{jobId}":{"get":{"summary":"Retrieving a recalculation job","operationId":"GET-product-get-recalculation-job","tags":["Products"],"description":"Retrieves the current status and details of a specific dynamic variant recalculation job. Use this endpoint to poll for job completion after triggering recalculation.","responses":{"200":{"description":"Job retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/dynamicVariantRecalculationJobResponse"}}}},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"404":{"$ref":"#/components/responses/product_NotFound_404"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}}}}}}
```

## Retrieving a product

> Retrieves a specified product details.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_read\_unpublished\` scope is only required if the product has not been published.\
> \* The \`product.product\_read\_by\_vendor\` scope is only required to fetch products belonging to the vendor.\
> \* The \`product.product\_manage\_by\_vendor\` scope is only required to manage products belonging to the vendor.\
> \
> \*\*\*

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_read_by_vendor","product.product_read_unpublished","product.product_manage_by_vendor"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"schemas":{"basicProductWithId":{"type":"object","description":"Products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"basicProductCreation":{"type":"object","description":"Creating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productType":{"type":"string","description":"Indicates the product type, which is immutable. Once the product type is set, it cannot be updated.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"id":{"type":"string","description":"Unique resource identifier."},"YRN":{"title":"YRN (attribute)","type":"string","description":"In YaaS, a global resource identifier is a Uniform Resource Name (URN) with a custom YaaS schema and is called a YaaS Resource Name, or YRN.\n\nIt is a unique identifier, which stores information about a resource, such as its type, ID or name of the tenant."},"productMedia":{"type":"array","uniqueItems":false,"description":"Media files attached to the product.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"yrn":{"$ref":"#/components/schemas/YRN"},"contentType":{"type":"string"},"createdAt":{"type":"string"},"uploadLink":{"type":"string"},"url":{"type":"string"},"cloudinaryUrl":{"type":"string"},"uncommittedMedia":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"customAttributes":{"type":"object"}}}},"productMetadataGet":{"type":"object","description":"Metadata for GET requests.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataWithVersion"},{"type":"object","properties":{"classificationMixins":{"type":"array","description":"List of mixin schemas used for classification.","items":{"type":"object","description":"Mixin schema.","properties":{"name":{"type":"string","description":"Name of the mixin","pattern":"^[a-zA-Z0-9_]\\S*$"},"mixinPath":{"type":"string","description":"The mixins path that should be used when defining attributes on a product. It's built based on the following pattern - `class_<sourceCategory.code>_<name>`."},"schemaUrl":{"type":"string","description":"URL of the mixin schema defined on the category level.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"usedSchemaUrl":{"type":"string","description":"If given mixin has been already used in the product, then this field contains the URL of the used mixin schema.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"obsoleteSchemaUrlUsed":{"type":"boolean","description":"Indicates whether the used mixin schema is obsolete - `usedSchemaUrl` differs from `schemaUrl`."},"required":{"type":"boolean","description":"Indicates whether the mixin is required."},"sourceCategoryId":{"type":"string","description":"Unique identifier of the category from which the mixin comes from. Can be this category ID or one of the parent categories IDs."}}}},"createdAt":{"type":"string","description":"Creation date in the ISO 8601 standard."},"modifiedAt":{"type":"string","description":"Modification date in the ISO 8601 standard."}}}]},"productMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document"}}}]},"bundleProductWithId":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/bundleProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"bundleProductCreation":{"type":"object","description":"Creating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"parentVariantProductWithId":{"type":"object","description":"Products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"parentVariantProductCreation":{"type":"object","description":"Creating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductWithId":{"type":"object","description":"Products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/variantProductMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"variantProductCreation":{"type":"object","description":"Creating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"metadata":{"$ref":"#/components/schemas/variantProductMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"variantProductMetadataGet":{"type":"object","description":"Variant metadata response.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataGet"},{"$ref":"#/components/schemas/variantProductMetadataWithVersion"}]},"variantProductMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/variantProductMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document."}}}]},"dynamicVariantProductWithId":{"type":"object","description":"Response schema for products of the DYNAMIC_VARIANT type.\n\n- **`sellable`** — not inherited from parents; must be set explicitly on each product. Root and intermediate variants are typically `false`; leaf variants are typically `true`.\n- **Root products** include a `variants` map containing all descendants with accumulated attributes.\n- **Child products** include `ownVariantAttributes` (attributes defined on this product) and `inheritedVariantAttributes` (read-only, merged from ancestors).\n- `parentVariantPath` is an ordered array of ancestor IDs from direct parent (index 0) to root (last index). Empty for root products.\n- `metadata.dynamicVariantInfo` is present only when a hierarchy integrity issue is detected.\n","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"name":{"$ref":"#/components/schemas/localizedValue"},"description":{"$ref":"#/components/schemas/localizedValue"},"productType":{"$ref":"#/components/schemas/productType"},"published":{"$ref":"#/components/schemas/published"},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly (i.e. it is a leaf in the hierarchy that a customer can add to a cart). This value is **not inherited** from parent variants — it must be set explicitly on each product. Root products and intermediate-level variants are typically `false`; leaf variants are typically `true`.\n"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy. Absent for root-level products."},"parentVariantPath":{"type":"array","description":"Ordered array of ancestor product identifiers, from the direct parent (index 0) to the root (last index). Empty for root-level products.\n","items":{"type":"string"}},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind within the hierarchy (for example, `\"H1_L1\"`)."},"ownVariantAttributes":{"$ref":"#/components/schemas/ownVariantAttributes"},"inheritedVariantAttributes":{"$ref":"#/components/schemas/inheritedVariantAttributes"},"variants":{"$ref":"#/components/schemas/variantsMap"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"vendor":{"$ref":"#/components/schemas/vendor"},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"relatedItems":{"type":"array","description":"List of items in a relationship with this product.","items":{"$ref":"#/components/schemas/relatedItem"}},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging."},"mixins":{"$ref":"#/components/schemas/productMixins"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/dynamicVariantProductMetadataGet"}},"required":["id","code","name","productType"]},"ownVariantAttributes":{"type":"object","description":"Map of variant attributes defined directly on this product. Keys are attribute identifiers (for example, `storageCapacity`). These are the attributes the caller can set by create/update requests. On responses they represent what is stored on this specific product.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"dynamicVariantAttribute":{"type":"object","description":"A single dynamic variant attribute. Combines a localized display name for the attribute itself with a typed, optionally localized value.\n","required":["value"],"properties":{"name":{"$ref":"#/components/schemas/localizedValue"},"value":{"$ref":"#/components/schemas/dynamicVariantAttributeValue"}}},"dynamicVariantAttributeValue":{"type":"object","description":"The value part of a dynamic variant attribute. Holds the canonical qualifier used for matching, an optional localized display label, and an optional unit code for measurement attributes.\n","required":["type","qualifier"],"properties":{"type":{"type":"string","description":"Data type of the qualifier value.\n","enum":["STRING","NUMBER","DECIMAL","BOOLEAN"]},"qualifier":{"description":"The canonical value used for variant matching. The JSON type must match `type`: a string for `STRING`, a number for `NUMBER` or `DECIMAL`, or a boolean for `BOOLEAN`.\n","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"name":{"$ref":"#/components/schemas/localizedValue"},"unit":{"type":"string","description":"Optional unit code for measurement attributes (for example, `\"MMT\"` for millimetres, `\"PCE\"` for pieces). Unit translations are resolved by the frontend from a separate dictionary.\n"}}},"inheritedVariantAttributes":{"type":"object","description":"Read-only map of variant attributes inherited from ancestor products in the hierarchy. These cannot be modified on this product — to change an inherited attribute, update the ancestor that owns it.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"variantsMap":{"type":"object","description":"Denormalized flat map of all descendant variants stored on the root product. Keys are variant product identifiers. In API responses each entry's `variantAttributes` contains accumulated attributes.\n","additionalProperties":{"$ref":"#/components/schemas/variantMapEntry"}},"variantMapEntry":{"type":"object","description":"A single entry in the root product's `variants` map. In API responses the `variantAttributes` field contains **accumulated** attributes — the entry's own delta attributes merged with all ancestor attributes up the chain, so storefront clients receive a ready-to-use combination without additional API calls. The `published` flag is included only when the caller has the `product.product_read_unpublished` scope.\n","properties":{"version":{"type":"integer","description":"Version of the source variant product at the time of the last recalculation."},"name":{"$ref":"#/components/schemas/localizedValue"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy."},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly."},"published":{"type":"boolean","description":"Publication state of this variant. Only included in responses when the caller has the `product.product_read_unpublished` scope; entries with `published: false` are otherwise omitted from the map.\n"},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind (for example, `\"H1_L1\"`)."},"variantAttributes":{"type":"object","description":"Accumulated variant attributes for this entry. For leaf variants this includes all ancestor attributes merged with the entry's own delta. Keys are attribute identifiers.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}}}},"dynamicVariantProductMetadataGet":{"type":"object","description":"Metadata for GET responses on DYNAMIC_VARIANT products. Extends the standard product metadata with hierarchy integrity information.","allOf":[{"$ref":"#/components/schemas/productMetadataGet"},{"type":"object","properties":{"dynamicVariantInfo":{"$ref":"#/components/schemas/dynamicVariantInfo"}}}]},"dynamicVariantInfo":{"type":"object","description":"Hierarchy integrity information populated when the variant tree has structural problems. Present only when an issue is detected.\n","properties":{"missingAncestorId":{"type":"string","description":"Identifier of an ancestor product that could not be found, indicating a broken hierarchy chain."},"cycleDetected":{"type":"boolean","description":"Indicates that a circular reference was detected in the `parentVariantId` chain."}}},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"productErrorMessage":{"allOf":[{"$ref":"#/components/schemas/coreErrorMessage"},{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the product."}}}]}},"responses":{"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"product_NotFound_404":{"description":"Resource has not been found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/productErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"parameters":{"path_tenant":{"name":"tenant","in":"path","required":true,"description":"Your Emporix tenant name.\n\n**Note**: The tenant should always be written in lowercase.\n","schema":{"pattern":"^[a-z][a-z0-9]+$","minLength":3,"maxLength":16,"type":"string"}},"path_productId":{"in":"path","name":"productId","schema":{"type":"string"},"required":true,"description":"Product unique identifier generated when the product is created."},"header_accept_language":{"name":"Accept-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Accept-Language request HTTP header defines which languages the client is able to understand, and which locale variant is preferred. If empty, the default system language is assumed. It can be a priority list working as a fallback mechanism."},"query_product_fields":{"name":"fields","in":"query","required":false,"description":"Fields to be returned in the response.\n\nWhen this parameter is passed, only the `id`, `yrn` and `{fieldName}` are retrieved for each product.\n\nYou can specify multiple fields by separating them with commas.\n","schema":{"type":"string"}},"query_expand_product":{"name":"expand","in":"query","required":false,"schema":{"type":"string"},"description":"Fields that should be expanded with additional information in the response body. Expressed as strings separated by commas.\n\nPossible values:\n  * `template`\n  * `parentVariant`\n"},"query_raw_value_product":{"in":"query","name":"rawValue","schema":{"type":"boolean"},"required":false,"description":"Flag indicating whether product variant(s) should include their parent variants' attribute values.\n* If set to `true`, the result contains values from both the variant and its parent variant.\n* If set to `false`, the result contains only variant values.\n"}}},"paths":{"/product/{tenant}/products/{productId}":{"get":{"responses":{"200":{"description":"Product successfully retrieved.\n","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/basicProductWithId"},{"$ref":"#/components/schemas/bundleProductWithId"},{"$ref":"#/components/schemas/parentVariantProductWithId"},{"$ref":"#/components/schemas/variantProductWithId"},{"$ref":"#/components/schemas/dynamicVariantProductWithId"}]}}}},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"404":{"$ref":"#/components/responses/product_NotFound_404"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Retrieves a specified product details.\n***\n\n**Additional scope information**\n\n* The `product.product_read_unpublished` scope is only required if the product has not been published.\n* The `product.product_read_by_vendor` scope is only required to fetch products belonging to the vendor.\n* The `product.product_manage_by_vendor` scope is only required to manage products belonging to the vendor.\n\n***","operationId":"GET-product-retrieve-product","parameters":[{"$ref":"#/components/parameters/path_tenant"},{"$ref":"#/components/parameters/path_productId"},{"$ref":"#/components/parameters/header_accept_language"},{"$ref":"#/components/parameters/query_product_fields"},{"$ref":"#/components/parameters/query_expand_product"},{"$ref":"#/components/parameters/query_raw_value_product"}],"summary":"Retrieving a product","tags":["Products"]}}}}
```

## Upserting a product

> Updates or creates a specified product by replacing all of its existing data with data from the request body.\
> If the \`metadata.version\` is provided then optimistic locking is enabled and version must match the version in the database.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_manage\_by\_vendor\` scope is only required for vendor employees to manage products belonging to the vendor.\
> \* The \`product.product\_publish\` scope is only required if you want to publish the product when updating it.\
> \* The \`product.product\_unpublish\` scope is only required if you want to unpublish the product when updating it.\
> \
> \*\*\*

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage","product.product_manage_by_vendor","product.product_publish","product.product_unpublish"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"schemas":{"resourceLocation":{"type":"object","properties":{"id":{"type":"string"},"yrn":{"$ref":"#/components/schemas/YRN"}}},"YRN":{"title":"YRN (attribute)","type":"string","description":"In YaaS, a global resource identifier is a Uniform Resource Name (URN) with a custom YaaS schema and is called a YaaS Resource Name, or YRN.\n\nIt is a unique identifier, which stores information about a resource, such as its type, ID or name of the tenant."},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"productErrorMessage":{"allOf":[{"$ref":"#/components/schemas/coreErrorMessage"},{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the product."}}}]},"coreErrorMessageWithDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/coreErrorMessage"},{"type":"object","properties":{"details":{"type":"array","description":"Error message details.","items":{"type":"object","properties":{"field":{"type":"string"},"type":{"type":"string"},"message":{"type":"string"},"moreInfo":{"type":"string"}}}}}}]},"basicProductUpdate":{"type":"object","description":"Updating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document"}}}]},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"bundleProductUpdate":{"type":"object","description":"Updating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"parentVariantProductUpdate":{"type":"object","description":"Updating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductUpdate":{"type":"object","description":"Updating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/variantProductMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product. This property is taken into account only for insert operations."}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/variantProductMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document."}}}]},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"dynamicVariantProductUpdate":{"type":"object","description":"Updating products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/dynamicVariantProduct"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}}}]},"dynamicVariantProduct":{"type":"object","description":"Base schema for products of the DYNAMIC_VARIANT type.","allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the immediate parent product in the variant hierarchy. Omit or leave empty for root-level dynamic variant products.\n"},"dynamicVariantType":{"type":"string","description":"Optional label identifying the variant level or kind within the hierarchy (for example, `\"H1_L1\"`). Used for display and filtering purposes.\n"},"sellable":{"type":"boolean","description":"Indicates whether this variant can be sold directly, if it's a leaf in the hierarchy that a customer can add to a cart. This value is **not inherited** from parent variants — it must be set explicitly on each product. Root products and intermediate-level variants are typically `false`. Leaf variants are typically `true`.\n"},"ownVariantAttributes":{"$ref":"#/components/schemas/ownVariantAttributes"}},"required":["name","code"]}]},"ownVariantAttributes":{"type":"object","description":"Map of variant attributes defined directly on this product. Keys are attribute identifiers (for example, `storageCapacity`). These are the attributes the caller can set by create/update requests. On responses they represent what is stored on this specific product.\n","additionalProperties":{"$ref":"#/components/schemas/dynamicVariantAttribute"}},"dynamicVariantAttribute":{"type":"object","description":"A single dynamic variant attribute. Combines a localized display name for the attribute itself with a typed, optionally localized value.\n","required":["value"],"properties":{"name":{"$ref":"#/components/schemas/localizedValue"},"value":{"$ref":"#/components/schemas/dynamicVariantAttributeValue"}}},"dynamicVariantAttributeValue":{"type":"object","description":"The value part of a dynamic variant attribute. Holds the canonical qualifier used for matching, an optional localized display label, and an optional unit code for measurement attributes.\n","required":["type","qualifier"],"properties":{"type":{"type":"string","description":"Data type of the qualifier value.\n","enum":["STRING","NUMBER","DECIMAL","BOOLEAN"]},"qualifier":{"description":"The canonical value used for variant matching. The JSON type must match `type`: a string for `STRING`, a number for `NUMBER` or `DECIMAL`, or a boolean for `BOOLEAN`.\n","oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"name":{"$ref":"#/components/schemas/localizedValue"},"unit":{"type":"string","description":"Optional unit code for measurement attributes (for example, `\"MMT\"` for millimetres, `\"PCE\"` for pieces). Unit translations are resolved by the frontend from a separate dictionary.\n"}}}},"responses":{"common_response_BadRequest_400":{"description":"Bad request due to validation, incorrect parameters, etc.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"product_NotFound_404":{"description":"Resource has not been found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/productErrorMessage"}}}},"common_response_Conflict_409":{"description":"There are three possible reasons:\n1. Product with given code already exists, please choose unique code for your product\n2. Optimistic locking failed. If user sends metadata/version attribute which is outdated (someone else updated product in the time user was performing his changes). User should retrieve the latest product data and retry the request.\n3. Optimistic locking failed. User did not provide metadata/version attribute in update request, but someone else updated product while it was internally handled by product service. Resending the same request can result in successful update, but the update can override recently persisted changes.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessageWithDetails"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"requestBodies":{"productUpdateBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/basicProductUpdate"},{"$ref":"#/components/schemas/bundleProductUpdate"},{"$ref":"#/components/schemas/parentVariantProductUpdate"},{"$ref":"#/components/schemas/variantProductUpdate"},{"$ref":"#/components/schemas/dynamicVariantProductUpdate"}]}}}}},"parameters":{"path_tenant":{"name":"tenant","in":"path","required":true,"description":"Your Emporix tenant name.\n\n**Note**: The tenant should always be written in lowercase.\n","schema":{"pattern":"^[a-z][a-z0-9]+$","minLength":3,"maxLength":16,"type":"string"}},"path_productId":{"in":"path","name":"productId","schema":{"type":"string"},"required":true,"description":"Product unique identifier generated when the product is created."},"header_content_language":{"name":"Content-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Content-Language request HTTP header defines a language or multiple languages of the request body.\n\n* If the `Content-Language` header is set to `*`, the localized fields should be provided as maps of translations, where the keys are language codes and values are the fields in their respective languages.\n* If the `Content-Language` header is set to a specific language, the localized fields should be provided as strings.\n* If the `Content-Language` header is empty, the endpoint interprets the localized fields as being provided in the default language or the languages defined in the Configuration Service.\n\n**Note**: You can provide the localized fields only in languages defined in the Configuration Service. In case the fields are provided in languages that are not defined in the Configuration Service, the request is rejected.\n"},"query_partial_product":{"name":"partial","in":"query","required":false,"description":"| Option  | Description |\n|---|---|\n| `true` | A partial product update is performed. |\n| `false` | A full product replacement is performed.|\n","schema":{"type":"boolean","default":false}},"query_skip_variants_generation":{"name":"skipVariantGeneration","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"The parameter is valid only for `PARENT_VARIANT` type. If true then variants are not automatically generated for the parent variant configuration."},"query_do_index":{"name":"doIndex","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"Allows to control whether the change of the state should cause reindexing or not."},"query_skip_related_items_validation":{"name":"skipRelatedItemsValidation","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"If set to `true`, the validation that checks whether related products exist is skipped. This is useful during data loading, where related products may not yet exist and will be created later. This parameter is only respected when the `allowToSkipRelatedProductsValidation` system setting is set to `true`. Otherwise, it is disregarded."}}},"paths":{"/product/{tenant}/products/{productId}":{"put":{"responses":{"201":{"description":"The resource has been successfully created.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/resourceLocation"}}}},"204":{"description":"The resource has been successfully updated.\n"},"400":{"$ref":"#/components/responses/common_response_BadRequest_400"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"404":{"$ref":"#/components/responses/product_NotFound_404"},"409":{"$ref":"#/components/responses/common_response_Conflict_409"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Updates or creates a specified product by replacing all of its existing data with data from the request body.\nIf the `metadata.version` is provided then optimistic locking is enabled and version must match the version in the database.\n***\n\n**Additional scope information**\n\n* The `product.product_manage_by_vendor` scope is only required for vendor employees to manage products belonging to the vendor.\n* The `product.product_publish` scope is only required if you want to publish the product when updating it.\n* The `product.product_unpublish` scope is only required if you want to unpublish the product when updating it.\n\n***","operationId":"PUT-product-update-product","requestBody":{"$ref":"#/components/requestBodies/productUpdateBody"},"parameters":[{"$ref":"#/components/parameters/path_tenant"},{"$ref":"#/components/parameters/path_productId"},{"$ref":"#/components/parameters/header_content_language"},{"$ref":"#/components/parameters/query_partial_product"},{"$ref":"#/components/parameters/query_skip_variants_generation"},{"$ref":"#/components/parameters/query_do_index"},{"$ref":"#/components/parameters/query_skip_related_items_validation"}],"summary":"Upserting a product","tags":["Products"]}}}}
```

## Deleting a product

> Deletes a specified product.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_manage\_by\_vendor\` scope is only required for vendor employees to delete products belonging to the vendor.\
> \
> \*\*\*

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage","product.product_manage_by_vendor"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"responses":{"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"schemas":{"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}}},"parameters":{"path_tenant":{"name":"tenant","in":"path","required":true,"description":"Your Emporix tenant name.\n\n**Note**: The tenant should always be written in lowercase.\n","schema":{"pattern":"^[a-z][a-z0-9]+$","minLength":3,"maxLength":16,"type":"string"}},"path_productId":{"in":"path","name":"productId","schema":{"type":"string"},"required":true,"description":"Product unique identifier generated when the product is created."},"query_force_product":{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Removing a parent variant product also removes all of its child variants. This applies to both `PARENT_VARIANT` roots with `VARIANT` children and `DYNAMIC_VARIANT` parent products with all descendant dynamic variants in the tree. This operation has to be confirmed by setting `force=true`.\n"},"query_do_index":{"name":"doIndex","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"Allows to control whether the change of the state should cause reindexing or not."}}},"paths":{"/product/{tenant}/products/{productId}":{"delete":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":false},"responses":{"204":{"description":"The resource has been successfully deleted.\n"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Deletes a specified product.\n***\n\n**Additional scope information**\n\n* The `product.product_manage_by_vendor` scope is only required for vendor employees to delete products belonging to the vendor.\n\n***","operationId":"DELETE-product-remove-product","parameters":[{"$ref":"#/components/parameters/path_tenant"},{"$ref":"#/components/parameters/path_productId"},{"$ref":"#/components/parameters/query_force_product"},{"$ref":"#/components/parameters/query_do_index"}],"summary":"Deleting a product","tags":["Products"]}}}}
```

## Partially updating a product

> Partially updates a specified product.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_manage\_by\_vendor\` scope is only required for vendor employees to manage products belonging to the vendor.\
> \* The \`product.product\_publish\` scope is only required if you want to publish the product when updating it.\
> \* The \`product.product\_unpublish\` scope is only required if you want to unpublish the product when updating it.\
> \
> \*\*\*

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_manage","product.product_manage_by_vendor","product.product_publish","product.product_unpublish"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"responses":{"common_response_BadRequest_400":{"description":"Bad request due to validation, incorrect parameters, etc.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_Conflict_409":{"description":"There are three possible reasons:\n1. Product with given code already exists, please choose unique code for your product\n2. Optimistic locking failed. If user sends metadata/version attribute which is outdated (someone else updated product in the time user was performing his changes). User should retrieve the latest product data and retry the request.\n3. Optimistic locking failed. User did not provide metadata/version attribute in update request, but someone else updated product while it was internally handled by product service. Resending the same request can result in successful update, but the update can override recently persisted changes.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessageWithDetails"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}},"schemas":{"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"coreErrorMessageWithDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/coreErrorMessage"},{"type":"object","properties":{"details":{"type":"array","description":"Error message details.","items":{"type":"object","properties":{"field":{"type":"string"},"type":{"type":"string"},"message":{"type":"string"},"moreInfo":{"type":"string"}}}}}}]},"productPartialUpdate":{"type":"object","description":"Partially updating a product.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"},"metadata":{"$ref":"#/components/schemas/productMetadataWithVersion"}}}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"productMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document"}}}]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}}},"requestBodies":{"productPartialUpdateBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/productPartialUpdate"}}}}},"parameters":{"path_tenant":{"name":"tenant","in":"path","required":true,"description":"Your Emporix tenant name.\n\n**Note**: The tenant should always be written in lowercase.\n","schema":{"pattern":"^[a-z][a-z0-9]+$","minLength":3,"maxLength":16,"type":"string"}},"path_productId":{"in":"path","name":"productId","schema":{"type":"string"},"required":true,"description":"Product unique identifier generated when the product is created."},"header_content_language":{"name":"Content-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Content-Language request HTTP header defines a language or multiple languages of the request body.\n\n* If the `Content-Language` header is set to `*`, the localized fields should be provided as maps of translations, where the keys are language codes and values are the fields in their respective languages.\n* If the `Content-Language` header is set to a specific language, the localized fields should be provided as strings.\n* If the `Content-Language` header is empty, the endpoint interprets the localized fields as being provided in the default language or the languages defined in the Configuration Service.\n\n**Note**: You can provide the localized fields only in languages defined in the Configuration Service. In case the fields are provided in languages that are not defined in the Configuration Service, the request is rejected.\n"},"query_skip_variants_generation":{"name":"skipVariantGeneration","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"The parameter is valid only for `PARENT_VARIANT` type. If true then variants are not automatically generated for the parent variant configuration."},"query_do_index":{"name":"doIndex","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"Allows to control whether the change of the state should cause reindexing or not."},"query_skip_related_items_validation":{"name":"skipRelatedItemsValidation","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"If set to `true`, the validation that checks whether related products exist is skipped. This is useful during data loading, where related products may not yet exist and will be created later. This parameter is only respected when the `allowToSkipRelatedProductsValidation` system setting is set to `true`. Otherwise, it is disregarded."}}},"paths":{"/product/{tenant}/products/{productId}":{"patch":{"responses":{"204":{"description":"The resource has been successfully updated.\n"},"400":{"$ref":"#/components/responses/common_response_BadRequest_400"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"404":{"description":"The requested resource does not exist.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"409":{"$ref":"#/components/responses/common_response_Conflict_409"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Partially updates a specified product.\n***\n\n**Additional scope information**\n\n* The `product.product_manage_by_vendor` scope is only required for vendor employees to manage products belonging to the vendor.\n* The `product.product_publish` scope is only required if you want to publish the product when updating it.\n* The `product.product_unpublish` scope is only required if you want to unpublish the product when updating it.\n\n***","operationId":"PATCH-product-update-product","requestBody":{"$ref":"#/components/requestBodies/productPartialUpdateBody"},"parameters":[{"$ref":"#/components/parameters/path_tenant"},{"$ref":"#/components/parameters/path_productId"},{"$ref":"#/components/parameters/header_content_language"},{"$ref":"#/components/parameters/query_skip_variants_generation"},{"$ref":"#/components/parameters/query_do_index"},{"$ref":"#/components/parameters/query_skip_related_items_validation"}],"summary":"Partially updating a product","tags":["Products"]}}}}
```

## Searching for products by YRNs

> Searches for specified products by their YRNs.\
> \
> This endpoint is \`deprecated\`. Please use the \[/product/{tenant}/products/search]\(/openapi/product/#operation/POST-product-search-products) instead.\
> \*\*\*\
> \
> \*\*Additional scope information\*\*\
> \
> \* The \`product.product\_read\_unpublished\` scope is only required if the response should contain unpublished products.\
> \
> \*\*\*<br>

```json
{"openapi":"3.0.0","info":{"title":"Product Service","version":"0.0.1"},"tags":[{"name":"Products","description":"Manage products. Supported product types include:\n- `BASIC` — standalone products\n- `BUNDLE` — groups of products sold together\n- `PARENT_VARIANT` — products with automatically generated variants defined by a template\n- `VARIANT` — individual variants of a `PARENT_VARIANT` product\n- `DYNAMIC_VARIANT` — products forming a flexible variant hierarchy of up to 4 levels. Each variant stores its own `ownVariantAttributes` (the attributes that distinguish it from its parent). A root `DYNAMIC_VARIANT` product stores a denormalized flat map of all descendants in its `variants` field with accumulated attributes. Use the `/recalculate` endpoint to rebuild variant trees after bulk imports.\n"}],"servers":[{"url":"https://api.emporix.io"}],"security":[{"OAuth2":["product.product_read_unpublished"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://api.emporix.io/oauth/token","scopes":{"product.product_manage":"Needed to manage products.","product.product_publish":"Needed to publish products.","product.product_unpublish":"Needed to unpublish products.","product.product_read_unpublished":"Needed to retrieve unpublished products.","product.product_read_by_vendor":"The scope allows vendor to read products with assigned vendor.","product.product_manage_by_vendor":"The scope allows vendor to manage products with assigned vendor.","product.price_manage":"Needed to manage product prices.","product.product_template_read":"Needed for reading product templates.","product.product_template_manage":"Needed for updating and removing a product template."}}}}},"parameters":{"header_accept_language":{"name":"Accept-Language","in":"header","required":false,"schema":{"type":"string"},"description":"The Accept-Language request HTTP header defines which languages the client is able to understand, and which locale variant is preferred. If empty, the default system language is assumed. It can be a priority list working as a fallback mechanism."}},"schemas":{"basicProductsArray":{"type":"array","description":"List of products of the BASIC type.","items":{"$ref":"#/components/schemas/basicProductWithId"}},"basicProductWithId":{"type":"object","description":"Products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"basicProductCreation":{"type":"object","description":"Creating products of the BASIC type.","allOf":[{"$ref":"#/components/schemas/basicProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"basicProduct":{"type":"object","description":"Products of the BASIC type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"}},"required":["name","code"]}]},"productCore":{"type":"object","properties":{"name":{"$ref":"#/components/schemas/localizedValue","description":"Product name."},"code":{"type":"string","minLength":1,"description":"Unique product identifier, defined by the user."},"description":{"$ref":"#/components/schemas/localizedValue","description":"Product description."},"vendor":{"$ref":"#/components/schemas/vendor"},"taxClasses":{"$ref":"#/components/schemas/taxClasses"},"published":{"$ref":"#/components/schemas/published"},"weightDependent":{"type":"boolean","description":"Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized."},"mixins":{"$ref":"#/components/schemas/productMixins"},"relatedItems":{"description":"List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.\nIn order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:\n`products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`\n","type":"array","items":{"$ref":"#/components/schemas/relatedItem"}},"brandId":{"type":"string","description":"ID of brand."},"labelIds":{"type":"array","items":{"type":"string"},"description":"Collection of label IDs."}}},"localizedValue":{"description":"Localized value which can have different structure which depends on provided `Content-Language` header.","oneOf":[{"type":"string"},{"type":"object","additionalProperties":{"type":"string"}}]},"vendor":{"type":"object","properties":{"id":{"type":"string","description":"An identifier of a vendor to whom the product belongs."},"name":{"type":"string","description":"Vendor name."}},"required":["id"]},"taxClasses":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).\nInformation about the association is required for price matching mechanism (see the price-service#MatchPrice)."},"published":{"type":"boolean","description":"Flag indicating whether the product has been published or not.","default":false},"productMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"relatedItem":{"title":"relatedItem","type":"object","properties":{"refId":{"type":"string","description":"Identifier of a product which is in the relationship with the main product. The product identifier has to exist. "},"type":{"type":"string","description":"A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key."}},"required":["refId","type"]},"productMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"properties":{"mixins":{"type":"object","description":"Links to the mixin schemas.","additionalProperties":true}}},"template":{"type":"object","description":"Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template. \n\n**Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.\n","properties":{"id":{"type":"string","description":"Identifier of the product template."},"version":{"type":"string","description":"Product template version."}},"required":["id","version"]},"productType":{"type":"string","description":"Indicates the product type, which is immutable. Once the product type is set, it cannot be updated.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"id":{"type":"string","description":"Unique resource identifier."},"YRN":{"title":"YRN (attribute)","type":"string","description":"In YaaS, a global resource identifier is a Uniform Resource Name (URN) with a custom YaaS schema and is called a YaaS Resource Name, or YRN.\n\nIt is a unique identifier, which stores information about a resource, such as its type, ID or name of the tenant."},"productMedia":{"type":"array","uniqueItems":false,"description":"Media files attached to the product.","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"yrn":{"$ref":"#/components/schemas/YRN"},"contentType":{"type":"string"},"createdAt":{"type":"string"},"uploadLink":{"type":"string"},"url":{"type":"string"},"cloudinaryUrl":{"type":"string"},"uncommittedMedia":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"customAttributes":{"type":"object"}}}},"productMetadataGet":{"type":"object","description":"Metadata for GET requests.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataWithVersion"},{"type":"object","properties":{"classificationMixins":{"type":"array","description":"List of mixin schemas used for classification.","items":{"type":"object","description":"Mixin schema.","properties":{"name":{"type":"string","description":"Name of the mixin","pattern":"^[a-zA-Z0-9_]\\S*$"},"mixinPath":{"type":"string","description":"The mixins path that should be used when defining attributes on a product. It's built based on the following pattern - `class_<sourceCategory.code>_<name>`."},"schemaUrl":{"type":"string","description":"URL of the mixin schema defined on the category level.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"usedSchemaUrl":{"type":"string","description":"If given mixin has been already used in the product, then this field contains the URL of the used mixin schema.","pattern":"^https?://[^\\s/$.?#].\\S*$"},"obsoleteSchemaUrlUsed":{"type":"boolean","description":"Indicates whether the used mixin schema is obsolete - `usedSchemaUrl` differs from `schemaUrl`."},"required":{"type":"boolean","description":"Indicates whether the mixin is required."},"sourceCategoryId":{"type":"string","description":"Unique identifier of the category from which the mixin comes from. Can be this category ID or one of the parent categories IDs."}}}},"createdAt":{"type":"string","description":"Creation date in the ISO 8601 standard."},"modifiedAt":{"type":"string","description":"Modification date in the ISO 8601 standard."}}}]},"productMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document"}}}]},"bundleProductsArray":{"type":"array","description":"List of products of the BUNDLE type.","items":{"$ref":"#/components/schemas/bundleProductWithId"}},"bundleProductWithId":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/bundleProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"bundleProductCreation":{"type":"object","description":"Creating products of the BUNDLE type.","allOf":[{"$ref":"#/components/schemas/bundleProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"bundleProduct":{"type":"object","description":"Products of the BUNDLE type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"bundledProducts":{"$ref":"#/components/schemas/bundledProducts"},"productType":{"$ref":"#/components/schemas/productTypeUpdate"}},"required":["name","code","bundledProducts","productType"]}]},"bundledProducts":{"type":"array","description":"List of bundled products","items":{"type":"object","properties":{"productId":{"type":"string","description":"Identifier of the bundled product."},"amount":{"type":"integer","description":"Amount of bundled products. Must be a positive number."}},"required":["productId","amount"]}},"productTypeUpdate":{"type":"string","description":"Indicates the product type, which is immutable. This property is taken into account only for insert operations.\n","default":"BASIC","enum":["BASIC","BUNDLE","PARENT_VARIANT","VARIANT","DYNAMIC_VARIANT"]},"parentVariantProductsArray":{"type":"array","description":"List of products of the PARENT_VARIANT type.","items":{"$ref":"#/components/schemas/parentVariantProductWithId"}},"parentVariantProductWithId":{"type":"object","description":"Products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/productMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"parentVariantProductCreation":{"type":"object","description":"Creating products of the PARENT_VARIANT type.","allOf":[{"$ref":"#/components/schemas/parentVariantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"parentVariantProduct":{"type":"object","description":"Products of the PARENT_VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/productMetadataCore"},"template":{"$ref":"#/components/schemas/template"},"variantAttributes":{"$ref":"#/components/schemas/variantAttributes"}},"required":["name","code","template","productType","variantAttributes"]}]},"variantAttributes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/values"},"description":"This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field."},"values":{"type":"array","items":{"$ref":"#/components/schemas/value"}},"value":{"type":"object","properties":{"key":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}}},"variantProductsArray":{"type":"array","description":"List of products of the VARIANT type.","items":{"$ref":"#/components/schemas/variantProductWithId"}},"variantProductWithId":{"type":"object","description":"Products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProductCreation"},{"type":"object","properties":{"id":{"$ref":"#/components/schemas/id"},"yrn":{"$ref":"#/components/schemas/YRN"},"media":{"$ref":"#/components/schemas/productMedia"},"metadata":{"$ref":"#/components/schemas/variantProductMetadataGet"},"customerSegmentIds":{"type":"array","description":"Customer segment IDs assigned to the product.","items":{"type":"string"}},"categoryIds":{"type":"array","description":"Category IDs assigned to the product.","items":{"type":"string"}}}}]},"variantProductCreation":{"type":"object","description":"Creating products of the VARIANT type.","allOf":[{"$ref":"#/components/schemas/variantProduct"},{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Custom product identifier. If not provided, it is automatically generated."},"metadata":{"$ref":"#/components/schemas/variantProductMetadataCore"},"parentVariantId":{"type":"string","description":"Identifier of the PARENT_VARIANT product."},"productType":{"$ref":"#/components/schemas/productType"}}}]},"variantProduct":{"type":"object","description":"Products of the VARIANT type.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productCore"},{"type":"object","properties":{"mixins":{"$ref":"#/components/schemas/productVariantMixins"}},"required":["name","code"]}]},"productVariantMixins":{"type":"object","description":"Mixins request.","additionalProperties":true},"variantProductMetadataCore":{"type":"object","description":"Metadata request.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataCore"},{"type":"object","properties":{"overridden":{"type":"array","description":"By default, all variant products inherit their attributes from the parent variant. You need to include the name of the attribute in the `metadata.overridden` field to be able to replace the attribute values. For the `mixins` and `metadata` fields, you can provide a nested path so that only a single mixin attribute is overridden, for example `mixins.productCustomAttributes.pricingMeasurePrice`. The same rule is valid for providing the mixins schema, as you can override just this particular field with the provided schema, for example metadata.mixins.yourCustomAttributes.\n\n**Note:**You cannot override the following attributes: `id`, `code`, `template`, `variantAttributes`.","items":{"type":"string","description":"Name of overridden product field, for example `published`."}}}}]},"variantProductMetadataGet":{"type":"object","description":"Variant metadata response.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/productMetadataGet"},{"$ref":"#/components/schemas/variantProductMetadataWithVersion"}]},"variantProductMetadataWithVersion":{"type":"object","description":"Metadata with the version information.","additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/variantProductMetadataCore"},{"type":"object","properties":{"version":{"type":"number","description":"Version of the document."}}}]},"coreErrorMessage":{"type":"object","properties":{"code":{"type":"integer","description":"HTTP Status Code."},"status":{"type":"string","description":"HTTP Status."},"message":{"type":"string","description":"Error message."}}},"searchQuery":{"type":"object","additionalProperties":false,"properties":{"yrns":{"description":"List of YRNs. Each YRN identifies a separate product.","type":"array","items":{"$ref":"#/components/schemas/YRN"}},"params":{"description":"Optional query parameters.","type":"object","properties":{"product":{"description":"Optional query parameters for products.","type":"object","properties":{"fields":{"description":"Optional projection for product.","type":"array","items":{"type":"string"}}}}}}},"required":["yrns"]}},"responses":{"common_response_BadRequest_400":{"description":"Bad request due to validation, incorrect parameters, etc.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_Unauthorized_401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"fault":{"type":"object","properties":{"faultstring":{"type":"string"},"detail":{"type":"object","properties":{"errorcode":{"type":"string"}}}}}}}}}},"common_response_Forbidden_403":{"description":"Access forbidden. The caller is not allowed to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}},"common_response_InternalServerError_500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/coreErrorMessage"}}}}}},"paths":{"/product/{tenant}/search":{"post":{"deprecated":true,"parameters":[{"$ref":"#/components/parameters/header_accept_language"}],"responses":{"200":{"description":"Search query result has been successfully retrieved.\n","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/basicProductsArray"},{"$ref":"#/components/schemas/bundleProductsArray"},{"$ref":"#/components/schemas/parentVariantProductsArray"},{"$ref":"#/components/schemas/variantProductsArray"}]}}}},"400":{"$ref":"#/components/responses/common_response_BadRequest_400"},"401":{"$ref":"#/components/responses/common_response_Unauthorized_401"},"403":{"$ref":"#/components/responses/common_response_Forbidden_403"},"500":{"$ref":"#/components/responses/common_response_InternalServerError_500"}},"description":"Searches for specified products by their YRNs.\n\nThis endpoint is `deprecated`. Please use the [/product/{tenant}/products/search](/openapi/product/#operation/POST-product-search-products) instead.\n***\n\n**Additional scope information**\n\n* The `product.product_read_unpublished` scope is only required if the response should contain unpublished products.\n\n***\n","operationId":"POST-product-search-for-products","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/searchQuery"}}},"required":false,"description":""},"summary":"Searching for products by YRNs","tags":["Products"]}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.emporix.io/api-references/api-guides/products-labels-and-brands/product-service/api-reference/products.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
