Multi-Product Purchase
Scope
A multi-product marketplace cart holds several items from one source merchant — one cart, one checkout, one merchant order. Buyers can discover products across many merchants (marketplace search spans the operator’s whole merchant set), but a single cart is scoped to one source merchant, which remains the seller of record.
The API sequence is the shared Firmly cart flow — identical to Agentic Commerce → Multi-Product Purchase. This page covers only the marketplace-specific framing; follow the Agentic page for the full cart-mutation, shipping, and race-condition detail.
What’s different from single-product
Two things change from Single Product:
- Iterative discovery — the buyer adds several items (all from the same source merchant) before checking out.
- Cart Review — a step between discovery and checkout where the buyer adjusts quantities and removes items.
Authentication, payment, and order metadata are unchanged.
The phases
| Phase | Single-Product | Multi-Product |
|---|---|---|
| 1. Hosting | Same | Same |
| 2. Authentication | Same | Same |
| 3. Discovery | One search | Iterative — buyer adds multiple items |
| 3.5 Cart Review | — | New — buyer adjusts the cart |
| 4. Checkout | One pass | One pass |
| 5. Order placement | One merchant order | One merchant order |
Adding multiple items
Each add targets the same source merchant (the {domain} in the cart endpoint URL). Add items one after another, not in parallel — concurrent adds mutate the same cart and can race, leaving stale cart state; see the race-condition retry pattern on the Agentic page.
// callFirmly: fetch wrapper adding x-firmly-authorization; see the Quickstart// `results` = the products[] returned by POST /api/v1/discovery/search.// Each result carries an opaque add_to_cart_ref — carry it straight through// rather than hand-building variant_ids.const adds = [{ ref: results[0].add_to_cart_ref, quantity: 1 },{ ref: results[1].add_to_cart_ref, quantity: 1 },{ ref: results[2].add_to_cart_ref, quantity: 2 }];let cart;for (const item of adds) {cart = await callFirmly(`/api/v2/domains/${merchantDomain}/cart/line-items`,{ add_to_cart_ref: item.ref, quantity: item.quantity });}renderMarketplaceCart(cart);
Cart review, shipping, and modifications
These are the shared cart mechanics — see Agentic Commerce → Multi-Product Purchase for the cart-modification table, multi-shipment handling, and the race-condition retry pattern. The marketplace operator renders them inside its own branded cart UI.
Attribution
Marketplace operator ID flows on the order metadata exactly as in Single Product, so the source merchant’s OMS records the operator as the traffic source.
Related
- Single Product Purchase — the simpler shape
- Why Firmly — what makes Marketplace different
- Integration Patterns — operator hosting, embedded options