Product Packaging
Product Packaging
Product packaging defines how the same item can exist in different units of measure. It is useful when a retailer buys a product in a larger pack, but sells it in smaller units.
For example, a retailer may buy iced tea as a 24-case, stock it as 6-packs, and also sell single bottles. Packaging lets the API describe these relationships between products.
This guide uses the {version} product and product family endpoints. The base URL for all requests is https://DOMAIN_PREFIX.retail.lightspeed.app/api/{version}/.
Packaging relationships
A packaging relationship is a directional link from an outer pack to an inner pack.
- The
outer_pack_product_skuis the SKU for the larger pack. - The
inner_pack_product_skuis the SKU for the smaller pack. - The
amountis how many inner packs can be made from one outer pack.
For example, if one 24-case can be broken into four 6-packs, the 24-case is the outer pack, the 6-pack is the inner pack, and the amount is 4.
A product can be an outer pack, an inner pack, or both. When a product is both, the relationships form a chain. For example:
CASE-24 -> PACK-6 -> BOTTLE-1In this example, BOTTLE-1 is the base unit because it is the smallest unit and is not broken down further.
Packaging fields
Use the packaging array on product create and product update payloads.
{
"packaging": [
{
"outer_pack_product_sku": "CASE-24",
"inner_pack_product_sku": "PACK-6",
"amount": 4
}
]
}The products referenced by outer_pack_product_sku and inner_pack_product_sku must already exist, or be included in the same create request.
Creating packaging with a product family
To create product packaging when creating a product, send a POST request to /product_families and include packaging on the product that is the outer pack.
The example below assumes the inner pack product already exists with SKU BOTTLE-1. The request creates a new standard product family for a 6-pack and links that 6-pack to the bottle.
POST /product_families
Request payload:
{
"name": "Iced Tea 6 Pack",
"classification": "STANDARD",
"products": [
{
"codes": [
{
"type": "CUSTOM",
"code": "PACK-6"
}
],
"packaging": [
{
"outer_pack_product_sku": "PACK-6",
"inner_pack_product_sku": "BOTTLE-1",
"amount": 6
}
]
}
]
}The API responds with the ID of the created family and the IDs of the products within it.
Response payload:
{
"data": {
"product_family_id": "6f32baa8-9a5f-4697-964f-cb2ffa6dff1a",
"product_ids": ["cae9eebf-abfa-4c19-b3cd-c6e4c09c512e"]
}
}For a variant family, you can also add products with packaging to an existing family with a POST request to /product_families/{productFamilyID}/products.
Creating a packaging chain
Packaging relationships can be chained by including more than one relationship. Each outer pack can only point to one inner pack, but an inner pack can be used by more than one outer pack.
The example below assumes BOTTLE-1 and PACK-6 already exist, and PACK-6 already has packaging that links it to BOTTLE-1. The request creates the outer 24-case and links it to the 6-pack.
POST /product_families
Request payload:
{
"name": "Iced Tea 24 Case",
"classification": "STANDARD",
"products": [
{
"codes": [
{
"type": "CUSTOM",
"code": "CASE-24"
}
],
"packaging": [
{
"outer_pack_product_sku": "CASE-24",
"inner_pack_product_sku": "PACK-6",
"amount": 4
}
]
}
]
}This creates the chain CASE-24 -> PACK-6 -> BOTTLE-1. The base unit is calculated from the end of the chain.
Updating packaging for a product
To update packaging for an existing product, send a PATCH request to /products/{productID}.
PATCH /products/cae9eebf-abfa-4c19-b3cd-c6e4c09c512e
Request payload:
{
"packaging": [
{
"outer_pack_product_sku": "PACK-6",
"inner_pack_product_sku": "BOTTLE-1",
"amount": 6
}
]
}The packaging array is the complete packaging set for that outer pack product. If the product already has packaging, any existing relationship not included in the request is removed.
The API returns the updated product ID.
Response payload:
{
"data": {
"id": "cae9eebf-abfa-4c19-b3cd-c6e4c09c512e"
}
}Deleting packaging for a product
To delete packaging for a product, update the product and send an empty packaging array.
PATCH /products/cae9eebf-abfa-4c19-b3cd-c6e4c09c512e
Request payload:
{
"packaging": []
}This removes the packaging relationship where the product is the outer pack.
If a product is deleted, packaging relationships that use that product are also removed.
Retrieving packaging
Packaging is returned as part of product responses.
Use GET /products/{productID} to retrieve one product, or GET /product_families/{productFamilyID} to retrieve the family and its products.
Response payload:
{
"data": {
"id": "cae9eebf-abfa-4c19-b3cd-c6e4c09c512e",
"family_id": "6f32baa8-9a5f-4697-964f-cb2ffa6dff1a",
"variant_name": "Iced Tea 6 Pack",
"sku": "PACK-6",
"packaging": [
{
"id": "8a0f7b6a-6d3f-4d7d-a9f8-0ff1848237a2",
"outer_pack_product_id": "cae9eebf-abfa-4c19-b3cd-c6e4c09c512e",
"inner_pack_product_id": "0e4066d7-7981-4900-b37c-627fd929ad59",
"amount": 6,
"created_at": "2026-07-01T12:00:00Z",
"updated_at": "2026-07-01T12:00:00Z",
"deleted_at": null
}
]
}
}The write payload uses SKUs because products may be created in the same request. The read response returns product IDs for the created relationship.
Validation notes
- Packaging is only supported for standard products and variant products. Composite products cannot have packaging relationships.
- Packaging can be set between standard products and variant products.
outer_pack_product_skuis required.inner_pack_product_skuis required.amountmust be greater than zero. Use whole numbers for packaging quantities.- A product can only be the outer pack in one packaging relationship.
- A product can be the inner pack in more than one packaging relationship.
- Packaging chains cannot contain loops. For example,
CASE-24 -> PACK-6 -> CASE-24is rejected. - The products in a packaging relationship must track inventory.
- Each packaging tree in a create request must include at least one product from that request.
