> For the complete documentation index, see [llms.txt](https://docs.chord.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.chord.co/chord-oms/content-management-cms/kits-and-bundles.md).

# Kits and Bundles

## Kits and Bundles

#### Introduction

Chord's OMS platform supports two methods of selling a collection of products under a single price:

1\. Kit (static bundle) 2. Bundle (dynamic bundle)

This document will review these two options to choose your best action.

#### What are kits?

A kit is a \*\*pre-selected, fixed collection of products under a single **SKU**\*\*. Your customer cannot modify the products within a kit. However, you can create multiple kits which contain all the combinations of products they wish to sell.

{% hint style="info" %}
Bundles offer the same functionality as kits but with more flexibility and less duplication.
{% endhint %}

When a kit product is synced to the OMS, it creates multiple variants by permuting all possible combinations of these same variants for the products within the kit.

For example, consider a kit called Plants that consists of three products and their variants:

| **Product** | **Variants**  | **SKU**       |
| ----------- | ------------- | ------------- |
| Plant 1     | Plant 1 Large | plant-1-large |
|             | Plant 1 Small | plant-1-small |
| Plant 2     | Plant 2 Red   | plant-2-red   |
|             | Plant 2 Green | plant-2-green |
| Plant 3     | Plant 3       | plant-3       |

The OMS will generate a product called \*\***Plants**\*\* with the following variants:

1\. plant-1-large|plant-2-red|plant-3 2. plant-1-large|plant-2-green|plant-3 3. plant-1-small|plant-2-red|plant-3 4. plant-1-small|plant-2-green|plant-3

The master SKU for the kit product is the combined SKUs of all parts separated by pipes. Using the example above, the **Plants** kit will have a master SKU of **plant-1|plant-2|plant-3**.

####

Create a kit

1. In the CMS, create a new entry of type **Kit.**
2. Set the store variable `SYNC_SKU_BASED_BUNDLES` to `enabled`. When OMS syncs the kits and bundles with the CMS, it will set the SKU of the bundle to the permutation of all products in the kit.

#### What are bundles?

A bundle is a **dynamically selected collection of products**. The products within a bundle are not pre-defined within OMS like they are with kits. Instead, customers who add a bundle to their cart may then choose from a collection of variants (called\*\* parts\*\*) to add to the bundle.

A store can define what parts are within a bundle through the front end and prevent users from changing the bundle's contents. In this manner, a bundle can behave similarly to a kit *without* requiring OMS to create and manage multiple variants.

This is useful if your store offers large numbers of possible parts within a bundle. Imagine maintaining distinct variants for every single combination of colors that a child can select in a pack of crayons.

The bundle has a single price regardless of which parts a customer adds. However, you can choose which parts may be added to a bundle.

A bundle is comprised of multiple parts. A part can be a product (including all its variants) or a specific variant.

#### Create a bundle

In Contentful, create a new Content Model named **Bundle.**

Click on **Add Content Type**

![](https://3559351341-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGejRW1RLC9yasX56Xzxu%2Fuploads%2Fgit-blob-0b693beb10401721f918451d800e408d9c5ad140%2Fkits-and-bundles-1.jpg?alt=media)

Name your new entry **Bundle,** and click **Create.**

![](https://3559351341-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGejRW1RLC9yasX56Xzxu%2Fuploads%2Fgit-blob-f4248dffd7d07ae1309f355f933c1a6681ccf5b0%2Fkits-and-bundles-2.jpg?alt=media)

Click **Add field**

![](https://3559351341-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGejRW1RLC9yasX56Xzxu%2Fuploads%2Fgit-blob-081c508de26dcaefeaa64f9c92ebb83cdcfc756b%2Fkits-and-bundles-3.jpg?alt=media)

Add the following fields.

![](https://3559351341-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGejRW1RLC9yasX56Xzxu%2Fuploads%2Fgit-blob-6ef6bee3ccef158bf44a297b2b21d87b9f1a42e2%2Fkits-and-bundles-4.jpg?alt=media)

Click on the **Content** tab and select Bundle in the dropdown, click\*\* Add Entry \*\*and individually add each Product that is part of the bundle.

![](https://3559351341-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGejRW1RLC9yasX56Xzxu%2Fuploads%2Fgit-blob-aa701894ce9c3dbd202f5f43fdc46ba31db14738%2Fkits-and-bundles-5.jpg?alt=media)

Once done, **Publish** your entries.

{% hint style="danger" %}
we strongly suggest creating and testing bundles in your staging environment first
{% endhint %}

### Data model

#### Product

A boolean `bundle` was added to the Product model to denote whether or not the product is a singular product or a bundle of products.

For example, the following products are bundles and will have `bundle: true`:

| Product ID | Name          |
| ---------- | ------------- |
| 1          | Plant Bouquet |
| 2          | Plant Bouquet |
| 3          | Plant Bouquet |

#### BundlesPart

Used to define and validate what products may be added to a specific bundle. It also defines the maximum quantity of parts allowed within the bundle.

For example, consider the bundles defined above:

| Bundle ID | Part ID | Count |
| --------- | ------- | ----- |
| 1         |         | 1     |
| 2         |         | 4     |
| 3         |         | 6     |

### API

#### Add a Bundle to the Cart

To add a bundle to the cart, the app calls `POST /api/orders/{order_number}/line_items`. The payload will include the `sku`, `variant_id`, and `id` of the bundle, along with the list of variants to include in the bundle within the `parts` array. Note that the `parts` array is within the `options` object.

The payload for adding a bundle to your cart:

```json
x{
   "line_item":{
      "sku":"KIT-1",
      "quantity":1,
      "options":{
         "parts":[
            {
               "sku":"PART-1",
               "quantity":1
            },
            {
               "sku":"PART-2",
               "quantity":1
            }
         ]
      }
   }
}
```

The `line_items` array in the order response will look like this:

```json
"line_items":[
	{
		"id":159,
		"quantity":1,
		"price":"65.0",
		"variant_id":329,
		"variant":{
		  "id":329,
		  "name":"Starter Kit",
		  "sku":"KIT",
		},
		"is_bundle":true,
		"parts":[
		  {
		     "id":170,
		     "sku":"PART-1",
		     "quantity":1
		  },
		  {
		     "id":171,
		     "sku":"PART-2",
		     "quantity":1
		  }
		]
	}
]
```

#### Updating/Removing Parts from a Cart

Once a bundle is in a cart, parts can be added or removed using the `/api/orders/{order_number}/line_items/{line_item_number}`endpoint, where the `line_item_number` is the ID of the line item for the bundle.

The payload is:

```jsx
{
	line_item: {
		id: 1,
		part_line_items: [
			{
				id: 1
				sku: 'sku-1',
				_destroy: true
			}
		]
	}
}
```

## Misc Code Notes

Parts in the API payload are converted to `part_line_item_attributes` hash in the `normalize_part_params` method. The `part_line_item_attributes` hash is attached to the `line_item_attributes` in the `options` array.

The `part_line_item` is created when the `line_item` is created in the `Spree::OrderContents#after_add_or_remove`method. Uses some Rails magic to instantiate the `part_line_item`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.chord.co/chord-oms/content-management-cms/kits-and-bundles.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
