@spree/docs 0.1.0
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/README.md +54 -0
- package/dist/api-reference/platform/authentication.md +38 -0
- package/dist/api-reference/store-api/authentication.md +188 -0
- package/dist/api-reference/store-api/errors.md +277 -0
- package/dist/api-reference/store-api/idempotency.md +129 -0
- package/dist/api-reference/store-api/introduction.md +34 -0
- package/dist/api-reference/store-api/localization.md +279 -0
- package/dist/api-reference/store-api/metadata.md +160 -0
- package/dist/api-reference/store-api/monetary-amounts.md +65 -0
- package/dist/api-reference/store-api/querying.md +399 -0
- package/dist/api-reference/store-api/rate-limitting.md +103 -0
- package/dist/api-reference/store-api/relations.md +185 -0
- package/dist/api-reference/storefront/authentication.md +88 -0
- package/dist/api-reference/tutorials/adyen-integration-guide-for-android.md +165 -0
- package/dist/api-reference/tutorials/adyen-integration-guide-for-ios.md +194 -0
- package/dist/api-reference/tutorials/quick-checkout-with-stripe.md +248 -0
- package/dist/api-reference/v2/fetching-multiple-resources.md +26 -0
- package/dist/api-reference/v2/filtering-and-sorting.md +53 -0
- package/dist/api-reference/v2/introduction.md +22 -0
- package/dist/api-reference/v2/pagination.md +37 -0
- package/dist/api-reference/webhooks-events.md +883 -0
- package/dist/developer/admin/admin.md +205 -0
- package/dist/developer/admin/authentication.md +59 -0
- package/dist/developer/admin/components.md +711 -0
- package/dist/developer/admin/custom-css.md +243 -0
- package/dist/developer/admin/custom-javascript.md +116 -0
- package/dist/developer/admin/extending-ui.md +1964 -0
- package/dist/developer/admin/form-builder.md +444 -0
- package/dist/developer/admin/helper-methods.md +531 -0
- package/dist/developer/admin/navigation.md +805 -0
- package/dist/developer/admin/tables.md +491 -0
- package/dist/developer/advanced/adding_spree_to_rails_app.md +106 -0
- package/dist/developer/cli/quickstart.md +137 -0
- package/dist/developer/contributing/creating-an-extension.md +258 -0
- package/dist/developer/contributing/developing-spree.md +339 -0
- package/dist/developer/contributing/quickstart.md +32 -0
- package/dist/developer/contributing/updating-extensions.md +67 -0
- package/dist/developer/core-concepts/addresses.md +265 -0
- package/dist/developer/core-concepts/adjustments.md +107 -0
- package/dist/developer/core-concepts/architecture.md +177 -0
- package/dist/developer/core-concepts/calculators.md +323 -0
- package/dist/developer/core-concepts/customers.md +230 -0
- package/dist/developer/core-concepts/events.md +624 -0
- package/dist/developer/core-concepts/imports-exports.md +698 -0
- package/dist/developer/core-concepts/inventory.md +191 -0
- package/dist/developer/core-concepts/markets.md +250 -0
- package/dist/developer/core-concepts/media.md +167 -0
- package/dist/developer/core-concepts/metafields.md +187 -0
- package/dist/developer/core-concepts/orders.md +328 -0
- package/dist/developer/core-concepts/payments.md +710 -0
- package/dist/developer/core-concepts/pricing.md +163 -0
- package/dist/developer/core-concepts/products.md +360 -0
- package/dist/developer/core-concepts/promotions.md +322 -0
- package/dist/developer/core-concepts/reports.md +206 -0
- package/dist/developer/core-concepts/search-filtering.md +237 -0
- package/dist/developer/core-concepts/shipments.md +212 -0
- package/dist/developer/core-concepts/slugs.md +111 -0
- package/dist/developer/core-concepts/staff-roles.md +123 -0
- package/dist/developer/core-concepts/store-credits-gift-cards.md +317 -0
- package/dist/developer/core-concepts/stores.md +117 -0
- package/dist/developer/core-concepts/taxes.md +135 -0
- package/dist/developer/core-concepts/translations.md +120 -0
- package/dist/developer/core-concepts/users.md +299 -0
- package/dist/developer/core-concepts/webhooks.md +378 -0
- package/dist/developer/create-spree-app/quickstart.md +158 -0
- package/dist/developer/customization/api.md +93 -0
- package/dist/developer/customization/authentication.md +88 -0
- package/dist/developer/customization/checkout.md +204 -0
- package/dist/developer/customization/configuration.md +55 -0
- package/dist/developer/customization/decorators.md +523 -0
- package/dist/developer/customization/dependencies.md +232 -0
- package/dist/developer/customization/emails.md +21 -0
- package/dist/developer/customization/extensions.md +92 -0
- package/dist/developer/customization/metadata.md +236 -0
- package/dist/developer/customization/model-preferences.md +130 -0
- package/dist/developer/customization/permissions.md +265 -0
- package/dist/developer/customization/quickstart.md +229 -0
- package/dist/developer/customization/routes.md +24 -0
- package/dist/developer/customization/v4/admin-panel.md +78 -0
- package/dist/developer/customization/v4/authentication.md +210 -0
- package/dist/developer/customization/v4/checkout.md +212 -0
- package/dist/developer/customization/v4/deface.md +251 -0
- package/dist/developer/customization/v4/images.md +86 -0
- package/dist/developer/customization/v4/storefront.md +450 -0
- package/dist/developer/deployment/assets.md +87 -0
- package/dist/developer/deployment/aws.md +335 -0
- package/dist/developer/deployment/caching.md +27 -0
- package/dist/developer/deployment/cdn.md +39 -0
- package/dist/developer/deployment/database.md +155 -0
- package/dist/developer/deployment/docker.md +128 -0
- package/dist/developer/deployment/emails.md +77 -0
- package/dist/developer/deployment/environment_variables.md +111 -0
- package/dist/developer/deployment/heroku.md +51 -0
- package/dist/developer/deployment/render.md +95 -0
- package/dist/developer/getting-started/quickstart.md +82 -0
- package/dist/developer/how-to/custom-payment-method.md +374 -0
- package/dist/developer/how-to/custom-promotion.md +373 -0
- package/dist/developer/how-to/custom-report.md +387 -0
- package/dist/developer/how-to/custom-search-provider.md +230 -0
- package/dist/developer/multi-store/quickstart.md +71 -0
- package/dist/developer/multi-store/setup.md +38 -0
- package/dist/developer/multi-tenant/configuration.md +41 -0
- package/dist/developer/multi-tenant/core-concepts.md +75 -0
- package/dist/developer/multi-tenant/installation.md +96 -0
- package/dist/developer/multi-tenant/quickstart.md +20 -0
- package/dist/developer/multi-vendor/installation.md +45 -0
- package/dist/developer/multi-vendor/quickstart.md +17 -0
- package/dist/developer/sdk/admin/quickstart.md +22 -0
- package/dist/developer/sdk/authentication.md +89 -0
- package/dist/developer/sdk/configuration.md +225 -0
- package/dist/developer/sdk/quickstart.md +82 -0
- package/dist/developer/sdk/store/account.md +67 -0
- package/dist/developer/sdk/store/cart-checkout.md +140 -0
- package/dist/developer/sdk/store/markets.md +151 -0
- package/dist/developer/sdk/store/payments.md +96 -0
- package/dist/developer/sdk/store/products.md +149 -0
- package/dist/developer/sdk/store/wishlists.md +52 -0
- package/dist/developer/security/pci_compliance.md +15 -0
- package/dist/developer/security/security_policy.md +68 -0
- package/dist/developer/storefront/blocks.md +285 -0
- package/dist/developer/storefront/custom-css.md +260 -0
- package/dist/developer/storefront/custom-javascript.md +166 -0
- package/dist/developer/storefront/helper-methods.md +1288 -0
- package/dist/developer/storefront/links.md +298 -0
- package/dist/developer/storefront/nextjs/architecture.md +150 -0
- package/dist/developer/storefront/nextjs/customization.md +141 -0
- package/dist/developer/storefront/nextjs/deployment.md +180 -0
- package/dist/developer/storefront/nextjs/quickstart.md +92 -0
- package/dist/developer/storefront/nextjs/spree-next-package.md +314 -0
- package/dist/developer/storefront/pages.md +163 -0
- package/dist/developer/storefront/sections.md +569 -0
- package/dist/developer/storefront/storefront.md +56 -0
- package/dist/developer/storefront/themes.md +161 -0
- package/dist/developer/tutorial/admin.md +134 -0
- package/dist/developer/tutorial/extending-models.md +380 -0
- package/dist/developer/tutorial/file-uploads.md +121 -0
- package/dist/developer/tutorial/introduction.md +33 -0
- package/dist/developer/tutorial/model.md +41 -0
- package/dist/developer/tutorial/page-builder.md +487 -0
- package/dist/developer/tutorial/rich-text.md +73 -0
- package/dist/developer/tutorial/seo.md +332 -0
- package/dist/developer/tutorial/storefront.md +352 -0
- package/dist/developer/tutorial/testing.md +558 -0
- package/dist/developer/upgrades/2.0-to-2.1.md +46 -0
- package/dist/developer/upgrades/2.1-to-2.2.md +59 -0
- package/dist/developer/upgrades/2.2-to-2.3.md +44 -0
- package/dist/developer/upgrades/2.3-to-2.4.md +42 -0
- package/dist/developer/upgrades/3.0-to-3.1.md +47 -0
- package/dist/developer/upgrades/3.1-to-3.2.md +34 -0
- package/dist/developer/upgrades/3.2-to-3.3.md +70 -0
- package/dist/developer/upgrades/3.3-to-3.4.md +36 -0
- package/dist/developer/upgrades/3.4-to-3.5.md +44 -0
- package/dist/developer/upgrades/3.5-to-3.6.md +40 -0
- package/dist/developer/upgrades/3.6-to-3.7.md +62 -0
- package/dist/developer/upgrades/3.7-to-4.0.md +152 -0
- package/dist/developer/upgrades/4.0-to-4.1.md +92 -0
- package/dist/developer/upgrades/4.1-to-4.2.md +109 -0
- package/dist/developer/upgrades/4.10-to-5.0.md +129 -0
- package/dist/developer/upgrades/4.2-to-4.3.md +100 -0
- package/dist/developer/upgrades/4.3-to-4.4.md +125 -0
- package/dist/developer/upgrades/4.4-to-4.5.md +94 -0
- package/dist/developer/upgrades/4.5-to-4.6.md +119 -0
- package/dist/developer/upgrades/4.6-to-4.7.md +39 -0
- package/dist/developer/upgrades/4.8-to-4.9.md +24 -0
- package/dist/developer/upgrades/4.9-to-4.10.md +24 -0
- package/dist/developer/upgrades/4.x-to-4.8.md +52 -0
- package/dist/developer/upgrades/5.0-to-5.1.md +28 -0
- package/dist/developer/upgrades/5.1-to-5.2.md +127 -0
- package/dist/developer/upgrades/5.2-to-5.3.md +338 -0
- package/dist/developer/upgrades/5.3-to-5.4.md +248 -0
- package/dist/developer/upgrades/quickstart.md +36 -0
- package/dist/integrations/analytics/google-analytics.md +64 -0
- package/dist/integrations/analytics/google-tag-manager.md +78 -0
- package/dist/integrations/integrations.md +39 -0
- package/dist/integrations/marketing/klaviyo.md +99 -0
- package/dist/integrations/payments/adyen.md +90 -0
- package/dist/integrations/payments/paypal.md +41 -0
- package/dist/integrations/payments/razorpay.md +45 -0
- package/dist/integrations/payments/stripe.md +109 -0
- package/dist/integrations/search/meilisearch.md +236 -0
- package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +57 -0
- package/dist/integrations/sso-mfa-social-login/storefront.md +56 -0
- package/package.json +27 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Search & Filtering
|
|
3
|
+
description: "Search, filter, and sort products and other resources via the Store API"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Spree provides powerful search, filtering, and sorting capabilities for products and other resources. The Store API supports:
|
|
9
|
+
|
|
10
|
+
- Full-text search across product names, descriptions, and SKUs
|
|
11
|
+
- Attribute-based filtering (price range, availability, stock status)
|
|
12
|
+
- Category and taxon filtering
|
|
13
|
+
- Faceted search with filter counts
|
|
14
|
+
- Flexible sorting options
|
|
15
|
+
|
|
16
|
+
## Product Search
|
|
17
|
+
|
|
18
|
+
Use the `search` parameter for full-text search across product fields:
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
```typescript SDK
|
|
22
|
+
const { data: products } = await client.products.list({
|
|
23
|
+
search: 'tote bag',
|
|
24
|
+
limit: 12,
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```bash cURL
|
|
29
|
+
curl 'https://api.mystore.com/api/v3/store/products?q[search]=tote+bag&limit=12' \
|
|
30
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Filtering Products
|
|
35
|
+
|
|
36
|
+
### By Price Range
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
```typescript SDK
|
|
40
|
+
const { data: products } = await client.products.list({
|
|
41
|
+
price_gte: 20,
|
|
42
|
+
price_lte: 100,
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```bash cURL
|
|
47
|
+
curl 'https://api.mystore.com/api/v3/store/products?q[price_gte]=20&q[price_lte]=100' \
|
|
48
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
### By Availability
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
```typescript SDK
|
|
56
|
+
const { data: products } = await client.products.list({
|
|
57
|
+
in_stock: true,
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```bash cURL
|
|
62
|
+
curl 'https://api.mystore.com/api/v3/store/products?q[in_stock]=true' \
|
|
63
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### By Category
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
```typescript SDK
|
|
71
|
+
// Products in a specific category
|
|
72
|
+
const { data: products } = await client.categories.products.list('clothing/shirts', {
|
|
73
|
+
limit: 12,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// Or filter by category ID
|
|
77
|
+
const { data: products } = await client.products.list({
|
|
78
|
+
categories_id_eq: 'ctg_xxx',
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```bash cURL
|
|
83
|
+
# Products in a category
|
|
84
|
+
curl 'https://api.mystore.com/api/v3/store/categories/clothing/shirts/products?limit=12' \
|
|
85
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
86
|
+
|
|
87
|
+
# Filter by category ID
|
|
88
|
+
curl 'https://api.mystore.com/api/v3/store/products?q[categories_id_eq]=ctg_xxx' \
|
|
89
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
### By Tags
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
```typescript SDK
|
|
97
|
+
const { data: products } = await client.products.list({
|
|
98
|
+
tags_cont: 'sale',
|
|
99
|
+
})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```bash cURL
|
|
103
|
+
curl 'https://api.mystore.com/api/v3/store/products?q[tags_cont]=sale' \
|
|
104
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
## Sorting
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
```typescript SDK
|
|
112
|
+
// Sort by price (low to high)
|
|
113
|
+
const sorted = await client.products.list({
|
|
114
|
+
sort: 'price_low_to_high',
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// Available sort options:
|
|
118
|
+
// price_low_to_high, price_high_to_low, newest, name_a_z, name_z_a
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```bash cURL
|
|
122
|
+
curl 'https://api.mystore.com/api/v3/store/products?sort=price_low_to_high' \
|
|
123
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## Product Filters (Faceted Search)
|
|
128
|
+
|
|
129
|
+
Get available filter options for building a faceted search UI. Returns option values, price ranges, and categories with counts:
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
```typescript SDK
|
|
133
|
+
const filters = await client.products.filters()
|
|
134
|
+
// {
|
|
135
|
+
// option_types: [{ name: "size", option_values: [{ name: "Small", count: 12 }, ...] }],
|
|
136
|
+
// price_range: { min: 9.99, max: 199.99 },
|
|
137
|
+
// categories: [{ id: "ctg_xxx", name: "Clothing", count: 45 }],
|
|
138
|
+
// }
|
|
139
|
+
|
|
140
|
+
// Scoped to a specific category
|
|
141
|
+
const categoryFilters = await client.products.filters({
|
|
142
|
+
category_id: 'ctg_xxx',
|
|
143
|
+
})
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```bash cURL
|
|
147
|
+
# All filters
|
|
148
|
+
curl 'https://api.mystore.com/api/v3/store/products/filters' \
|
|
149
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
150
|
+
|
|
151
|
+
# Scoped to a category
|
|
152
|
+
curl 'https://api.mystore.com/api/v3/store/products/filters?category_id=ctg_xxx' \
|
|
153
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
## Filtering Other Resources
|
|
158
|
+
|
|
159
|
+
The Store API uses query parameters prefixed with `q[]` for filtering any resource collection. Common filter predicates:
|
|
160
|
+
|
|
161
|
+
### Equality Predicates
|
|
162
|
+
|
|
163
|
+
| Predicate | Description | Example |
|
|
164
|
+
|-----------|-------------|---------|
|
|
165
|
+
| `eq` | Equals | `q[status_eq]=active` |
|
|
166
|
+
| `not_eq` | Not equals | `q[status_not_eq]=archived` |
|
|
167
|
+
| `in` | In array | `q[id_in][]=1&q[id_in][]=2` |
|
|
168
|
+
|
|
169
|
+
### String Predicates
|
|
170
|
+
|
|
171
|
+
| Predicate | Description | Example |
|
|
172
|
+
|-----------|-------------|---------|
|
|
173
|
+
| `cont` | Contains | `q[name_cont]=shirt` |
|
|
174
|
+
| `start` | Starts with | `q[name_start]=spree` |
|
|
175
|
+
| `end` | Ends with | `q[email_end]=@example.com` |
|
|
176
|
+
| `i_cont` | Case-insensitive contains | `q[name_i_cont]=SHIRT` |
|
|
177
|
+
|
|
178
|
+
### Comparison Predicates
|
|
179
|
+
|
|
180
|
+
| Predicate | Description | Example |
|
|
181
|
+
|-----------|-------------|---------|
|
|
182
|
+
| `gt` | Greater than | `q[price_gt]=50` |
|
|
183
|
+
| `gteq` | Greater than or equal | `q[quantity_gteq]=10` |
|
|
184
|
+
| `lt` | Less than | `q[price_lt]=100` |
|
|
185
|
+
| `lteq` | Less than or equal | `q[created_at_lteq]=2025-12-31` |
|
|
186
|
+
|
|
187
|
+
### NULL Predicates
|
|
188
|
+
|
|
189
|
+
| Predicate | Description | Example |
|
|
190
|
+
|-----------|-------------|---------|
|
|
191
|
+
| `null` | Is NULL | `q[deleted_at_null]=true` |
|
|
192
|
+
| `not_null` | Is not NULL | `q[published_at_not_null]=true` |
|
|
193
|
+
| `present` | Is not NULL and not empty | `q[image_present]=true` |
|
|
194
|
+
|
|
195
|
+
> **INFO:** Only attributes explicitly allowed by each resource can be used for filtering. Attempting to filter on unsupported fields will be silently ignored.
|
|
196
|
+
|
|
197
|
+
## Pagination
|
|
198
|
+
|
|
199
|
+
All list endpoints support pagination:
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
```typescript SDK
|
|
203
|
+
const { data: products, meta } = await client.products.list({
|
|
204
|
+
page: 1,
|
|
205
|
+
limit: 24,
|
|
206
|
+
})
|
|
207
|
+
// meta.total_count => 150
|
|
208
|
+
// meta.total_pages => 7
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
```bash cURL
|
|
212
|
+
curl 'https://api.mystore.com/api/v3/store/products?page=1&limit=24' \
|
|
213
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
See [Querying](/api-reference/store-api/querying) for the full list of filtering, sorting, and pagination options.
|
|
218
|
+
|
|
219
|
+
## Search Providers
|
|
220
|
+
|
|
221
|
+
Spree uses a pluggable search provider architecture. The default provider uses SQL (ILIKE + Ransack). For production catalogs with 1,000+ products, we recommend switching to [Meilisearch](/integrations/search/meilisearch) for typo tolerance, relevance ranking, and faster faceted search.
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
# config/initializers/spree.rb
|
|
225
|
+
Spree.search_provider = 'Spree::SearchProvider::Meilisearch'
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
No client-side or API changes are needed — the same `q[search]`, filter params, and sort options work with any provider.
|
|
229
|
+
|
|
230
|
+
See [Build a Custom Search Provider](/developer/how-to/custom-search-provider) for architecture details and how to build custom providers.
|
|
231
|
+
|
|
232
|
+
## Related Documentation
|
|
233
|
+
|
|
234
|
+
- [Products](/developer/core-concepts/products) — Product catalog and listing
|
|
235
|
+
- [Querying](/api-reference/store-api/querying) — API filtering, sorting, and pagination reference
|
|
236
|
+
- [Build a Custom Search Provider](/developer/how-to/custom-search-provider) — Step-by-step guide
|
|
237
|
+
- [Meilisearch Integration](/integrations/search/meilisearch) — Setup guide
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shipments
|
|
3
|
+
description: Shipping methods, rates, split shipments, and fulfillment
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
A shipment represents a package being sent to a customer from a [Stock Location](/developer/core-concepts/inventory#stock-locations). Each order can have one or more shipments — Spree automatically splits orders into multiple shipments when items need to ship from different locations or require different shipping methods.
|
|
9
|
+
|
|
10
|
+
```mermaid
|
|
11
|
+
erDiagram
|
|
12
|
+
Order ||--o{ Shipment : "has many"
|
|
13
|
+
Shipment ||--o{ ShippingRate : "has many"
|
|
14
|
+
Shipment ||--o{ InventoryUnit : "has many"
|
|
15
|
+
Shipment }o--|| StockLocation : "ships from"
|
|
16
|
+
Shipment }o--|| ShippingMethod : "selected method"
|
|
17
|
+
ShippingMethod ||--o{ ShippingRate : "has many"
|
|
18
|
+
ShippingMethod }o--o{ Zone : "serves"
|
|
19
|
+
ShippingMethod }o--o{ ShippingCategory : "handles"
|
|
20
|
+
ShippingMethod }o--o{ Store : "available in"
|
|
21
|
+
Product }o--|| ShippingCategory : "belongs to"
|
|
22
|
+
|
|
23
|
+
Shipment {
|
|
24
|
+
string number
|
|
25
|
+
string tracking
|
|
26
|
+
string state
|
|
27
|
+
decimal cost
|
|
28
|
+
datetime shipped_at
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
ShippingMethod {
|
|
32
|
+
string name
|
|
33
|
+
string tracking_url
|
|
34
|
+
integer position
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
ShippingRate {
|
|
38
|
+
decimal cost
|
|
39
|
+
boolean selected
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Key relationships:**
|
|
44
|
+
- **Shipment** tracks delivery of items from a [Stock Location](/developer/core-concepts/inventory#stock-locations)
|
|
45
|
+
- **Shipping Method** defines the carrier/service (UPS, FedEx, etc.)
|
|
46
|
+
- **Shipping Rate** represents the calculated cost for a method
|
|
47
|
+
- **[Zone](/developer/core-concepts/addresses#zones)** defines geographic regions for shipping availability
|
|
48
|
+
- **Shipping Category** groups products with similar shipping requirements
|
|
49
|
+
|
|
50
|
+
## Shipment Attributes
|
|
51
|
+
|
|
52
|
+
| Attribute | Description | Example |
|
|
53
|
+
|-----------|-------------|---------|
|
|
54
|
+
| `number` | Unique shipment identifier | `H12345678901` |
|
|
55
|
+
| `tracking` | Carrier tracking number | `1Z999AA10123456784` |
|
|
56
|
+
| `state` | Current shipment state | `shipped` |
|
|
57
|
+
| `cost` | Shipping cost | `9.99` |
|
|
58
|
+
| `shipped_at` | When the shipment was shipped | `2025-07-21T14:36:00Z` |
|
|
59
|
+
| `stock_location` | Where items ship from | `Warehouse NYC` |
|
|
60
|
+
| `selected_shipping_rate` | The rate chosen by the customer | `{ cost: 9.99, name: "UPS Ground" }` |
|
|
61
|
+
|
|
62
|
+
## Shipment States
|
|
63
|
+
|
|
64
|
+
**Step 1: pending**
|
|
65
|
+
|
|
66
|
+
The shipment has backordered inventory or the order is not yet paid.
|
|
67
|
+
|
|
68
|
+
**Step 2: ready**
|
|
69
|
+
|
|
70
|
+
All items are in stock and the order is paid. Ready to ship.
|
|
71
|
+
|
|
72
|
+
**Step 3: shipped**
|
|
73
|
+
|
|
74
|
+
The shipment is on its way to the customer.
|
|
75
|
+
|
|
76
|
+
**Step 4: canceled**
|
|
77
|
+
|
|
78
|
+
The shipment was canceled. All items are restocked.
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## Selecting Shipping Rates
|
|
82
|
+
|
|
83
|
+
During checkout, after the customer provides a shipping address, Spree calculates available shipping rates for each shipment. The customer must select a rate before proceeding.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
```typescript SDK
|
|
87
|
+
// Get shipments with available shipping rates
|
|
88
|
+
const order = await client.orders.get(orderId, {
|
|
89
|
+
expand: ['shipments'],
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
// Each shipment has available shipping rates
|
|
93
|
+
order.shipments?.forEach(shipment => {
|
|
94
|
+
console.log(shipment.number) // "H12345678901"
|
|
95
|
+
console.log(shipment.shipping_rates) // [{ id: "sr_xxx", name: "UPS Ground", cost: "9.99", selected: true }, ...]
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// Select a shipping rate
|
|
99
|
+
await client.carts.shipments.update(cartId, shipment.id, {
|
|
100
|
+
selected_shipping_rate_id: 'sr_xxx',
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```bash cURL
|
|
105
|
+
# Get shipments
|
|
106
|
+
curl 'https://api.mystore.com/api/v3/store/carts/cart_xxx?expand=shipments' \
|
|
107
|
+
-H 'Authorization: Bearer spree_pk_xxx' \
|
|
108
|
+
-H 'X-Spree-Token: abc123'
|
|
109
|
+
|
|
110
|
+
# Select a shipping rate
|
|
111
|
+
curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx/shipments/shp_xxx' \
|
|
112
|
+
-H 'Authorization: Bearer spree_pk_xxx' \
|
|
113
|
+
-H 'X-Spree-Token: abc123' \
|
|
114
|
+
-H 'Content-Type: application/json' \
|
|
115
|
+
-d '{ "selected_shipping_rate_id": "sr_xxx" }'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
## Shipping Methods
|
|
120
|
+
|
|
121
|
+
Shipping methods represent the carrier services available to customers (e.g., UPS Ground, FedEx Overnight, DHL International). Each shipping method is scoped to:
|
|
122
|
+
|
|
123
|
+
- **[Zones](/developer/core-concepts/addresses#zones)** — geographic regions where the method is available
|
|
124
|
+
- **Shipping Categories** — product groups the method handles
|
|
125
|
+
- **[Stores](/developer/core-concepts/stores)** — which stores offer this method
|
|
126
|
+
|
|
127
|
+
Only methods whose zone matches the customer's shipping address are offered at checkout.
|
|
128
|
+
|
|
129
|
+
### Shipping Categories
|
|
130
|
+
|
|
131
|
+
Shipping categories group products with similar shipping requirements. For example:
|
|
132
|
+
|
|
133
|
+
- **Light** — lightweight items like stickers
|
|
134
|
+
- **Regular** — standard products
|
|
135
|
+
- **Heavy** — items over a certain weight
|
|
136
|
+
- **Oversized** — large items requiring special handling
|
|
137
|
+
|
|
138
|
+
Each product is assigned a shipping category. Shipping methods can be restricted to handle only certain categories, and the shipping cost calculator uses the category to determine pricing.
|
|
139
|
+
|
|
140
|
+
### Calculators
|
|
141
|
+
|
|
142
|
+
Each shipping method uses a [Calculator](/developer/core-concepts/calculators) to determine the cost. Spree includes these built-in calculators:
|
|
143
|
+
|
|
144
|
+
| Calculator | Description |
|
|
145
|
+
|------------|-------------|
|
|
146
|
+
| Flat rate per order | Same cost regardless of items |
|
|
147
|
+
| Flat rate per item | Fixed cost per item |
|
|
148
|
+
| Flat percent | Percentage of the order total |
|
|
149
|
+
| Flexible rate | One rate for the first item, another for each additional |
|
|
150
|
+
| Price sack | Tiered pricing based on order total |
|
|
151
|
+
|
|
152
|
+
You can create custom calculators for more complex pricing. See the [Calculators guide](/developer/core-concepts/calculators).
|
|
153
|
+
|
|
154
|
+
## Split Shipments
|
|
155
|
+
|
|
156
|
+
When items in an order ship from different stock locations or have different shipping categories, Spree automatically splits the order into multiple shipments.
|
|
157
|
+
|
|
158
|
+
```mermaid
|
|
159
|
+
flowchart TB
|
|
160
|
+
A[Order with 3 items] --> B{Stock check}
|
|
161
|
+
B --> C["Item A & B: NYC Warehouse"]
|
|
162
|
+
B --> D["Item C: LA Warehouse"]
|
|
163
|
+
C --> E["Shipment 1: UPS Ground"]
|
|
164
|
+
D --> F["Shipment 2: FedEx 2Day"]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### How Splitting Works
|
|
168
|
+
|
|
169
|
+
1. When an order reaches the delivery step, Spree evaluates where each item is in stock
|
|
170
|
+
2. Items are grouped by stock location and shipping category
|
|
171
|
+
3. Each group becomes a separate shipment with its own shipping rates
|
|
172
|
+
4. The customer selects a shipping rate for each shipment independently
|
|
173
|
+
|
|
174
|
+
### Weight Splitting
|
|
175
|
+
|
|
176
|
+
By default, Spree also splits shipments when a package exceeds a weight threshold (default: 150 units). This prevents individual packages from being too heavy.
|
|
177
|
+
|
|
178
|
+
> **INFO:** Split shipment behavior is customizable. See the [Customization Quickstart](/developer/customization/quickstart) for details on creating custom splitting rules.
|
|
179
|
+
|
|
180
|
+
## Examples
|
|
181
|
+
|
|
182
|
+
### Simple Setup
|
|
183
|
+
|
|
184
|
+
A store selling T-shirts to the US and Europe with 2 carriers:
|
|
185
|
+
|
|
186
|
+
| Method | Zone | Pricing |
|
|
187
|
+
|--------|------|---------|
|
|
188
|
+
| USPS Ground | US | $5 first item + $2 each additional |
|
|
189
|
+
| FedEx | EU | $10 per item |
|
|
190
|
+
|
|
191
|
+
This requires:
|
|
192
|
+
- 1 shipping category (default)
|
|
193
|
+
- 1 stock location
|
|
194
|
+
- 2 shipping methods with appropriate zones and calculators
|
|
195
|
+
|
|
196
|
+
### Advanced Setup
|
|
197
|
+
|
|
198
|
+
A store shipping from 2 locations (New York, Los Angeles) with 3 carriers and 3 shipping categories:
|
|
199
|
+
|
|
200
|
+
| Category / Method | DHL | FedEx | USPS |
|
|
201
|
+
|:-|:-|:-|:-|
|
|
202
|
+
| Light | $5/item | $10 flat | $8/item |
|
|
203
|
+
| Regular | $5/item | $2/item | $8/item |
|
|
204
|
+
| Heavy | $50/item | $20 + $15/add'l | $20/item |
|
|
205
|
+
|
|
206
|
+
## Related Documentation
|
|
207
|
+
|
|
208
|
+
- [Orders](/developer/core-concepts/orders) — Checkout flow and shipping rate selection
|
|
209
|
+
- [Inventory](/developer/core-concepts/inventory) — Stock locations and inventory management
|
|
210
|
+
- [Calculators](/developer/core-concepts/calculators) — Shipping rate calculators
|
|
211
|
+
- [Addresses](/developer/core-concepts/addresses) — Shipping address and zones
|
|
212
|
+
- [Events](/developer/core-concepts/events) — Subscribe to shipment events (e.g., `shipment.shipped`)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Slugs
|
|
3
|
+
description: SEO-friendly URL identifiers for products, categories, and other resources
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Spree generates SEO-friendly URL slugs for resources like products, categories, and stores. Instead of accessing resources by ID, you can use clean, readable URLs based on resource names.
|
|
9
|
+
|
|
10
|
+
Both the Store API and Admin API accept slugs or IDs interchangeably for resource lookups.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
```typescript SDK
|
|
14
|
+
// Both work — slug or ID
|
|
15
|
+
const product = await client.products.get('spree-tote')
|
|
16
|
+
const product = await client.products.get('prod_86Rf07xd4z')
|
|
17
|
+
|
|
18
|
+
// Categories use permalink slugs
|
|
19
|
+
const category = await client.categories.get('clothing/shirts')
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```bash cURL
|
|
23
|
+
# By slug
|
|
24
|
+
curl 'https://api.mystore.com/api/v3/store/products/spree-tote' \
|
|
25
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
26
|
+
|
|
27
|
+
# By ID
|
|
28
|
+
curl 'https://api.mystore.com/api/v3/store/products/prod_86Rf07xd4z' \
|
|
29
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Slug Generation
|
|
34
|
+
|
|
35
|
+
Slugs are automatically generated from resource names:
|
|
36
|
+
|
|
37
|
+
| Input | Generated Slug |
|
|
38
|
+
|-------|---------------|
|
|
39
|
+
| `Spree T-Shirt` | `spree-t-shirt` |
|
|
40
|
+
| `Café & Restaurant` | `cafe-and-restaurant` |
|
|
41
|
+
| `Summer Collection 2025` | `summer-collection-2025` |
|
|
42
|
+
|
|
43
|
+
If a slug already exists, Spree appends the SKU or a unique identifier to ensure uniqueness.
|
|
44
|
+
|
|
45
|
+
## Models with Slugs
|
|
46
|
+
|
|
47
|
+
| Resource | Slug Column | Translatable | Hierarchical |
|
|
48
|
+
|----------|-------------|:---:|:---:|
|
|
49
|
+
| Product | `slug` | Yes | No |
|
|
50
|
+
| Category | `permalink` | Yes | Yes |
|
|
51
|
+
| Store | `code` | No | No |
|
|
52
|
+
| Post | `slug` | Yes | No |
|
|
53
|
+
|
|
54
|
+
### Category Permalinks
|
|
55
|
+
|
|
56
|
+
Category slugs include the full parent path, making them hierarchical:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
clothing → "clothing"
|
|
60
|
+
clothing/shirts → "clothing/shirts"
|
|
61
|
+
clothing/shirts/t-shirts → "clothing/shirts/t-shirts"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
When a parent category is renamed, all child permalinks update automatically.
|
|
65
|
+
|
|
66
|
+
## Slug History
|
|
67
|
+
|
|
68
|
+
When a slug changes (e.g., a product is renamed), Spree preserves the old slug. Requests using old slugs still find the resource, enabling:
|
|
69
|
+
|
|
70
|
+
- **SEO continuity** — no broken links when names change
|
|
71
|
+
- **Bookmark compatibility** — saved URLs keep working
|
|
72
|
+
- **Graceful URL migration** — old links resolve automatically
|
|
73
|
+
|
|
74
|
+
## Internationalization
|
|
75
|
+
|
|
76
|
+
Products, categories, and posts support localized slugs — a different slug per locale:
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
```typescript SDK
|
|
80
|
+
// English
|
|
81
|
+
const product = await client.products.get('red-shoes')
|
|
82
|
+
|
|
83
|
+
// French (with locale header)
|
|
84
|
+
const product = await client.products.get('chaussures-rouges', {
|
|
85
|
+
locale: 'fr',
|
|
86
|
+
})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```bash cURL
|
|
90
|
+
# English
|
|
91
|
+
curl 'https://api.mystore.com/api/v3/store/products/red-shoes' \
|
|
92
|
+
-H 'Authorization: Bearer spree_pk_xxx'
|
|
93
|
+
|
|
94
|
+
# French
|
|
95
|
+
curl 'https://api.mystore.com/api/v3/store/products/chaussures-rouges' \
|
|
96
|
+
-H 'Authorization: Bearer spree_pk_xxx' \
|
|
97
|
+
-H 'X-Spree-Locale: fr'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
Slugs are unique within the same locale but can be duplicated across different locales.
|
|
102
|
+
|
|
103
|
+
## Reserved Words
|
|
104
|
+
|
|
105
|
+
Spree prevents certain words from being used as slugs to avoid route conflicts: `new`, `edit`, `index`, `login`, `logout`, `admin`, and others.
|
|
106
|
+
|
|
107
|
+
## Related Documentation
|
|
108
|
+
|
|
109
|
+
- [Products](/developer/core-concepts/products) — Product catalog
|
|
110
|
+
- [Translations](/developer/core-concepts/translations) — Multi-language content
|
|
111
|
+
- [Querying](/api-reference/store-api/querying) — API resource lookup
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Staff & Roles
|
|
3
|
+
description: Admin users, roles, invitations, and permissions
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Admin users manage the store via the Admin Panel. They have roles that control what they can access.
|
|
9
|
+
|
|
10
|
+
```mermaid
|
|
11
|
+
erDiagram
|
|
12
|
+
AdminUser ||--o{ RoleUser : "has many"
|
|
13
|
+
RoleUser }o--|| Role : "belongs to"
|
|
14
|
+
RoleUser }o--|| Store : "scoped to"
|
|
15
|
+
AdminUser ||--o{ Invitation : "invites"
|
|
16
|
+
|
|
17
|
+
AdminUser {
|
|
18
|
+
string id
|
|
19
|
+
string email
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
RoleUser {
|
|
23
|
+
string role_id
|
|
24
|
+
string resource_type
|
|
25
|
+
string resource_id
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Role {
|
|
29
|
+
string name
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Invitation {
|
|
33
|
+
string email
|
|
34
|
+
string status
|
|
35
|
+
string token
|
|
36
|
+
datetime expires_at
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Roles
|
|
41
|
+
|
|
42
|
+
Admin users can have different roles that control their permissions:
|
|
43
|
+
|
|
44
|
+
| Role | Description |
|
|
45
|
+
|------|-------------|
|
|
46
|
+
| `admin` | Full access to all Admin Panel features |
|
|
47
|
+
|
|
48
|
+
> **INFO:** You can create custom roles with specific permissions. See the [Customize Permissions guide](/developer/customization/permissions) for details.
|
|
49
|
+
|
|
50
|
+
## Creating Admin Users
|
|
51
|
+
|
|
52
|
+
Use the Spree CLI to create admin users:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
spree user create
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The CLI will prompt you for the email and password. You can also pass them directly:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
spree user create --email admin@example.com --password secret123
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The created user gets the `admin` role on the default store.
|
|
65
|
+
|
|
66
|
+
## Inviting Admin Users
|
|
67
|
+
|
|
68
|
+
You can invite new admins through the Admin Panel or programmatically.
|
|
69
|
+
|
|
70
|
+
**Via Admin Panel:**
|
|
71
|
+
|
|
72
|
+
1. Navigate to **Settings → Users**
|
|
73
|
+
2. Click **Invite User**
|
|
74
|
+
3. Enter the email address and select a role
|
|
75
|
+
4. Click **Send Invitation**
|
|
76
|
+
|
|
77
|
+
The invitee receives an email with an invitation link. If they already have an account, they log in to accept. Otherwise, they create an account first.
|
|
78
|
+
|
|
79
|
+
```mermaid
|
|
80
|
+
flowchart TB
|
|
81
|
+
A[Admin creates invitation] --> B[Invitation email sent]
|
|
82
|
+
B --> C[Invitee clicks link]
|
|
83
|
+
C --> D{Has account?}
|
|
84
|
+
D -->|Yes| E[Log in]
|
|
85
|
+
D -->|No| F[Create account]
|
|
86
|
+
E --> G[Accept invitation]
|
|
87
|
+
F --> G
|
|
88
|
+
G --> H[Role assigned to store]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Invitation Details
|
|
92
|
+
|
|
93
|
+
| Attribute | Description |
|
|
94
|
+
|-----------|-------------|
|
|
95
|
+
| `email` | Invitee's email address |
|
|
96
|
+
| `token` | Secure token for the invitation link |
|
|
97
|
+
| `status` | `pending` or `accepted` |
|
|
98
|
+
| `expires_at` | Expiration date (default: 2 weeks) |
|
|
99
|
+
| `resource` | The store being granted access to |
|
|
100
|
+
| `role` | The role to assign upon acceptance |
|
|
101
|
+
|
|
102
|
+
### Invitation Events
|
|
103
|
+
|
|
104
|
+
The invitation system publishes [events](/developer/core-concepts/events) you can subscribe to:
|
|
105
|
+
|
|
106
|
+
| Event | Description |
|
|
107
|
+
|-------|-------------|
|
|
108
|
+
| `invitation.created` | Invitation was created (triggers email) |
|
|
109
|
+
| `invitation.accepted` | Invitation was accepted and role assigned |
|
|
110
|
+
| `invitation.resent` | Invitation was resent to the invitee |
|
|
111
|
+
|
|
112
|
+
## Permissions
|
|
113
|
+
|
|
114
|
+
Spree uses [CanCanCan](https://github.com/CanCanCommunity/cancancan) for authorization. Permissions apply to both customers (Store API access) and admins (Admin Panel access).
|
|
115
|
+
|
|
116
|
+
See the [Customize Permissions guide](/developer/customization/permissions) for details on creating custom roles and permission sets.
|
|
117
|
+
|
|
118
|
+
## Related Documentation
|
|
119
|
+
|
|
120
|
+
- [Customers](/developer/core-concepts/customers) — Customer accounts and authentication
|
|
121
|
+
- [Stores](/developer/core-concepts/stores) — Multi-store setup
|
|
122
|
+
- [Permissions](/developer/customization/permissions) — Roles and authorization
|
|
123
|
+
- [Events](/developer/core-concepts/events) — Subscribe to invitation events
|