This article is for Apex developers, integration developers, and implementation partners who build custom cart logic outside the standard storefront UI. Use it to understand the supported public ShoppingCartApi contract for adding items, updating cart items, and handling multi-cart behavior safely.
What this API is for
ShoppingCartApi is the supported Apex entry point for custom code that needs to mutate shopping carts without relying on storefront Lightning controllers.
Use it when you need to:
- add one or more products to a cart from Apex
- create a cart implicitly as part of an add-to-cart operation
- update an existing cart item's quantity, custom fields, or addons
- create buyer-visible cart lines that should remain read-only in storefront flows
- preserve predictable multi-cart and result-order behavior in custom server-side logic
Supported public operations
The current public Apex contract exposes these operations:
Add items to cart
- Method: ShoppingCartApi.addToCart(request)
- Request type: ShoppingCartApi.AddToCartRequest
- Result type: ShoppingCartApi.AddToCartResult
Update an existing cart item
- Method: ShoppingCartApi.updateCartItem(request)
- Request type: ShoppingCartApi.UpdateCartItemRequest
- Result type: ShoppingCartApi.UpdateCartItemResult
Both methods throw ShoppingCartApi.ApiException when validation fails or the underlying cart operation cannot be completed.
Add items to a cart
Use ShoppingCartApi.addToCart when your integration needs to add one or more products in a single atomic operation.
The add request supports:
- contactId: required shopper contact
- shoppingCartId: optional target cart
- items: required list of products to add
Each item supports:
- webProductId: required product to add
- quantity: required quantity
- fields: optional map of custom cart item field values
- isReadOnly: optional flag that marks the created cart line as read-only
The result returns:
- shoppingCartId: the cart that received the items
- shoppingCartItemIds: the created cart item record IDs in the same order as the request items
The order of shoppingCartItemIds is part of the public contract. Result entry n corresponds to request item n.
Update an existing cart item
Use ShoppingCartApi.updateCartItem when your integration needs to change an existing cart line.
The update request supports:
- shoppingCartId: required cart containing the item
- shoppingCartItemId: required cart item to update
- quantity: optional new quantity
- fields: optional map of custom field values to update
- addons: optional list of addon IDs
- isReadOnly: optional flag to mark the line as read-only after the update
The result returns:
- shoppingCartId: the cart containing the updated item
- shoppingCartItemId: the updated cart item
Use updateCartItem to change quantity or line details instead of relying on repeated add calls to combine quantities.
Request map handling and allowed fields
Use the fields map to pass additional cart item data on add and update operations.
Important contract details:
- add requests accept extra cart item data through AddToCartItem.fields
- update requests accept extra cart item data through UpdateCartItemRequest.fields
- values in the fields map are converted to string form before they are passed downstream
- integrations should format picklist, numeric, and boolean values exactly as the target cart item fields expect
- update requests reject prohibited system-managed fields such as price, parent references, cart references, and product references
Use the dedicated isReadOnly flag instead of trying to set the managed read-only field through the fields map.
Read-only behavior
The public contract includes a dedicated isReadOnly flag for both add and update operations.
For add operations:
- the API can create protected lines from the start
- when the cart service creates related child rows for the added item, the read-only state is carried to those generated rows in the same add flow
For update operations:
- setting isReadOnly to true lets an integration lock the item after the update
- this property should be documented as a lock-only convenience flag in the public contract
- false should not be documented as a guaranteed unlock path
Read-only behavior differs between Apex integrations and storefront editing flows.
- ShoppingCartApi.updateCartItem supports controlled programmatic updates to items that are already read-only
- storefront controller flows continue to enforce the buyer-facing lock on read-only items
- if a buyer-driven storefront flow tries to edit a protected item, the service returns: This shopping cart item can no longer be edited.
This distinction matters for integrators. Do not assume every cart update path honors read-only lines in the same way.
How cart resolution works
Cart resolution differs slightly between add and update operations.
addToCart with shoppingCartId provided
When you supply shoppingCartId, the API validates that the cart exists and uses that cart.
addToCart with shoppingCartId omitted
When shoppingCartId is omitted, the API resolves the current contact's active cart when possible.
- if an active cart exists, the API adds to that cart
- if no active cart is available, the service creates a cart as part of the add flow
updateCartItem
Update requests require shoppingCartId and shoppingCartItemId. The provided cart must match the item being updated.
Active cart behavior in multi-cart scenarios
Multi-cart behavior matters most when a new cart is created during addToCart.
If the add operation creates a new cart, the API returns that cart ID in the result. Custom integration logic should continue using the returned shoppingCartId rather than assuming a previously active cart remains correct.
If the add operation uses an existing cart, the API returns that cart ID in the result for downstream processing.
Atomic behavior and merge expectations
Both add and update operations run inside a savepoint and roll back the entire operation if any part of the request fails. Treat both APIs as all-or-nothing operations.
ShoppingCartApi.addToCart also has an important contract boundary for repeated adds.
- the public Apex API does not expose mergeIfProductIsInCart
- add requests are intentionally executed with merge behavior disabled
- each request item keeps a one-to-one relationship with the corresponding result entry in shoppingCartItemIds
- repeated add calls should not be documented as automatic quantity merges
- integrations that need to change quantity should use ShoppingCartApi.updateCartItem
This keeps totals and result mapping predictable for integration scenarios.
Validation and error handling
ShoppingCartApi performs request validation before and during execution.
Add request validation
- request must not be null
- contactId is required
- items must contain at least one entry
- item entries cannot be null
- each item must include webProductId and quantity
- when shoppingCartId is supplied, it must reference an existing cart
- a price book must be resolvable from cart or storefront context
Update request validation
- request must not be null
- shoppingCartId is required
- shoppingCartItemId is required
- the cart item must exist and belong to the specified cart
- the cart item must belong to the current user
- only allowed fields can be updated through the fields map
- quantity must be a positive integer when supplied
- addons must all be valid and allowed for the item
Error-handling guidance for integrators
Handle ShoppingCartApi.ApiException in your custom logic and surface a business-safe message to the caller.
Common failure cases to plan for include:
- Shopping cart not found
- Shopping cart item not found
- Price book could not be resolved
- Unexpected add to cart result size
- Cart item creation failed
- Prohibited field update attempted
- Invalid quantity
- Invalid or unauthorized addon
- downstream null reference errors can be surfaced with their original message
Notes on custom fields and addons
When you supply fields on add requests, the API converts the values to string form before handing them to downstream logic. Format those values exactly as the target cart item fields expect.
On update requests, the API validates field names and only applies allowed custom cart item fields.
When you update addons, the API validates each addon ID before applying the change.
When to use ShoppingCartApi versus storefront controller methods
Use ShoppingCartApi when:
- you are writing Apex integration logic
- you need a stable server-side mutation contract
- your code should not depend on storefront Aura or LWC controller patterns
- you need clear ordering and rollback guarantees for server-side cart mutations
Use storefront controller methods only when:
- you are extending the storefront UI itself
- your component already runs inside the same Experience Cloud cart context
- you intentionally need UI-oriented controller behavior rather than a reusable Apex integration contract
Do not treat internal storefront controller methods as a substitute for the public ShoppingCartApi contract in general integration code.
Contract boundary to document clearly
Keep this article focused on the supported ShoppingCartApi mutation contract.
Do not mix in undocumented internal controller behavior, internal service refactors, or release-history details unless they change the public integration behavior.