Product Tutorial
How to add your first products
This tutorial presents how to create a basic product. To learn more about types of products available in the Emporix Commerce Engine, check out the Products guide.
Take a look at the relationships between prices and other resources in the Emporix Commerce Engine:
Countries and regions are predefined in the Emporix API Country Service. You can check which countries and regions are available by sending requests to the following endpoints:
Creating your first product is a process made up of defining sales tax rates, adding the product and adding media files for a product.
Define sales tax rates
Sales tax rates are stored in tax configurations. Each configuration indicates a country and defines tax classes applicable to it.
You can manage your tax configurations through the Emporix API Tax Service.
For more information, check out the Tax classes guide.
To define sales tax rates for a country, send a request to the Creating a new tax configuration endpoint.
Add products
To add a single basic product, send a request to the Creating a new product endpoint.
Simple product example:
You can also add multiple basic products at the same time. To achieve that, send a request to the Creating multiple products endpoint.
Add media for a product
To add media files, for example images or videos, for a particular product, upload them directly to the Emporix database, or link to their location on an external website. In this example, create a PUBLIC BLOB asset and associate it with a product by sending a request to the Creating an asset endpoint with the media.asset_manage scope.
To upload a file, send a multipart/form-data request and create a BLOB asset with PUBLIC access. To reference an external URL without uploading the file, send an application/json request and create a LINK asset. Storefront-visible product media requires PUBLIC access. For more information, check out the Media Tutorial.
How to create a basic product with a template
You can create a product template that contains additional attributes describing your product, and then create products using that template. Templates are optional but useful for organizing product attributes consistently across your catalog.
Create a product template
To create a new product template, call the Creating a new product template endpoint.
The id from the response is the product template ID that you can use when creating products.
When creating a product template for a basic product, do not set variantAttribute to true in the attribute metadata. Variant attributes are only for PARENT_VARIANT and VARIANT product types.
Create a product using a template
By applying a product template, you can create a product that contains additional attributes, which are included in the product's mixins.productTemplateAttributes field.
To create a new product by applying a product template to it, call the Creating a new product endpoint and provide the template's ID in the request body.
How to create a product bundle
With Emporix API, you can group together two or more products that already exist in the system so that they can be sold at one collective price. Product bundles do not require product templates or variant generation.
To learn more about product bundles, check out the Products guide.
To create a product bundle, perform the following steps:
Before you start, ensure you have defined the tax classes.
The products you want to bundle must already exist in the system.
The
product.product_publishscope is only required if you want to publish the product on its creation.
Create a bundle of products
You can group together two or more products that already exist in the system so that they can be sold at one collective price. To achieve that, call the Creating a new product endpoint.
In this example, we create a bundle containing a T-shirt product and socks product that already exist in the system.
The value of the productId from the response is the {{bundle_Id}}.
Required fields for bundles:
name: Product namecode: Unique product identifierbundledProducts: Array of products to include in the bundle (each withproductIdandamount)productType: Must be set to"BUNDLE"
Optional fields:
template: Product templates are optional for bundlesdescription: Product descriptiontaxClasses: Tax class configurationpublished: Publication statusmixins: Additional product attributes
How to update multiple products in one operation
If you want to update multiple products, use the bulk update feature to update several products in one operation. Send a request to the Upserting multiple products endpoint.
The product.product_update scope is required. The product.product_publish and product.product_unpublish scopes are only required if you want to publish or unpublish the products on the update.
When the update request is sent successfully, the response for a particular product is returned at the same position (index) at which it is located in the request body. The expected response is as follows:
When something goes wrong, you might see some error message in the response. See some examples of error notifications you might encounter:
404: The first product was not found, check if you have provided the correct id.
409: The second product returns conflict, check if you have provided the correct product schema version.
404: The third product cannot be updated because the product template provided in the payload was not found, check if you have provided the correct data.
To test the endpoint, open the API reference or check the example of a curl request.
Related services:
Tax:
Product:
Media:
How to create a parent variant product with variants
Variants are derivatives of the parent variant product. They contain the same attributes as their parent variant, but assume different attribute values.
The product.product_publish scope is only required if you want to publish the product on its creation.
Create a product template with variant attributes
Create a product template that defines the variant attributes (for example, color and size) and their allowed values. Set variantAttribute to true in the attribute metadata so they can be used for variant generation.
Call the Creating a new product template endpoint.
The id from the response is the product template ID. Use it as {{product_template_Id}} in the next step.
Create a parent variant product
Variants are created automatically whenever their parent variant product is created or updated. The combinations of variants are created based on the attributes defined in the product template applied to the parent variant, and the attributes and values specified in the variantAttributes field of the parent variant.
Before you start, ensure that the skipVariantGeneration parameter is set to false.
When creating or updating a product of the PARENT_VARIANT type, by default, product variants are generated. If you do not want to create product variants for the product, set the skipVariantGeneration parameter to true.
The product template can contain more attributes and values than are needed to create a parent variant. In the variantAttributes field, specify the attributes and values from the product template that are relevant to the particular parent variant product and its variants.
To create a single parent_variant type of product with variants, send a request to the Creating a new product endpoint.
Optional: Create multiple parent variant products
If you want to create multiple parent_variant products at the same time, send a request to the Creating multiple products endpoint.
To test the endpoint, open the API reference or check the example of a curl request.
How to create variants with new attributes and values
If you want to create variants by adding new variant attributes and/or values for a parent variant, perform the following steps.
You can add new attribute values either by adding them to the product template and then updating the product, or by updating the product with new values under variantAttributes, if they already exist in the product template.
The product.product_publish scope is only required if you want to publish the product on its creation.
Update a product template with new attributes and values
To add new variant attribute values to your product template, update the template by calling the Updating a product template endpoint. In this example, we add PURPLE to the existing color attribute values.
Each of the attributes has its own metadata element, where you can specify whether the attribute is mandatory, if it can be used as a variant attribute, and what its default value is.
Update the existing parent variant product with the new product template
Since updating the product template results in it being assigned a new version, update the parent variant by sending a request to the Partially updating a product endpoint and providing the new template.version value.
In the variantAttributes field, specify the attributes and attribute values that the variant products will assume. Based on the specified attributes, variant product combinations will be created automatically.
When creating or updating a product of the PARENT_VARIANT type, by default, product variants are generated. If you do not want to create product variants for the product, set the skipVariantGeneration parameter to true.
As a result, new product variants are created automatically, in combinations that include the newly specified attributes and values.
How to override variant attribute values
You may choose to update the basic fields of a particular variant, for example name, description, or relatedItems.
The product.product_publish and product.product_unpublish scopes are only required if you want to publish or unpublish the product on its update.
Updating a variant with new attribute values
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.
You cannot override the following attributes: id, code, template, variantAttributes.
The parentVariantId field cannot be updated. It can only be set when creating a new variant product. When updating an existing variant, this field should be omitted or will be ignored if included.
Update a specific variant product by sending a request to the Upserting a product endpoint.
In the following example, we override the following fields:
publishedtaxClasses
How to work with dynamic variant products
Dynamic variants let you build flexible, multi-level product hierarchies without a fixed attribute template. Each variant in the tree is an independent product that declares only its own distinguishing attributes. The API provides a full picture including accumulated attributes, inherited values, and a ready-to-use variant map. With this, your storefront receives complete, up-to-date data with a single API call.
Compared with standard variants (PARENT_VARIANT / VARIANT), dynamic variants do not require a predefined shared variant template and support deeper, flexible hierarchies where each level can introduce different attribute dimensions. Standard variants are better for fixed, predictable option sets (for example, size and color only), while dynamic variants are better when hierarchy depth or variant dimensions can change over time.
Key features
No template required
Each variant defines its own attributes directly on the product. You can introduce new attribute dimensions at any level without modifying a shared template.
Order-independent ingestion
Variants can be created in any order - a child can exist before its parent. This is essential for bulk catalog imports where the full tree is not available in a single pass. After the import completes, a single recalculation call rebuilds the entire tree.
Single API call for the storefront
Fetching the root product returns a variants map containing every descendant with fully accumulated attributes - parent attributes merged into child entries. The storefront never needs to make additional calls to resolve the complete attribute combination for a sellable variant.
Ready-to-render variant selectors
The variants map on the root product is a flat map keyed by variant ID. Each entry carries variantAttributes (accumulated), name (localized), code (the variant product code), sellable, dynamicVariantType, and parentVariantId. This gives your product page everything it needs to render multi-step variant selectors (for example, "Storage -> Color -> Bundle") without any client-side tree reconstruction.
Delta storage, no cascading writes
Each variant stores only the attributes it introduces at its own level (ownVariantAttributes). Changing a mid-level variant attribute updates only that variant's entry on each ancestor.
Hierarchy integrity signals
The metadata.dynamicVariantInfo field on any product response surfaces broken chains (missingAncestorId) or circular references (cycleDetected) so you can detect and fix data issues proactively.
The variant tree model
A DYNAMIC_VARIANT hierarchy is a tree of independent products:
Root product - holds a denormalized
variantsmap of all descendants. In API responses each entry'svariantAttributescontains accumulated (fully merged) attributes.Child products - expose
ownVariantAttributes(what is stored on this product, writable) andinheritedVariantAttributes(merged from ancestors, read-only).parentVariantPatharray — carried by every child, it's an ordered list of ancestor IDs from direct parent (index 0) to root (last index).sellableflag - marks variants that can be added to a cart. Non-sellable intermediate variants exist only to group attributes.
Creating dynamic variants
Create the root product
The root is a DYNAMIC_VARIANT product with no parentVariantId. It acts as the anchor for the entire tree and is the product your storefront links to. To create the root product, call the Creating a new product endpoint.
Create L1 variant products
To create an L1 variant product, call the Creating a new product endpoint.
L1 variants are direct children of the root. Set parentVariantId to the root product ID and declare the attributes that distinguish this variant from the root in ownVariantAttributes. Set sellable: false if this variant is an intermediate grouping level.
Each attribute value uses the dynamicVariantAttribute structure:
name- localized display label for the attribute itselfvalue.type-STRING,NUMBER,DECIMAL, orBOOLEANvalue.qualifier- the canonical value used for matching and filteringvalue.name- localized display label for the selected valuevalue.unit- optional unit code for measurement attributes (for example,"MMT"for millimetres)
Create L2 leaf variants
To create an L2 variant product, call the Creating a new product endpoint.
L2 variants are children of L1 variants. They declare only the attributes they introduce at their own level, the L1 attributes are inherited automatically. Set sellable: true on variants that can be purchased.
Retrieve the root product - the storefront view
To retrieve the root product with its complete variant tree, call the Retrieving a product endpoint. The variants map on the root contains every descendant with accumulated attributes, each entry already has its own attributes merged with all ancestor attributes up the chain.
The response includes a variants map ready for your storefront:
Each entry in variants includes code — the same business code as on the corresponding variant product (for example MOBILE-15-PRO-L1 matches the L1 product created earlier).
Notice that mobile-15-pro-l2-retail (L2) already contains storageCapacity, colorFinish, and displaySize from its L1 parent - even though those attributes are not stored on the L2 product itself.
To test the endpoint, open the API reference or check the example of a curl request.
Using the variants map on the storefront
The variants map gives your product page everything it needs to build a variant selector UI without additional API calls:
Group by
dynamicVariantTypeto determine the selection steps (e.g. first chooseH1_L1, thenH1_L2).Filter by
parentVariantIdto show only the children of the currently selected variant.Read
variantAttributeson each entry to render the selector labels and values - all attributes are already accumulated, so an L2 entry shows all dimensions the customer needs to see.Check
sellable: trueto identify which variants can be added to a cart. Non-sellable intermediate variants are grouping nodes only.Use
name(localized) for display in search results, breadcrumbs, or option labels.Use
codefor the variant product business code (for example cart lines, pricing, or integrations that key on SKU-style identifiers).
Retrieving a child product - own versus inherited attributes
When you fetch a child product directly, the response separates its attributes into two maps:
ownVariantAttributes- the attributes stored on this product. These are writable: you can change them via PUT or PATCH.inheritedVariantAttributes- the attributes inherited from ancestor products. These are read-only on this product. To change an inherited attribute, update the ancestor that owns it. To retrieve a child product, call the Retrieving a product endpoint.
To test the endpoint, open the API reference or check the example of a curl request.
Updating a dynamic variant
To update a variant's own attributes, send a PUT or PATCH request with the new ownVariantAttributes. Only the attributes in ownVariantAttributes are accepted - any attempt to modify inheritedVariantAttributes is ignored. To update a dynamic variant, call the Upserting a product endpoint.
For a single product write, the variants map on all ancestor products is updated synchronously and inline — no recalculation job is needed.
To test the endpoint, open the API reference or check the example of a curl request.
How to recalculate dynamic variant trees after a bulk import
When importing large catalogs, variants are often created in arbitrary order — a child product may be written before its parent exists. In this case the inline synchronous update is skipped for products whose parent is not yet present. After the full batch has been ingested, trigger an asynchronous recalculation to rebuild all variant trees.
Call the recalculation endpoint after the entire batch has been ingested, not per individual product write. For single product writes the tree is updated synchronously and no recalculation is needed.
Trigger recalculation
To trigger recalculation, call the Triggering dynamic variant recalculation endpoint with a list of up to 1000 product IDs at any hierarchy level. You do not need to know which products are roots, the system resolves the root for each submitted ID automatically and creates one job per unique root product.
The response is 202 Accepted with one job per unique root product resolved from the submitted IDs:
If a recalculation job for a given root is already PENDING or PROCESSING, the affected IDs are returned in skippedProductIds and the existing job is referenced in the jobs list. This prevents duplicate concurrent recalculations of the same tree.
Poll for job completion
Use the job ID from the response and call the Retrieving a recalculation job endpoint to poll for completion. Jobs move through the following lifecycle:
PENDING
Job created, waiting to be picked up by a subscriber
PROCESSING
A subscriber has started rebuilding the variant tree
FINISHED
Tree rebuilt successfully
FAILED
Processing failed; may be retried
FAILED_PERMANENT
Processing failed permanently; manual intervention required
A finished job:
A failed job includes an error message and the number of attempts made:
Returns 404 if the job does not exist or has been automatically removed. Jobs are retained for approximately 30 days after reaching a terminal state (FINISHED, FAILED, or FAILED_PERMANENT).
List all jobs (optional)
To monitor the overall import progress, call the Listing recalculation jobs endpoint. Filter by status to focus on jobs that need attention.
Available status filter values: PENDING, PROCESSING, FINISHED, FAILED, FAILED_PERMANENT.
To test the endpoint, open the API reference or check the example of a curl request.
Recommended bulk import workflow
How to handle classification of products
Classification categories allow you to organize products with consistent attributes across your catalog. By assigning products to classification categories, they automatically receive reusable attribute schemas that ensure data quality and consistency while reducing manual work.
Creating a product with classification mixins
To create a product with classification mixins, assign it first to a classification category and then update it with classification mixin attributes.
Assign your product to classification category
Assign the product to a classification category using the Assigning a resource to a category endpoint:
Update product with classification mixin attributes
Update the product with classification mixin attributes using the Partially updating a product endpoint. Use the mixinPath from the classification category's classificationMixins field:
Product response with classification mixins
To retrieve a product that is assigned to a classification category, send a request to the Retrieving a product endpoint. The response includes the classificationMixins field in the metadata:
The response includes the classificationMixins field:
Last updated
Was this helpful?

