Carts and Orders overview

Overview of the concepts related to Carts, Orders, and the overall checkout process.

General concepts

This section covers key concepts and structures that apply to both Carts and Orders. Understanding these fundamentals is essential for effectively managing the checkout process and related resources.

Line Items

A Line Item is a snapshot of a Product Variant at the time it is added to a Cart.
The snapshot of a Product Variant is created from the ProductProjection as follows:
  • The current projection is used.
  • If the Cart is bound to a Store, the following additional checks and projections are performed:
    • For Stores with active Product Selections, the selected Product Variant must be included in at least one of the active Product Selections.
    • The selected Product Variant must be available in a Store.
    • All LocalizedStrings are filtered by the locales defined in the Store. If the API cannot find a matching locale in the Store languages, the first locale found in the Project settings is used as a fallback.
    • All Prices are filtered according to the Product distribution Channels defined in the Store. Prices without a Channel are also included.
    • All ProductVariantAvailabilities are filtered according to the Inventory supply Channel defined in the Store. Inventory entries without a Channel are also included.
If the Product Variant changes, the relation to the current ProductProjection is kept, but the Line Item is not updated automatically. The Line Item can be updated through the Carts API on demand. With this update, the Product Variant data is copied to the variant field of the LineItem.

Carts containing Line Items that reference deleted Product Variants cannot be used to create Orders.

Custom Line Items

A Custom Line Item is a generic item not associated with a Product Variant. It can be used for selling services or virtual goods that do not require inventory tracking, such as additional fees or vouchers.
You add Custom Line Items to a Cart in the same way as Line Items. However, Line Item price selection doesn't apply to Custom Line Items; instead, you control the price and taxes of the item.
The monetary value of a Custom Line Item can be negative; therefore, it can be used for discounts applied by vouchers. Furthermore, Custom Line Items can be used to implement more complex cart logic through Cart Predicates.
The InventoryMode of a Cart has no effect on Custom Line Items.

Stores

Stores can be used to model various concepts, including physical retail locations, brand stores, and regions. They let you specify which project resources are available within a Store's context.

If a Customer is assigned to one or more Stores, they are considered a Store-specific Customer. Store-specific Customers can only be associated with Carts and Orders in their assigned Stores. In contrast, global Customers are not assigned to any Stores and can be associated with Carts and Orders either in specific Stores, or without a Store.

For more information, see Global versus Store-specific Customers.

Guest checkout

To offer checkout functionality without requiring a visitor to sign in or create an account, you can create an anonymous session. When you create a Cart, Shopping List, or Payment, you can set an anonymousId on the resource to link it to the anonymous session.
It is good practice to create an anonymous session only once the visitor begins interacting with the Cart, for example, by adding an item to it. This avoids creating a large number of unused sessions. For more information, see Manage token requests.
Carts with an anonymousId are known as anonymous Carts. If you create an Order from an anonymous Cart, the Order is automatically assigned the same anonymousId.
If the visitor signs in to an existing account, or creates a new account, you can link a single anonymous Cart, or link all of their existing anonymous resources (Carts, Orders, Shopping Lists, and Payments) to the Customer.
A visitor might have an existing active Cart associated with their account, but they aren't signed in. In this case, if the visitor starts shopping with an anonymous Cart and later signs in to their account, the default behavior is to attempt to merge the items into their existing active Cart, in a process called a Cart merge.
For more information about transferring resources to a Customer, see Customer authentication.

Carts

Carts hold Product Variants that are referred to as Line Items once added to the Cart, and Custom Line Items. During checkout, a Cart is ordered.
The status of a Cart is defined by its CartState. Carts that can be updated and ordered have the CartState Active and are known as active Carts:

Create a Cart

To create a Cart, you can use the following endpoints:

Update a Cart

To update a Cart, you can use the Update Cart, Update Cart in Store, or Update Cart in Business Unit B2B endpoints along with one or more update actions.

