@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
@@ -74,7 +74,7 @@ If no market matches the customer's country, the store's **default market** is u
74
74
  Fetch all markets for the current store, including their countries:
75
75
 
76
76
 
77
- ```typescript SDK
77
+ ```typescript Store SDK
78
78
  const { data: markets } = await client.markets.list()
79
79
  // [
80
80
  // {
@@ -94,6 +94,10 @@ const { data: markets } = await client.markets.list()
94
94
  // ]
95
95
  ```
96
96
 
97
+ ```typescript Admin SDK
98
+ const { data: markets } = await adminClient.markets.list()
99
+ ```
100
+
97
101
  ```bash cURL
98
102
  curl 'https://api.mystore.com/api/v3/store/markets' \
99
103
  -H 'X-Spree-API-Key: pk_xxx'
@@ -105,7 +109,7 @@ curl 'https://api.mystore.com/api/v3/store/markets' \
105
109
  When you know a customer's country (e.g., from geolocation or a country picker), resolve which market applies:
106
110
 
107
111
 
108
- ```typescript SDK
112
+ ```typescript Store SDK
109
113
  const market = await client.markets.resolve('DE')
110
114
  // { id: "mkt_gbHJdmfr", name: "Europe", currency: "EUR", tax_inclusive: true, ... }
111
115
  ```
@@ -125,7 +129,7 @@ This is useful for building a country switcher — resolve the market to show th
125
129
  List countries belonging to a specific market. Useful for populating address form dropdowns during checkout:
126
130
 
127
131
 
128
- ```typescript SDK
132
+ ```typescript Store SDK
129
133
  const { data: countries } = await client.markets.countries.list('mkt_k5nR8xLq')
130
134
  // [
131
135
  // { iso: "CA", name: "Canada", states_required: true, zipcode_required: true },
@@ -134,7 +138,7 @@ const { data: countries } = await client.markets.countries.list('mkt_k5nR8xLq')
134
138
 
135
139
  // Get a country with its states (for address form dropdowns)
136
140
  const usa = await client.markets.countries.get('mkt_k5nR8xLq', 'US', {
137
- include: 'states',
141
+ expand: ['states'],
138
142
  })
139
143
  ```
140
144
 
@@ -152,15 +156,21 @@ curl 'https://api.mystore.com/api/v3/store/markets/mkt_k5nR8xLq/countries/US?exp
152
156
  You can also fetch countries flat (across all markets) or include the market on a country:
153
157
 
154
158
 
155
- ```typescript SDK
159
+ ```typescript Store SDK
156
160
  // All countries across all markets
157
161
  const { data: countries } = await client.countries.list()
158
162
 
159
163
  // Get a country with its market details
160
- const germany = await client.countries.get('DE', { include: 'market' })
164
+ const germany = await client.countries.get('DE', { expand: ['market'] })
161
165
  // { iso: "DE", name: "Germany", market: { currency: "EUR", default_locale: "de", tax_inclusive: true } }
162
166
  ```
163
167
 
168
+ ```typescript Admin SDK
169
+ const { data: countries } = await adminClient.countries.list()
170
+
171
+ const germany = await adminClient.countries.get('DE')
172
+ ```
173
+
164
174
  ```bash cURL
165
175
  # All countries across all markets
166
176
  curl 'https://api.mystore.com/api/v3/store/countries' \
@@ -174,12 +184,12 @@ curl 'https://api.mystore.com/api/v3/store/countries/DE?expand=market' \
174
184
 
175
185
  ## Currency and Locale
176
186
 
177
- Each market defines a currency and set of supported locales. When a market is resolved, its currency and locale become the defaults for the session.
187
+ Each market defines a [currency and set of supported locales](../../api-reference/store-api/monetary-amounts.md). When a market is resolved, its currency and locale become the defaults for the session.
178
188
 
179
189
  You can discover all available currencies and locales (aggregated from all markets) via dedicated endpoints:
180
190
 
181
191
 
182
- ```typescript SDK
192
+ ```typescript Store SDK
183
193
  const { data: currencies } = await client.currencies.list()
184
194
  // [{ iso_code: "USD", name: "US Dollar", symbol: "$" }, { iso_code: "EUR", name: "Euro", symbol: "€" }]
185
195
 
