@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,299 @@
1
+ ---
2
+ title: Users
3
+ description: Customers and admin users — authentication, accounts, and permissions
4
+ ---
5
+
6
+ ## Overview
7
+
8
+ Spree has two separate user types:
9
+
10
+ - **Customers** — users who browse your store, manage their account, and purchase products via the Store API
11
+ - **Admins** — users who manage the store via the Admin Panel
12
+
13
+ | User type | Class | Default |
14
+ |-----------|-------|---------|
15
+ | Customers | `Spree.user_class` | `Spree::User` |
16
+ | Admins | `Spree.admin_user_class` | `Spree::AdminUser` |
17
+
18
+ > **INFO:** You can use your own user classes. See the [Customize Authentication guide](/developer/customization/authentication) for details.
19
+
20
+ ## Customers
21
+
22
+ Customers interact with your store through the Store API. They can register, log in, manage their profile, and view order history.
23
+
24
+ ```mermaid
25
+ erDiagram
26
+ Customer ||--o{ Order : "places"
27
+ Customer ||--o{ Address : "has many"
28
+ Customer ||--o{ Wishlist : "has many"
29
+ Customer ||--o{ StoreCredit : "has many"
30
+ Customer ||--o{ PaymentSource : "has many"
31
+
32
+ Customer {
33
+ string id
34
+ string email
35
+ string first_name
36
+ string last_name
37
+ }
38
+
39
+ Order {
40
+ string number
41
+ string state
42
+ }
43
+
44
+ Address {
45
+ string firstname
46
+ string lastname
47
+ string address1
48
+ string city
49
+ }
50
+
51
+ Wishlist {
52
+ string name
53
+ boolean is_default
54
+ }
55
+ ```
56
+
57
+ ### Registration
58
+
59
+
60
+ ```typescript SDK
61
+ const { token, user } = await client.customers.create({
62
+ email: 'john@example.com',
63
+ password: 'password123',
64
+ password_confirmation: 'password123',
65
+ first_name: 'John',
66
+ last_name: 'Doe',
67
+ })
68
+ // token => JWT token for subsequent authenticated requests
69
+ // user => { id: "usr_xxx", email: "john@example.com", first_name: "John", ... }
70
+ ```
71
+
72
+ ```bash cURL
73
+ curl -X POST 'https://api.mystore.com/api/v3/store/customers' \
74
+ -H 'X-Spree-Api-Key: spree_pk_xxx' \
75
+ -H 'Content-Type: application/json' \
76
+ -d '{
77
+ "email": "john@example.com",
78
+ "password": "password123",
79
+ "password_confirmation": "password123",
80
+ "first_name": "John",
81
+ "last_name": "Doe"
82
+ }'
83
+ ```
84
+
85
+
86
+ ### Login
87
+
88
+
89
+ ```typescript SDK
90
+ const { token, user } = await client.auth.login({
91
+ email: 'john@example.com',
92
+ password: 'password123',
93
+ })
94
+ // Use the token for authenticated requests
95
+ ```
96
+
97
+ ```bash cURL
98
+ curl -X POST 'https://api.mystore.com/api/v3/store/auth/login' \
99
+ -H 'Authorization: Bearer spree_pk_xxx' \
100
+ -H 'Content-Type: application/json' \
101
+ -d '{
102
+ "email": "john@example.com",
103
+ "password": "password123"
104
+ }'
105
+ ```
106
+
107
+
108
+ The response includes a JWT `token` and a `user` object. Pass the token in subsequent requests via the `Authorization: Bearer <token>` header.
109
+
110
+ ### Token Refresh
111
+
112
+ Refresh an expiring token to keep the session alive:
113
+
114
+
115
+ ```typescript SDK
116
+ const { token } = await client.auth.refresh({
117
+ token: existingToken,
118
+ })
119
+ ```
120
+
121
+ ```bash cURL
122
+ curl -X POST 'https://api.mystore.com/api/v3/store/auth/refresh' \
123
+ -H 'Authorization: Bearer <jwt_token>'
124
+ ```
125
+
126
+
127
+ ### Customer Profile
128
+
129
+
130
+ ```typescript SDK
131
+ // Get current customer
132
+ const customer = await client.customer.get()
133
+ // {
134
+ // id: "usr_xxx",
135
+ // email: "john@example.com",
136
+ // first_name: "John",
137
+ // last_name: "Doe",
138
+ // default_shipping_address: { ... },
139
+ // default_billing_address: { ... },
140
+ // addresses: [{ ... }, { ... }],
141
+ // }
142
+
143
+ // Update profile
144
+ const updated = await client.customer.update({
145
+ first_name: 'Jonathan',
146
+ accepts_email_marketing: true,
147
+ })
148
+ ```
149
+
150
+ ```bash cURL
151
+ # Get current customer
152
+ curl 'https://api.mystore.com/api/v3/store/customer' \
153
+ -H 'Authorization: Bearer <jwt_token>'
154
+
155
+ # Update profile
156
+ curl -X PATCH 'https://api.mystore.com/api/v3/store/customer' \
157
+ -H 'Authorization: Bearer <jwt_token>' \
158
+ -H 'Content-Type: application/json' \
159
+ -d '{ "first_name": "Jonathan", "accepts_email_marketing": true }'
160
+ ```
161
+
162
+
163
+ ### Customer Resources
164
+
165
+ Authenticated customers have access to these resources:
166
+
167
+ | Resource | Description |
168
+ |----------|-------------|
169
+ | [**Addresses**](/developer/core-concepts/addresses#customer-address-book) | Billing and shipping addresses with default selection |
170
+ | [**Orders**](/developer/core-concepts/orders#order-history) | Past order history |
171
+ | **Credit Cards** | Saved credit cards for checkout |
172
+ | **Payment Sources** | Other saved payment methods (PayPal, Klarna, etc.) |
173
+ | **Store Credits** | Balance assigned by the store, usable at checkout |
174
+ | **Gift Cards** | Gift cards owned by or assigned to the customer |
175
+ | **Wishlists** | Saved product lists |
176
+
177
+ ### Guest Checkout
178
+
179
+ Customers don't need to register to purchase. Guest checkout uses an order token (`X-Spree-Token`) to identify the cart. See [Orders — Cart](/developer/core-concepts/orders#cart) for details.
180
+
181
+ ## Admin Users
182
+
183
+ Admin users manage the store via the Admin Panel. They have roles that control what they can access.
184
+
185
+ ```mermaid
186
+ erDiagram
187
+ AdminUser ||--o{ RoleUser : "has many"
188
+ RoleUser }o--|| Role : "belongs to"
189
+ RoleUser }o--|| Store : "scoped to"
190
+ AdminUser ||--o{ Invitation : "invites"
191
+
192
+ AdminUser {
193
+ string id
194
+ string email
195
+ }
196
+
197
+ RoleUser {
198
+ string role_id
199
+ string resource_type
200
+ string resource_id
201
+ }
202
+
203
+ Role {
204
+ string name
205
+ }
206
+
207
+ Invitation {
208
+ string email
209
+ string status
210
+ string token
211
+ datetime expires_at
212
+ }
213
+ ```
214
+
215
+ ### Roles
216
+
217
+ Admin users can have different roles that control their permissions:
218
+
219
+ | Role | Description |
220
+ |------|-------------|
221
+ | `admin` | Full access to all Admin Panel features |
222
+
223
+ > **INFO:** You can create custom roles with specific permissions. See the [Customize Permissions guide](/developer/customization/permissions) for details.
224
+
225
+ ### Creating Admin Users
226
+
227
+ Use the Spree CLI to create admin users:
228
+
229
+ ```bash
230
+ spree user create
231
+ ```
232
+
233
+ The CLI will prompt you for the email and password. You can also pass them directly:
234
+
235
+ ```bash
236
+ spree user create --email admin@example.com --password secret123
237
+ ```
238
+
239
+ The created user gets the `admin` role on the default store.
240
+
241
+ ### Inviting Admin Users
242
+
243
+ You can invite new admins through the Admin Panel or programmatically.
244
+
245
+ **Via Admin Panel:**
246
+
247
+ 1. Navigate to **Settings → Users**
248
+ 2. Click **Invite User**
249
+ 3. Enter the email address and select a role
250
+ 4. Click **Send Invitation**
251
+
252
+ 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.
253
+
254
+ ```mermaid
255
+ flowchart TB
256
+ A[Admin creates invitation] --> B[Invitation email sent]
257
+ B --> C[Invitee clicks link]
258
+ C --> D{Has account?}
259
+ D -->|Yes| E[Log in]
260
+ D -->|No| F[Create account]
261
+ E --> G[Accept invitation]
262
+ F --> G
263
+ G --> H[Role assigned to store]
264
+ ```
265
+
266
+ #### Invitation Details
267
+
268
+ | Attribute | Description |
269
+ |-----------|-------------|
270
+ | `email` | Invitee's email address |
271
+ | `token` | Secure token for the invitation link |
272
+ | `status` | `pending` or `accepted` |
273
+ | `expires_at` | Expiration date (default: 2 weeks) |
274
+ | `resource` | The store being granted access to |
275
+ | `role` | The role to assign upon acceptance |
276
+
277
+ #### Invitation Events
278
+
279
+ The invitation system publishes [events](/developer/core-concepts/events) you can subscribe to:
280
+
281
+ | Event | Description |
282
+ |-------|-------------|
283
+ | `invitation.created` | Invitation was created (triggers email) |
284
+ | `invitation.accepted` | Invitation was accepted and role assigned |
285
+ | `invitation.resent` | Invitation was resent to the invitee |
286
+
287
+ ## Permissions
288
+
289
+ Spree uses [CanCanCan](https://github.com/CanCanCommunity/cancancan) for authorization. Permissions apply to both customers (Store API access) and admins (Admin Panel access).
290
+
291
+ See the [Customize Permissions guide](/developer/customization/permissions) for details on creating custom roles and permission sets.
292
+
293
+ ## Related Documentation
294
+
295
+ - [Addresses](/developer/core-concepts/addresses) — Customer address management
296
+ - [Orders](/developer/core-concepts/orders) — Order history and checkout
297
+ - [Authentication](/developer/customization/authentication) — Custom authentication setup
298
+ - [Permissions](/developer/customization/permissions) — Roles and authorization
299
+ - [Events](/developer/core-concepts/events) — Subscribe to user and invitation events
@@ -0,0 +1,378 @@
1
+ ---
2
+ title: Webhooks
3
+ description: Send real-time HTTP notifications to external services when events occur in your store.
4
+ ---
5
+
6
+ ## Overview
7
+
8
+ Webhooks allow your Spree store to send real-time HTTP POST notifications to external services when events occur. When an order is completed, a product is updated, or inventory changes, Spree can automatically notify your CRM, fulfillment service, analytics platform, or any other system.
9
+
10
+ Webhooks are built on top of Spree's [event system](/developer/core-concepts/events), providing:
11
+
12
+ - **Multi-store support** - Each store has its own webhook endpoints
13
+ - **Event filtering** - Subscribe to specific events or patterns with wildcards
14
+ - **Secure delivery** - HMAC-SHA256 signatures for payload verification
15
+ - **Automatic retries** - Failed deliveries retry with exponential backoff
16
+ - **Full audit trail** - Track every delivery attempt with response codes and timing
17
+
18
+ ## How Webhooks Work
19
+
20
+ ```mermaid
21
+ flowchart LR
22
+ subgraph Spree Store
23
+ A[Event Published] --> B[WebhookEventSubscriber]
24
+ B --> C{Find Matching<br/>Endpoints}
25
+ C --> D[Create WebhookDelivery]
26
+ D --> E[Queue DeliveryJob]
27
+ end
28
+
29
+ subgraph Delivery
30
+ E --> F[Build JSON Payload]
31
+ F --> G[Sign with HMAC-SHA256]
32
+ G --> H[HTTP POST]
33
+ end
34
+
35
+ subgraph External Service
36
+ H --> I{Response}
37
+ I -->|2xx| J[Success]
38
+ I -->|Error| K[Retry with Backoff]
39
+ K -->|Max Retries| L[Mark Failed]
40
+ K -->|Retry| H
41
+ end
42
+ ```
43
+
44
+ 1. An event is published (e.g., `order.completed`)
45
+ 2. The `WebhookEventSubscriber` receives all events
46
+ 3. It finds active webhook endpoints subscribed to that event
47
+ 4. For each endpoint, it creates a `WebhookDelivery` record and queues a job
48
+ 5. The job sends an HTTP POST request with the event payload and HMAC signature
49
+
50
+ ## Creating Webhook Endpoints
51
+
52
+ ### Via Admin Panel
53
+
54
+ Navigate to **Settings → Developers → Webhooks** in the admin panel to create and manage webhook endpoints.
55
+
56
+ ### Via Code
57
+
58
+ ```ruby
59
+ endpoint = Spree::WebhookEndpoint.create!(
60
+ store: Spree::Store.default,
61
+ url: 'https://example.com/webhooks/spree',
62
+ subscriptions: ['order.*', 'product.created'],
63
+ active: true
64
+ )
65
+
66
+ # The secret_key is auto-generated
67
+ endpoint.secret_key # => "a1b2c3d4e5f6..." (64-character hex string)
68
+ ```
69
+
70
+ ### Endpoint Attributes
71
+
72
+ | Attribute | Type | Description |
73
+ |-----------|------|-------------|
74
+ | `url` | String | The HTTPS endpoint URL to receive webhooks |
75
+ | `active` | Boolean | Enable/disable delivery to this endpoint |
76
+ | `subscriptions` | Array | Event patterns to subscribe to |
77
+ | `secret_key` | String | Auto-generated key for HMAC signature verification |
78
+ | `store_id` | Integer | The store this endpoint belongs to |
79
+
80
+ ## Event Subscriptions
81
+
82
+ The `subscriptions` attribute controls which events trigger webhooks to this endpoint.
83
+
84
+ ### Subscribe to Specific Events
85
+
86
+ ```ruby
87
+ endpoint.subscriptions = ['order.completed', 'order.canceled']
88
+ ```
89
+
90
+ ### Subscribe to Event Patterns
91
+
92
+ Use wildcards to subscribe to multiple related events:
93
+
94
+ ```ruby
95
+ # All order events
96
+ endpoint.subscriptions = ['order.*']
97
+
98
+ # All creation events
99
+ endpoint.subscriptions = ['*.created']
100
+
101
+ # Multiple patterns
102
+ endpoint.subscriptions = ['order.*', 'payment.*', 'shipment.shipped']
103
+ ```
104
+
105
+ ### Subscribe to All Events
106
+
107
+ Leave subscriptions empty or use `*` to receive all events:
108
+
109
+ ```ruby
110
+ endpoint.subscriptions = [] # All events
111
+ endpoint.subscriptions = ['*'] # All events (explicit)
112
+ ```
113
+
114
+ ## Webhook Payload
115
+
116
+ Each webhook delivery sends a JSON payload with the following structure. The `data` object uses the same [Store API V3 serializers](/api-reference/introduction) as the REST API, so webhook payloads and API responses share the same schema:
117
+
118
+ ```json
119
+ {
120
+ "id": "550e8400-e29b-41d4-a716-446655440000",
121
+ "name": "order.completed",
122
+ "created_at": "2025-01-15T10:30:00Z",
123
+ "data": {
124
+ "id": "or_m3Rp9wXz",
125
+ "number": "R123456789",
126
+ "state": "complete",
127
+ "total": "99.99",
128
+ "display_total": "$99.99",
129
+ "item_count": 3,
130
+ "currency": "USD",
131
+ "items": [ ... ],
132
+ "shipments": [ ... ],
133
+ "payments": [ ... ]
134
+ },
135
+ "metadata": {
136
+ "spree_version": "5.1.0"
137
+ }
138
+ }
139
+ ```
140
+
141
+ | Field | Description |
142
+ |-------|-------------|
143
+ | `id` | Unique UUID for this event |
144
+ | `name` | Event name (e.g., `order.completed`) |
145
+ | `created_at` | ISO8601 timestamp when event occurred |
146
+ | `data` | Serialized resource data (V3 API format with [prefixed IDs](/api-reference/introduction)) |
147
+ | `metadata` | Additional context including Spree version |
148
+
149
+ For complete payload schemas for each event type, see [Webhook Events & Payloads](/api-reference/webhooks-events).
150
+
151
+ ## HTTP Request Details
152
+
153
+ ### Headers
154
+
155
+ Each webhook request includes these headers:
156
+
157
+ | Header | Description |
158
+ |--------|-------------|
159
+ | `Content-Type` | `application/json` |
160
+ | `User-Agent` | `Spree-Webhooks/1.0` |
161
+ | `X-Spree-Webhook-Event` | Event name (e.g., `order.completed`) |
162
+ | `X-Spree-Webhook-Signature` | HMAC-SHA256 signature for verification |
163
+
164
+ ### Verifying Webhook Signatures
165
+
166
+ To ensure webhooks are genuinely from your Spree store, verify the signature:
167
+
168
+ ```ruby
169
+ # In your webhook receiver
170
+ def verify_webhook(request)
171
+ payload = request.body.read
172
+ signature = request.headers['X-Spree-Webhook-Signature']
173
+ secret_key = ENV['SPREE_WEBHOOK_SECRET'] # Your endpoint's secret_key
174
+
175
+ expected = OpenSSL::HMAC.hexdigest('SHA256', secret_key, payload)
176
+
177
+ ActiveSupport::SecurityUtils.secure_compare(signature, expected)
178
+ end
179
+ ```
180
+
181
+ Example in a Rails controller:
182
+
183
+ ```ruby
184
+ class WebhooksController < ApplicationController
185
+ skip_before_action :verify_authenticity_token
186
+
187
+ def receive
188
+ unless verify_signature
189
+ head :unauthorized
190
+ return
191
+ end
192
+
193
+ event = JSON.parse(request.body.read)
194
+
195
+ case event['name']
196
+ when 'order.completed'
197
+ handle_order_completed(event['data'])
198
+ when 'product.updated'
199
+ handle_product_updated(event['data'])
200
+ end
201
+
202
+ head :ok
203
+ end
204
+
205
+ private
206
+
207
+ def verify_signature
208
+ payload = request.body.read
209
+ request.body.rewind
210
+
211
+ signature = request.headers['X-Spree-Webhook-Signature']
212
+ expected = OpenSSL::HMAC.hexdigest('SHA256', ENV['SPREE_WEBHOOK_SECRET'], payload)
213
+
214
+ ActiveSupport::SecurityUtils.secure_compare(signature.to_s, expected)
215
+ end
216
+ end
217
+ ```
218
+
219
+ ## Delivery Status & Retries
220
+
221
+ ### Automatic Retries
222
+
223
+ Failed webhook deliveries automatically retry up to 5 times with exponential backoff. This handles temporary network issues and endpoint downtime.
224
+
225
+ ### Checking Delivery Status
226
+
227
+ ```ruby
228
+ endpoint = Spree::WebhookEndpoint.find(id)
229
+
230
+ # Recent deliveries
231
+ endpoint.webhook_deliveries.recent
232
+
233
+ # Filter by status
234
+ endpoint.webhook_deliveries.successful
235
+ endpoint.webhook_deliveries.failed
236
+ endpoint.webhook_deliveries.pending
237
+
238
+ # Filter by event
239
+ endpoint.webhook_deliveries.for_event('order.completed')
240
+ ```
241
+
242
+ ### Delivery Attributes
243
+
244
+ | Attribute | Description |
245
+ |-----------|-------------|
246
+ | `event_name` | Name of the event delivered |
247
+ | `payload` | Complete webhook payload sent |
248
+ | `response_code` | HTTP status code (nil if pending) |
249
+ | `success` | Boolean indicating 2xx response |
250
+ | `execution_time` | Delivery time in milliseconds |
251
+ | `error_type` | `'timeout'`, `'connection_error'`, or nil |
252
+ | `request_errors` | Error message details |
253
+ | `response_body` | Response from endpoint (truncated) |
254
+ | `delivered_at` | Timestamp of delivery attempt |
255
+
256
+ ## Configuration
257
+
258
+ ### Enabling/Disabling Webhooks
259
+
260
+ Webhooks are enabled by default. To disable globally:
261
+
262
+ ```ruby
263
+ # config/initializers/spree.rb
264
+ Spree::Api::Config.webhooks_enabled = false
265
+ ```
266
+
267
+ ### SSL Verification
268
+
269
+ SSL verification is enabled by default in production. In development, it's disabled to allow testing with self-signed certificates:
270
+
271
+ ```ruby
272
+ # config/initializers/spree.rb
273
+ Spree::Api::Config.webhooks_verify_ssl = true # Force SSL verification
274
+ Spree::Api::Config.webhooks_verify_ssl = false # Disable (not recommended for production)
275
+ ```
276
+
277
+ ## Available Events
278
+
279
+ Webhooks can subscribe to any event in Spree's event system. See [Events](/developer/core-concepts/events#available-events) for a complete list.
280
+
281
+ Common webhook events include:
282
+
283
+ | Event | Description |
284
+ |-------|-------------|
285
+ | `order.completed` | Order checkout finished |
286
+ | `order.canceled` | Order was canceled |
287
+ | `order.paid` | Order is fully paid |
288
+ | `shipment.shipped` | Shipment was shipped |
289
+ | `payment.paid` | Payment was completed |
290
+ | `product.created` | New product created |
291
+ | `product.updated` | Product was modified |
292
+ | `customer.created` | New customer registered |
293
+
294
+ ## Testing Webhooks
295
+
296
+ ### In Development
297
+
298
+ Use tools like [ngrok](https://ngrok.com) or [webhook.site](https://webhook.site) to test webhooks locally:
299
+
300
+ ```ruby
301
+ # Create a test endpoint
302
+ endpoint = Spree::WebhookEndpoint.create!(
303
+ store: Spree::Store.default,
304
+ url: 'https://your-ngrok-url.ngrok.io/webhooks',
305
+ subscriptions: ['order.*'],
306
+ active: true
307
+ )
308
+
309
+ # Trigger an event
310
+ order = Spree::Order.complete.last
311
+ order.publish_event('order.completed')
312
+
313
+ # Check delivery
314
+ endpoint.webhook_deliveries.last.success?
315
+ ```
316
+
317
+ ### In Tests
318
+
319
+ ```ruby
320
+ RSpec.describe 'Webhook delivery' do
321
+ let(:store) { create(:store) }
322
+ let(:endpoint) { create(:webhook_endpoint, store: store, subscriptions: ['order.completed']) }
323
+ let(:order) { create(:completed_order_with_totals, store: store) }
324
+
325
+ it 'delivers webhook when order completes' do
326
+ stub_request(:post, endpoint.url).to_return(status: 200)
327
+
328
+ expect {
329
+ order.publish_event('order.completed')
330
+ }.to have_enqueued_job(Spree::WebhookDeliveryJob)
331
+ end
332
+ end
333
+ ```
334
+
335
+ ## Best Practices
336
+
337
+
338
+ - **Respond quickly** — Return a 2xx response as fast as possible. Process webhook data asynchronously in a background job.
339
+
340
+ - **Verify signatures** — Always verify the `X-Spree-Webhook-Signature` header to ensure the webhook is authentic.
341
+
342
+ - **Handle duplicates** — Use the event `id` to detect and handle duplicate deliveries. Webhooks may be retried.
343
+
344
+ - **Subscribe selectively** — Only subscribe to events you need. Use specific patterns rather than `*` when possible.
345
+
346
+
347
+ ## Troubleshooting
348
+
349
+ ### Webhooks Not Delivering
350
+
351
+ 1. Check that webhooks are enabled: `Spree::Api::Config.webhooks_enabled`
352
+ 2. Verify the endpoint is active: `endpoint.active?`
353
+ 3. Confirm the endpoint subscribes to the event: `endpoint.subscribed_to?('order.completed')`
354
+ 4. Check the event has a `store_id` matching the endpoint's store
355
+
356
+ ### Signature Verification Failing
357
+
358
+ 1. Ensure you're using the raw request body (not parsed JSON)
359
+ 2. Verify you're using the correct `secret_key` for this endpoint
360
+ 3. Check that no middleware is modifying the request body
361
+
362
+ ### Deliveries Failing
363
+
364
+ Check the delivery record for details:
365
+
366
+ ```ruby
367
+ delivery = endpoint.webhook_deliveries.failed.last
368
+ delivery.error_type # => 'timeout' or 'connection_error'
369
+ delivery.request_errors # => Error message
370
+ delivery.response_code # => HTTP status code
371
+ delivery.response_body # => Response from your endpoint
372
+ ```
373
+
374
+ ## Related Documentation
375
+
376
+ - [Events](/developer/core-concepts/events) - Understanding Spree's event system
377
+ - [Customization Quickstart](/developer/customization/quickstart) - Overview of all customization options
378
+ - [Dependencies](/developer/customization/dependencies) - Customizing Spree services