Merchant API: product bundles
About this article
This article describes how you can create, update, and retrieve product bundles via ChannelEngine's Merchant API.
Table of contents
How bundles differ from regular products
How bundle stock is calculated
Introduction
A product bundle is a sellable unit made up of two or more existing products, sold together at one combined price. On ChannelEngine, a bundle has its own Merchant product number and GTIN.
Bundling products is a popular way to maximize profits, promote differentiated products, sell unpopular products, and reduce decision-making pressure.
You can manage product bundles on ChannelEngine via the web interface, CSV upload, and the Merchant API. This article describes how to manage product bundles via the Merchant API.
Overview
Refer to the flowchart below to visualize how a bundle is assembled from existing products and exported to a channel.
Requirements
- A ChannelEngine account with a Merchant API key, found under Settings, Merchant API keys, and your base API URL:
https://{your-subdomain}.channelengine.net/api. - All bundle parts (products) must already exist on ChannelEngine. Create them via a product feed or
POST /v2/productsfirst. - A valid and unique Merchant product number for the bundle.
- A valid and unique GTIN for the bundle. ChannelEngine does not validate GTIN format, but marketplaces do. GTINs such as 0000000000000 are not valid.
Available API endpoints
-
Create bundles:
POST /v2/productbundles
Use this endpoint to create one or more bundles from existing products. -
Retrieve bundles:
GET /v2/productbundles
Use this endpoint to retrieve existing bundles, their parts, quantities, and percentage splits. -
Update the percentage split:
PUT /v2/productbundles
Use this endpoint to change how the bundle price is divided across its parts. -
Update the composition:
PUT /v2/productbundles/composition
Use this endpoint to add or remove parts and to change their quantities.
Further updates run through the standard product endpoints:
-
Update the bundle's content, such as its name, description, or custom fields:
PATCH /v2/products -
Update the total bundle price:
PUT/v2/offer
DELETE /v2/products/{merchantProductNo} or POST /v2/products/bulkdelete . orHow bundles differ from regular products
| Regular product | Product bundle |
| A standalone item with its own stock and price. | A grouping of existing products. |
Created via POST /v2/products or a product feed. |
Created via POST /v2/productbundles, the web interface, or a CSV upload. |
| Stock and price are submitted by you. | Stock is derived from the parts. The price is submitted by you. |
| Orderable directly by SKU. | Orderable by its own SKU. When ordered, the product parts appear on the order with their own SKUs. |
Limitations
- It is not possible to send parts of a bundle across partial shipments that you create via ChannelEngine because your marketplace expects one tracking code for the bundle. However, your carrier might support sending your bundle parts separately under one tracking code; for guidance, see ChannelEngine: how do I ship multiple packages under one tracking code?
- It is not possible to cancel a part of a bundle. If a specific product in the bundle is out of stock, you must report the entire bundle as out of stock. This is due to the channel acknowledging the full bundle as the sold item.
- Returns are only supported if you use the new returns and refunds flow on ChannelEngine, which treats returns and refunds as two separate processes. For more guidance, see ChannelEngine: returns and refunds [beta].
-
Marketplace fulfillment services generally do not support fulfilling product bundles that you create from individually listed products. Therefore, it is not possible to set the fulfillment type on a created product bundle to fulfillment by marketplace. For more guidance on managing marketplace fulfillment on ChannelEngine, see ChannelEngine: hybrid fulfillment.
NB: on select marketplaces, if agreed with the marketplace's fulfillment center, you can pre-stock the marketplace's warehouse with the physical product bundle and set the fulfillment type of the same product bundle - the bundle that you create on ChannelEngine - to marketplace fulfillment. If you have such an agreement, e.g.: for FBA, then contact your customer service manager or the Support team to ensure your products are correctly tracked. - Bundles are not automatically deactivated if you remove one if its parts from your product feed or via the API. Although a bundle's stock level is based on the sum of the availability of its parts, the bundle is not automatically deactivated. You must deactivate bundles manually.
- ChannelEngine only imports orders related to bundles if the bundle exists on ChannelEngine at the time of the import.
How bundle stock is calculated
A bundle's stock is calculated automatically from the part with the lowest availability, adjusted for the quantities in the bundle. E.g.: if a bundle contains one unit of product A with a stock of 10 and two units of product B with a stock of 6, the bundle stock is 3, because product B covers only three sets of two.
Create a bundle
Use POST /v2/productbundles to create one or more bundles. Bundles on ChannelEngine are created by grouping existing products into a new product, i.e.: bundle.
Each bundle needs a unique Merchant product number, a GTIN, a name, a total price, and a Parts array. Each part in the Parts array requires:
-
MerchantProductNo: the SKU of the bundle part, which must already exist on ChannelEngine. -
Quantity: how many units of the product the bundle includes. -
PricePercentage: the share of the total bundle price allocated to the part. The values across all parts must total exactly 100. See percentage split.
[
{
"MerchantProductNo": "BUNDLE-STARTER-KIT",
"Ean": "9999999990001",
"Name": "Yoga Starter Kit",
"Description": "Everything you need to get started with yoga.",
"Price": 89.99,
"Parts": [
{
"MerchantProductNo": "SKU-MAT-GRN",
"Quantity": 1,
"PricePercentage": 55
},
{
"MerchantProductNo": "SKU-BLOCK-CORK",
"Quantity": 2,
"PricePercentage": 25
},
{
"MerchantProductNo": "SKU-STRAP",
"Quantity": 1,
"PricePercentage": 20
}
]
}
]Percentage split
Bundle parts do not have a price of their own. Instead, you specify how much of the final selling price is allocated to each part, i.e.: the percentage split. E.g.: if the bundle price is 100%, Product A might account for 30%, and Product B for 70%. ChannelEngine then calculates each part's price from the total bundle price and the percentages you provide.
The percentage is allocated to the part as a whole, regardless of how many units of the product it contains. E.g.: if a part is assigned 20%, and it consists of two units of the same product, each unit accounts for 10% of the total bundle price.
Applied to the example above, at a bundle price of 89.99:
| Part | Quantity | PricePercentage | Part price | Price per unit |
SKU-MAT-GRN |
1 | 55 | 49.49 | 49.49 |
SKU-BLOCK-CORK |
2 | 25 | 22.50 | 11.25 |
SKU-STRAP |
1 | 20 | 18.00 | 18.00 |
The two cork blocks take 25% between them, which is 11.25 each. Amounts are rounded to two decimals.
The split also lets promotions, price rules, and repricing apply correctly to the bundle. To learn more about the percentage split, see ChannelEngine: product bundles.
Copy attributes from a part
Use the optional CopyAttributesFrom field to inherit content attributes, such as brand, color, and category, from one of the bundle parts. Set CopyCustomFields to true to copy that product's custom fields as well.
Update a bundle
Two PUT endpoints update bundles, depending on what you need to change.
Update the percentage split
Use PUT /v2/productbundles to change how the bundle price is divided across its parts. This endpoint does not change which products are in the bundle.
Include every part in the request. Any part you leave out has its percentage reset. The values must total exactly 100. ChannelEngine recalculates each part's price from the updated percentages.
[
{
"MerchantProductNo": "BUNDLE-STARTER-KIT",
"Parts": [
{
"MerchantProductNo": "SKU-MAT-GRN",
"PricePercentage": 60
},
{
"MerchantProductNo": "SKU-BLOCK-CORK",
"PricePercentage": 25
},
{
"MerchantProductNo": "SKU-STRAP",
"PricePercentage": 15
}
]
}
]| Field | Required | Notes |
MerchantProductNo |
Yes | The Merchant product number of the bundle. Maximum 64 characters. |
Parts[].MerchantProductNo |
Yes | The Merchant product number of the bundle part. |
Parts[].PricePercentage |
Yes | A decimal between 0 and 100. The sum across all parts must equal exactly 100. |
Update the composition
Use PUT /v2/productbundles/composition to change which products are in a bundle and in what quantities. You can update several bundles in one call.
Include every part you want to keep. Any part you leave out is removed from the bundle.
[
{
"MerchantProductNo": "BUNDLE-STARTER-KIT",
"Parts": [
{
"MerchantProductNo": "SKU-MAT-GRN",
"Quantity": 1,
"PricePercentage": 50
},
{
"MerchantProductNo": "SKU-BLOCK-CORK",
"Quantity": 2,
"PricePercentage": 30
},
{
"MerchantProductNo": "SKU-STRAP",
"Quantity": 1,
"PricePercentage": 20
}
]
}
]| Rule | Detail |
| All parts required | Include every part of the bundle. Parts omitted from the request are removed. |
| Quantity | An integer between 1 and 9,999. Required for each part. |
| Percentage split | Must total exactly 100 across all parts. |
| No-op requests | If the request matches the current composition exactly, no new version is created. |
| Response codes | 200 on success. 409 if validation fails for any bundle in the batch, e.g.: percentages do not total 100, a part does not exist, or the bundle does not exist. Because this is a bulk endpoint, you can receive a 409 even when some bundles were updated successfully. |
Each composition change is versioned. Open orders keep the composition that applied when they were placed, so shipments, cancelations, and returns stay tied to the original parts. Review earlier versions in the Bundle composition section of the bundle's product details page.
Retrieve bundles
Use GET /v2/productbundles to retrieve your bundles. The endpoint supports the filters such as: Search, EanList, MerchantProductNoList, PageSize, and Page.
Each bundle in the response contains its Merchant product number, EAN, name, price, and a Parts array with the bundle parts, their quantities, and their percentage splits. Use it to audit a bundle's composition or to verify a bundle you just created.
GET /v2/productbundles returns all bundles in your tenant. Apply pagination and filters to avoid timeouts and large payloads.
Delete a bundle
Bundles can only be deleted in the ChannelEngine web interface. Deletion is a soft delete: the bundle is deactivated and removed from channel exports, but the record is kept for order history. Once the bundle is deleted, its Merchant product number cannot be reused.
To learn more about deleting a bundle, see ChannelEngine: product bundles.
Common issues
| Issue | Cause | Solution |
| The request returns a 409. | Percentages do not total 100, a part does not exist, or the bundle does not exist. | Check the percentage split and confirm that every part and the bundle itself exist on ChannelEngine. |
| A part disappeared after an update. | The part was left out of the Parts array. |
Always send the complete composition, including parts you are not changing. |
| The bundle is rejected by the marketplace. | The GTIN is invalid or reused from a product. | Assign the bundle a valid, unique GTIN and check the marketplace's bundle requirements. |
| The bundle sells out unexpectedly. | Bundle stock follows the scarcest parts. | Monitor stock of each individual part, and avoid listing low-stock bundles on many channels at once. |
| A bundle stays active after a part is removed. | Bundles are not deactivated automatically. | Deactivate the bundle in the web interface. |
Next steps
- ChannelEngine: product bundles: the full feature guide, including the web interface workflow and composition history.
- ChannelEngine: create product bundles in bulk via CSV upload.
- ChannelEngine: parent-child relationships: set up bundle variations for channels that require a two- or three-level structure.
Comments
0 comments
Article is closed for comments.