Skip to main content

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

EventDescription
customer.createdNew Customer 360 row
customer.updatedProfile field changed
customer.taggedTag added
lifecycle.changedLifecycle stage transition
opt_in.changedChannel opt-in toggled
order.createdShopify order received (post-import)
order.attributedAttribution complete for order
campaign.launchedCampaign send begins
campaign.completedCampaign + attribution window done
campaign.approved / .rejectedApproval decision
journey.enrolledCustomer entered journey
journey.exitedCustomer exited (with reason)
journey.step_executedSpecific journey step ran
anomaly.firedAnomaly detected (P1/P2/P3)
gdpr.completedGDPR erasure / export finished
webhook.failedOutbound 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.

See also