@@ -221,31 +231,65 @@ See [Pricing — Price Rules](pricing.md#price-rules) for details on configuring
221
231
 
222
232
  Markets are managed in the admin dashboard under **Settings → Markets**. When you run `rails db:seed`, Spree automatically creates a default market for each store.
223
233
 
224
- To create markets programmatically:
234
+ To create markets programmatically, use the [Admin API](../../api-reference/admin-api/introduction.md). See the [Admin API endpoints](../../api-reference/admin-api/endpoints.md) for the full list of `/markets` routes and required scopes:
235
+
225
236
 
226
- ```ruby
227
- # North America market
228
- current_store.markets.create!(
237
+ ```typescript Admin SDK
238
+ import { createAdminClient } from '@spree/admin-sdk'
239
+
240
+ const client = createAdminClient({
241
+ baseUrl: 'https://store.example.com',
242
+ secretKey: 'sk_xxx',
243
+ })
244
+
245
+ // North America market (countries by ISO code)
246
+ const northAmerica = await client.markets.create({
229
247
  name: 'North America',
230
248
  currency: 'USD',
231
249
  default_locale: 'en',
232
- countries: [usa, canada],
233
- default: true
234
- )
250
+ country_isos: ['US', 'CA'],
251
+ default: true,
252
+ })
235
253
 
236
- # Europe market with tax-inclusive pricing
237
- current_store.markets.create!(
254
+ // Europe market with tax-inclusive pricing
255
+ const europe = await client.markets.create({
238
256
  name: 'Europe',
239
257
  currency: 'EUR',
240
258
  default_locale: 'de',
241
- supported_locales: 'de,en,fr',
259
+ supported_locales: ['de', 'en', 'fr'],
242
260
  tax_inclusive: true,
243
- countries: [germany, france, austria, netherlands]
244
- )
261
+ country_isos: ['DE', 'FR', 'AT', 'NL'],
262
+ })
245
263
  ```
246
264
 
265
+ ```bash CLI
266
+ spree api post /markets -d '{
267
+ "name": "North America",
268
+ "currency": "USD",
269
+ "default_locale": "en",
270
+ "country_isos": ["US", "CA"],
271
+ "default": true
272
+ }'
273
+ ```
274
+
275
+
276
+ Update or remove a market the same way:
277
+
278
+
279
+ ```typescript Admin SDK
280
+ await client.markets.update('market_xxx', { tax_inclusive: true })
281
+ await client.markets.delete('market_xxx')
282
+ ```
283
+
284
+ ```bash CLI
285
+ spree api patch /markets/market_xxx -d '{"tax_inclusive": true}'
286
+ spree api delete /markets/market_xxx
287
+ ```
288
+
289
+
247
290
  ## Related Documentation
248
291
 
292
+ - [Markets (Store SDK)](../sdk/store/markets.md) — Listing, resolving, and reading markets from the Store SDK
249
293
  - [Stores](stores.md) — Multi-store setup and configuration
250
294
  - [Pricing](pricing.md) — Price Lists, Price Rules, and the Pricing Context
251
295
  - [Addresses](addresses.md) — Countries, States, and Zones
@@ -54,6 +54,31 @@ curl -X POST 'https://api.mystore.com/api/v3/admin/products/prod_86Rf07xd4z/medi
54
54
  ```
55
55
 
56
56
 
57
+ #### Creating media from a remote URL
58
+
59
+ When the image already lives at a public URL, pass `url` instead of a `signed_id` — Spree fetches the remote file and stores it as product media, so you skip the direct-upload step entirely.
60
+
61
+
62
+ ```typescript Admin SDK
63
+ await client.products.media.create('prod_86Rf07xd4z', {
64
+ url: 'https://cdn.example.com/images/tote-front.jpg',
65
+ position: 1,
66
+ })
67
+ ```
68
+
69
+ ```bash cURL
70
+ curl -X POST 'https://api.mystore.com/api/v3/admin/products/prod_86Rf07xd4z/media' \
71
+ -H 'X-Spree-API-Key: sk_xxx' \
72
+ -H 'Content-Type: application/json' \
73
+ -d '{
74
+ "url": "https://cdn.example.com/images/tote-front.jpg",
75
+ "position": 1
76
+ }'
77
+ ```
78
+
79
+
80
+ > **NOTE:** The fetch runs in the background, so this request returns `202 Accepted` with no body — the media appears in the gallery once the download and processing finish. Re-fetch the product's media to know when it's ready.
81
+
57
82
  #### Sharing a single image across variants
58
83
 
