@spree/docs 0.1.6 → 0.1.8
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/store.yaml +2514 -1558
- package/dist/developer/core-concepts/orders.md +8 -8
- package/dist/developer/core-concepts/pricing.md +75 -0
- package/dist/developer/core-concepts/promotions.md +4 -4
- package/dist/developer/core-concepts/store-credits-gift-cards.md +9 -3
- package/dist/developer/sdk/quickstart.md +3 -1
- package/dist/developer/sdk/store/cart-checkout.md +15 -5
- package/dist/developer/sdk/store/products.md +19 -0
- package/dist/developer/storefront/nextjs/spree-next-package.md +8 -6
- package/package.json +1 -1
|
@@ -238,23 +238,23 @@ Apply or remove promotional coupon codes during checkout:
|
|
|
238
238
|
|
|
239
239
|
|
|
240
240
|
```typescript SDK
|
|
241
|
-
// Apply a
|
|
242
|
-
await client.carts.
|
|
241
|
+
// Apply a discount code
|
|
242
|
+
await client.carts.discountCodes.apply(cartId, 'SAVE20')
|
|
243
243
|
|
|
244
|
-
// Remove a
|
|
245
|
-
await client.carts.
|
|
244
|
+
// Remove a discount code
|
|
245
|
+
await client.carts.discountCodes.remove(cartId, 'SAVE20')
|
|
246
246
|
```
|
|
247
247
|
|
|
248
248
|
```bash cURL
|
|
249
|
-
# Apply a
|
|
250
|
-
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_xxx/
|
|
249
|
+
# Apply a discount code
|
|
250
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_xxx/discount_codes' \
|
|
251
251
|
-H 'Authorization: Bearer spree_pk_xxx' \
|
|
252
252
|
-H 'X-Spree-Token: abc123' \
|
|
253
253
|
-H 'Content-Type: application/json' \
|
|
254
254
|
-d '{ "code": "SAVE20" }'
|
|
255
255
|
|
|
256
|
-
# Remove a
|
|
257
|
-
curl -X DELETE 'https://api.mystore.com/api/v3/store/carts/cart_xxx/
|
|
256
|
+
# Remove a discount code
|
|
257
|
+
curl -X DELETE 'https://api.mystore.com/api/v3/store/carts/cart_xxx/discount_codes/SAVE20' \
|
|
258
258
|
-H 'Authorization: Bearer spree_pk_xxx' \
|
|
259
259
|
-H 'X-Spree-Token: abc123'
|
|
260
260
|
```
|
|
@@ -155,6 +155,81 @@ Price Lists are managed in the Admin Panel under **Products → Price Lists**, o
|
|
|
155
155
|
|
|
156
156
|
Each Price List contains prices for specific variants and currencies. Products can be added to a Price List, and individual variant prices set within it.
|
|
157
157
|
|
|
158
|
+
## Price History (EU Omnibus Directive)
|
|
159
|
+
|
|
160
|
+
Spree automatically records price changes for EU Omnibus Directive compliance. When a product goes on sale, EU regulations require displaying the lowest price in the preceding 30 days alongside the discounted price.
|
|
161
|
+
|
|
162
|
+
### How It Works
|
|
163
|
+
|
|
164
|
+
Every time a base price amount changes, a `PriceHistory` record is created automatically. Price list prices are not tracked — only the base price visible to all customers.
|
|
165
|
+
|
|
166
|
+
### Fetching Prior Price via API
|
|
167
|
+
|
|
168
|
+
The prior price is available as an expandable field on product and variant endpoints:
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
```typescript SDK
|
|
172
|
+
const product = await client.products.get('spree-tote', {
|
|
173
|
+
expand: ['prior_price'],
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
if (product.prior_price) {
|
|
177
|
+
console.log(product.prior_price.amount) // "9.99"
|
|
178
|
+
console.log(product.prior_price.display_amount) // "$9.99"
|
|
179
|
+
console.log(product.prior_price.currency) // "USD"
|
|
180
|
+
console.log(product.prior_price.recorded_at) // "2026-03-10T..."
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```bash cURL
|
|
185
|
+
curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=prior_price' \
|
|
186
|
+
-H 'X-Spree-API-Key: spree_pk_xxx'
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
The response includes a `prior_price` object when expanded:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"id": "prod_xxx",
|
|
195
|
+
"name": "Spree Tote",
|
|
196
|
+
"price": { "amount": "15.99", "currency": "USD", "display_amount": "$15.99" },
|
|
197
|
+
"prior_price": {
|
|
198
|
+
"amount": "9.99",
|
|
199
|
+
"amount_in_cents": 999,
|
|
200
|
+
"currency": "USD",
|
|
201
|
+
"display_amount": "$9.99",
|
|
202
|
+
"recorded_at": "2026-03-10T14:30:00Z"
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Configuration
|
|
208
|
+
|
|
209
|
+
Price history tracking is enabled by default. To disable it (e.g., for non-EU stores):
|
|
210
|
+
|
|
211
|
+
```ruby
|
|
212
|
+
# config/initializers/spree.rb
|
|
213
|
+
Spree.config do |config|
|
|
214
|
+
config.track_price_history = false
|
|
215
|
+
config.price_history_retention_days = 30 # default
|
|
216
|
+
end
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Price history retention defaults to 30 days and can be configured globally. A Rake task is provided for cleanup:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
bundle exec rake spree:price_history:prune
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Seeding Existing Prices
|
|
226
|
+
|
|
227
|
+
After enabling price history on an existing store, seed the current prices as a baseline:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
bundle exec rake spree:price_history:seed
|
|
231
|
+
```
|
|
232
|
+
|
|
158
233
|
## Related Documentation
|
|
159
234
|
|
|
160
235
|
- [Products](products.md) — Products, Variants, and base prices
|
|
@@ -278,13 +278,13 @@ Customers apply coupon codes during checkout via the Store API:
|
|
|
278
278
|
|
|
279
279
|
|
|
280
280
|
```typescript SDK
|
|
281
|
-
// Apply a
|
|
282
|
-
const cart = await client.carts.
|
|
281
|
+
// Apply a discount code to the cart
|
|
282
|
+
const cart = await client.carts.discountCodes.apply('cart_abc123', 'SUMMER20', {
|
|
283
283
|
spreeToken: '<token>',
|
|
284
284
|
})
|
|
285
285
|
|
|
286
|
-
// Remove a
|
|
287
|
-
await client.carts.
|
|
286
|
+
// Remove a discount code from the cart
|
|
287
|
+
await client.carts.discountCodes.remove('cart_abc123', 'SUMMER20', {
|
|
288
288
|
spreeToken: '<token>',
|
|
289
289
|
})
|
|
290
290
|
```
|
|
@@ -248,15 +248,21 @@ Gift cards are applied using the same coupon codes endpoint as promotion codes.
|
|
|
248
248
|
|
|
249
249
|
```typescript SDK
|
|
250
250
|
// Apply gift card code to cart (works for guests and registered customers)
|
|
251
|
-
|
|
251
|
+
// Gift cards use a dedicated endpoint — they reduce amount_due, not total
|
|
252
|
+
const cart = await client.carts.giftCards.apply('cart_abc123', 'abc1234def', {
|
|
253
|
+
spreeToken: '<token>',
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
// Remove gift card (ID from cart.gift_card.id)
|
|
257
|
+
await client.carts.giftCards.remove('cart_abc123', cart.gift_card.id, {
|
|
252
258
|
spreeToken: '<token>',
|
|
253
259
|
})
|
|
254
260
|
```
|
|
255
261
|
|
|
256
262
|
```bash cURL
|
|
257
263
|
# Apply gift card to cart (works for guests and registered customers)
|
|
258
|
-
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_abc123/
|
|
259
|
-
-H '
|
|
264
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_abc123/gift_cards' \
|
|
265
|
+
-H 'X-Spree-Api-Key: pk_xxx' \
|
|
260
266
|
-H 'X-Spree-Token: <token>' \
|
|
261
267
|
-H 'Content-Type: application/json' \
|
|
262
268
|
-d '{ "code": "abc1234def" }'
|
|
@@ -61,13 +61,15 @@ The SDK uses a resource builder pattern for nested resources:
|
|
|
61
61
|
| `carts` | `paymentMethods` | `list` |
|
|
62
62
|
| `carts` | `paymentSessions` | `create`, `get`, `update`, `complete` |
|
|
63
63
|
| `carts` | `fulfillments` | `list`, `update` |
|
|
64
|
-
| `carts` | `
|
|
64
|
+
| `carts` | `discountCodes` | `apply`, `remove` |
|
|
65
|
+
| `carts` | `giftCards` | `apply`, `remove` |
|
|
65
66
|
| `carts` | `storeCredits` | `apply`, `remove` |
|
|
66
67
|
| `customer` | `addresses` | `list`, `get`, `create`, `update`, `delete`, `markAsDefault` |
|
|
67
68
|
| `customer` | `creditCards` | `list`, `get`, `delete` |
|
|
68
69
|
| `customer` | `giftCards` | `list`, `get` |
|
|
69
70
|
| `customer` | `orders` | `list` |
|
|
70
71
|
| `customer` | `paymentSetupSessions` | `create`, `get`, `complete` |
|
|
72
|
+
| `policies` | — | `list`, `get` |
|
|
71
73
|
| `categories` | `products` | `list` |
|
|
72
74
|
| `wishlists` | `items` | `create`, `update`, `delete` |
|
|
73
75
|
|
|
@@ -55,16 +55,26 @@ await client.carts.items.update(cartId, lineItemId, {
|
|
|
55
55
|
await client.carts.items.delete(cartId, lineItemId, options);
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
###
|
|
58
|
+
### Discount Codes
|
|
59
59
|
|
|
60
60
|
```typescript
|
|
61
61
|
const options = { spreeToken: cart.token };
|
|
62
62
|
|
|
63
|
-
// Apply a
|
|
64
|
-
await client.carts.
|
|
63
|
+
// Apply a discount code
|
|
64
|
+
await client.carts.discountCodes.apply(cartId, 'SAVE20', options);
|
|
65
65
|
|
|
66
|
-
// Remove a
|
|
67
|
-
await client.carts.
|
|
66
|
+
// Remove a discount code
|
|
67
|
+
await client.carts.discountCodes.remove(cartId, 'SAVE20', options);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Gift Cards
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Apply a gift card (reduces amount_due, not total)
|
|
74
|
+
const cart = await client.carts.giftCards.apply(cartId, 'GC-ABCD-1234', options);
|
|
75
|
+
|
|
76
|
+
// Remove a gift card (ID from cart.gift_card.id)
|
|
77
|
+
await client.carts.giftCards.remove(cartId, 'gc_abc123', options);
|
|
68
78
|
```
|
|
69
79
|
|
|
70
80
|
## Checkout
|
|
@@ -84,6 +84,25 @@ const product = await client.products.get('spree-tote', {
|
|
|
84
84
|
});
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
+
### Prior Price (EU Omnibus Directive)
|
|
88
|
+
|
|
89
|
+
When a product is on sale, EU regulations require displaying the lowest price in the last 30 days. Use the `prior_price` expand to fetch this:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const product = await client.products.get('spree-tote', {
|
|
93
|
+
expand: ['prior_price'],
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (product.prior_price) {
|
|
97
|
+
console.log(product.prior_price.amount); // "9.99"
|
|
98
|
+
console.log(product.prior_price.display_amount); // "$9.99"
|
|
99
|
+
console.log(product.prior_price.currency); // "USD"
|
|
100
|
+
console.log(product.prior_price.recorded_at); // "2026-03-10T..."
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
> **INFO:** Prior price is only relevant on product detail pages (PDP), not on listings. It returns `null` if no price history exists within the 30-day window. Price history tracking can be disabled globally via `Spree::Config[:track_price_history] = false`.
|
|
105
|
+
|
|
87
106
|
### Product Filters
|
|
88
107
|
|
|
89
108
|
Get available filters (price range, availability, options, categories) and sort options for building filter UIs:
|
|
@@ -120,19 +120,21 @@ Checkout functions use the implicit cart resolved from cookies. No `orderId` is
|
|
|
120
120
|
import {
|
|
121
121
|
getCheckout,
|
|
122
122
|
updateCheckout,
|
|
123
|
-
getFulfillments,
|
|
124
123
|
selectDeliveryRate,
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
applyDiscountCode,
|
|
125
|
+
removeDiscountCode,
|
|
126
|
+
applyGiftCard,
|
|
127
|
+
removeGiftCard,
|
|
127
128
|
complete,
|
|
128
129
|
} from '@spree/next';
|
|
129
130
|
|
|
130
131
|
const checkout = await getCheckout();
|
|
131
132
|
await updateCheckout({ shipping_address: { ... }, billing_address: { ... } });
|
|
132
|
-
const fulfillments = await getFulfillments();
|
|
133
133
|
await selectDeliveryRate(fulfillmentId, deliveryRateId);
|
|
134
|
-
await
|
|
135
|
-
await
|
|
134
|
+
await applyDiscountCode('SAVE20');
|
|
135
|
+
await removeDiscountCode('SAVE20');
|
|
136
|
+
await applyGiftCard('GC-ABCD-1234');
|
|
137
|
+
await removeGiftCard('gc_abc123');
|
|
136
138
|
await complete();
|
|
137
139
|
```
|
|
138
140
|
|