spree api command group turns the CLI into a first-class Admin API client: generic HTTP verbs against any endpoint, schema introspection without leaving the terminal, and credentials that resolve automatically — from a local dev project to a production store profile. It works against any Spree 5.5+ instance and is designed to be driven by both humans and AI coding agents.
Credentials
Credentials resolve through four layers — first match wins:| Layer | How |
|---|---|
| Flags | --base-url / --api-key (and --profile, which selects a saved profile explicitly) |
| Environment | SPREE_API_KEY (+ SPREE_BASE_URL) — the path for CI and agents. SPREE_BASE_URL is optional: a bare key defaults to http://localhost:3000, so local dev needs only the key. Set it for a remote store. |
| Project | Inside a Spree project with the dev stack running, the CLI mints a read-only key on first use and stores it in .spree/credentials.json (gitignored) |
| Profile | ~/.config/spree/config.json, written by spree auth login |
--base-url (or SPREE_BASE_URL paired with SPREE_API_KEY) re-points a key deliberately. So against local dev:
spree api get inside your project just works:
read_all only. Writes always require an explicitly created key:
Reading data
-q takes Ransack predicates as repeatable key=value pairs; sorting, pagination, and shaping flags pass through under the Admin API conventions:
--fields trims the response to the attributes you name (comma-separated). The resource id is always returned even if you don’t list it, so you only need to name the extra fields. --expand is the companion axis — --fields selects top-level attributes, --expand pulls in related resources:
Output format
Output is JSON on stdout, and it adapts to where it goes:- In a terminal — indented and syntax-colored, for reading.
- Piped or redirected — compact, single-line, uncolored, so it stays fast and feeds cleanly into
jq(color codes would corrupt it).
--format table renders collections as a table for humans (nested objects collapse to {…}, arrays to [N]).
Writing data
Request bodies are flat JSON (no root wrapping), inline, from a file, or from stdin:Idempotency-Key, so retries are safe.
Creating products
A product is a catalog grouping; everything purchasable — SKU, price, stock, weight — lives on its variants. For a simple product with no options, ship a top-levelprices array and Spree creates the single backing variant for you:
variants array, each with its own options and prices (and optionally stock_items):
spree api schema "POST /products" for the full request body.
Discovering endpoints and schemas
The CLI bundles a snapshot of the Admin API OpenAPI spec, so discovery works offline:spree api endpoints shows the read_* / write_* scope each endpoint requires (see Authentication) — useful for deciding what to grant a new key.
Shell completion
Tab-completion suggests resource paths, Ransack predicate stems (name_cont=, status_eq=, …), and scope names — all offline from the bundled spec. Add the generated script to your shell:
spree api get /pro⇥ completes to /products, and spree api get /products -q name_⇥ offers the Ransack predicates.
Errors and exit codes
API errors print the error envelope to stderr and exit1; usage and configuration problems exit 2. A scope denial includes the exact remediation:
Using it with AI agents
Agents with shell access (Claude Code, Cursor, and similar) can drive a Spree back office throughspree api with no extra configuration: inside a project the credentials self-provision read-only, and for remote stores two environment variables (SPREE_BASE_URL, SPREE_API_KEY) are the whole contract. The endpoints/schema commands give agents request shapes on demand instead of loading the entire API surface up front, and error messages name the missing scope so agents can self-correct.
