Skip to main content

Overview

Spree is a commerce engine you drive through a REST API. It holds the catalog, works out what a customer owes, takes the money, and tracks what was delivered. You build the storefront, the mobile app, Point of Sale or an internal tool on top of it. There is no built-in storefront you have to accept, however we do provide a reference one built in Next.js. Everything a customer-facing app needs is on the Store API, and everything a back office needs is on the Admin API. Both ship as fully typed TypeScript clients.

The shape of a purchase

Four things carry a purchase from browsing to delivery. Each one has a job the others don’t:

Product

What you sell. A product has variants — the actual buyable items, each with its own price and stock.

Cart

What a customer is assembling. It changes constantly and is usually abandoned.

Order

What they committed to. A permanent financial record that must not change quietly.

Fulfillment

What actually ships. One parcel, from one location, with one tracking number.
A cart and an order are separate records, and that distinction shapes most of the API. A cart tolerates half-finished states — no address yet, no payment chosen. An order has to keep saying what the customer actually agreed to pay, so once it exists, today’s prices and promotions can’t quietly rewrite it. Completing a cart creates the order.

How the pieces relate

Three things in that diagram are worth calling out, because they’re where Spree differs from what you might expect: Money added or removed is never one mixed list. Tax, discounts and fees are three separate kinds of row. “What tax did we charge?” is a direct question with a direct answer instead of a filter over a mixed pile. See Order totals. Delivery is described by a profile, not a category. A delivery profile says how a product travels — physically shipped, or digital — and which locations and methods serve it. Stock lives per location. A variant can have a stock level at each stock location, so availability is a real question about real warehouses rather than a single number.

The two APIs

The split is about exposure, not convenience. A publishable key is safe in browser code because it can only reach what a shopper is allowed to see. A secret key never belongs in a browser. Both APIs share the same filtering, pagination and error shapes, so what you learn on one carries to the other. Both return prefixed IDs — prod_86Rf07xd4z, cart_k5nR8xLq — so an ID tells you what it points at.
Money is always a string: "135.60", never 135.60. JavaScript can’t represent every decimal exactly — 0.1 + 0.2 gives 0.30000000000000004 — which is not something you want inside a price. Every amount also comes formatted for its currency as display_total, display_price and so on. Render the display_ one.

Building on top

Spree assumes you’ll extend it, and gives you three ways in that survive an upgrade: For merchant-managed data, reach for custom fields before anything heavier — they’re queryable and editable in the dashboard without touching code.

Multi-store, multi-market, multi-seller

One Spree installation can run more than one business:
  • Stores are separate businesses — their own catalog, orders, customers and settings. Data does not cross between them.
  • Channels are the ways one store sells: a website, a mobile app, a retail till.
  • Markets are the regions a store sells into, each with its currency, locale and tax treatment.
  • Sellers let one store list goods from many vendors, for a marketplace.

What you install

Spree runs on PostgreSQL, MySQL or SQLite. Check database configuration for more details.

Where to go next

Two ways in, depending on how you prefer to learn.

Build something

Add one feature end to end — a model with its own API, a screen in the dashboard, a page on the storefront, and the tests around it. Start here if you learn by doing.

Read the reference

Every part of the platform, one page each: products and pricing, carts and orders, payments, fulfillment, promotions. Start here if you already know what you need.
Building a storefront rather than extending the backend? Go straight to the Spree Next.js Storefront.