Grouped Products & Combinations
A combination (also called a set or kombin) is not a separate entity in Akinon Commerce — it is a Grouped Product. A grouped product is a product record whose product_type is grouped and which points to a list of simple products through a dedicated relation. Everything a merchant thinks of as "a combination" — the look, the set, the package — is stored, priced, indexed, and rendered as a grouped product.
This guide explains how a combination is defined, which fields feed it, how one is set up, how it is priced, how it behaves in listing and search, and how it reaches the storefront.
1. How a Combination Is Defined
A combination is made of two parts:
The grouped product itself — a product whose
product_typeisgrouped(enum value3). It carries the name, SKU, base code, attribute set, images, categories and the combination's own price.The group product items — one record per member, each linking the combination to one simple product and carrying that member's display order and default quantity.
Grouped product "Suit Package" SKU: SP01
│
├── item (order=0, initial_quantity=1) ──► Simple product "Jacket" JKT01
├── item (order=1, initial_quantity=1) ──► Simple product "Pants" PNT02
├── item (order=2, initial_quantity=1) ──► Simple product "Shirt" SRT03
└── item (order=3, initial_quantity=2) ──► Simple product "Tie" TIE04Fields that feed the combination
The group product item is the only place combination-specific data lives. It has exactly four meaningful fields:
from_product
product reference
The grouped product (the combination). Its product_type must be grouped.
to_product
product reference
A member of the combination. Its product_type must be simple.
order
positive integer
Display order of the member inside the combination. 0 is the highest priority and is shown first. This is the Sorting column on the Omnitron product page.
initial_quantity
positive integer
Default quantity of that member shown before it is added to the basket, and the multiplier used in total-price calculation. This is the Quantity column on the Omnitron product page.
The pair (from_product, to_product) is unique — the same simple product cannot be added to the same combination twice.
Omnitron and Commerce hold these same four fields, and the integration carries them across unchanged, so the Sorting and Quantity values a merchant enters in Omnitron are the order and initial_quantity Commerce sorts and prices with.

