Overview
Something happens in a store — an order is placed, a payment clears, a product sells out — and you want something else to happen: notify a warehouse, post to a channel, update a spreadsheet. Events are how you attach that behaviour without editing Spree. Spree announces what happened; your code decides what to do about it. There are two ways to listen, and which you want depends on where your code lives:
If you’re building a headless storefront, webhooks are almost certainly what you want. Subscribers are for when you’re running Spree as your own application and want to add behaviour to it.
What Spree announces
Most records announce their own lifecycle:
Those exist for orders, carts, products, variants, customers, payments, fulfillments, returns, media, price changes and more.
On top of that, meaningful business moments get their own events:
For the full list of events and their payloads, see Webhook Events & Payloads.
The distinction matters when choosing what to listen for.
order.updated fires whenever anything about an order changes — including an admin editing a note. order.placed fires once, when a customer actually bought something. Sending a confirmation email on the wrong one is how customers receive nine copies.
What an event carries
An event carries the record it’s about, serialized:Event payload
Reacting in another system
Point a webhook at your endpoint and subscribe it to the events you care about. That’s covered fully in Webhooks — including signature verification, which you should not skip.Reacting inside Spree
A subscriber is a small class that names the events it wants and does something when one arrives.server/app/subscribers/order_placed_subscriber.rb
server/app/subscribers/order_placed_subscriber.rb
server/config/initializers/spree.rb
Subscribers run in the background
By default a subscriber runs as a background job, so a slow API call in your code doesn’t slow down the customer’s checkout — and a failure doesn’t roll back their order. That’s almost always what you want. If you genuinely need to run inside the same transaction, you can ask to:server/app/subscribers/order_placed_subscriber.rb
Publishing your own events
Anything in your own code can announce something, and subscribers and webhooks treat it like any built-in event:server/app/services/fraud_check.rb
Guidance
Listen for the specific event.order.placed rather than order.updated with a status check.
Assume events can arrive more than once. A retry after a network blip can redeliver. Make handlers safe to run twice — check whether you’ve already acted before acting.
Don’t chain long sequences of subscribers. When one event triggers a subscriber that triggers another, working out what happened after the fact becomes archaeology. Prefer one handler that does the sequence.
Keep failures contained. A subscriber that raises shouldn’t take down anything else. Handle your own errors and log them.
Related
- Webhooks — reacting from outside Spree
- Orders — the order lifecycle these events describe
- Imports & Exports — completion events for bulk work

