Overview
A cart is everything that happens before a purchase is final: adding items, entering an address, choosing delivery, and paying. Completing a cart creates an Order — a separate, permanent record. The two are kept apart because they want opposite things. A cart changes constantly, tolerates half-finished states, and is often abandoned. An order is a financial record: it must not change quietly, and it has to keep saying what the customer actually agreed to pay.Cart attributes
Every amount comes in two forms:
total is the raw value ("135.60") and display_total is formatted for the currency ("$135.60"). Render the display_ one.
Money is sent as a string, not a number. JavaScript numbers can’t represent every decimal exactly —
0.1 + 0.2 gives 0.30000000000000004 — which is not something you want inside a price. Let Spree do the arithmetic and render the formatted strings.Creating a cart and adding items
Checkout requirements
A cart tells you what it still needs before it can be completed:Response
code — message is translated prose
meant for a person, and step is only a grouping hint.
This is what lets you design your own checkout. Spree tells you what’s missing; you decide how and when to ask for it — one long page, a few steps, or whatever suits your storefront.
Seven checks run on every cart read:
Checkout steps
A cart also reports a step list, so you can render a progress indicator:current_step is simply the step of the first unmet requirement.
Five steps are built in, and three only appear when they apply:
So a free digital order reports
address then complete. A storefront that hardcodes
five steps will show two that never apply.
Requirements use one grouping name that is not a step:
cart. Missing line
items, the order minimum and stock problems are filed under it, and there is no
cart entry in the step list — current_step reports those as address. If you
group requirements by step to place them on screens, give cart a home.current_step and requirements do not appear on it.
To add your own step or requirement, see
Customizing checkout.
Checkout
1
Add the customer's details
Store SDK
2
Choose delivery
Each fulfillment offers delivery rates. Pick one per fulfillment.
Store SDK
3
Take payment
For providers like Stripe, create a payment session and confirm it with their own SDK.
Store SDK
4
Complete the cart
Store SDK
What completion guarantees
Completing a cart moves real money, so Spree is careful about it: Double submission is safe. A customer double-clicking “Place order” gets the same order back rather than a second charge. This holds even when your app runs on several servers. An interrupted completion recovers. If something dies after the customer was charged, trying again finishes the job instead of charging twice. Totals are worked out at the last moment. The amount charged is calculated when the cart is completed, not taken from an earlier request — so a price or promotion that changed while the customer was reviewing can’t lead to the wrong charge. If a cart can’t be completed you get told why — a payment failure, or unmet requirements — and the cart is left alone so the customer can fix it and try again.Abandoned carts
Carts emitcart.created, cart.updated and cart.deleted events, which also reach webhooks — enough to drive abandonment email without polling for changes.
Completed carts are kept rather than deleted, and an order records which cart it came from, so you can measure conversion. Abandoned carts are cleared out on a schedule you control; carts with a payment in progress are never removed.
Related
- Orders — the record a cart becomes
- Payments — payment methods and sessions
- Fulfillments — delivery options