After all update actions are performed, the Cart:

  • removes any Line Items that are invalid due to deleted Products, Product Variants, or Prices.

  • removes any Line Items that are invalid due to an inactive StandalonePrice.

    When a Product is unpublished, any associated Line Items already present in a Cart remain unaffected and can still be ordered. To prevent this, do the following:

    • If the Product uses Embedded Prices, remove them from the unpublished Product.
    • If the Product uses Standalone Prices, deactivate or delete the Standalone Prices.
  • updates any LineItem price field if the result of the Line Item price selection has changed because of a Product update.
  • updates the ShippingInfo, in particular, the price and shippingMethodState fields.
  • updates the discounts, which may affect the LineItem or CustomLineItem totalPrice fields and ShippingInfo discountedPrice field:
    • if a Cart Discount becomes invalid due to deactivation, expiration, or the predicate no longer matches the Cart's content, the discount is removed.
    • if a Cart Discount becomes active and applicable (since the last update), the discount is added.
    • if a Discount Code becomes invalid due to usage limits, deactivation, expiration, or the predicate no longer matches the Cart's content, the discount is removed.
  • updates the Cart totalPrice field.
  • updates the Tax Rates, in particular, the taxedPrice field.
  • updates the LineItem productKey.
To perform the above-mentioned updates without additional update actions, send a request with only the Recalculate update action.
To update the Product data saved in the Line Items, use the Recalculate update action with updateProductData set to true.

Freeze a Cart

To prevent a Cart from being modified by changes to prices and, in specific cases, discounts, you can freeze it.

This is useful during checkout, as it helps ensure that the price the customer sees in their cart is the price they will pay, even if promotions or product prices change before the order is placed.

The following applies to frozen Carts:

  • Prices remain as they were when the Cart was frozen. However, if a Price that a Line Item depends on is deleted entirely, the affected Line Item is removed from the frozen Cart.
  • Update actions as well as background services modifying prices on the Cart are deactivated for frozen Carts.
  • Inventory is not reserved for Line Items in frozen Carts.
  • Frozen Carts can either be ordered or unfrozen. When unfrozen, a Cart continues to accept new updates.

Impact of changes on frozen Carts

ResourceChangeImpact on frozen Cart
PricesUpdatedIgnored. The frozen Cart retains the price at the time of freezing.
DeletedThe Line Item that uses the deleted price is removed from the frozen Cart.
Cart DiscountsCreatedIgnored. New Cart Discounts are not applied.
ActivatedIgnored. Cart Discounts that become active are not applied.
ExpiredRemain applied as they were at the time of freezing.
InactivatedRemoved from the frozen Cart.
DeletedRemoved from the frozen Cart.
Invalidated (due to Cart predicates not matching)Removed from the frozen Cart.
Product DiscountsCreatedIgnored. New product discounts are not applied.
ExpiredRemain applied as they were at the time of freezing.
InactivatedRemain applied as they were at the time of freezing.
DeletedRemain applied as they were at the time of freezing.
Discount CodesCreatedCan be added. If the Discount Code predicate does not match the Cart, the state changes to DoesNotMatchCart and doesn't change the Cart total.
Removed (from Cart)Can be removed, and the Cart total is updated.
Invalidated (due to Cart predicates not matching)Discount Code remains in the Cart, the state changes to DoesNotMatchCart, and the Cart total is updated. If later, the Discount Code becomes valid, it will not automatically re-apply.
InactivatedDiscount Code remains in the Cart, the state changes to NotActive and the discount is removed, updating the Cart total.
Deleted (from Project)Discount Code remains in the Cart with the last known status (for example: NotActive), but no longer affects the Cart total.
OtherUpdates that affect the price of Cart itemsNot accepted. Maintains price stability of the Line Items and Custom Line Items. To view the list of price-related updated actions that are not allowed, see the frozen CartState.
Updates that do not affect the price of Cart itemsAccepted, and the Cart total is updated accordingly. For example, setting the shipping method.
Anonymous user signs in or signs upThe frozen Cart is not merged.
When applying update actions, the API still performs validations on the Cart to ensure that it is convertible to an Order, and reports errors if such a validation fails.

Creating an Order will fail if the frozen Cart contains a Discount that must be removed (according to the previously mentioned restrictions), or if a Tax Rate for one or more items has changed.

Lifetime

The lifetime of a Cart is controlled by the deleteDaysAfterLastModification property and can be adjusted according to your requirements. During this lifetime, a Cart is kept as it was the last time when actions were performed on it. It contains Line Items and Custom Line Items with prices that were valid at the time of the last Cart update and Cart Discounts that were active at that time. Any read method on a Cart alone will not lead to a representation with up-to-date prices and so on, only Cart updates will trigger this.