59
84
  Pass a `variant_ids` array on the same media endpoint to link/unlink variants. The server replaces the asset's link set on every call — empty array clears all links, omitting the field leaves them untouched.
@@ -99,10 +124,10 @@ All variants are cropped to fill the exact dimensions and converted to WebP form
99
124
 
100
125
  ### Thumbnails (Always Available)
101
126
 
102
- Every product response includes a `thumbnail_url` field — ready to use without any expands. Similarly, each variant includes a `thumbnail` URL and a `media_count` counter.
127
+ Every product response includes a `thumbnail_url` field — ready to use without any expands. Similarly, each variant includes a `thumbnail_url` and a `media_count` counter.
103
128
 
104
129
 
105
- ```typescript SDK
130
+ ```typescript Store SDK
106
131
  // List products — thumbnail_url is always included
107
132
  const { data: products } = await client.products.list({ limit: 12 })
108
133
 
@@ -111,6 +136,10 @@ products.forEach(product => {
111
136
  })
112
137
  ```
113
138
 
139
+ ```typescript Admin SDK
140
+ const { data: products } = await adminClient.products.list({ limit: 12 })
141
+ ```
142
+
114
143
  ```bash cURL
115
144
  # thumbnail_url is always in the response — no ?expand needed
116
145
  curl 'https://api.mystore.com/api/v3/store/products?limit=12' \
@@ -122,10 +151,10 @@ curl 'https://api.mystore.com/api/v3/store/products?limit=12' \
122
151
 
123
152
  ### Full Media (On Demand)
124
153
 
125
- On the product detail page, expand `media` and `variants` to get the full set of media with all named variant URLs:
154
+ On the product detail page, [expand media and variants](../../api-reference/store-api/relations.md) to get the full set of media with all named variant URLs:
126
155
 
127
156
 
128
- ```typescript SDK
157
+ ```typescript Store SDK
129
158
  const product = await client.products.get('spree-tote', {
130
159
  expand: ['media', 'variants'],
131
160
  })
@@ -135,12 +164,18 @@ product.media // [{ id, media_type, product_id, variant_ids, original_url, mini_
135
164
 
136
165
  // Each variant has its own thumbnail and media_count
137
166
  product.variants?.forEach(variant => {
138
- variant.thumbnail // "https://cdn.../tote-red.webp" — always available
167
+ variant.thumbnail_url // "https://cdn.../tote-red.webp" — present in the response, null when the variant has no media
139
168
  variant.media_count // 3 — quick check without loading media
140
169
  variant.media // full media array (only with ?expand=media)
141
170
  })
142
171
  ```
143
172
 
173
+ ```typescript Admin SDK
174
+ const product = await adminClient.products.get('prod_86Rf07xd4z', {
175
+ expand: ['media', 'variants'],
176
+ })
177
+ ```
178
+
144
179
  ```bash cURL
145
180
  curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=media,variants' \
146
181
  -H 'X-Spree-API-Key: pk_xxx'
@@ -174,7 +209,7 @@ curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=media,vari
174
209
  | Field | Available on | Always Returned | Description |
175
210
  |-------|-------------|:---:|-------------|
176
211
  | `thumbnail_url` | Product | Yes | URL to the product's first media |
177
- | `thumbnail` | Variant | Yes | URL to the variant's first media |
212
+ | `thumbnail_url` | Variant | Yes | URL to the variant's first media |
178
213
  | `media_count` | Variant | Yes | Number of media items (counter cache) |
179
214
  | `media` | Product, Variant | No | Full media array (requires `?expand=media`) |
180
215
 
@@ -224,4 +259,6 @@ Spree supports two storage service types:
224
259
  ## Related Documentation
225
260
 
226
261
  - [Products](products.md) — Product catalog and media
262
+ - [Products & Categories](../sdk/store/products.md) — Store SDK guide for fetching products, `thumbnail_url`, and expanded media
263
+ - [Admin SDK](../sdk/admin/resources.md) — Admin SDK resource methods, including the nested `products.media` create/update calls
227
264
  - [Deployment — Assets](../deployment/assets.md) — Storage and CDN configuration
@@ -3,9 +3,12 @@ title: Metafields
3
3
  description: Add custom structured data to products, orders, and other resources with type-safe metafields
4
4
  ---
5
5
 
6
+ import { Since } from '/snippets/since.mdx';
7
+
8
+
6
9
  ## Overview
