@spree/docs 0.1.93 → 0.1.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-reference/admin-api/authentication.md +8 -7
- package/dist/api-reference/admin-api/endpoints.md +348 -0
- package/dist/api-reference/admin-api/errors.md +2 -0
- package/dist/api-reference/admin-api/introduction.md +11 -0
- package/dist/api-reference/store.yaml +243 -232
- package/dist/developer/agentic/overview.md +1 -1
- package/dist/developer/cli/admin-api.md +146 -0
- package/dist/developer/cli/quickstart.md +40 -5
- package/dist/developer/core-concepts/addresses.md +32 -16
- package/dist/developer/core-concepts/adjustments.md +11 -5
- package/dist/developer/core-concepts/architecture.md +8 -8
- package/dist/developer/core-concepts/calculators.md +31 -51
- package/dist/developer/core-concepts/channels.md +13 -6
- package/dist/developer/core-concepts/customers.md +47 -23
- package/dist/developer/core-concepts/events.md +22 -17
- package/dist/developer/core-concepts/imports-exports.md +69 -14
- package/dist/developer/core-concepts/inventory.md +79 -1
- package/dist/developer/core-concepts/markets.md +64 -20
- package/dist/developer/core-concepts/media.md +43 -6
- package/dist/developer/core-concepts/metafields.md +76 -13
- package/dist/developer/core-concepts/orders.md +95 -17
- package/dist/developer/core-concepts/payments.md +14 -13
- package/dist/developer/core-concepts/pricing.md +95 -9
- package/dist/developer/core-concepts/products.md +192 -26
- package/dist/developer/core-concepts/promotions.md +61 -4
- package/dist/developer/core-concepts/reports.md +4 -2
- package/dist/developer/core-concepts/search-filtering.md +82 -32
- package/dist/developer/core-concepts/shipments.md +16 -13
- package/dist/developer/core-concepts/slugs.md +20 -11
- package/dist/developer/core-concepts/staff-roles.md +51 -1
- package/dist/developer/core-concepts/store-credits-gift-cards.md +90 -9
- package/dist/developer/core-concepts/stores.md +16 -14
- package/dist/developer/core-concepts/taxes.md +28 -0
- package/dist/developer/core-concepts/translations.md +16 -7
- package/dist/developer/core-concepts/users.md +13 -9
- package/dist/developer/core-concepts/webhooks.md +95 -64
- package/dist/developer/getting-started/quickstart.md +20 -0
- package/dist/developer/how-to/custom-api-authentication.md +103 -23
- package/dist/developer/multi-store/quickstart.md +1 -1
- package/dist/developer/sdk/admin/authentication.md +1 -1
- package/dist/developer/sdk/admin/resources.md +2 -0
- package/dist/developer/upgrades/5.3-to-5.4.md +1 -1
- package/dist/developer/upgrades/5.4-to-5.5.md +1 -1
- package/dist/integrations/integrations.md +0 -7
- package/package.json +1 -1
- package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +0 -57
- package/dist/integrations/sso-mfa-social-login/storefront.md +0 -56
|
@@ -19,7 +19,7 @@ Spree ships first-class tooling for AI-assisted development. Whether you use Cla
|
|
|
19
19
|
- [Agent Skills](agent-skills.md) — 25 skills teaching agents Spree's conventions, customization patterns, and upgrade flows — installable into 60+ agent tools, plus a Claude Code plugin with slash commands and safety hooks.
|
|
20
20
|
- [Docs MCP Server](mcp.md) — Connect your agent to the Spree documentation MCP server to search and read the latest docs while building.
|
|
21
21
|
- [LLM-Ready Docs](llm-docs.md) — llms.txt, per-page Markdown, and the `@spree/docs` npm package for fast local reads.
|
|
22
|
-
- [Spree CLI](../cli/quickstart.md) — A predictable command surface (`spree dev`, `spree generate`, `spree migrate
|
|
22
|
+
- [Spree CLI](../cli/quickstart.md) — A predictable command surface (`spree dev`, `spree generate`, `spree migrate`) plus `spree api` — call the Admin API directly to inspect and drive the store, with zero-config credentials in local dev. Agents debug and act end-to-end.
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
## A typical agentic workflow
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Call the Admin API from the CLI"
|
|
3
|
+
sidebarTitle: "Admin API"
|
|
4
|
+
description: "Use spree api to call the Spree Admin API with generic get/post/patch/delete commands, schema introspection, and zero-config credentials — built for scripts and AI agents."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The `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.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
spree api get /products -q status_eq=active --sort -created_at --limit 10
|
|
11
|
+
spree api get /orders/ord_x8k2J9aQ --expand items,payments
|
|
12
|
+
spree api post /products -d '{"name":"Classic Tee"}'
|
|
13
|
+
spree api patch /orders/ord_x8k2J9aQ/cancel
|
|
14
|
+
spree api endpoints --resource orders
|
|
15
|
+
spree api schema "POST /orders/{id}/refunds"
|
|
16
|
+
spree api status
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Credentials
|
|
20
|
+
|
|
21
|
+
Credentials resolve through four layers — first match wins:
|
|
22
|
+
|
|
23
|
+
| Layer | How |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Flags | `--base-url` / `--api-key` (and `--profile`, which selects a saved profile explicitly) |
|
|
26
|
+
| 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. |
|
|
27
|
+
| 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) |
|
|
28
|
+
| Profile | `~/.config/spree/config.json`, written by `spree auth login` |
|
|
29
|
+
|
|
30
|
+
Host and key resolve **together** per source — a saved or minted key is never silently re-pointed at a host from a different layer. Only `--base-url` (or `SPREE_BASE_URL` paired with `SPREE_API_KEY`) re-points a key deliberately. So against local dev:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
SPREE_API_KEY=sk_xxx spree api get /products # → http://localhost:3000
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Zero configuration is needed for local development — the first `spree api get` inside your project just works:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cd my-store
|
|
40
|
+
spree api get /products
|
|
41
|
+
# No credentials found — minting a read-only API key via the dev stack...
|
|
42
|
+
# Saved to .spree/credentials.json (scopes: read_all)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Auto-minted keys carry `read_all` only. Writes always require an explicitly created key:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
spree api-key create --type secret --scopes read_orders,write_products
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For remote stores, create a secret key in the admin under **Settings → API Keys** and save it as a profile — the key is read from a prompt, never from a flag:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
spree auth login --profile prod --base-url https://store.example.com
|
|
55
|
+
spree api get /orders --profile prod -q "status_eq=complete"
|
|
56
|
+
spree auth status
|
|
57
|
+
spree auth logout --profile prod
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Reading data
|
|
61
|
+
|
|
62
|
+
`-q` takes [Ransack](../../api-reference/admin-api/querying.md) predicates as repeatable `key=value` pairs; sorting, pagination, and shaping flags pass through under the Admin API conventions:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
spree api get /products -q name_cont=shirt -q status_eq=active
|
|
66
|
+
spree api get /orders --sort -created_at --page 2 --limit 50
|
|
67
|
+
spree api get /products/prod_86Rf07xd --expand variants,variants.prices
|
|
68
|
+
spree api get /customers --fields id,email --format table
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`--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:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
spree api get /products --fields name,price # → id + name + price
|
|
75
|
+
spree api get /products --fields name --expand variants
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Output format
|
|
79
|
+
|
|
80
|
+
Output is JSON on stdout, and it adapts to where it goes:
|
|
81
|
+
|
|
82
|
+
- **In a terminal** — indented and syntax-colored, for reading.
|
|
83
|
+
- **Piped or redirected** — compact, single-line, uncolored, so it stays fast and feeds cleanly into `jq` (color codes would corrupt it).
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
spree api get /products --limit 5 | jq '.data[].name'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`--format table` renders collections as a table for humans (nested objects collapse to `{…}`, arrays to `[N]`).
|
|
90
|
+
|
|
91
|
+
## Writing data
|
|
92
|
+
|
|
93
|
+
Request bodies are flat JSON (no root wrapping), inline, from a file, or from stdin:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
spree api post /products -d '{"name":"Classic Tee","price":29.99}'
|
|
97
|
+
spree api post /orders/ord_x8k2J9aQ/refunds -d @refund.json
|
|
98
|
+
cat prices.json | spree api post /prices/bulk_upsert -d -
|
|
99
|
+
spree api delete /products/prod_86Rf07xd
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Mutations automatically carry an `Idempotency-Key`, so retries are safe.
|
|
103
|
+
|
|
104
|
+
## Discovering endpoints and schemas
|
|
105
|
+
|
|
106
|
+
The CLI bundles a snapshot of the Admin API OpenAPI spec, so discovery works offline:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
spree api endpoints --resource orders # methods, paths, required scopes
|
|
110
|
+
spree api endpoints --search "gift card"
|
|
111
|
+
spree api schema "POST /orders" # parameters + request/response schema
|
|
112
|
+
spree api status # resolved credentials + server reachability
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`spree api endpoints` shows the `read_*` / `write_*` scope each endpoint requires (see [Authentication](../../api-reference/admin-api/authentication.md)) — useful for deciding what to grant a new key.
|
|
116
|
+
|
|
117
|
+
### Shell completion
|
|
118
|
+
|
|
119
|
+
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:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# zsh — add to ~/.zshrc
|
|
123
|
+
eval "$(spree completion zsh)"
|
|
124
|
+
# bash — add to ~/.bashrc
|
|
125
|
+
eval "$(spree completion bash)"
|
|
126
|
+
# fish — add to ~/.config/fish/config.fish
|
|
127
|
+
spree completion fish | source
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Then `spree api get /pro⇥` completes to `/products`, and `spree api get /products -q name_⇥` offers the Ransack predicates.
|
|
131
|
+
|
|
132
|
+
## Errors and exit codes
|
|
133
|
+
|
|
134
|
+
API errors print the error envelope to stderr and exit `1`; usage and configuration problems exit `2`. A scope denial includes the exact remediation:
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
access_denied: API key lacks scope: write_products
|
|
138
|
+
{
|
|
139
|
+
"details": { "required_scope": "write_products" }
|
|
140
|
+
}
|
|
141
|
+
Hint: mint a key carrying this scope — spree api-key create --type secret --scopes write_products
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Using it with AI agents
|
|
145
|
+
|
|
146
|
+
Agents with shell access (Claude Code, Cursor, and similar) can drive a Spree back office through `spree 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.
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Spree CLI
|
|
3
3
|
sidebarTitle: Overview
|
|
4
|
-
description: Install and use the @spree/cli to scaffold, run, build, migrate
|
|
4
|
+
description: Install and use the @spree/cli to scaffold, run, build, and migrate Spree projects — and call the Admin API directly from the command line.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The Spree CLI (`@spree/cli`)
|
|
7
|
+
The Spree CLI (`@spree/cli`) does two things from your terminal:
|
|
8
|
+
|
|
9
|
+
1. **Manages your Spree project** — boot the Docker stack, run generators and migrations, tail logs, open a console, upgrade versions.
|
|
10
|
+
2. **Calls the Admin API** — generic `get`/`post`/`patch`/`delete` commands to read, write, and explore your store's data, with zero-config credentials in local dev. See [Admin API from the CLI](admin-api.md).
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
spree dev # boot the project
|
|
14
|
+
spree api get /orders -q status_eq=complete --limit 10 # query the Admin API
|
|
15
|
+
spree api post /products -d '{"name":"Classic Tee"}' # create a resource
|
|
16
|
+
spree api endpoints --search refund # discover endpoints, offline
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The `spree api` commands work against any Spree 5.5+ instance and are built for both humans and AI agents — see the dedicated [Admin API from the CLI](admin-api.md) guide. The rest of this page covers project management.
|
|
8
20
|
|
|
9
21
|
## Installation
|
|
10
22
|
|
|
@@ -164,16 +176,39 @@ spree user create --email admin@example.com --password secret123
|
|
|
164
176
|
|
|
165
177
|
### `spree api-key`
|
|
166
178
|
|
|
167
|
-
Manage Store and Admin API keys.
|
|
179
|
+
Manage Store and Admin API keys. Secret keys carry [scopes](../../api-reference/admin-api/authentication.md) and require at least one.
|
|
168
180
|
|
|
169
181
|
```bash
|
|
170
182
|
spree api-key list # List all keys
|
|
171
183
|
spree api-key create # Interactive
|
|
172
|
-
spree api-key create --name "Storefront" --type publishable
|
|
173
|
-
spree api-key create --name "Admin" --type secret
|
|
184
|
+
spree api-key create --name "Storefront" --type publishable # Store API key
|
|
185
|
+
spree api-key create --name "Admin" --type secret --scopes read_all # Admin API key
|
|
174
186
|
spree api-key revoke <id> # Revoke a key
|
|
175
187
|
```
|
|
176
188
|
|
|
189
|
+
### `spree api`
|
|
190
|
+
|
|
191
|
+
Call the Admin API with generic `get`/`post`/`patch`/`delete` commands — zero-config inside a project (a read-only key is minted on first use), env vars or profiles for remote stores. See [Admin API from the CLI](admin-api.md) for the full guide.
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
spree api get /products -q status_eq=active --limit 10
|
|
195
|
+
spree api post /products -d '{"name":"Classic Tee"}'
|
|
196
|
+
spree api endpoints --resource orders # endpoints + required scopes, offline
|
|
197
|
+
spree api schema "POST /orders" # request/response schema, offline
|
|
198
|
+
spree api status
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `spree auth`
|
|
202
|
+
|
|
203
|
+
Save Admin API credentials for remote stores as named profiles.
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
spree auth login --profile prod --base-url https://store.example.com
|
|
207
|
+
spree api get /orders --profile prod
|
|
208
|
+
spree auth status
|
|
209
|
+
spree auth logout --profile prod
|
|
210
|
+
```
|
|
211
|
+
|
|
177
212
|
## Dev workflow commands
|
|
178
213
|
|
|
179
214
|
These mirror the Rails commands you'd run if you were running the app directly on your host — but each is routed through `docker compose exec` against the running stack.
|
|
@@ -30,7 +30,6 @@ An address represents a shipping or billing location. Every order has a shipping
|
|
|
30
30
|
| `postal_code` | Postal code (not required for all countries) |
|
|
31
31
|
| `phone` | Phone number |
|
|
32
32
|
| `company` | Company name (optional) |
|
|
33
|
-
| `label` | User-facing label like "Home" or "Office" (optional, unique per customer) |
|
|
34
33
|
| `country_iso` | Country (ISO alpha-2 code, e.g., `US`) |
|
|
35
34
|
| `state_abbr` | State/province abbreviation (required for some countries, e.g., `CA`) |
|
|
36
35
|
|
|
@@ -41,7 +40,7 @@ Whether a state or zipcode is required depends on the country. For example, the
|
|
|
41
40
|
Customers can save multiple addresses and set a default for shipping and billing. When a customer completes checkout, the selected addresses are cloned onto the order — so editing an address later doesn't change past orders.
|
|
42
41
|
|
|
43
42
|
|
|
44
|
-
```typescript SDK
|
|
43
|
+
```typescript Store SDK
|
|
45
44
|
// List addresses
|
|
46
45
|
const { data: addresses } = await client.customer.addresses.list()
|
|
47
46
|
|
|
@@ -63,17 +62,20 @@ await client.customer.addresses.update('addr_xxx', { city: 'Brooklyn' })
|
|
|
63
62
|
// Delete an address
|
|
64
63
|
await client.customer.addresses.delete('addr_xxx')
|
|
65
64
|
|
|
66
|
-
// Set as default shipping or billing address
|
|
67
|
-
await client.customer.addresses.
|
|
65
|
+
// Set as default shipping or billing address — pass the boolean flags to create or update
|
|
66
|
+
await client.customer.addresses.update('addr_xxx', { is_default_shipping: true })
|
|
67
|
+
await client.customer.addresses.update('addr_xxx', { is_default_billing: true })
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
```bash cURL
|
|
71
71
|
# List addresses
|
|
72
|
-
curl 'https://api.mystore.com/api/v3/store/
|
|
72
|
+
curl 'https://api.mystore.com/api/v3/store/customers/me/addresses' \
|
|
73
|
+
-H 'X-Spree-API-Key: pk_xxx' \
|
|
73
74
|
-H 'Authorization: Bearer <jwt_token>'
|
|
74
75
|
|
|
75
76
|
# Create an address
|
|
76
|
-
curl -X POST 'https://api.mystore.com/api/v3/store/
|
|
77
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/customers/me/addresses' \
|
|
78
|
+
-H 'X-Spree-API-Key: pk_xxx' \
|
|
77
79
|
-H 'Authorization: Bearer <jwt_token>' \
|
|
78
80
|
-H 'Content-Type: application/json' \
|
|
79
81
|
-d '{
|
|
@@ -88,23 +90,25 @@ curl -X POST 'https://api.mystore.com/api/v3/store/customer/addresses' \
|
|
|
88
90
|
}'
|
|
89
91
|
|
|
90
92
|
# Update an address
|
|
91
|
-
curl -X PATCH 'https://api.mystore.com/api/v3/store/
|
|
93
|
+
curl -X PATCH 'https://api.mystore.com/api/v3/store/customers/me/addresses/addr_xxx' \
|
|
94
|
+
-H 'X-Spree-API-Key: pk_xxx' \
|
|
92
95
|
-H 'Authorization: Bearer <jwt_token>' \
|
|
93
96
|
-H 'Content-Type: application/json' \
|
|
94
97
|
-d '{ "city": "Brooklyn" }'
|
|
95
98
|
|
|
96
99
|
# Delete an address
|
|
97
|
-
curl -X DELETE 'https://api.mystore.com/api/v3/store/
|
|
100
|
+
curl -X DELETE 'https://api.mystore.com/api/v3/store/customers/me/addresses/addr_xxx' \
|
|
101
|
+
-H 'X-Spree-API-Key: pk_xxx' \
|
|
98
102
|
-H 'Authorization: Bearer <jwt_token>'
|
|
99
103
|
```
|
|
100
104
|
|
|
101
105
|
|
|
102
106
|
### Checkout Addresses
|
|
103
107
|
|
|
104
|
-
During checkout, you can either reference a saved address by ID or pass a new address inline:
|
|
108
|
+
During checkout, you can either reference a saved address by ID or pass a new address inline. See the [cart and checkout SDK guide](../sdk/store/cart-checkout.md) for the full flow of passing addresses during checkout:
|
|
105
109
|
|
|
106
110
|
|
|
107
|
-
```typescript SDK
|
|
111
|
+
```typescript Store SDK
|
|
108
112
|
// Use saved addresses
|
|
109
113
|
await client.carts.update(cartId, {
|
|
110
114
|
shipping_address_id: 'addr_xxx',
|
|
@@ -173,19 +177,25 @@ Each country includes metadata that drives address form behavior:
|
|
|
173
177
|
Only countries assigned to a [Market](markets.md) are available during checkout. This lets you control exactly where you sell.
|
|
174
178
|
|
|
175
179
|
|
|
176
|
-
```typescript SDK
|
|
180
|
+
```typescript Store SDK
|
|
177
181
|
// List all countries available in this store
|
|
178
182
|
const { data: countries } = await client.countries.list()
|
|
179
183
|
|
|
180
184
|
// Get a country with its states (for address form dropdowns)
|
|
181
|
-
const usa = await client.countries.get('US', {
|
|
185
|
+
const usa = await client.countries.get('US', { expand: ['states'] })
|
|
182
186
|
// usa.states => [{ name: "Alabama", abbr: "AL" }, { name: "Alaska", abbr: "AK" }, ...]
|
|
183
187
|
|
|
184
188
|
// Get a country with its market (for currency/locale resolution)
|
|
185
|
-
const germany = await client.countries.get('DE', {
|
|
189
|
+
const germany = await client.countries.get('DE', { expand: ['market'] })
|
|
186
190
|
// germany.market => { currency: "EUR", default_locale: "de", tax_inclusive: true }
|
|
187
191
|
```
|
|
188
192
|
|
|
193
|
+
```typescript Admin SDK
|
|
194
|
+
const { data: countries } = await adminClient.countries.list()
|
|
195
|
+
|
|
196
|
+
const usa = await adminClient.countries.get('US')
|
|
197
|
+
```
|
|
198
|
+
|
|
189
199
|
```bash cURL
|
|
190
200
|
# List all countries
|
|
191
201
|
curl 'https://api.mystore.com/api/v3/store/countries' \
|
|
@@ -207,11 +217,11 @@ Use the `states_required` and `zipcode_required` fields to build adaptive addres
|
|
|
207
217
|
|
|
208
218
|
States (provinces, regions) belong to a country and are used for address validation and zone matching. Countries like the US, Canada, Australia, and India have predefined states — for these countries, customers must select a state from the list rather than typing a name.
|
|
209
219
|
|
|
210
|
-
States are fetched via the country endpoint using `?expand=states
|
|
220
|
+
States are fetched via the country endpoint using [`?expand=states`](../../api-reference/store-api/relations.md):
|
|
211
221
|
|
|
212
222
|
|
|
213
|
-
```typescript SDK
|
|
214
|
-
const usa = await client.countries.get('US', {
|
|
223
|
+
```typescript Store SDK
|
|
224
|
+
const usa = await client.countries.get('US', { expand: ['states'] })
|
|
215
225
|
|
|
216
226
|
// Build a state picker from the response
|
|
217
227
|
usa.states.forEach(state => {
|
|
@@ -219,6 +229,10 @@ usa.states.forEach(state => {
|
|
|
219
229
|
})
|
|
220
230
|
```
|
|
221
231
|
|
|
232
|
+
```typescript Admin SDK
|
|
233
|
+
const usa = await adminClient.countries.get('US', { expand: ['states'] })
|
|
234
|
+
```
|
|
235
|
+
|
|
222
236
|
```bash cURL
|
|
223
237
|
curl 'https://api.mystore.com/api/v3/store/countries/US?expand=states' \
|
|
224
238
|
-H 'X-Spree-API-Key: pk_xxx'
|
|
@@ -263,3 +277,5 @@ Here's how geography flows through a typical checkout:
|
|
|
263
277
|
- [Taxes](taxes.md) — How zones and addresses affect taxation
|
|
264
278
|
- [Shipments](shipments.md) — How zones and addresses affect shipping availability
|
|
265
279
|
- [Orders](orders.md) — Order billing and shipping addresses
|
|
280
|
+
- [Account SDK guide](../sdk/store/account.md) — Managing the logged-in customer's address book with `client.customer.addresses`
|
|
281
|
+
- [Store API authentication](../../api-reference/store-api/authentication.md) — How to obtain and send the customer JWT (`Authorization: Bearer` header)
|
|
@@ -70,11 +70,11 @@ Adjustments are created by two sources:
|
|
|
70
70
|
|
|
71
71
|
## Store API
|
|
72
72
|
|
|
73
|
-
Adjustments appear in order responses when you expand
|
|
73
|
+
Adjustments appear in order responses when you [`?expand=items,fulfillments`](../../api-reference/store-api/relations.md) on the order. The response exposes the [`amount`, `adjustment_total`, and the tax totals](../../api-reference/store-api/monetary-amounts.md) as money fields:
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
```typescript SDK
|
|
77
|
-
const order = await client.orders.get('or_abc123', {
|
|
76
|
+
```typescript Store SDK
|
|
77
|
+
const order = await client.orders.get('or_abc123', { expand: ['items', 'fulfillments'] }, {
|
|
78
78
|
spreeToken: '<token>',
|
|
79
79
|
})
|
|
80
80
|
|
|
@@ -86,12 +86,17 @@ order.items?.forEach(item => {
|
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
// Order-level totals
|
|
89
|
-
order.adjustment_total
|
|
90
|
-
order.
|
|
89
|
+
order.adjustment_total // total of all adjustments
|
|
90
|
+
order.discount_total // total promotional discounts
|
|
91
|
+
order.display_discount_total // formatted promotional discounts
|
|
91
92
|
order.additional_tax_total
|
|
92
93
|
order.included_tax_total
|
|
93
94
|
```
|
|
94
95
|
|
|
96
|
+
```typescript Admin SDK
|
|
97
|
+
const order = await adminClient.orders.get('or_abc123')
|
|
98
|
+
```
|
|
99
|
+
|
|
95
100
|
```bash cURL
|
|
96
101
|
curl 'https://api.mystore.com/api/v3/store/orders/or_abc123?expand=items,fulfillments' \
|
|
97
102
|
-H 'X-Spree-API-Key: pk_xxx' \
|
|
@@ -105,3 +110,4 @@ curl 'https://api.mystore.com/api/v3/store/orders/or_abc123?expand=items,fulfill
|
|
|
105
110
|
- [Taxes](taxes.md) — Tax adjustments
|
|
106
111
|
- [Shipments](shipments.md) — Shipping adjustments
|
|
107
112
|
- [Orders](orders.md) — How adjustments affect order totals
|
|
113
|
+
- [Calculators](calculators.md) — How tax rate and promotion action amounts are computed
|
|
@@ -106,14 +106,14 @@ erDiagram
|
|
|
106
106
|
|
|
107
107
|
## APIs
|
|
108
108
|
|
|
109
|
-
Spree exposes two REST APIs
|
|
109
|
+
Spree exposes two REST APIs:
|
|
110
110
|
|
|
111
111
|
| API | Purpose | Authentication |
|
|
112
112
|
|-----|---------|----------------|
|
|
113
|
-
| [**Store API**](../../api-reference/introduction.md) | Customer-facing — cart, checkout, products, account | Publishable API key + JWT |
|
|
114
|
-
| **Admin API** | Operational — manage products, orders, customers, settings | Secret API key |
|
|
113
|
+
| [**Store API**](../../api-reference/store-api/introduction.md) | Customer-facing — cart, checkout, products, account | [Publishable API key + JWT](../../api-reference/store-api/authentication.md) |
|
|
114
|
+
| [**Admin API**](../../api-reference/admin-api/introduction.md) | Operational — manage products, orders, customers, settings | [Secret API key](../../api-reference/admin-api/authentication.md) + JWT |
|
|
115
115
|
|
|
116
|
-
Both APIs
|
|
116
|
+
Both APIs share the same list shapes, filtering, querying, and pagination, and offer fully typed TypeScript clients — [@spree/sdk](../sdk/quickstart.md) for the Store API and [@spree/admin-sdk](../sdk/admin/quickstart.md) for the Admin API.
|
|
117
117
|
|
|
118
118
|
Events from both APIs can trigger [Webhooks](webhooks.md) to notify external systems in real time.
|
|
119
119
|
|
|
@@ -138,7 +138,7 @@ Spree is designed to be customized without modifying core code. The main extensi
|
|
|
138
138
|
| **Events & Subscribers** | React to order completion, payment, shipment events | [Events Guide](events.md) |
|
|
139
139
|
| **Webhooks** | Notify external systems of changes | [Webhooks Guide](webhooks.md) |
|
|
140
140
|
| **Dependencies** | Swap out services (tax calculation, shipping estimation) | [Dependencies Guide](../customization/dependencies.md) |
|
|
141
|
-
| **Decorators** | Modify existing
|
|
141
|
+
| **Decorators** | Modify existing core models & classes behavior (use sparingly) | [Decorators Guide](../customization/decorators.md) |
|
|
142
142
|
|
|
143
143
|
> **INFO:** For most customizations, prefer **Events** and **Dependencies** over Decorators. They're easier to maintain and won't break during upgrades.
|
|
144
144
|
|
|
@@ -163,9 +163,9 @@ Spree is distributed as a set of packages:
|
|
|
163
163
|
|
|
164
164
|
| Package | Purpose |
|
|
165
165
|
|---------|---------|
|
|
166
|
-
| [`@spree/sdk`](../sdk/quickstart.md) | TypeScript SDK for Store API
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
| [`@spree/sdk`](../sdk/quickstart.md) | TypeScript SDK for the Store API |
|
|
167
|
+
| [`@spree/admin-sdk`](../sdk/admin/quickstart.md) | TypeScript SDK for the Admin API |
|
|
168
|
+
| [`@spree/cli`](../cli/quickstart.md) | Command line interface for managing local environment and using the Admin API from the terminal |
|
|
169
169
|
|
|
170
170
|
## Related Documentation
|
|
171
171
|
|
|
@@ -47,7 +47,7 @@ erDiagram
|
|
|
47
47
|
- Used by **[Tax Rates](taxes.md)** to calculate tax amounts
|
|
48
48
|
- Used by **[Shipping Methods](shipments.md)** to calculate shipping costs
|
|
49
49
|
- Used by **[Promotion Actions](promotions.md)** to calculate discounts
|
|
50
|
-
- Calculators store preferences (rates, percentages, etc.) for their calculations
|
|
50
|
+
- Calculators store [preferences (rates, percentages, etc.)](../customization/model-preferences.md) for their calculations
|
|
51
51
|
|
|
52
52
|
Spree makes extensive use of the `Spree::Calculator` model and there are several subclasses provided to deal with various types of calculations flat rate, percentage discount, sales tax, VAT, etc. All calculators extend the `Spree::Calculator` class and must provide the following methods:
|
|
53
53
|
|
|
@@ -61,7 +61,7 @@ def compute(object=nil)
|
|
|
61
61
|
end
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
Calculators link to a `calculable` object, which are typically one of `Spree::ShippingMethod`, `Spree::TaxRate`, or `Spree::Promotion::Actions::CreateAdjustment`. These three classes use the `Spree::
|
|
64
|
+
Calculators link to a `calculable` object, which are typically one of `Spree::ShippingMethod`, `Spree::TaxRate`, or `Spree::Promotion::Actions::CreateAdjustment`. These three classes use the `Spree::CalculatedAdjustments` module described below to provide an easy way to calculate adjustments for their objects.
|
|
65
65
|
|
|
66
66
|
## Available Calculators
|
|
67
67
|
|
|
@@ -95,7 +95,7 @@ This calculator has two preferences: `amount` and `currency`. These can be set l
|
|
|
95
95
|
|
|
96
96
|
```ruby
|
|
97
97
|
calculator.preferred_amount = 10
|
|
98
|
-
calculator.
|
|
98
|
+
calculator.preferred_currency = "USD"
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
The currency for this calculator is used to check to see if a shipping method is available for an order. If an order's currency does not match the shipping method's currency, then that shipping method will not be displayed on the frontend.
|
|
@@ -128,53 +128,31 @@ Thus, if you have ten items in your shopping cart, your `first_item` preference
|
|
|
128
128
|
|
|
129
129
|
### Per Item
|
|
130
130
|
|
|
131
|
-
The Per Item calculator
|
|
131
|
+
The Per Item calculator (`Spree::Calculator::Shipping::PerItem`) is a shipping calculator that charges a flat amount for every item in a shipment.
|
|
132
132
|
|
|
133
133
|
This calculator takes two preferences:
|
|
134
134
|
|
|
135
|
-
* `amount`: The amount per item
|
|
135
|
+
* `amount`: The flat amount charged per item.
|
|
136
136
|
* `currency`: The currency for this calculator.
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
The list of matching products is compared against the line items for the order being calculated. If any of the matching products are included in the order, they are eligible for this calculator. The calculation is this:
|
|
141
|
-
|
|
142
|
-
\[matching product quantity\] x \[amount\]
|
|
143
|
-
|
|
144
|
-
Every matching product within an order will add to the calculator's total. For example, assuming the calculator has an `amount` of 5 and there's an order with the following line items:
|
|
145
|
-
|
|
146
|
-
* Product A: `$15.00` x `2` within matching products
|
|
147
|
-
* Product B: `$10.00` x `1` within matching products
|
|
148
|
-
* Product C: `$20.00` x `4` excluded from matching products
|
|
149
|
-
|
|
150
|
-
The calculation would be:
|
|
138
|
+
It computes a flat rate per item by multiplying the `amount` preference by the total item quantity in the shipment package:
|
|
151
139
|
|
|
152
140
|
```text
|
|
153
|
-
|
|
154
|
-
= 10 + 5
|
|
141
|
+
[amount] x [total item quantity in package]
|
|
155
142
|
```
|
|
156
143
|
|
|
157
|
-
|
|
144
|
+
For example, with an `amount` of `5` and a package containing `3` items in total, the calculator computes an amount of `15` (`5 x 3`).
|
|
158
145
|
|
|
159
146
|
### Percent Per Item
|
|
160
147
|
|
|
161
|
-
The Percent Per Item calculator
|
|
148
|
+
The Percent Per Item calculator (`Spree::Calculator::PercentOnLineItem`) applies a percentage discount to a single line item. It takes two preferences:
|
|
162
149
|
|
|
163
|
-
|
|
150
|
+
* `percent`: The percentage to apply to the line item's amount.
|
|
151
|
+
* `apply_only_on_full_priced_items`: When enabled, skips line items that are already on sale.
|
|
164
152
|
|
|
165
|
-
|
|
166
|
-
* Product B: $10.00 x 1 within matching products
|
|
167
|
-
* Product C: $20.00 x 4 excluded from matching products
|
|
168
|
-
|
|
169
|
-
The calculation would be:
|
|
170
|
-
|
|
171
|
-
```text
|
|
172
|
-
= ($15 x 2 x 10%) + ($10 x 10%)
|
|
173
|
-
= ($30 x 10%) + ($10 x 10%)
|
|
174
|
-
= $3 + $1
|
|
175
|
-
```
|
|
153
|
+
For each line item, the calculator computes `line item amount` x `percent` / `100`, capped at the line item's amount so a promotion adjustment never pushes the total negative.
|
|
176
154
|
|
|
177
|
-
|
|
155
|
+
For example, a `$30` line item at `10%` yields a `$3` discount (`$30 x 10% = $3`).
|
|
178
156
|
|
|
179
157
|
### Price Sack
|
|
180
158
|
|
|
@@ -269,15 +247,24 @@ end
|
|
|
269
247
|
|
|
270
248
|
## Calculated Adjustments
|
|
271
249
|
|
|
272
|
-
If you wish to use Spree's calculator functionality for your own application, you can include the `Spree::
|
|
250
|
+
If you wish to use Spree's calculator functionality for your own application, you can include the `Spree::CalculatedAdjustments` module into a model of your choosing.
|
|
273
251
|
|
|
274
252
|
```ruby app/models/plan.rb
|
|
275
253
|
class Plan < ActiveRecord::Base
|
|
276
|
-
include Spree::
|
|
254
|
+
include Spree::CalculatedAdjustments
|
|
277
255
|
end
|
|
278
256
|
```
|
|
279
257
|
|
|
280
|
-
To have calculators available for this class, you will need to register them:
|
|
258
|
+
To have calculators available for this class, you will need to register them. `Spree.calculators` is a fixed-member struct (`SpreeCalculators`, defined in `spree/core/lib/spree/core/engine.rb`) that exposes only the four built-in buckets:
|
|
259
|
+
|
|
260
|
+
* `shipping_methods`
|
|
261
|
+
* `tax_rates`
|
|
262
|
+
* `promotion_actions_create_adjustments`
|
|
263
|
+
* `promotion_actions_create_item_adjustments`
|
|
264
|
+
|
|
265
|
+
`Plan.calculators` internally calls `Spree.calculators.send(:plans)` (the tableized model name), so both registration and lookup raise `NoMethodError` until you extend the struct to add a matching `plans` member. Ruby structs cannot gain members at runtime, so this means redefining the `SpreeCalculators` struct (or reassigning `Spree.calculators` to an object that responds to `plans`) before you register anything onto it.
|
|
266
|
+
|
|
267
|
+
Once the struct exposes a `plans` member you can register calculators:
|
|
281
268
|
|
|
282
269
|
**Spree 5.2+:**
|
|
283
270
|
|
|
@@ -302,22 +289,15 @@ Plan.calculators
|
|
|
302
289
|
|
|
303
290
|
Using this method, you can then display the calculators as you please. Each object for this new class will need to have a calculator associated so that adjustments can be calculated on them.
|
|
304
291
|
|
|
305
|
-
|
|
292
|
+
`Spree::CalculatedAdjustments` provides a `has_one :calculator` association (with `accepts_nested_attributes_for` and a presence validation), delegates `compute` to that calculator, exposes a `with_calculator` scope, `calculator_type` / `calculator_type=` accessors, and the `Plan.calculators` registry shown above. To work out what the calculator would compute an amount to be, call `compute` on an instance:
|
|
306
293
|
|
|
307
294
|
```ruby
|
|
308
|
-
plan.
|
|
295
|
+
plan.compute(<calculable object>)
|
|
309
296
|
```
|
|
310
297
|
|
|
311
|
-
|
|
298
|
+
The module does not define `create_adjustment`, `update_adjustment`, or `compute_amount`. If you also need to build adjustments, include `Spree::AdjustmentSource`, which adds `create_adjustment(order, adjustable, included = false)`. That method calls a `compute_amount` you define on the including model (as `Spree::TaxRate` and the `Spree::Promotion::Actions` classes do). There is no `update_adjustment` method in core.
|
|
312
299
|
|
|
313
|
-
|
|
314
|
-
plan.update_adjustment(<adjustment object>, <calculable object>)
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
To work out what the calculator would compute an amount to be:
|
|
318
|
-
|
|
319
|
-
```ruby
|
|
320
|
-
plan.compute_amount(<calculable object>)
|
|
321
|
-
```
|
|
300
|
+
## Related Documentation
|
|
322
301
|
|
|
323
|
-
|
|
302
|
+
- [Adjustments](adjustments.md) — the records calculators compute amounts for.
|
|
303
|
+
- [Dependencies](../customization/dependencies.md) — swap out calculators via the Dependencies system.
|