What are webhooks?
Think of webhooks as “reverse API calls.” Instead of an external service asking your app for updates, your app tells the external service when something happens. For example, when a new order is created in your app, Exo can automatically notify:- A Zapier workflow that sends a Slack message
- A Make scenario that updates a spreadsheet
- An n8n workflow that creates an invoice
Triggers
Each resource defines which events it responds to. There are three trigger types:| Trigger | When it fires |
|---|---|
on_create | A new record is created |
on_update | An existing record is updated |
on_delete | A record is deleted |
How webhook delivery works
When a trigger fires, here’s what happens:- Exo detects the model event (created, updated, or deleted)
- It finds all webhook subscriptions that match the resource and event
- For each matching subscription, Exo dispatches a background job
- The job sends an HTTP POST to the subscriber’s URL with the event data
- The payload includes an HMAC signature so the receiver can verify it’s authentic
Webhooks are delivered via Laravel’s queue system. Make sure you have a queue worker running (
php artisan queue:work) for webhooks to be sent.Webhook payload
Every webhook delivery sends a JSON payload like this:data field contains the output of your resource’s transform method. The event and resource fields tell the receiver what happened and to which resource.
Ownership and webhooks
Webhook subscriptions respect the same ownership rules as the API:- Admins receive webhooks for all records, regardless of owner
- Regular users only receive webhooks for records they own (based on the resource’s
ownerColumn)
on_create for orders, they only receive webhooks for orders where user_id matches their ID.
Custom webhook queue
By default, webhook delivery jobs run on the queue defined inconfig('exo.queue'). You can override this per resource:
null to use the default queue.