Outbound webhooks (Zapier)
What this is
Outbound webhooks let your systems receive Sumeru events in real time. Use cases:
- Sync customer changes to your CRM
- Notify Slack on big orders
- Trigger Zapier flows
- Pipe attribution data to your data warehouse
- Build custom integrations
Subscribe
curl -X POST \
-H "Authorization: Bearer copt_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhook",
"events": ["campaign.completed", "order.attributed"],
"secret": "auto"
}' \
"https://api.sumeru.systems/api/v1/webhook-subscriptions"
Response:
{
"data": {
"id": "whk_abc123",
"url": "https://yourapp.com/webhook",
"events": ["campaign.completed", "order.attributed"],
"secret": "wsec_xY7aB3cKz9...",
"active": true,
"created_at": "2026-05-10T14:23:00Z"
}
}
Save the secret — it's shown once. You'll use it to
verify signatures.
Available events
| Event | Description |
|---|---|
customer.created | New Customer 360 row |
customer.updated | Profile field changed |
customer.tagged | Tag added |
lifecycle.changed | Lifecycle stage transition |
opt_in.changed | Channel opt-in toggled |
order.created | Shopify order received (post-import) |
order.attributed | Attribution complete for order |
campaign.launched | Campaign send begins |
campaign.completed | Campaign + attribution window done |
campaign.approved / .rejected | Approval decision |
journey.enrolled | Customer entered journey |
journey.exited | Customer exited (with reason) |
journey.step_executed | Specific journey step ran |
anomaly.fired | Anomaly detected (P1/P2/P3) |
gdpr.completed | GDPR erasure / export finished |
webhook.failed | Outbound webhook delivery failed (meta) |
Subscribe to * for all events (only recommended for
audit-style consumers).
Payload shape
Common envelope:
{
"id": "evt_abc123",
"type": "campaign.completed",
"created_at": "2026-05-10T14:23:00Z",
"shop_domain": "yourshop.com",
"data": {
"campaign_id": "cam_xyz789",
"name": "Spring Sale",
"audience_size": 4200,
"sent": 4150,
"skipped": 50,
"revenue_attributed": 14280.00,
"lift_vs_holdout": 0.18
}
}
id is unique per event delivery (idempotent retry).
Signature verification
Header: X-Sumeru-Signature: sha256=<hex>
import crypto from 'node:crypto';
function verifySumeruWebhook(rawBody, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
try {
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
} catch {
return false;
}
}
// Express handler
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-sumeru-signature'];
if (!verifySumeruWebhook(req.body, sig, process.env.ATLANTIS_SECRET)) {
return res.status(401).send('invalid signature');
}
const event = JSON.parse(req.body.toString());
// process event
res.status(200).end();
});
Key: verify on the raw body (before JSON parse).
Retry policy
5 retries with exponential backoff: 1s, 5s, 30s, 5min, 30min.
After 5 failures, event marked failed and surfaced in
admin failures dashboard. Manual replay available.
Auto-disable
If a subscription has > 100 failed deliveries in 24 hours, it's auto-disabled with notification. Re-enable from admin (after fixing the endpoint).
Listing + managing subscriptions
# List all
curl -H "Authorization: Bearer copt_live_..." \
"https://api.sumeru.systems/api/v1/webhook-subscriptions"
# Pause
curl -X PATCH \
-H "Authorization: Bearer copt_live_..." \
-d '{"active": false}' \
"https://api.sumeru.systems/api/v1/webhook-subscriptions/whk_abc123"
# Rotate secret
curl -X POST \
-H "Authorization: Bearer copt_live_..." \
"https://api.sumeru.systems/api/v1/webhook-subscriptions/whk_abc123/rotate"
# Delete
curl -X DELETE \
-H "Authorization: Bearer copt_live_..." \
"https://api.sumeru.systems/api/v1/webhook-subscriptions/whk_abc123"
Replay
For a specific failed delivery:
curl -X POST \
-H "Authorization: Bearer copt_live_..." \
"https://api.sumeru.systems/api/v1/webhook-subscriptions/whk_abc123/deliveries/del_abc/replay"
Best practices
✅ Idempotent endpoints. Same event might arrive twice on retry; your code shouldn't double-act.
✅ 2xx fast, process async. Return 200 within a second; do work in background.
✅ Verify signatures every time. Without verification, anyone can forge events.
✅ Subscribe narrowly. Specific event types reduce volume and make debugging easier.
❌ Don't expose webhook URLs in client-side code. They're unauthenticated for delivery; URL itself is sensitive.
❌ Don't return non-2xx for "I don't want this event." Filter at subscribe time, not at delivery.