7
10
 
8
- Metafields provide a flexible, type-safe system for adding custom structured data to Spree resources. Unlike [metadata](../customization/metadata.md) which is simple JSON storage, metafields are schema-defined with strong typing, validation, and visibility controls.
11
+ Metafields provide a flexible, type-safe system for adding custom structured attributes to Spree models. Unlike [metadata](../customization/metadata.md) which is simple JSON storage, metafields are schema-defined with strong typing, validation, and visibility controls.
9
12
 
10
13
  Use metafields for:
11
14
 
@@ -14,8 +17,6 @@ Use metafields for:
14
17
  - Integration data from external systems
15
18
  - Order-specific custom attributes
16
19
 
17
- > **NOTE:** Metafields are available from Spree 5.2 onwards.
18
-
19
20
  ## Architecture
20
21
 
21
22
  ```mermaid
@@ -75,12 +76,11 @@ flowchart LR
75
76
 
76
77
  ## Visibility Control
77
78
 
78
- Metafields support three visibility levels via the `display_on` attribute:
79
+ Metafields support two visibility levels via the `display_on` attribute:
79
80
 
80
81
  | Visibility | Store API | Admin API | Use Case |
81
82
  |------------|:---------:|:---------:|----------|
82
83
  | `both` | Yes | Yes | Public product specifications |
83
- | `front_end` | Yes | No | Customer-facing data |
84
84
  | `back_end` | No | Yes | Internal notes, integration IDs |
85
85
 
86
86
  ## Supported Resources
@@ -104,10 +104,12 @@ Namespaces organize metafields into logical groups and prevent key conflicts:
104
104
 
105
105
  ## Store API
106
106
 
107
- Metafields with `display_on` set to `both` or `front_end` are included in Store API responses when you request the `custom_fields` expand:
107
+ Metafields with `display_on` set to `both` are included in Store API responses when you [request the `custom_fields` expand](../../api-reference/store-api/relations.md):
108
+
109
+ > **INFO:** Metafields in API are called Custom Fields as we plan to rename Metafields to Custom Fields completely in Spree 6.0.
108
110
 
109
111
 
110
- ```typescript SDK
112
+ ```typescript Store SDK
111
113
  const product = await client.products.get('spree-tote', {
112
114
  expand: ['custom_fields'],
113
115
  })
@@ -115,8 +117,14 @@ const product = await client.products.get('spree-tote', {
115
117
  product.custom_fields?.forEach(field => {
116
118
  console.log(field.key) // "properties.manufacturer"
117
119
  console.log(field.label) // "Manufacturer"
118
- console.log(field.value) // "Wilson"
119
- console.log(field.type) // "short_text"
120
+ console.log(field.value) // "Wilson"
121
+ console.log(field.field_type) // "short_text"
122
+ })
123
+ ```
124
+
125
+ ```typescript Admin SDK
126
+ const product = await adminClient.products.get('prod_86Rf07xd4z', {
127
+ expand: ['custom_fields'],
120
128
  })
121
129
  ```
122
130
 
@@ -137,14 +145,14 @@ curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=custom_fie
137
145
  "id": "cf_k5nR8xLq",
138
146
  "label": "Manufacturer",
139
147
  "key": "properties.manufacturer",
140
- "type": "short_text",
148
+ "field_type": "short_text",
141
149
  "value": "Wilson"
142
150
  },
143
151
  {
144
152
  "id": "cf_m3Rp9wXz",
145
153
  "label": "Material",
146
154
  "key": "properties.material",
147
- "type": "short_text",
155
+ "field_type": "short_text",
148
156
  "value": "100% Cotton"
149
157
  }
150
158
  ]
@@ -153,16 +161,70 @@ curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=custom_fie
153
161
 
154
162
  > **NOTE:** The `display_on` attribute is intentionally excluded from Store API responses for security.
155
163
 
156
- ## Admin Panel Management
164
+ ## Admin Management
157
165
 
158
166
  ### Managing Definitions
159
167
 
160
168
  Navigate to **Settings → Metafield Definitions** in the Admin Panel to create and manage metafield definitions. Select the resource type, enter namespace and key, choose the data type, and set visibility.
161
169
 
