The B2B Cart

Build a Cart that carries Business Unit context, tracks a purchase order, ships to multiple sites, and can be frozen for committee review.

Ask about this Page
Copy for LLM
View as Markdown

After completing this page, you should be able to:

  • Create a B2B Cart scoped to a Business Unit, with a distribution Channel and a native purchase order number.

  • Configure a single Cart to ship to multiple destinations.

  • Choose the right Cart freeze or lock strategy for a buying committee or a support agent.

  • Decide whether a filled Cart should become a Direct Order or a Quote Request.

  • Decide between Custom Fields and Custom Objects when a B2B requirement has no native field.

A Horizon Hotels procurement officer reopens last month's basket, bumps two quantities, and submits it. An Atlas Corporate buyer assembles a 180-line requisition that ships to four sites, attaches a purchase order number their finance team will reconcile against, and hands the basket to a buying committee before anyone places the order. Both purchases start as a Cart, but the B2B Cart carries organizational context, multi-site delivery needs, and review steps that a single shopper does not need. For the general Cart lifecycle, including sessions, merges, and updates, see the Implement carts and shopping lists path.

Business Unit context on the Cart

A B2B Cart is created through the as-associate endpoint you met in Configure associate access, scoped to a Business Unit. The platform records the Business Unit on the Cart's businessUnit field and enforces the acting Associate's permissions server-side through the same Permission Gate.
POST /{projectKey}/as-associate/{associateId}/in-business-unit/key=atlas-apac/carts HTTP/1.1
Content-Type: application/json

{
  "currency": "AUD",
  "store": { "typeId": "store", "key": "atlas-apac-store" },
  "purchaseOrderNumber": "PO-2026-04-1180",
  "lineItems": [
    {
      "sku": "ZET-MON-27",
      "quantity": 40,
      "distributionChannel": { "typeId": "channel", "key": "atlas-apac-pricing" }
    }
  ]
}

Two fields connect this Cart back to earlier modules:

  • store sets the commercial context (assortment and Channel) you designed in Design B2B catalogs.
  • distributionChannel on each Line Item is the link to Configure B2B pricing: it makes each item resolve the buyer's negotiated, Channel-scoped Price rather than an unscoped one.
The businessUnit is taken from the URL path, not the request body, so the Cart always belongs to the Business Unit you addressed.

Native purchase order tracking

B2B buyers reconcile orders against a purchase order (PO) raised in their own procurement system. commercetools models this natively with the purchaseOrderNumber field. It exists on Cart, Quote Request, Staged Quote, Quote, and Order, and a value set on the Cart is inherited by the Order or Quote Request created from it, so you set it once at the start of the flow.
Use the native purchaseOrderNumber field rather than a Custom Field for the PO. Custom Fields remain the right tool for other B2B context that has no native field, such as a cost-center reference on a Line Item or an internal requisition label.

Payment by invoice

Most B2B orders are settled by invoice on account against agreed net terms, not by card capture at checkout. The purchaseOrderNumber ties the Order to the buyer's procurement record, and a downstream financial system issues the invoice and reconciles payment on those terms. Model the settlement with the Payments resource, and treat card authorization at checkout as the exception for B2B rather than the default.

Modeling B2B-specific data

The purchaseOrderNumber shows the first rule of B2B data modeling: prefer a native field whenever one exists. When a requirement has no native field, commercetools offers two extension tools, Custom Fields and Custom Objects, and choosing between them is a recurring decision.
  • Custom Fields attach typed data to an existing resource. Use them when the data belongs to a Cart, Order, Line Item, Customer, Business Unit, or Quote, such as payment terms on a Cart, a cost-center reference on a Line Item, or an internal requisition label on an Order.
  • Custom Objects are standalone key-value records with no host resource. Use them for data that does not belong to a single resource instance, such as a buyer's credit limit, organization-wide configuration, or lookup tables that several resources reference.
The rule of thumb: if the data describes this Cart, Order, or Line Item, reach for a Custom Field; if it stands on its own and is referenced from elsewhere, model it as a Custom Object.

Shipping one Cart to many destinations

A single B2B order frequently ships to several sites: a head office places one order, but pallets go to four hotels. The Cart's shippingMode controls this.
Use the default Single ShippingMode when the whole Cart ships to one destination. Use Multiple when one order must deliver quantities to several registered itemShippingAddresses.
With Multiple, register the destinations in itemShippingAddresses and then allocate each Line Item's quantity across those addresses through shippingDetails. Until every Line Item is fully allocated, the platform does not calculate taxedPrice, so an unallocated quantity is a common cause of a Cart that "won't show tax".

Freezing a Cart for committee review

B2B purchases often pass through a buying committee before submission. While the committee reviews, you do not want the catalog price to move underneath the agreed basket. Freezing the Cart holds the agreed amounts in place. The freezeStrategy field chooses how strict that hold is.
Use the default SoftFreeze FreezeStrategy when the committee only needs Line Item prices to hold. Use HardFreeze when the final total must stay unchanged because Cart Discounts, Discount Codes, and Shipping Methods must also remain fixed.
POST /{projectKey}/as-associate/{associateId}/in-business-unit/key=atlas-apac/carts/{cartId} HTTP/1.1
Content-Type: application/json