order and Quantity its initial_quantity — here the shirt is second in the set and comes two to a set.Validation rules
Three rules are enforced when a member is added or changed:
The combination must be a grouped product
Group Product Item: product_type of relation 'from_product' must be 'grouped'
The member must be a simple product
Group Product Item: product_type of relation 'to_product' must be 'simple'
The member must not already be in the combination
Group Product Item already exists
A violation returns HTTP 406 with an error code identifying the rule. The codes and full error payloads are in the OpenAPI specification referenced below.
Setting up a combination
The order matters. A combination can only be assembled out of products that are already sellable on their own, and membership is always added after the combination itself exists.
Prepare the members. Every simple product that will go into the set has to be sellable in that channel on its own — category, catalog, price and stock. A member missing any one of these is left out of the set on the storefront with no warning, which is why this step comes first; Where combinations are authored covers what to check when a piece of a set goes missing.
Create the grouped product. A product whose
product_typeisgrouped, with its own name, SKU and attribute set. It needs a category and a place in the channel's catalog, but no price and no stock of its own — both are derived from its members. For the Omnitron admin screens, see Product Types > Grouped Product.Give it a full-look image. The combination's own image, showing the whole set worn together. This is a prerequisite rather than a finishing touch: a combination with no image of its own is not indexed as a selectable entry. See Imagery.
Add the members one at a time. One record per member, each carrying its
orderandinitial_quantity. Members cannot be supplied in the same call that creates the grouped product — see Managing combination items via API.Leave the price alone. The combination's price is derived from its members, so a price entered by hand on the grouped product is overwritten the next time it is recalculated. See Pricing for which derivation is used and what triggers a recalculation.
Managing combination items via API
Combination items are exposed as a standard admin REST resource.
Path: /api/v1/group_product_items/ Permission: admin user only (this is not a storefront endpoint)
GET
List items. Filterable by from_product and to_product (both product IDs).
POST
Add a simple product to a combination.
PUT / PATCH
Change the member, its order or initial_quantity.
DELETE
Remove a member from the combination.
Adding a member to a combination
POST /group_product_items/ takes the grouped product, the member, and the two display fields:
The created row comes back with its identifier:
A request that breaks one of the rules above returns HTTP 406.
Which combinations contain a given product?
The relation is navigable in both directions. To find every combination a simple product belongs to — the data a "Complete the look" / "Shop this combination" module on a simple product's detail page needs — filter the list by the member: GET /group_product_items/?to_product=341.
The from_product values are the combinations the member appears in; resolve each one to build the suggestion module.
Where combinations are authored
Combinations exist in both Omnitron and Commerce, with the same four fields on either side. Which one you write to depends on how the catalog is run:
Omnitron-fronted catalogs (the usual case) — the merchant builds the combination on the Omnitron product page and the channel integration syncs it to Commerce. Product references are remapped to the channel's Commerce product IDs on the way, so the two systems never share identifiers.
Commerce-direct catalogs — the combination is posted straight to the Commerce endpoint above.
Two conditions gate what actually reaches Commerce:
A combination item is only sent once both of its products are already integrated to that channel. A membership pointing at a product that has not synced yet is skipped and picked up on a later run.
The grouped product itself only enters the channel's product set when it is active and assigned to the channel's catalog.
2. Pricing
A grouped product has its own price, derived from the prices of its members. Which derivation is used is controlled by a dynamic setting.
GROUPED_PRODUCT_PRICE_SELECTOR
Key
GROUPED_PRODUCT_PRICE_SELECTOR
Type
string (dotted path)
Default
omnishop.catalogs.selector.group_product_min_price_selector
omnishop.catalogs.selector.group_product_min_price_selector
The cheapest member's price ("starting from" pricing).
omnishop.catalogs.selector.group_product_max_price_selector
The most expensive member's price.
omnishop.catalogs.selector.group_product_sum_price_selector
The sum of all members' prices, each multiplied by its initial_quantity.
See Dynamic Settings #60 for the registry entry.
When the price is recalculated
The grouped product's price is recomputed whenever the inputs change:
A member is added to or changed in a combination — that combination is repriced immediately.
A member's price changes — every combination containing that member is repriced.
The selector setting is changed — existing combinations are repriced in the background, so on large catalogs the new prices appear gradually rather than all at once.
Price lists
Everything above applies per price list. When a request resolves to a specific price list, member prices and the combination total are read from that list instead of the default one.
3. Listing & Listability
Grouped products are always listable. Unlike simple and meta products — whose listability depends on variant-listable attributes and stock — a combination is listable from the moment it is created and stays that way.
Consequences:
A combination appears in category listings and collections like any other listed product, provided it is assigned to them.
It gets a pretty URL of its own, which is its canonical address. The numeric route
/group-product/{product_id}/stays valid and redirects to it.
4. Search Behavior
How a combination is indexed
A combination is indexed as a single searchable product, with its members attached to it:
A member is only indexed under the combination if it has at least one image, and only if it has stock (or
PRODUCT_STOCK_OUT_VISIBILITY_ENABLEDis on).A member does not carry its own categories, collections or sorting into the combination. This is deliberate: it stops a member from pulling the combination into a category it does not belong to, and stops member sorting values from competing with ordinary listed products.
The combination's stock is the sum of its members' stock, and it counts as in stock when any member is.
HIDE_GROUPED_PRODUCTS_ON_SEARCH
Key
HIDE_GROUPED_PRODUCTS_ON_SEARCH
Type
boolean
Default
false
When set to true, combinations are indexed without any searchable text. They remain listable and still reachable by URL and from category pages, but a search query can no longer match them.
Use it when combinations should be reachable only from curated entry points (a category, a landing page, a link from a member's detail page) and should not compete with individual products in the search box.
See Dynamic Settings #84 and Search Structure for the registry entries.
5. Storefront Display
Detail endpoint
Path: GET /group-product/{product_id}/ Permission: public
The combination's canonical address is its pretty URL; this numeric route redirects there, so follow redirects when calling it.
The endpoint serves grouped products only; any other product ID returns 404. It also honours the end-of-life attribute: if PRODUCT_END_OF_LIFE_ATTRIBUTE is set and the grouped product carries a truthy value for it, the endpoint returns 404 regardless of stock (for single products the same check additionally requires the product to be out of stock).
Response contract
product
object
The grouped product itself, serialized like any product detail (name, images, attributes, price).
group_products
list
The members, in display order. Each member is a full product payload plus initial_quantity.
in_stock
boolean
Whether any member is in stock.
group_products_total_price
string
Sum of member prices × initial_quantity.
group_products_total_retail_price
string
Sum of member retail prices × initial_quantity.
Example response
The member objects use the same product schema as any product detail response, so only the combination-specific fields are shown below.

Deduplicating variants on the detail page
The member list returned by the endpoint is not simply every member you added. When several members are variants of the same model, only one of them is returned — the one most suitable to show, preferring a listable and in-stock variant. Members that are not variants of anything are all returned. The result is ordered by order, and ties by the order the members were added.
Note that in_stock is evaluated over every active member, not just the returned ones, so a combination can report in_stock: true on the strength of a variant that was not selected for display.
This means a combination can safely contain several size or colour variants of the same model; the detail page shows one representative card per model rather than repeating it. Stock is evaluated for the requesting channel, so the representative can differ by price list or channel.
Imagery
A combination has an image set of its own, returned alongside the members' images and independent of them. The two play different roles, and both are worth getting right:
The combination's own image is the full look — the model wearing every piece together. It is what makes a set recognisable as a set.
Each member's image is that single garment's product shot, shown on the member's card so the customer can tell the pieces apart before adding them.
Rendering
Storefronts consume the endpoint above and render the combination on its own page.

For what the resulting page looks like to a customer — the per-member cards, variant selection on each card, the "Add the full set" path versus adding members one by one, and how out-of-stock members change the display — see the Group Product (Set Product) Experience tutorial, under Tutorials → Instore. That page documents the Instore implementation, but the flows and the pricing/stock scenarios it walks through are the ones this endpoint drives.
6. Basket Behavior
A grouped product cannot itself be added to the basket. An attempt to add one is rejected as though the product did not exist — the same rule applies to meta products — so do not expose an add-to-basket action on the combination itself.
What the customer buys are the members:
Each member is added to the basket as an ordinary simple product line.
initial_quantityis the default quantity presented in the UI, not a constraint — the customer can raise or lower it before adding.Members are added independently, so a customer may take part of the combination. Any "Add the whole set" action on the storefront is a client-side convenience that issues one basket call per member.
Because the basket holds simple products only, everything downstream — promotions, stock reservation, order lines, cancellation, returns — treats a purchased combination as separate items, not as a single sellable unit. If you need the set to behave as one indivisible sellable unit, use a Bundle Product instead.
7. Related Settings & Pages
Which price is stored on the combination (min / max / sum).
Hides combinations from search by blanking their indexed text.
Whether out-of-stock members are still indexed under the combination.
Returns 404 for the combination's detail page when set.
Omnitron admin steps for creating grouped products and all other types.
How the search index and its dynamic settings work end to end.
Group Product (Set Product) Experience (Tutorials → Instore)
What the combination page looks like to a customer, end to end.
Admin → Group Product Items (API Reference → Commerce OpenAPIs → Admin)
Full contract for managing combination members.
Products → Grouped Product (API Reference → Commerce OpenAPIs → Products)
Full contract for the combination detail endpoint.
Last updated
Was this helpful?

