@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.
Files changed (183) hide show
  1. package/README.md +54 -0
  2. package/dist/api-reference/platform/authentication.md +38 -0
  3. package/dist/api-reference/store-api/authentication.md +188 -0
  4. package/dist/api-reference/store-api/errors.md +277 -0
  5. package/dist/api-reference/store-api/idempotency.md +129 -0
  6. package/dist/api-reference/store-api/introduction.md +34 -0
  7. package/dist/api-reference/store-api/localization.md +279 -0
  8. package/dist/api-reference/store-api/metadata.md +160 -0
  9. package/dist/api-reference/store-api/monetary-amounts.md +65 -0
  10. package/dist/api-reference/store-api/querying.md +399 -0
  11. package/dist/api-reference/store-api/rate-limitting.md +103 -0
  12. package/dist/api-reference/store-api/relations.md +185 -0
  13. package/dist/api-reference/storefront/authentication.md +88 -0
  14. package/dist/api-reference/tutorials/adyen-integration-guide-for-android.md +165 -0
  15. package/dist/api-reference/tutorials/adyen-integration-guide-for-ios.md +194 -0
  16. package/dist/api-reference/tutorials/quick-checkout-with-stripe.md +248 -0
  17. package/dist/api-reference/v2/fetching-multiple-resources.md +26 -0
  18. package/dist/api-reference/v2/filtering-and-sorting.md +53 -0
  19. package/dist/api-reference/v2/introduction.md +22 -0
  20. package/dist/api-reference/v2/pagination.md +37 -0
  21. package/dist/api-reference/webhooks-events.md +883 -0
  22. package/dist/developer/admin/admin.md +205 -0
  23. package/dist/developer/admin/authentication.md +59 -0
  24. package/dist/developer/admin/components.md +711 -0
  25. package/dist/developer/admin/custom-css.md +243 -0
  26. package/dist/developer/admin/custom-javascript.md +116 -0
  27. package/dist/developer/admin/extending-ui.md +1964 -0
  28. package/dist/developer/admin/form-builder.md +444 -0
  29. package/dist/developer/admin/helper-methods.md +531 -0
  30. package/dist/developer/admin/navigation.md +805 -0
  31. package/dist/developer/admin/tables.md +491 -0
  32. package/dist/developer/advanced/adding_spree_to_rails_app.md +106 -0
  33. package/dist/developer/cli/quickstart.md +137 -0
  34. package/dist/developer/contributing/creating-an-extension.md +258 -0
  35. package/dist/developer/contributing/developing-spree.md +339 -0
  36. package/dist/developer/contributing/quickstart.md +32 -0
  37. package/dist/developer/contributing/updating-extensions.md +67 -0
  38. package/dist/developer/core-concepts/addresses.md +265 -0
  39. package/dist/developer/core-concepts/adjustments.md +107 -0
  40. package/dist/developer/core-concepts/architecture.md +177 -0
  41. package/dist/developer/core-concepts/calculators.md +323 -0
  42. package/dist/developer/core-concepts/customers.md +230 -0
  43. package/dist/developer/core-concepts/events.md +624 -0
  44. package/dist/developer/core-concepts/imports-exports.md +698 -0
  45. package/dist/developer/core-concepts/inventory.md +191 -0
  46. package/dist/developer/core-concepts/markets.md +250 -0
  47. package/dist/developer/core-concepts/media.md +167 -0
  48. package/dist/developer/core-concepts/metafields.md +187 -0
  49. package/dist/developer/core-concepts/orders.md +328 -0
  50. package/dist/developer/core-concepts/payments.md +710 -0
  51. package/dist/developer/core-concepts/pricing.md +163 -0
  52. package/dist/developer/core-concepts/products.md +360 -0
  53. package/dist/developer/core-concepts/promotions.md +322 -0
  54. package/dist/developer/core-concepts/reports.md +206 -0
  55. package/dist/developer/core-concepts/search-filtering.md +237 -0
  56. package/dist/developer/core-concepts/shipments.md +212 -0
  57. package/dist/developer/core-concepts/slugs.md +111 -0
  58. package/dist/developer/core-concepts/staff-roles.md +123 -0
  59. package/dist/developer/core-concepts/store-credits-gift-cards.md +317 -0
  60. package/dist/developer/core-concepts/stores.md +117 -0
  61. package/dist/developer/core-concepts/taxes.md +135 -0
  62. package/dist/developer/core-concepts/translations.md +120 -0
  63. package/dist/developer/core-concepts/users.md +299 -0
  64. package/dist/developer/core-concepts/webhooks.md +378 -0
  65. package/dist/developer/create-spree-app/quickstart.md +158 -0
  66. package/dist/developer/customization/api.md +93 -0
  67. package/dist/developer/customization/authentication.md +88 -0
  68. package/dist/developer/customization/checkout.md +204 -0
  69. package/dist/developer/customization/configuration.md +55 -0
  70. package/dist/developer/customization/decorators.md +523 -0
  71. package/dist/developer/customization/dependencies.md +232 -0
  72. package/dist/developer/customization/emails.md +21 -0
  73. package/dist/developer/customization/extensions.md +92 -0
  74. package/dist/developer/customization/metadata.md +236 -0
  75. package/dist/developer/customization/model-preferences.md +130 -0
  76. package/dist/developer/customization/permissions.md +265 -0
  77. package/dist/developer/customization/quickstart.md +229 -0
  78. package/dist/developer/customization/routes.md +24 -0
  79. package/dist/developer/customization/v4/admin-panel.md +78 -0
  80. package/dist/developer/customization/v4/authentication.md +210 -0
  81. package/dist/developer/customization/v4/checkout.md +212 -0
  82. package/dist/developer/customization/v4/deface.md +251 -0
  83. package/dist/developer/customization/v4/images.md +86 -0
  84. package/dist/developer/customization/v4/storefront.md +450 -0
  85. package/dist/developer/deployment/assets.md +87 -0
  86. package/dist/developer/deployment/aws.md +335 -0
  87. package/dist/developer/deployment/caching.md +27 -0
  88. package/dist/developer/deployment/cdn.md +39 -0
  89. package/dist/developer/deployment/database.md +155 -0
  90. package/dist/developer/deployment/docker.md +128 -0
  91. package/dist/developer/deployment/emails.md +77 -0
  92. package/dist/developer/deployment/environment_variables.md +111 -0
  93. package/dist/developer/deployment/heroku.md +51 -0
  94. package/dist/developer/deployment/render.md +95 -0
  95. package/dist/developer/getting-started/quickstart.md +82 -0
  96. package/dist/developer/how-to/custom-payment-method.md +374 -0
  97. package/dist/developer/how-to/custom-promotion.md +373 -0
  98. package/dist/developer/how-to/custom-report.md +387 -0
  99. package/dist/developer/how-to/custom-search-provider.md +230 -0
  100. package/dist/developer/multi-store/quickstart.md +71 -0
  101. package/dist/developer/multi-store/setup.md +38 -0
  102. package/dist/developer/multi-tenant/configuration.md +41 -0
  103. package/dist/developer/multi-tenant/core-concepts.md +75 -0
  104. package/dist/developer/multi-tenant/installation.md +96 -0
  105. package/dist/developer/multi-tenant/quickstart.md +20 -0
  106. package/dist/developer/multi-vendor/installation.md +45 -0
  107. package/dist/developer/multi-vendor/quickstart.md +17 -0
  108. package/dist/developer/sdk/admin/quickstart.md +22 -0
  109. package/dist/developer/sdk/authentication.md +89 -0
  110. package/dist/developer/sdk/configuration.md +225 -0
  111. package/dist/developer/sdk/quickstart.md +82 -0
  112. package/dist/developer/sdk/store/account.md +67 -0
  113. package/dist/developer/sdk/store/cart-checkout.md +140 -0
  114. package/dist/developer/sdk/store/markets.md +151 -0
  115. package/dist/developer/sdk/store/payments.md +96 -0
  116. package/dist/developer/sdk/store/products.md +149 -0
  117. package/dist/developer/sdk/store/wishlists.md +52 -0
  118. package/dist/developer/security/pci_compliance.md +15 -0
  119. package/dist/developer/security/security_policy.md +68 -0
  120. package/dist/developer/storefront/blocks.md +285 -0
  121. package/dist/developer/storefront/custom-css.md +260 -0
  122. package/dist/developer/storefront/custom-javascript.md +166 -0
  123. package/dist/developer/storefront/helper-methods.md +1288 -0
  124. package/dist/developer/storefront/links.md +298 -0
  125. package/dist/developer/storefront/nextjs/architecture.md +150 -0
  126. package/dist/developer/storefront/nextjs/customization.md +141 -0
  127. package/dist/developer/storefront/nextjs/deployment.md +180 -0
  128. package/dist/developer/storefront/nextjs/quickstart.md +92 -0
  129. package/dist/developer/storefront/nextjs/spree-next-package.md +314 -0
  130. package/dist/developer/storefront/pages.md +163 -0
  131. package/dist/developer/storefront/sections.md +569 -0
  132. package/dist/developer/storefront/storefront.md +56 -0
  133. package/dist/developer/storefront/themes.md +161 -0
  134. package/dist/developer/tutorial/admin.md +134 -0
  135. package/dist/developer/tutorial/extending-models.md +380 -0
  136. package/dist/developer/tutorial/file-uploads.md +121 -0
  137. package/dist/developer/tutorial/introduction.md +33 -0
  138. package/dist/developer/tutorial/model.md +41 -0
  139. package/dist/developer/tutorial/page-builder.md +487 -0
  140. package/dist/developer/tutorial/rich-text.md +73 -0
  141. package/dist/developer/tutorial/seo.md +332 -0
  142. package/dist/developer/tutorial/storefront.md +352 -0
  143. package/dist/developer/tutorial/testing.md +558 -0
  144. package/dist/developer/upgrades/2.0-to-2.1.md +46 -0
  145. package/dist/developer/upgrades/2.1-to-2.2.md +59 -0
  146. package/dist/developer/upgrades/2.2-to-2.3.md +44 -0
  147. package/dist/developer/upgrades/2.3-to-2.4.md +42 -0
  148. package/dist/developer/upgrades/3.0-to-3.1.md +47 -0
  149. package/dist/developer/upgrades/3.1-to-3.2.md +34 -0
  150. package/dist/developer/upgrades/3.2-to-3.3.md +70 -0
  151. package/dist/developer/upgrades/3.3-to-3.4.md +36 -0
  152. package/dist/developer/upgrades/3.4-to-3.5.md +44 -0
  153. package/dist/developer/upgrades/3.5-to-3.6.md +40 -0
  154. package/dist/developer/upgrades/3.6-to-3.7.md +62 -0
  155. package/dist/developer/upgrades/3.7-to-4.0.md +152 -0
  156. package/dist/developer/upgrades/4.0-to-4.1.md +92 -0
  157. package/dist/developer/upgrades/4.1-to-4.2.md +109 -0
  158. package/dist/developer/upgrades/4.10-to-5.0.md +129 -0
  159. package/dist/developer/upgrades/4.2-to-4.3.md +100 -0
  160. package/dist/developer/upgrades/4.3-to-4.4.md +125 -0
  161. package/dist/developer/upgrades/4.4-to-4.5.md +94 -0
  162. package/dist/developer/upgrades/4.5-to-4.6.md +119 -0
  163. package/dist/developer/upgrades/4.6-to-4.7.md +39 -0
  164. package/dist/developer/upgrades/4.8-to-4.9.md +24 -0
  165. package/dist/developer/upgrades/4.9-to-4.10.md +24 -0
  166. package/dist/developer/upgrades/4.x-to-4.8.md +52 -0
  167. package/dist/developer/upgrades/5.0-to-5.1.md +28 -0
  168. package/dist/developer/upgrades/5.1-to-5.2.md +127 -0
  169. package/dist/developer/upgrades/5.2-to-5.3.md +338 -0
  170. package/dist/developer/upgrades/5.3-to-5.4.md +248 -0
  171. package/dist/developer/upgrades/quickstart.md +36 -0
  172. package/dist/integrations/analytics/google-analytics.md +64 -0
  173. package/dist/integrations/analytics/google-tag-manager.md +78 -0
  174. package/dist/integrations/integrations.md +39 -0
  175. package/dist/integrations/marketing/klaviyo.md +99 -0
  176. package/dist/integrations/payments/adyen.md +90 -0
  177. package/dist/integrations/payments/paypal.md +41 -0
  178. package/dist/integrations/payments/razorpay.md +45 -0
  179. package/dist/integrations/payments/stripe.md +109 -0
  180. package/dist/integrations/search/meilisearch.md +236 -0
  181. package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +57 -0
  182. package/dist/integrations/sso-mfa-social-login/storefront.md +56 -0
  183. package/package.json +27 -0
