@spree/docs 0.1.92 → 0.1.94

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.
Files changed (46) hide show
  1. package/dist/api-reference/admin-api/authentication.md +34 -18
  2. package/dist/api-reference/admin-api/endpoints.md +348 -0
  3. package/dist/api-reference/admin-api/errors.md +2 -0
  4. package/dist/api-reference/admin-api/introduction.md +11 -0
  5. package/dist/api-reference/store.yaml +243 -232
  6. package/dist/developer/agentic/overview.md +1 -1
  7. package/dist/developer/cli/admin-api.md +146 -0
  8. package/dist/developer/cli/quickstart.md +40 -5
  9. package/dist/developer/core-concepts/addresses.md +32 -16
  10. package/dist/developer/core-concepts/adjustments.md +11 -5
  11. package/dist/developer/core-concepts/architecture.md +8 -8
  12. package/dist/developer/core-concepts/calculators.md +31 -51
  13. package/dist/developer/core-concepts/channels.md +13 -6
  14. package/dist/developer/core-concepts/customers.md +47 -23
  15. package/dist/developer/core-concepts/events.md +22 -17
  16. package/dist/developer/core-concepts/imports-exports.md +69 -14
  17. package/dist/developer/core-concepts/inventory.md +79 -1
  18. package/dist/developer/core-concepts/markets.md +64 -20
  19. package/dist/developer/core-concepts/media.md +43 -6
  20. package/dist/developer/core-concepts/metafields.md +76 -13
  21. package/dist/developer/core-concepts/orders.md +95 -17
  22. package/dist/developer/core-concepts/payments.md +14 -13
  23. package/dist/developer/core-concepts/pricing.md +95 -9
  24. package/dist/developer/core-concepts/products.md +192 -26
  25. package/dist/developer/core-concepts/promotions.md +61 -4
  26. package/dist/developer/core-concepts/reports.md +4 -2
  27. package/dist/developer/core-concepts/search-filtering.md +82 -32
  28. package/dist/developer/core-concepts/shipments.md +16 -13
  29. package/dist/developer/core-concepts/slugs.md +20 -11
  30. package/dist/developer/core-concepts/staff-roles.md +51 -1
  31. package/dist/developer/core-concepts/store-credits-gift-cards.md +90 -9
  32. package/dist/developer/core-concepts/stores.md +16 -14
  33. package/dist/developer/core-concepts/taxes.md +28 -0
  34. package/dist/developer/core-concepts/translations.md +16 -7
  35. package/dist/developer/core-concepts/users.md +13 -9
  36. package/dist/developer/core-concepts/webhooks.md +95 -64
  37. package/dist/developer/how-to/custom-api-authentication.md +103 -23
  38. package/dist/developer/multi-store/quickstart.md +1 -1
  39. package/dist/developer/sdk/admin/authentication.md +1 -1
  40. package/dist/developer/sdk/admin/resources.md +2 -0
  41. package/dist/developer/upgrades/5.3-to-5.4.md +1 -1
  42. package/dist/developer/upgrades/5.4-to-5.5.md +1 -1
  43. package/dist/integrations/integrations.md +0 -7
  44. package/package.json +1 -1
  45. package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +0 -57
  46. 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`, `spree upgrade`) that agents can drive end-to-end.
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, and upgrade Docker-based Spree Commerce projects from the command line.
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`) manages Docker-based Spree projects created with [create-spree-app](../create-spree-app/quickstart.md).
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 # Store API key
173
- spree api-key create --name "Admin" --type secret # Admin API key
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.markAsDefault('addr_xxx', 'shipping')
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/customer/addresses' \
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/customer/addresses' \
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/customer/addresses/addr_xxx' \
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/customer/addresses/addr_xxx' \
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', { include: 'states' })
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', { include: 'market' })
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', { include: 'states' })
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 line items or fulfillments:
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 // total of all adjustments
90
- order.promo_total // total promotional discounts
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, both under API v3:
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 use [prefixed IDs](../../api-reference/introduction.md) (e.g., `prod_86Rf07xd4z`, `or_m3Rp9wXz`), flat JSON request/response structures, and full TypeScript types via the [@spree/sdk](../sdk/quickstart.md).
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 model/controller behavior (use sparingly) | [Decorators Guide](../customization/decorators.md) |
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 and Admin API |
167
-
168
- > **INFO:** For headless commerce, you only need the `spree` package. Build your customer-facing frontend with any technology (Next.js, Nuxt, mobile apps) using the Store API and SDK.
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::Core::CalculatedAdjustment` module described below to provide an easy way to calculate adjustments for their objects.
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.currency = "USD"
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 computes a value for every item within an order. This is useful for providing a discount for a specific product, without it affecting others.
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 to calculate.
135
+ * `amount`: The flat amount charged per item.
136
136
  * `currency`: The currency for this calculator.
137
137
 
138
- This calculator depends on its `calculable` responding to a `promotion` method, which should return a `Spree::Promotion` or similar object. This object should then return a list of rules, which should respond to a `products` method. This is used to return a result of matching products.
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
- = (2 x 5) + (1 x 5)
154
- = 10 + 5
141
+ [amount] x [total item quantity in package]
155
142
  ```
156
143
 
157
- meaning the calculator will compute an amount of 15.
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 works in a near-identical fashion to the [Per Item Calculator](#per-item), with the exception that rather than providing a flat-rate per item, it is a percentage.
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
- Assuming a calculator amount of 10% and an order such as this:
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
- * Product A: $15.00 x 2 within matching products
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
- The calculator will calculate a discount of $4.
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::Core::CalculatedAdjustments` module into a model of your choosing.
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::Core::CalculatedAdjustments
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
- This module provides a `has_one` association to a `calculator` object, as well as some convenience helpers for creating and updating adjustments for objects. Assuming that an object has a calculator associated with it first, creating an adjustment is simple:
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.create_adjustment("#{plan.name}", <target object>, <calculable object>)
295
+ plan.compute(<calculable object>)
309
296
  ```
310
297
 
311
- To update this adjustment:
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
- ```ruby
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
- `create_adjustment`, `update_adjustment` and `compute_amount` will call `compute` on the `Calculator` object. This `calculable` amount is whatever object your `CustomCalculator` class supports.
302
+ - [Adjustments](adjustments.md) the records calculators compute amounts for.
303
+ - [Dependencies](../customization/dependencies.md) — swap out calculators via the Dependencies system.