Price precision

  • Prices with TypedMoney can be cent-precision or high-precision.
  • When calculating net and gross prices, prices with decimals are rounded. If the fraction of centAmount is exactly 0.5, the RoundingMode defined by taxRoundingMode is applied to the Cart's price.
  • If the tax is not included in the price (includedInPrice=false on the TaxRate), the tax portions are derived from the net prices. If the tax is included in the price (includedInPrice=true on the TaxRate), then the tax portions are derived from the gross prices. This only applies when the Platform TaxMode is used.
  • If the prices are discounted and if tax is included in the price (includedInPrice=true on the TaxRate), the discount is applied to the gross price of a Line Item or Cart. If includedInPrice=false, the discount is applied to the net price of a Line Item or Cart.
  • When prices are discounted with relative discounts, they are always rounded in favor of the customer with half-down rounding.
  • If a Line Item's priceMode is ExternalPrice and uses high-precision money, the totalPrice of the Line Item is calculated by multiplying the price by the quantity and then rounded using the HalfEven rounding mode.

Taxes

Tax rate selection

A Cart cannot calculate taxes for the items in it until the shippingAddress property is set.
The shippingAddress.country and shippingAddress.state properties affect the selection criteria. These are compared to the TaxRate's country and state fields. A Tax Rate is only eligible if the country and state properties are an exact match.
Since the state field is optional on both TaxRate and shippingAddress, this means the following:
  • If shippingAddress.country and TaxRate.country are an exact match, and no state properties are present, the TaxRate applies to the Cart.
  • If shippingAddress.country and TaxRate.country are an exact match, but only one of shippingAddress.state or TaxRate.state is present, the Tax Rate does not apply to the Cart.
  • If shippingAddress.country and TaxRate.country are an exact match, and shippingAddress.state and TaxRate.state are an exact match, the Tax Rate applies to the Cart.
  • If shippingAddress.country and TaxRate.country are present, and shippingAddress.state and TaxRate.state are present, but there is a mismatch of either country or state, the Tax Rate does not apply to the Cart.
If you need to include a state or country sub-unit for shipping purposes, use shippingAddress.region to avoid Tax Rate conflicts.

Tax modes

By default, newly created Carts use the Platform TaxMode. With this tax mode, the taxedPrice of a Cart is calculated by Composable Commerce automatically based on the Tax Rate that applies for the country (and optionally, state) of the Cart's shippingAddress. The Tax Rate is taken from the TaxCategory assigned to Products and Shipping Methods.
If you prefer to have more control over how taxes are calculated in your Project, including the use of an external tax calculation service, you can use one of the following TaxModes:
  • External: you are responsible for explicitly setting the Tax Rates for Line Items and Custom Line Items. With this tax mode, you must specify whether tax is included in the price for Line Items or Custom Line Items. This mode is suitable when you want Composable Commerce to handle the tax calculations based on the provided Tax Rates.
  • ExternalAmount: you are responsible for providing the exact tax amounts for Line Items and Custom Line Items, and explicitly setting the taxedPrice of the Cart using Set Cart Total Tax. This mode is suitable when you want full control over the tax calculation. For more information about how to set tax amounts, see ExternalAmount TaxMode.
When includedInPrice: true, the tax is calculated in a top-down manner, and when includedInPrice: false, the tax is calculated in a bottom-up manner.
The following example shows the impact of includedInPrice in the Cart calculation with taxRoundingMode: HalfEven and taxCalculationMode: LineItemLevel.
Line ItemProduct Variant AProduct Variant BShipping
Line Item: Price$15$25$5
Quantity105---
External Tax Rate: includedInPricefalsetruefalse
External Tax Rate: amount0.190.150.15
Taxed Item Price: totalNet$150$108.70$5
Taxed Item Price: totalGross$178.5$125$5.75
Calculation formula15 x 10 (1 + 0.19)25 x 5 / (1 + 0.15)5 x (1 + 0.15)

Tax calculation mode

Due to the principle of rounding on every calculation step, this slight difference in when to apply tax can have a considerable effect on the Cart total.

Composable Commerce offers two tax calculation modes to support different use cases:

  • The LineItemLevel TaxCalculationMode enforces tax calculation after multiplying the individual item price by the quantity.
  • The UnitPriceLevel mode calculates the taxed price before multiplying by the quantity.