170
+ Definitions are also [managed via the Admin API](../../api-reference/admin-api/endpoints.md). `storefront_visible: true` is equivalent to `display_on: both` — it exposes the field to the Store API:
171
+
172
+
173
+ ```typescript Admin SDK
174
+ import { createAdminClient } from '@spree/admin-sdk'
175
+
176
+ const client = createAdminClient({
177
+ baseUrl: 'https://store.example.com',
178
+ secretKey: 'sk_xxx',
179
+ })
180
+
181
+ const definition = await client.customFieldDefinitions.create({
182
+ resource_type: 'Spree::Product',
183
+ namespace: 'properties',
184
+ key: 'manufacturer',
185
+ label: 'Manufacturer',
186
+ field_type: 'short_text',
187
+ storefront_visible: true,
188
+ })
189
+
190
+ await client.customFieldDefinitions.update(definition.id, { storefront_visible: false })
191
+ await client.customFieldDefinitions.delete(definition.id)
192
+ ```
193
+
194
+ ```bash CLI
195
+ spree api post /custom_field_definitions -d '{
196
+ "resource_type": "Spree::Product",
197
+ "namespace": "properties",
198
+ "key": "manufacturer",
199
+ "label": "Manufacturer",
200
+ "field_type": "short_text",
201
+ "storefront_visible": true
202
+ }'
203
+ ```
204
+
205
+
162
206
  ### Managing Values
163
207
 
164
208
  When editing a resource (e.g., a product), metafields appear in a dedicated section. The admin panel automatically builds forms for all defined metafields.
165
209
 
210
+ To set a value programmatically, use the resource's nested `customFields` accessor (parent ID first):
211
+
212
+
213
+ ```typescript Admin SDK
214
+ await client.products.customFields.create('prod_xxx', {
215
+ custom_field_definition_id: 'cfdef_xxx',
216
+ value: 'Wilson',
217
+ })
218
+ ```
219
+
220
+ ```bash CLI
221
+ spree api post /products/prod_xxx/custom_fields -d '{
222
+ "custom_field_definition_id": "cfdef_xxx",
223
+ "value": "Wilson"
224
+ }'
225
+ ```
226
+
227
+
166
228
  ## Metafields vs Metadata
167
229
 
168
230
  Spree has two permanent, complementary systems for custom data — **metadata for machines, metafields for humans**. They serve different purposes and are not interchangeable. Neither is going away.
@@ -182,10 +244,11 @@ Spree has two permanent, complementary systems for custom data — **metadata fo
182
244
 
183
245
  **Use [Metadata](../customization/metadata.md)** for external system IDs, tracking attribution, syncing with integrations, or simple write-and-forget data that only backend systems need to read.
184
246
 