@@ -0,0 +1,163 @@
1
+ ---
2
+ title: Pricing
3
+ description: Prices, Price Lists, Price Rules, and the Pricing Context — Spree's flexible pricing engine for regional, wholesale, volume, and market-based pricing.
4
+ ---
5
+
6
+ ## Overview
7
+
8
+ Spree's pricing system supports both simple single-currency pricing and advanced multi-currency, rule-based pricing through Price Lists. Every [Variant](/developer/core-concepts/products#variants) can have multiple prices — a base price per currency, plus additional prices from Price Lists that apply conditionally based on rules like geography, customer segment, or quantity.
9
+
10
+ ## Prices
11
+
12
+ Each variant has one or more `Price` records — one per currency. The API automatically returns the correct price based on the current currency and [Market](/developer/core-concepts/markets) context.
13
+
14
+ | Attribute | Description | Example |
15
+ |-----------|-------------|---------|
16
+ | `amount` | Current selling price | `99.90` |
17
+ | `compare_at_amount` | Original/compare price for strikethrough display | `129.90` |
18
+ | `currency` | ISO 4217 currency code | `USD` |
19
+
20
+ > **WARNING:** If a product doesn't have a price in the selected currency, it won't appear in Store API responses by default.
21
+
22
+ ### Fetching Prices via API
23
+
24
+ The Store API returns the resolved price (including Price List rules) for the current currency and market context:
25
+
26
+
27
+ ```typescript SDK
28
+ // Product price is included by default
29
+ const product = await client.products.get('spree-tote')
30
+ console.log(product.price) // "15.99" — resolved for current currency
31
+ console.log(product.original_price) // "19.99" — compare-at price (if set)
32
+
33
+ // Each variant has its own price
34
+ const detailed = await client.products.get('spree-tote', {
35
+ expand: ['variants'],
36
+ })
37
+ detailed.variants?.forEach(variant => {
38
+ console.log(variant.price) // "15.99"
39
+ console.log(variant.original_price) // "19.99"
40
+ })
41
+ ```
42
+
43
+ ```bash cURL
44
+ # Product price is always in the response
45
+ curl 'https://api.mystore.com/api/v3/store/products/spree-tote' \
46
+ -H 'Authorization: Bearer spree_pk_xxx'
47
+
48
+ # With variants
49
+ curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=variants' \
50
+ -H 'Authorization: Bearer spree_pk_xxx'
51
+ ```
52
+
53
+
54
+ ## Price Lists
55
+
56
+ Price Lists allow you to create different pricing strategies based on various conditions. This enables advanced pricing scenarios like:
57
+
58
+ - **Market-based pricing** — different prices for different [Markets](/developer/core-concepts/markets) (e.g., North America vs Europe)
59
+ - **Regional pricing** — different prices for different geographic zones
60
+ - **Wholesale/B2B pricing** — special prices for business customers
61
+ - **Volume discounts** — tiered pricing based on quantity purchased
62
+ - **Promotional pricing** — time-limited special offers
63
+ - **VIP customer pricing** — exclusive prices for specific customers
64
+
65
+ ### How Price Lists Work
66
+
67
+ When a customer views a product, Spree's pricing resolver determines which price to use:
68
+
69
+ 1. **Price List priority** — Price Lists are ordered by position; higher priority lists are checked first
70
+ 2. **Status** — only `active` or `scheduled` Price Lists are considered
71
+ 3. **Date range** — the current time must fall within `starts_at` and `ends_at` (if set)
72
+ 4. **Price Rules** — all configured rules must match (or any, depending on `match_policy`)
73
+
74
+ If no applicable Price List is found, the base price is used.
75
+
76
+ ### Price List Attributes
77
+
78
+ | Attribute | Description |
79
+ |-----------|-------------|
80
+ | `name` | Human-readable name for the Price List |
81
+ | `status` | `draft`, `active`, `scheduled`, or `inactive` |
82
+ | `starts_at` | Optional start date when the Price List becomes applicable |
83
+ | `ends_at` | Optional end date when the Price List stops being applicable |
84
+ | `match_policy` | How rules are evaluated: `all` (every rule must match) or `any` (at least one) |
85
+ | `position` | Priority order (lower numbers = higher priority) |
86
+
87
+ ## Price Rules
88
+
89
+ Price Rules define conditions that must be met for a Price List to apply. Spree includes five built-in rule types:
90
+
91
+ | Rule | Description | Use Case |
92
+ |------|-------------|----------|
93
+ | **Market Rule** | Matches based on the current [Market](/developer/core-concepts/markets) | Regional pricing across markets |
94
+ | **Zone Rule** | Matches based on the customer's geographic zone | Country or state-level pricing |
95
+ | **User Rule** | Matches specific customer accounts | VIP customers, wholesale accounts |
96
+ | **Customer Group Rule** | Matches members of customer groups | Loyalty tiers, membership pricing |
97
+ | **Volume Rule** | Matches based on quantity purchased | Bulk discounts, tiered pricing |
98
+
99
+ ### Market Rule
100
+
101
+ The recommended approach for regional pricing when using Markets. Applies the Price List when the customer is in one of the specified markets.
102
+
103
+ **Example:** Price a product at $29.99 in North America and €24.99 in Europe, rather than relying on exchange rate conversion.
104
+
105
+ ### Zone Rule
106
+
107
+ Applies based on the customer's geographic zone. Useful for regional or country-specific pricing when not using Markets.
108
+
109
+ ### User Rule
110
+
111
+ Limits the Price List to specific customer accounts. Useful for VIP customers, employee pricing, or wholesale accounts.
112
+
113
+ ### Customer Group Rule
114
+
115
+ Applies to members of specific customer groups. Useful for wholesale tiers, loyalty programs, or membership-based pricing.
116
+
117
+ ### Volume Rule
118
+
119
+ Applies based on quantity purchased. Supports `min_quantity` and `max_quantity` to create tiered pricing:
120
+
121
+ | Tier | Quantity | Price |
122
+ |------|----------|-------|
123
+ | Base | 1–9 | $10.00 |
124
+ | Bulk Tier 1 | 10–49 | $8.50 |
125
+ | Bulk Tier 2 | 50+ | $7.00 |
126
+
127
+ > **INFO:** Custom Price Rules can be created for specialized pricing logic. See the [Customization Quickstart](/developer/customization/quickstart) for details.
128
+
129
+ ## Pricing Context
130
+
131
+ When resolving prices, Spree considers the full context of the request:
132
+
133
+ | Context | Source | Description |
134
+ |---------|--------|-------------|
135
+ | Currency | Market or request header | The currency to price in |
136
+ | Market | Customer's country | The [Market](/developer/core-concepts/markets) for market-based rules |
137
+ | Zone | Customer's address | The geographic zone for zone-based rules |
138
+ | Customer | JWT authentication | The logged-in customer for user-based rules |
139
+ | Quantity | Cart line item | The quantity for volume-based rules |
140
+ | Date | Current time | For time-based Price List scheduling |
141
+
142
+ The Store API automatically builds this context from the request headers (`X-Spree-Currency`, `X-Spree-Country`) and authentication state. You don't need to construct it manually — just make API requests and the correct price is resolved.
143
+
144
+ > **INFO:** Price resolution results are cached for 15 minutes. Different context combinations are cached separately.
145
+
146
+ ## Time-Based Pricing
147
+
148
+ Price Lists support scheduling through `starts_at` and `ends_at` attributes. Scheduled Price Lists automatically become applicable when the current time falls within their date range — no manual activation needed.
149
+
150
+ **Example:** A Black Friday sale Price List with `starts_at: 2025-11-28 00:00` and `ends_at: 2025-11-28 23:59` will automatically activate and deactivate.
151
+
152
+ ## Managing Price Lists
153
+
154
+ Price Lists are managed in the Admin Panel under **Products → Price Lists**, or via the Admin API.
155
+
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
+
158
+ ## Related Documentation
159
+
160
+ - [Products](/developer/core-concepts/products) — Products, Variants, and base prices
161
+ - [Markets](/developer/core-concepts/markets) — Geographic regions with currency and locale
162
+ - [Taxes](/developer/core-concepts/taxes) — Tax categories, tax rates, and zones
163
+ - [Promotions](/developer/core-concepts/promotions) — Discount-based pricing via promotion rules
@@ -0,0 +1,360 @@
1
+ ---
2
+ title: Products
3
+ description: Products, variants, option types, images, prices, and categories
4
+ ---
5
+
6
+ ## Overview
7
+
8
+ A product represents something you sell. Each product has one or more **variants** — the actual purchasable items with their own SKU, price, and inventory. For example, a "T-Shirt" product might have variants for each size and color combination.
9
+
10
+ Products are organized into **categories** — a flexible hierarchy for grouping products. Categories can be filtered, sorted, and searched via the Store API.
11
+
12
+ > **INFO:** Product names, descriptions, slugs, and SEO fields are [translatable](/developer/core-concepts/translations#resource-translations).
13
+
14
+ ```mermaid
15
+ erDiagram
16
+ Product ||--o{ Variant : "has many"
17
+ Product }o--o{ OptionType : "has many"
18
+ Product ||--o{ Classification : "has many"
19
+ Variant ||--o{ Price : "has many"
20
+ Variant ||--o{ StockItem : "has many"
21
+ Variant ||--o{ Image : "has many"
22
+ Variant }o--o{ OptionValue : "has many"
23
+ OptionType ||--o{ OptionValue : "has many"
24
+ Taxon ||--o{ Classification : "has many"
25
+ Taxonomy ||--o{ Taxon : "has many"
26
+
27
+ Product {
28
+ string name
29
+ string slug
30
+ string status
31
+ text description
32
+ datetime available_on
33
+ }
34
+
35
+ Variant {
36
+ string sku
37
+ boolean is_master
38
+ decimal weight
39
+ }
40
+
41
+ Price {
42
+ decimal amount
43
+ decimal compare_at_amount
44
+ string currency
45
+ }
46
+
47
+ OptionType {
48
+ string name
49
+ string presentation
50
+ }
51
+
52
+ OptionValue {
53
+ string name
54
+ string presentation
55
+ }
56
+ ```
57
+
58
+ ## Product Attributes
59
+
60
+ | Attribute | Description | Translatable |
61
+ |-----------|-------------|:---:|
62
+ | `name` | Product name | Yes |
63
+ | `description` | Full product description | Yes |
64
+ | `slug` | URL-friendly identifier (e.g., `spree-tote`) | Yes |
65
+ | `status` | `draft`, `active`, or `archived` | No |
66
+ | `available_on` | Date the product becomes available for sale | No |
67
+ | `discontinue_on` | Date the product is no longer available | No |
68
+ | `meta_title` | Custom SEO title | Yes |
69
+ | `meta_description` | SEO description | Yes |
70
+ | `meta_keywords` | SEO keywords | Yes |
71
+ | `purchasable` | Whether the product can be added to cart | No |
72
+ | `in_stock` | Whether any variant has stock available | No |
73
+ | `price` | Default variant's price in the current currency | No |
74
+ | `thumbnail_url` | URL to the product's first image — always returned, no expand needed | No |
75
+ | `tags` | Array of tag strings for filtering | No |
76
+
77
+ ## Listing Products
78
+
79
+
80
+ ```typescript SDK
81
+ // List products with pagination
82
+ const { data: products, meta } = await client.products.list({
83
+ limit: 12,
84
+ page: 1,
85
+ })
86
+
87
+ // Filter by price range and availability
88
+ const filtered = await client.products.list({
89
+ price_gte: 10,
90
+ price_lte: 50,
91
+ in_stock: true,
92
+ })
93
+
94
+ // Search by keyword
95
+ const results = await client.products.list({
96
+ search: 'tote bag',
97
+ })
98
+
99
+ // Sort products
100
+ const sorted = await client.products.list({
101
+ sort: 'price_high_to_low', // or: price_low_to_high, newest, name_a_z, name_z_a
102
+ })
103
+ ```
104
+
105
+ ```bash cURL
106
+ # List products
107
+ curl 'https://api.mystore.com/api/v3/store/products?limit=12&page=1' \
108
+ -H 'Authorization: Bearer spree_pk_xxx'
109
+
110
+ # Filter by price and stock
111
+ curl 'https://api.mystore.com/api/v3/store/products?q[price_gte]=10&q[price_lte]=50&q[in_stock]=true' \
112
+ -H 'Authorization: Bearer spree_pk_xxx'
113
+
114
+ # Search
115
+ curl 'https://api.mystore.com/api/v3/store/products?q[search]=tote+bag' \
116
+ -H 'Authorization: Bearer spree_pk_xxx'
117
+ ```
118
+
119
+
120
+ See [Querying](/api-reference/store-api/querying) for the full list of filtering, sorting, and pagination options.
121
+
122
+ ## Getting a Product
123
+
124
+
125
+ ```typescript SDK
126
+ // Get by slug
127
+ const product = await client.products.get('spree-tote')
128
+
129
+ // Get with included relations
130
+ const detailed = await client.products.get('spree-tote', {
131
+ expand: ['variants', 'media', 'option_types', 'categories'],
132
+ })
133
+ // detailed.variants => [{ id: "var_xxx", sku: "TOTE-S-R", price: { amount: "15.99", currency: "USD" }, ... }]
134
+ // detailed.media => [{ id: "img_xxx", url: "https://cdn...", position: 1 }]
135
+ // detailed.option_types => [{ name: "size", presentation: "Size", option_values: [...] }]
136
+ ```
137
+
138
+ ```bash cURL
139
+ curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=variants,media,option_types,categories' \
140
+ -H 'Authorization: Bearer spree_pk_xxx'
141
+ ```
142
+
143
+
144
+ ## Product Filters
145
+
146
+ Get available filter options for building a faceted search UI. Returns price ranges, option values, and categories with counts:
147
+
148
+
149
+ ```typescript SDK
150
+ const filters = await client.products.filters()
151
+ // {
152
+ // option_types: [{ name: "size", option_values: [{ name: "Small", count: 12 }, ...] }],
153
+ // price_range: { min: 9.99, max: 199.99 },
154
+ // categories: [{ id: "ctg_xxx", name: "Clothing", count: 45 }],
155
+ // }
156
+
157
+ // Scoped to a specific category
158
+ const categoryFilters = await client.products.filters({
159
+ category_id: 'ctg_xxx',
160
+ })
161
+ ```
162
+
163
+ ```bash cURL
164
+ curl 'https://api.mystore.com/api/v3/store/products/filters' \
165
+ -H 'Authorization: Bearer spree_pk_xxx'
166
+
167
+ # Scoped to a category
168
+ curl 'https://api.mystore.com/api/v3/store/products/filters?category_id=ctg_xxx' \
169
+ -H 'Authorization: Bearer spree_pk_xxx'
170
+ ```
171
+
172
+
173
+ ## Variants
174
+
175
+ Variants are the purchasable units of a product. Each variant has its own SKU, price, inventory, and images, and is defined by a unique combination of option values.
176
+
177
+ | Attribute | Description |
178
+ |-----------|-------------|
179
+ | `sku` | Unique stock keeping unit |
180
+ | `barcode` | Barcode (UPC, EAN, etc.) |
181
+ | `price` | Price in the current currency |
182
+ | `original_price` | Compare-at price for showing discounts |
183
+ | `weight`, `height`, `width`, `depth` | Dimensions for shipping calculations |
184
+ | `in_stock` | Whether stock is available |
185
+ | `backorderable` | Whether the variant can be ordered when out of stock |
186
+ | `option_values` | The option values that define this variant (e.g., Size: Small, Color: Red) |
187
+
188
+ ### Master Variant
189
+
190
+ Every product has a **master variant** that holds default pricing and inventory. If a product has no option types (e.g., a book with no size/color), the master variant is the only purchasable variant.
191
+
192
+ ### Regular Variants
193
+
194
+ When a product has option types, each unique combination of option values creates a variant. For example, a T-shirt with sizes (S, M, L) and colors (Red, Green) has 6 variants:
195
+
196
+ | SKU | Size | Color |
197
+ |-----|------|-------|
198
+ | `TEE-S-R` | Small | Red |
199
+ | `TEE-S-G` | Small | Green |
200
+ | `TEE-M-R` | Medium | Red |
201
+ | `TEE-M-G` | Medium | Green |
202
+ | `TEE-L-R` | Large | Red |
203
+ | `TEE-L-G` | Large | Green |
204
+
205
+ The product's `default_variant_id` points to the first non-master variant (or the master variant if none exist).
206
+
207
+ ## Option Types and Option Values
208
+
209
+ Option types define the axes of variation for a product (e.g., Size, Color, Material). Option values are the specific choices within each type (e.g., Small, Medium, Large).
210
+
211
+ A product must have at least one option type to have multiple variants. Option types and their values are included in the product response when requested:
212
+
213
+
214
+ ```typescript SDK
215
+ const product = await client.products.get('spree-tee', {
216
+ expand: ['option_types'],
217
+ })
218
+
219
+ product.option_types?.forEach(optionType => {
220
+ console.log(optionType.presentation) // "Size"
221
+ optionType.option_values.forEach(value => {
222
+ console.log(value.presentation) // "Small", "Medium", "Large"
223
+ })
224
+ })
225
+ ```
226
+
227
+ ```bash cURL
228
+ curl 'https://api.mystore.com/api/v3/store/products/spree-tee?expand=option_types' \
229
+ -H 'Authorization: Bearer spree_pk_xxx'
230
+ ```
231
+
232
+
233
+ > **INFO:** Option type `name` and `presentation` fields are translatable.
234
+
235
+ ## Media
236
+
237
+ Media can be attached to the product (via the master variant) or to individual variants. When displaying a product, show the images for the selected variant, falling back to the product-level images.
238
+
239
+ ### Thumbnails
240
+
241
+ Every product response includes a `thumbnail_url` field — the URL to the first image, ready to use without any expands. Similarly, each variant includes a `thumbnail_url` URL and an `media_count` counter.
242
+
243
+ Use these fields for product listing pages to avoid loading all images:
244
+
245
+
246
+ ```typescript SDK
247
+ // List products — thumbnail_url is always included
248
+ const { data: products } = await client.products.list({ limit: 12 })
249
+
250
+ products.forEach(product => {
251
+ product.thumbnail_url // "https://cdn.../tote-front.jpg" — no expand needed
252
+ })
253
+ ```
254
+
255
+ ```bash cURL
256
+ # thumbnail_url is always in the response — no ?expand needed
257
+ curl 'https://api.mystore.com/api/v3/store/products?limit=12' \
258
+ -H 'Authorization: Bearer spree_pk_xxx'
259
+ ```
260
+
261
+
262
+ > **WARNING:** Avoid using `?expand=media` on listing pages. This loads **all** images for every product in the response, which is unnecessary when you only need a thumbnail. Use `thumbnail_url` instead and only expand full media on the product detail page.
263
+
264
+ ### All Images
265
+
266
+ On the product detail page, expand `media` and `variants` to get the full set of images. Images are ordered by `position`:
267
+
268
+
269
+ ```typescript SDK
270
+ const product = await client.products.get('spree-tote', {
271
+ expand: ['media', 'variants'],
272
+ })
273
+
274
+ // Product-level images (from master variant)
275
+ product.media // [{ url: "https://cdn.../tote-front.jpg", position: 1 }, ...]
276
+
277
+ // Each variant has its own thumbnail and media_count
278
+ product.variants?.forEach(variant => {
279
+ variant.thumbnail // "https://cdn.../tote-red.jpg" — always available
280
+ variant.media_count // 3 — quick check without loading media
281
+ variant.media // full image array (only when ?expand=media)
282
+ })
283
+ ```
284
+
285
+ ```bash cURL
286
+ curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=media,variants' \
287
+ -H 'Authorization: Bearer spree_pk_xxx'
288
+ ```
289
+
290
+
291
+ | Field | Available on | Always returned | Description |
292
+ |-------|-------------|:---:|-------------|
293
+ | `thumbnail_url` | Product | Yes | URL to the product's first media |
294
+ | `thumbnail_url` | Variant | Yes | URL to the variant's first media |
295
+ | `media_count` | Variant | Yes | Number of media |
296
+ | `media` | Product, Variant | No | Full image array (requires `?expand=media`) |
297
+
298
+ ## Prices
299
+
300
+ Each variant can have multiple prices — one per currency, plus additional prices from [Price Lists](/developer/core-concepts/pricing) that apply conditionally based on market, geography, customer segment, or quantity.
301
+
302
+ The API automatically returns the correct price based on the current currency and market context:
303
+
304
+ | Field | Description |
305
+ |-------|-------------|
306
+ | `price` | Current selling price |
307
+ | `original_price` | Compare-at price (for showing strikethrough discounts) |
308
+
309
+ See the [Pricing](/developer/core-concepts/pricing) guide for details on Price Lists, Price Rules, and market-specific pricing.
310
+
311
+ ## Categories
312
+
313
+ Categories provide a flexible way to organize products into hierarchical trees. Internally, Spree uses Taxonomies (category trees) and Taxons (nodes within those trees), but the Store API exposes them simply as **Categories**.
314
+
315
+ For example:
316
+ - **Categories** → Clothing → T-Shirts, Dresses
317
+ - **Brands** → Nike, Adidas, Puma
318
+ - **Collections** → Summer 2025, Best Sellers
319
+
320
+ Products can belong to multiple categories.
321
+
322
+
323
+ ```typescript SDK
324
+ // List categories
325
+ const { data: categories } = await client.categories.list()
326
+
327
+ // Get a category by permalink
328
+ const category = await client.categories.get('clothing/shirts')
329
+
330
+ // List products in a category
331
+ const { data: products } = await client.categories.products.list('clothing/shirts', {
332
+ limit: 12,
333
+ })
334
+ ```
335
+
336
+ ```bash cURL
337
+ # List categories
338
+ curl 'https://api.mystore.com/api/v3/store/categories' \
339
+ -H 'Authorization: Bearer spree_pk_xxx'
340
+
341
+ # Get a category by permalink
342
+ curl 'https://api.mystore.com/api/v3/store/categories/clothing/shirts' \
343
+ -H 'Authorization: Bearer spree_pk_xxx'
344
+
345
+ # List products in a category
346
+ curl 'https://api.mystore.com/api/v3/store/categories/clothing/shirts/products?limit=12' \
347
+ -H 'Authorization: Bearer spree_pk_xxx'
348
+ ```
349
+
350
+
351
+ > **INFO:** Category `name` and `description` fields are translatable.
352
+
353
+ ## Related Documentation
354
+
355
+ - [Pricing](/developer/core-concepts/pricing) — Price Lists, Price Rules, and market-specific pricing
356
+ - [Inventory](/developer/core-concepts/inventory) — Stock management and backorders
357
+ - [Media](/developer/core-concepts/media) — Image management
358
+ - [Translations](/developer/core-concepts/translations) — Translating product content
359
+ - [Search & Filtering](/developer/core-concepts/search-filtering) — Full-text search and Ransack filtering
360
+ - [Querying](/api-reference/store-api/querying) — API filtering, sorting, and pagination