The following example demonstrates the differences in the Cart total depending on the different tax calculation modes. Let's assume:

Line Item #QuantityUnit PriceLine Item Total, Net
(LineItemLevel)
Line Item Total, Net
(UnitPriceLevel)
Line Item Total, Gross
11$1.00$0.84$0.84$1.00
210$1.08$9.08$9.10$10.80
310$108.08$908.24$908.20$1080.80
41$2.00$1.68$1.68$2.00
550$0.01$0.42$0.50$0.50
61$4.90$4.12$4.12$4.90
Cart Total, Net
(LineItemLevel)
Cart Total, Net
(UnitPriceLevel)
Cart Total, Gross
$924.38$924.44$1100.00

As seen from the example, if a Line Item has a quantity of 1, the two modes have no impact on the total net value of a Line Item (see Line Item #1, 4, and 6). However, if the quantity is more than 1, the two modes calculate the total net value of a Line Item with a difference of several cents (see Line Item #2, 3, and 5).

Depending on the specific Line Item values, the chosen mode can give a greater or lesser net value (see Line Item #2 compared to #3). A difference of 6 cents is accumulated in the Cart total. The connection to rounding is especially clear with Line Item #5.

Due to rounding after applying tax to 0.01 and multiplying by quantity 50 upon that, the net value when using UnitPriceLevel ends up being equal to the gross value. With LineItemLevel, where quantity multiplication is performed as a first calculation step, the rounding occurs to a greater value, and the net value ends up being $0.42.

Inventory

To define how inventory is managed in your Project, choose an InventoryMode option that best suits your use case:
  • None: the default inventory mode. This mode does not track or update inventory levels. Adding or ordering items from a Cart has no impact on inventory.

    This mode is suitable for scenarios where inventory management is handled entirely by an external system, such as an Inventory Management Service (IMS), or when you want to implement custom inventory logic within your application.

  • TrackOnly: tracks and updates inventory levels upon ordering. Using this mode, you can create an Order even if the Line Item quantity is zero or negative.

    This mode can be used for allowing overselling scenarios, accepting backorders, or when you want to allow customers to order items even if they are temporarily out of stock.

  • ReserveOnOrder: requires that there is available stock to create an Order. If you want to allow order creation for a temporarily out-of-stock item, you can set the restockableInDays field on InventoryEntry to any value. Once an Order is created, the inventory is reduced.

    This mode helps prevent overselling by reserving stock for Orders.

Orders

An Order is a snapshot of a transaction between a customer and a business. It serves as a durable record of the transaction and includes details such as the selected items, pricing, customer information, shipping and billing addresses, selected shipping methods, payment information, and order state. While it does not inherently manage the full post-purchase lifecycle (such as fulfillment, returns, or refunds), it acts as the foundation upon which those processes can be built or integrated.

Create an Order

To create an Order, you use one of the following methods: from a Cart, from a Quote, or by using Order Import.

From a Cart

This is the most common method for creating an Order, used for typical customer purchases during checkout.

The following information is copied to the Order:

  • Line Items and Custom Line Items (with prices and any associated Custom Fields)
  • Shipping and billing addresses
  • Customer information
  • Custom Fields (Cart-level)
  • Selected Shipping Method
  • Payment information
  • Discount Codes
  • Direct Discounts
  • Tax settings
  • Inventory Mode
  • Origin
  • Refused Gift Line Items
  • Cart reference
  • Any associated Store or Business Unit

From a Quote

This method creates an Order based on the agreed-upon terms of a Quote and is commonly used in B2B scenarios or when price negotiations are required. The Order includes the negotiated prices, quantities, and any other specific conditions outlined in the Quote.
The Quote transitions through different states during the negotiation process. To create an Order from a Quote, the Quote must have the Pending state.

Using Order Import

This method lets you import existing Orders from external systems or other Composable Commerce Projects. This is useful when you need to migrate from a legacy system or consolidate Orders from different sources.

Order Import requires that you provide all necessary Order data in a specific format. This data must adhere to the Composable Commerce Order model.

For more information, see the Create Order by Import endpoint.

Update an Order

An Order is a legally binding purchase agreement between the Merchant and the customer; therefore, changes to it should be carefully considered.

To update the Order, you have two options: direct updates or Order Edits. The option you choose depends on whether a financial change to the purchase agreement is required.
If, for instance, a customer provides an incorrect shipping address by mistake, a change is required to ensure the goods can be delivered to the customer. Composable Commerce offers a direct update action to change the shipping address for such cases. However, if the proposed change to the shipping address results in changes to the applicable taxes of the Order items, a direct update to the Order is not possible. In this case, because a financial change will occur, you must use an Order Edit instead, which ensures the amendment is traceable for audit purposes.
To learn about which update actions are available for each method, see Overview of update actions for Cart, Order, and Order Edit.

Non-financial changes

Use the Order update actions to directly modify an Order when no financial change occurs.

For example, changes to:

  • Order number, State, or locale
  • Customer's email address or billing address
  • Shipping information, such as addresses, that do not require recalculation of the Shipping Method and shipping rates
  • Payment information
  • Deliveries and returns
  • Any other change that does not affect the Order total

Financial changes

Use Order Edits when you need to update an Order that results in a financial change.

For example, changes to:

  • Line Items and Custom Line Items (such as quantity)
  • Shipping information, such as addresses, that require recalculation of the Shipping Method and shipping rates
  • Discounts
  • Any other change that affects the Order total

In addition to any updates that financially impact the Order, you can also update non-financial properties within the same Order Edit. For example, you can update a Customer's email address alongside any changes that affect the total price of the Order.

The Order Edits API does not support tracking or reserving inventory. You can only create an Order Edit if the InventoryMode of the Order and its LineItems is None.
Shipping addresses, including country and state, are used to identify applicable Shipping Methods and shipping rates for an Order. You can update shipping addresses using direct updates or Order Edits, however, Composable Commerce only triggers reevaluation of Shipping Methods and shipping rates when changes are initiated through an Order Edit.

Intended flow

The basic flow for an Order Edit:

  1. Create an OrderEdit: use the Create OrderEdit endpoint to create an OrderEdit entity. Upon creation, the OrderEdit contains a reference to the target Order within the resource field; however, no data is copied between the entities. At this point, you can consider the OrderEdit to be a staging area to collect the proposed changes.
  2. Add the proposed changes: use the Update OrderEdit by ID endpoint to add the individual update actions to the OrderEdit. Immediately upon adding the update actions to the OrderEdit, the stagedActions are run against the Order; a so-called dry run. As a response, the Order is returned as if the Order actions had been applied. This allows you to preview the changes and understand the impact on the total price of the Order. The response will also contain Messages which capture the changes applied to the Order. Dry runs are always performed against the latest version of the Order.
    If the Order endpoint contains API Extensions, they are also called during the dry run.
  3. Review the preview: ensure a careful review of the preview takes place, as the Order always respects the current product catalog, price configuration, and promotions. For example, if an OrderEdit is made soon after Order placement, changes will likely be minimal. However, if more time has passed, price adjustments and expired promotions may significantly impact the Order.
    We recommend that you review the Messages within the preview to understand the proposed changes. For example, the OrderEditApplied Message details the before and after values of the net total, gross total, and tax portion.
  4. Apply the changes: use the Apply OrderEdit endpoint to apply your proposed changes to the original Order.
    When you apply an Order Edit, the Order is recalculated using the same criteria listed under Update a Cart. During recalculation, Discounts that have become invalid or are otherwise no longer applicable are removed. Only Discounts that are valid at the time of the Order Edit application are applied to the updated Order.
    The Order (not the OrderEdit) triggers the OrderEditApplied Message, which contains both the original and the newly applied values. At this point, you can delete the Order Edit (if desired). Deleting an Order Edit does not affect the related Order.

State

To check the state of an Order Edit, use the result field.
StateDescription
NotProcessedThe changes have not been applied to the Order. This status shows on results returned from the Query OrderEdits endpoint.
PreviewSuccessA preview of the modified Order, including any available Messages, is available for evaluation. This status can show after OrderEdit creation and when an OrderEdit is fetched or updated via key or ID.
PreviewFailureA preview could not be generated due to one or more invalid changes specified in the errors field. This status can show after OrderEdit creation and when an OrderEdit is fetched or updated via key or ID.
AppliedThe changes have been applied to the Order. This state contains information detailing the state before (excerptBeforeEdit) and after (excerptAfterEdit) the OrderEdit was applied. Once applied, any additional changes must be done in a new OrderEdit.

Overview of update actions for Cart, Order, and Order Edit

Update actionCartOrderOrder Edit
Set Key-
Set Order Number-
Set Purchase Order Number-
Set Customer ID
Set Customer Email
Set Customer Group-
Set Anonymous ID--
Set Business Unit B2B
Add LineItem-
Remove LineItem-
Add CustomLineItem-
Remove CustomLineItem-
Add Shopping List-
Set Cart Total Tax--
Set Order Total Tax--
Change TaxMode-
Change Tax RoundingMode-
Change Tax CalculationMode-
Add DiscountCode-
Remove DiscountCode-
Set DirectDiscounts-
Add Payment
Remove Payment
Change PaymentState-
Set Billing Address
Set Shipping Address
Add ItemShippingAddress
Remove ItemShippingAddress
Update ItemShippingAddress
Add ShippingMethod--
Add Custom ShippingMethod--
Remove Shipping Method--
Set ShippingMethod-
Set ShippingAddress and ShippingMethod--
Set ShippingAddress and Custom ShippingMethod--
Set Custom ShippingMethod-
Set ShippingRateInput-
Add Delivery-
Remove Delivery-
Change ShipmentState-
Add ReturnInfo-
Set ReturnInfo-
Set ReturnShipmentState-
Set ReturnPaymentState-
Change OrderState-
Transition State-
Update SyncInfo-
Set Locale
Set Country-
Set Store-
Set Custom Type
Set CustomField
Set DeleteDaysAfterLastModification--
Freeze Cart--
Unfreeze Cart--
Recalculate--

on LineItem

Update actionCartOrderOrder Edit
Change LineItem Quantity-
Change LineItems Order--
Set LineItem TaxRate-
Set LineItem TaxAmount-
Set LineItem Price-
Set LineItem TotalPrice-
Set LineItem DistributionChannel-
Set LineItem ShippingDetails
Set LineItem RecurrenceInfo--
Apply DeltaToLineItemShippingDetailTargets--
Set LineItem Custom Type
Set LineItem CustomField
Set LineItem InventoryMode--
Set LineItem SupplyChannel--
Transition LineItem State-
Import LineItem State-

on CustomLineItem

Update actionCartOrderOrder Edit
Change CustomLineItem Quantity-
Set CustomLineItem TaxRate-
Set CustomLineItem TaxAmount-
Change CustomLineItem Money-
Change CustomLineItem Price Mode--
Set CustomLineItem ShippingDetails
Set CustomLineItem RecurrenceInfo--
Apply DeltaToCustomLineItemShippingDetailsTargets--
Set CustomLineItem Custom Type
Set CustomLineItem CustomField
Transition CustomLineItem State-
Import CustomLineItem State-

on Billing Address

Update actionCartOrderOrder Edit
Set Billing Address Custom Type
Set Billing Address CustomField

on Shipping Address

Update actionCartOrderOrder Edit
Set Shipping Address Custom Type
Set Shipping Address CustomField

on ItemShipping Address

Update actionCartOrderOrder Edit
Set ItemShipping Address Custom Type
Set ItemShipping Address CustomField

on ShippingMethod

Update actionCartOrderOrder Edit
Set ShippingMethod TaxAmount-
Set ShippingMethod TaxRate-

on Shipping

Update actionCartOrderOrder Edit
Set Shipping Custom Type
Set Shipping CustomField

on Delivery

Update actionCartOrderOrder Edit
Set Deliver Address-
Add Parcel to Delivery-
Remove Parcel from Delivery-
Set Delivery Items-
Set Delivery Custom Type-
Set Delivery CustomField-

on Delivery Address

Update actionCartOrderOrder Edit
Set Delivery Address Custom Type-
Set Delivery Address CustomField-

on Parcel

Update actionCartOrderOrder Edit
Set Parcel Measurements-
Set Parcel Tracking Data-
Set Parcel Items-
Set Parcel Custom Type-
Set Parcel CustomField-

on ReturnItem

Update actionCartOrderOrder Edit
Set ReturnItem Custom Type-
Set ReturnItem CustomField-