185
- > **WARNING:** Product Properties are deprecated and will be removed in Spree 6.0. For new projects, always use Metafields. For existing projects, plan to migrate using the [migration guide](../upgrades/5.1-to-5.2.md#3-migrate-to-metafields-or-keep-using-properties).
247
+ > **WARNING:** Product Properties are deprecated and will be removed in Spree 6.0. For new projects, always use Metafields. For existing projects, plan to migrate using the [migration guide](../upgrades/5.1-to-5.2.md#migrate-to-metafields-or-keep-using-product-properties).
186
248
 
187
249
  ## Related Documentation
188
250
 
189
251
  - [Metadata](../customization/metadata.md) — Simple key-value metadata
190
252
  - [Products](products.md) — Product catalog
191
253
  - [Events](events.md) — Subscribe to metafield events
254
+ - [Admin SDK](../sdk/admin/resources.md) — Manage definitions and values from TypeScript
@@ -62,28 +62,27 @@ The API returns these key fields on every order:
62
62
  | Attribute | Description |
63
63
  |-----------|-------------|
64
64
  | `number` | Unique order number (e.g., `R123456789`), shown to customers |
65
- | `state` | Current checkout state (`cart`, `address`, `delivery`, `payment`, `confirm`, `complete`) |
66
65
  | `email` | Customer's email address |
67
66
  | `currency` | Order currency (e.g., `USD`) |
68
- | `item_count` | Total number of items |
67
+ | `total_quantity` | Total number of items |
69
68
  | `item_total` / `display_item_total` | Sum of line item prices |
70
69
  | `delivery_total` / `display_delivery_total` | Delivery cost |
71
70
  | `tax_total` / `display_tax_total` | Total tax |
72
- | `promo_total` / `display_promo_total` | Total discount from promotions |
71
+ | `discount_total` / `display_discount_total` | Total discount from promotions |
73
72
  | `adjustment_total` / `display_adjustment_total` | Sum of all adjustments (tax + delivery + promos) |
74
73
  | `total` / `display_total` | Final order total |
75
- | `payment_state` | Payment status (`balance_due`, `paid`, `credit_owed`, `failed`, `void`) |
74
+ | `payment_status` | Payment status (`balance_due`, `paid`, `credit_owed`, `failed`, `void`) |
76
75
  | `fulfillment_status` | Fulfillment status (`pending`, `ready`, `partial`, `shipped`, `backorder`) |
77
76
  | `completed_at` | Timestamp when the order was placed |
78
77
 
79
- The `display_*` fields return formatted strings with currency symbols (e.g., `"$15.99"`).
78
+ The [`display_*` fields return formatted strings with currency symbols](../../api-reference/store-api/monetary-amounts.md) (e.g., `"$15.99"`).
80
79
 
81
80
  ## Cart
82
81
 
83
- A cart is simply an order in the `cart` state. Guest carts are identified by a cart token; authenticated users' carts are linked to their account.
82
+ A cart is simply an order in the `cart` state. Guest carts are [identified by a cart token; authenticated users' carts are linked to their account](../../api-reference/store-api/authentication.md).
84
83
 
85
84
 
86
- ```typescript SDK
85
+ ```typescript Store SDK
87
86
  // Create a cart
88
87
  const cart = await client.carts.create()
89
88
  // cart.token => "abc123" (save this for guest checkout)
@@ -171,21 +170,21 @@ Order is placed. `completed_at` is set and fulfillment begins.
171
170
  If the order doesn't meet the requirements for the next state (e.g., missing address), the API returns an error.
172
171
 
173
172
 
174
- ```typescript SDK
173
+ ```typescript Store SDK
175
174
  // Set addresses
176
175
  await client.carts.update(cartId, {
177
176
  email: 'john@example.com',
178
- ship_address: {
179
- firstname: 'John', lastname: 'Doe',
177
+ shipping_address: {
178
+ first_name: 'John', last_name: 'Doe',
180
179
  address1: '123 Main St', city: 'Los Angeles',
181
- country_iso: 'US', state_abbr: 'CA', zipcode: '90001',
180
+ country_iso: 'US', state_abbr: 'CA', postal_code: '90001',
182
181
  phone: '555-0100',
183
182
  },
184
183
  })
185
184
 
186
185
  // Get fulfillments and select a delivery rate
187
186
  // (the Store API/SDK exposes shipments as `fulfillments`)
188
- const cart = await client.carts.get(cartId, { expand: ['fulfillments'] })
187
+ const cart = await client.carts.get(cartId)
189
188
  await client.carts.fulfillments.update(cartId, cart.fulfillments[0].id, {
190
189
  selected_delivery_rate_id: 'rate_xxx',
191
190
  })
@@ -211,10 +210,10 @@ curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
211
210
  -H 'Content-Type: application/json' \
212
211
  -d '{
213
212
  "email": "john@example.com",
214
- "ship_address": {
215
- "firstname": "John", "lastname": "Doe",
213
+ "shipping_address": {
214
+ "first_name": "John", "last_name": "Doe",
216
215
  "address1": "123 Main St", "city": "Los Angeles",
217
- "country_iso": "US", "state_abbr": "CA", "zipcode": "90001",
216
+ "country_iso": "US", "state_abbr": "CA", "postal_code": "90001",
218
217
  "phone": "555-0100"
219
218
  }
220
219
  }'
@@ -238,7 +237,7 @@ curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_xxx/complete' \
238
237
  Apply or remove promotional coupon codes during checkout:
239
238
 
240
239
 
241
- ```typescript SDK
240
+ ```typescript Store SDK
242
241
  // Apply a discount code
243
242
  await client.carts.discountCodes.apply(cartId, 'SAVE20')
244
243
 
@@ -266,7 +265,7 @@ curl -X DELETE 'https://api.mystore.com/api/v3/store/carts/cart_xxx/discount_cod
266
265
  Authenticated customers can view their past orders:
267
266
 
268
267
 
269
- ```typescript SDK
268
+ ```typescript Store SDK
270
269
  // List past orders
271
270
  const { data: orders } = await client.customer.orders.list()
272
271
 
@@ -276,6 +275,10 @@ const order = await client.orders.get('or_xxx', {
276
275
  })
277
276
  ```
278
277
 
278
+ ```typescript Admin SDK
279
+ const order = await adminClient.orders.get('or_xxx')
280
+ ```
281
+
279
282
  ```bash cURL
280
283
  # List past orders
281
284
  curl 'https://api.mystore.com/api/v3/store/customer/orders' \
@@ -287,6 +290,80 @@ curl 'https://api.mystore.com/api/v3/store/orders/or_xxx?expand=items,fulfillmen
287
290
  ```
288
291
 
289
292
 
293
+ ## Managing Orders
294
+
295
+ Everything above is the **Store API** — the customer's own cart and orders. Back-office order management (listing every order, creating phone/manual orders, capturing payments, cancelling) uses the [Admin API](../../api-reference/admin-api/introduction.md).
296
+
297
+ ### Listing and creating orders
298
+
299
+ List orders with [Ransack filters and pagination](../../api-reference/admin-api/querying.md) (`state_eq`, `limit`, sorting). A draft order is created in one call; pass line items as `items` (each `{ variant_id, quantity }`):
300
+
301
+
302
+ ```typescript Admin SDK
303
+ import { createAdminClient } from '@spree/admin-sdk'
304
+
305
+ const client = createAdminClient({
306
+ baseUrl: 'https://store.example.com',
307
+ secretKey: 'sk_xxx',
308
+ })
309
+
310
+ // List orders (Ransack filters)
311
+ const { data: orders } = await client.orders.list({ state_eq: 'complete', limit: 25 })
312
+
313
+ // Create a draft order on a customer's behalf
314
+ const order = await client.orders.create({
315
+ email: 'buyer@example.com',
316
+ items: [{ variant_id: 'variant_xxx', quantity: 2 }],
317
+ currency: 'USD',
318
+ })
319
+ ```
320
+
321
+ ```bash CLI
322
+ spree api get /orders -q state_eq=complete --limit 25
323
+ spree api post /orders -d '{
324
+ "email": "buyer@example.com",
325
+ "items": [{ "variant_id": "variant_xxx", "quantity": 2 }]
326
+ }'
327
+ ```
328
+
329
+
330
+ ### Order state actions
331
+
332
+ Orders move through their [state machine](#checkout-flow) via dedicated actions rather than raw `state` writes:
333
+
334
+
335
+ ```typescript Admin SDK
336
+ await client.orders.complete('or_xxx') // finalize a draft
337
+ await client.orders.cancel('or_xxx', { reason: 'customer' })
338
+ await client.orders.approve('or_xxx')
339
+ await client.orders.resume('or_xxx')
340
+ await client.orders.resendConfirmation('or_xxx')
341
+ ```
342
+
343
+ ```bash CLI
344
+ spree api patch /orders/or_xxx/complete
345
+ spree api patch /orders/or_xxx/cancel -d '{"reason": "customer"}'
346
+ spree api patch /orders/or_xxx/approve
347
+ ```
348
+
349
+
350
+ ### Payments and refunds
351
+
352
+ Capture or void an authorized payment, and issue refunds, through the nested order resources:
353
+
354
+
355
+ ```typescript Admin SDK
356
+ await client.orders.payments.capture('or_xxx', 'pay_xxx')
357
+ await client.orders.payments.void('or_xxx', 'pay_xxx')
358
+ await client.orders.refunds.create('or_xxx', { payment_id: 'pay_xxx', amount: 19.99 })
359
+ ```
360
+
361
+ ```bash CLI
362
+ spree api patch /orders/or_xxx/payments/pay_xxx/capture
363
+ spree api post /orders/or_xxx/refunds -d '{"payment_id": "pay_xxx", "amount": 19.99}'
364
+ ```
365
+
366
+
290
367
  ## Line Items
291
368
 
292
369
  Line items represent individual products in an order. Each line item links to a [Variant](products.md#variants) and tracks the quantity and price at the time of purchase.
@@ -323,6 +400,7 @@ For more details, see [Shipments](shipments.md) and [Payments](payments.md).
323
400
 
324
401
  ## Related Documentation
325
402
 
403
+ - [Cart, Checkout & Orders](../sdk/store/cart-checkout.md) — Store SDK guide for carts, checkout, coupon codes, and order history
326
404
  - [Payments](payments.md) — Payment processing and payment sessions
327
405
  - [Shipments](shipments.md) — Fulfillment and shipping rates
328
406
  - [Addresses](addresses.md) — Billing and shipping addresses