{
  "version": 7,
  "actions": [
    { "action": "freezeCart", "freezeStrategy": "HardFreeze" }
  ]
}
Freezing blocks only the updates that would change the Cart's total price; a buyer can still adjust quantities that do not affect price. To prevent all edits, for example while a support agent works on the Cart, lock the Cart instead. A lock records which API Client holds it, and is released with unlockCart.
Freeze and lock solve different problems. A freeze protects the agreed price during committee review but still allows price-neutral edits. A lock prevents every change while one actor operates on the Cart. Reaching for a freeze when you need a lock (or the reverse) is a common B2B design mistake.

Reordering with Cart replication

High-frequency buyers resubmit a standing basket. Two mechanisms serve this, and they are different tools:

  • Reorder is buyer-driven and one-off. To repeat a past purchase, replicate an existing Cart or Order into a fresh, active Cart, then adjust quantities before checkout. A saved Shopping List serves the same goal from a curated template.
  • Recurring Order is scheduled and automated. For a fixed cadence, model the basket as a Recurring Order instead, which you design later in this module.

Reach for a reorder when a person decides to buy again, and for a Recurring Order when the schedule should decide.

Supporting punch-out procurement

Large buyers often shop from their own procurement portal rather than the seller's storefront, a pattern called punch-out. The buyer's system connects to the seller's catalog, the buyer assembles a basket, and the order returns to the buyer's system for internal approval before it is sent to the seller. commercetools does not ship a punch-out connector, but you can support a Level 1 punch-out flow by combining features you have already met:
  • Product Selections expose only the buyer's contracted catalog and negotiated prices through their Store, so the punch-out session shows the right assortment.
  • as-associate Carts assemble the basket in the buyer's Business Unit context, carrying the Store and distribution Channel so prices resolve correctly.
  • Approval Flows enforce the buyer's internal spending thresholds before an order is committed.

The integration work sits in the middleware that bridges the buyer's procurement protocol to these resources; the platform supplies the scoped catalog, the contextual Cart, and the governance a punch-out workflow needs.

Direct Order or Quote: the decision point

A filled B2B Cart leads to one of two paths, and choosing between them is the architectural decision this module turns on:

  • Direct Order: the buyer is entitled to a price they accept as-is, so the Cart becomes an Order directly. This fits self-service reordering.
  • Quote: the basket needs negotiation, such as volume pricing or custom terms, before it becomes an Order. A supported Cart becomes a Quote Request. This fits large or bespoke purchases.
These paths have one platform constraint that shapes the design: a Quote Request cannot be created from a Cart with shippingMode: Multiple. It also cannot be created from an anonymous Cart or a Cart with Discount Codes, and the source Cart must have a shippingAddress. If a buyer needs both negotiated terms and delivery to several sites, design separate single-shipping Quote Requests per destination, or negotiate the terms first and then use Direct Orders for the multi-site purchasing pattern.
The rest of this module follows the Quote lifecycle in detail, then returns to automated reordering with Recurring Orders.

Worked example: choosing the right Atlas Cart path

Atlas Corporate's APAC division has two related purchasing needs: one order must ship to several sites, and another large basket needs negotiation. Keep those paths separate:

  1. For a multi-site Direct Order, create the Cart with context. POST to the as-associate / in-business-unit/key=atlas-apac Carts endpoint, in AUD, against the atlas-apac-store, setting purchaseOrderNumber to the buyer's PO. Each Line Item carries the atlas-apac-pricing distribution Channel so prices resolve to Atlas's negotiated rates.
  2. Distribute the shipment for the Direct Order. Set shippingMode: Multiple, register the four hotel addresses in itemShippingAddresses, and allocate each Line Item's quantity across them with shippingDetails. Confirm taxedPrice now appears, proving every quantity is allocated.
  3. Freeze for the committee. Apply freezeCart with HardFreeze so neither the catalog price nor any discount or shipping cost can move while the committee reviews the agreed total. When the committee approves, create the Order from this Cart.
  4. For negotiated terms, create a supported Quote Request Cart. Use a separate Cart with shippingMode: Single, a shippingAddress, and no Discount Codes. Keep the Business Unit context, purchase order number, Store, and distribution Channel, then create the Quote Request from that Cart.

This design uses multi-shipping where the platform supports it, and uses the Quote flow only from a Cart shape that Quote Requests support.

Key takeaways

  • A B2B Cart is created through the as-associate and in-business-unit path; the Business Unit comes from the URL, and Line Item distributionChannel resolves the buyer's negotiated Price.
  • Use the native purchaseOrderNumber for PO tracking; it propagates from Cart to the Order or Quote Request created from it. Reserve Custom Fields for context with no native field.
  • For B2B data with no native field, use a Custom Field for data that belongs to a resource and a Custom Object for standalone data referenced from elsewhere.
  • shippingMode: Multiple ships one Cart to many itemShippingAddresses; unallocated quantities suppress taxedPrice.
  • SoftFreeze locks prices; HardFreeze also locks discounts and shipping. A freeze allows price-neutral edits, while a lock blocks all edits.
  • Reorder a past purchase by replicating a Cart or Order; use a Recurring Order for a fixed, scheduled cadence instead.
  • Most B2B orders settle by invoice on account against net terms; the purchaseOrderNumber links the Order to the buyer's procurement record.
  • Support punch-out procurement by combining Product Selections, as-associate Carts, and Approval Flows through middleware, not a built-in connector.
  • A filled Cart becomes either a Direct Order (price accepted) or, when the Cart uses a supported single-shipping shape, a Quote Request (price negotiated).

Test your knowledge