For the complete documentation index, see llms.txt. This page is also available as Markdown.

Product Tutorial

How to add your first products

Take a look at the relationships between prices and other resources in the Emporix Commerce Engine:

Creating your first product is a process made up of defining sales tax rates, adding the product and adding media files for a product.

1

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.

To define sales tax rates for a country, send a request to the Creating a new tax configuration endpoint.

2

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.

3

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.

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.

1

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.

2

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 create a product bundle, perform the following steps:

1

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 name

  • code: Unique product identifier

  • bundledProducts: Array of products to include in the bundle (each with productId and amount)

  • productType: Must be set to "BUNDLE"

Optional fields:

  • template: Product templates are optional for bundles

  • description: Product description

  • taxClasses: Tax class configuration

  • published: Publication status

  • mixins: 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.

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.

Related services:

Tax:

API Reference

Product:

API Reference

Media:

API Reference

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.

1

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.

2

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.

To create a single parent_variant type of product with variants, send a request to the Creating a new product endpoint.

3

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.

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.

1

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.

2

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.

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.

1

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.

Update a specific variant product by sending a request to the Upserting a product endpoint.

In the following example, we override the following fields:

  • published

  • taxClasses

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.

Dynamic variants are designed for catalogs where the variant structure is not known in advance or where variants are loaded in bulk from an external system. For simpler, template-driven variants, use the PARENT_VARIANT / VARIANT product types instead.

Key features

Key feature
Description

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 variants map of all descendants. In API responses each entry's variantAttributes contains accumulated (fully merged) attributes.

  • Child products - expose ownVariantAttributes (what is stored on this product, writable) and inheritedVariantAttributes (merged from ancestors, read-only).

  • parentVariantPath array — carried by every child, it's an ordered list of ancestor IDs from direct parent (index 0) to root (last index).

  • sellable flag - marks variants that can be added to a cart. Non-sellable intermediate variants exist only to group attributes.

Creating dynamic variants

1

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.

2

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 itself

  • value.type - STRING, NUMBER, DECIMAL, or BOOLEAN

  • value.qualifier - the canonical value used for matching and filtering

  • value.name - localized display label for the selected value

  • value.unit - optional unit code for measurement attributes (for example, "MMT" for millimetres)

3

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.

4

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.

API Reference

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:

  1. Group by dynamicVariantType to determine the selection steps (e.g. first choose H1_L1, then H1_L2).

  2. Filter by parentVariantId to show only the children of the currently selected variant.

  3. Read variantAttributes on 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.

  4. Check sellable: true to identify which variants can be added to a cart. Non-sellable intermediate variants are grouping nodes only.

  5. Use name (localized) for display in search results, breadcrumbs, or option labels.

  6. Use code for 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.

API Reference

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.

API Reference

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.

1

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.

2

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:

Status
Meaning

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

3

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.

API Reference
1

Import all products

Import all the products, root + all variant levels, using the POST /products or POST /products/bulk. Variants may arrive in any order.

2

Do the recalculation

After the full batch is complete, call POST /products/recalculate with all imported IDs.

3

Retrieve the job details

Poll GET /products/recalculate/jobs/{jobId} until status is FINISHED.

4

Fetch the root product

The variants map is now fully populated and ready for the storefront.

The attempts field on a job tracks how many times the subscriber has attempted processing. If status is FAILED and attempts is greater than 1, the system has already retried. A FAILED_PERMANENT status indicates the job is not retried automatically and requires investigation.

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.

1

Assign your product to classification category

Assign the product to a classification category using the Assigning a resource to a category endpoint:

2

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:

When updating a product with classification mixins, you don't need to provide the schema URL in metadata.mixins for classification mixins. The system automatically populates these schema URLs based on the product's category assignments.

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:

To learn about the end-to-end flow for implementing classification in your B2B commerce platform, along with the category service , see the Classification tutorial.

Last updated

Was this helpful?