Svix and Standard Webhooks — Complete Guide
In this tutorial, you will learn about Svix and Standard Webhooks. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Svix and Standard Webhooks: use managed webhook delivery platforms, implement the Standard Webhooks specification, compare Svix vs custom solutions, and integrate webhook infrastructure as a service.
What You Learn
You will learn about Svix as a managed webhook delivery platform, the Standard Webhooks specification for interoperability, how to integrate Svix into your application, and when to use a managed solution versus building custom webhook infrastructure.
Why It Matters
Building webhook infrastructure is complex: delivery guarantees, retry logic, Rate Limiting, monitoring, and scaling. Managed platforms like Svix handle this complexity. Standard Webhooks ensures your webhooks work with any consumer that follows the spec.
Real-World Use
DodaTech's partner integration platform uses Svix to manage webhook delivery. Svix handles 500K daily deliveries with built-in retries, rate limiting, and monitoring. This eliminated 3 months of custom webhook infrastructure development and reduced operational overhead by 80%.
Standard Webhooks Specification
// Standard Webhooks compliant payload
const standardWebhook = {
// Required fields
id: 'msg_2e8d8b7c5f',
type: 'payment.succeeded',
timestamp: '2026-06-28T12:00:00Z',
// Data payload
data: {
id: 'pi_123',
amount: 5000,
currency: 'usd',
},
};
// Standard Webhooks signature header format
// Header: webhook-id, webhook-timestamp, webhook-signature
const headers = {
'webhook-id': 'msg_2e8d8b7c5f',
'webhook-timestamp': '1759118400', // Unix timestamp
'webhook-signature': 'v1,AbCdEf123456...', // Comma-separated signatures
};
// Verification
function verifyStandardWebhook(payload, headers, secret) {
const webhookId = headers['webhook-id'];
const webhookTimestamp = headers['webhook-timestamp'];
const webhookSignature = headers['webhook-signature'];
// Construct signed content
const signedContent = `${webhookId}.${webhookTimestamp}.${JSON.stringify(payload)}`;
// Extract signatures
const signatures = webhookSignature.split(' ').map(sig => {
const [version, signature] = sig.split(',');
return { version, signature };
});
// Verify each signature
for (const { version, signature } of signatures) {
const expectedSig = crypto
.createHmac('sha256', secret)
.update(signedContent)
.digest('base64');
if (crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSig)
)) {
return { valid: true, version };
}
}
return { valid: false };
}
Expected output: Standard Webhooks defines a consistent format: required fields (id, type, timestamp, data), standardized headers (webhook-id, webhook-timestamp, webhook-signature), and HMAC verification over concatenated signed content.
Svix Integration
const { Svix } = require('svix');
// Initialize Svix client
const svix = new Svix(process.env.SVIX_API_KEY);
// Create an application
async function createApplication(name) {
const app = await svix.application.create({
name,
uid: `app_${Date.now()}`,
});
console.log(`Created application: ${app.id}`);
return app;
}
// Create an endpoint (subscriber)
async function createEndpoint(appId, url, events) {
const endpoint = await svix.endpoint.create(appId, {
url,
description: 'Production webhook consumer',
filterTypes: events,
channels: ['production'],
disabled: false,
rateLimit: 100, // 100 per minute
secret: null, // Auto-generate secret
});
console.log(`Created endpoint: ${endpoint.id}`);
return endpoint;
}
// Send a webhook message
async function sendWebhook(appId, eventType, data) {
const message = await svix.message.create(appId, {
eventType,
payload: {
id: `msg_${Date.now()}`,
type: eventType,
timestamp: new Date().toISOString(),
data,
},
channels: ['production'],
});
console.log(`Sent message: ${message.id}`);
return message;
}
// Usage
async function example() {
const app = await createApplication('My App');
const endpoint = await createEndpoint(
app.id,
'https://consumer.example.com/webhooks',
['payment.succeeded', 'payment.failed']
);
await sendWebhook(app.id, 'payment.succeeded', {
id: 'pi_123',
amount: 5000,
});
}
Expected output: Svix API manages the full webhook lifecycle: applications, endpoints, and message delivery. The platform handles signing, retries, rate limiting, and logging automatically.
Consuming Standard Webhooks
const express = require('express');
const { Webhook } = require('svix');
const app = express();
const SVIX_SECRET = process.env.SVIX_SECRET;
// Svix webhook verification middleware
async function verifySvixWebhook(req, res, next) {
const wh = new Webhook(SVIX_SECRET);
try {
const payload = wh.verify(
JSON.stringify(req.body),
{
'webhook-id': req.headers['webhook-id'],
'webhook-timestamp': req.headers['webhook-timestamp'],
'webhook-signature': req.headers['webhook-signature'],
}
);
req.webhookPayload = payload;
next();
} catch (err) {
console.error('Svix verification failed:', err.message);
return res.status(401).send('Invalid signature');
}
}
// Standard Webhooks consumer endpoint
app.post('/webhooks', verifySvixWebhook, (req, res) => {
const { type, data } = req.webhookPayload;
console.log(`Received ${type}:`, data.id);
// Acknowledge immediately
res.status(200).json({ status: 'ok' });
// Process asynchronously
setImmediate(() => {
handleEvent(type, data);
});
});
function handleEvent(type, data) {
switch (type) {
case 'payment.succeeded':
console.log(`Payment succeeded: ${data.id}`);
break;
case 'payment.failed':
console.log(`Payment failed: ${data.id}`);
break;
default:
console.log(`Unknown event: ${type}`);
}
}
Expected output: Svix's Webhook class verifies Standard Webhooks signatures. The consumer is provider-agnostic. Any platform using Standard Webhooks can send to this endpoint.
Dashboard and Monitoring
// Svix operational endpoints
class SvixOperations {
constructor(svixClient) {
this.svix = svixClient;
}
async getDeliveryAttempts(messageId) {
const attempts = await this.svix.messageAttempt.list(
'app_id',
messageId
);
return attempts.data;
}
async getEndpointStats(endpointId) {
const stats = await this.svix.endpoint.getStats(
'app_id',
endpointId,
{ since: new Date(Date.now() - 86400000) } // Last 24 hours
);
return stats;
}
async getMessageStatus(messageId) {
const message = await this.svix.message.get('app_id', messageId);
const attempts = await this.getDeliveryAttempts(messageId);
const successfulAttempts = attempts.filter(a => a.status === 0); // 0 = success
const lastAttempt = attempts[attempts.length - 1];
return {
id: message.id,
eventType: message.eventType,
status: lastAttempt?.status === 0 ? 'delivered' : 'failed',
attempts: attempts.length,
lastAttemptTime: lastAttempt?.timestamp,
nextRetry: lastAttempt?.nextAttempt,
};
}
async listFailedMessages(appId) {
const messages = await this.svix.message.list(appId, {
status: 'failed',
});
return messages.data;
}
}
// Usage: Check delivery health
async function checkDeliveryHealth() {
const ops = new SvixOperations(svix);
const failedMessages = await ops.listFailedMessages('app_id');
console.log(`Failed messages (24h): ${failedMessages.length}`);
for (const msg of failedMessages.slice(0, 5)) {
const status = await ops.getMessageStatus(msg.id);
console.log(` ${msg.id}: ${status.attempts} attempts`);
}
}
Expected output: Svix provides rich operational APIs: delivery attempt details, endpoint statistics, failed message listing, and per-message status. These enable custom monitoring dashboards.
Custom vs Managed: Decision Framework
// Decision matrix
function decideWebhookInfrastructure({ monthlyVolume, events, subscribers, teamSize }) {
const factors = {
// Below these thresholds, build custom is reasonable
volume: monthlyVolume < 100000,
subscribers: subscribers < 50,
events: events < 10,
teamSize: teamSize < 3,
};
const allLowVolume = Object.values(factors).every(v => v === true);
if (allLowVolume) {
return {
recommendation: 'custom',
reason: 'Low volume, few subscribers. Custom webhook code is manageable.',
estimatedEffort: '1-2 weeks',
};
}
return {
recommendation: 'managed',
reason: 'High volume or many subscribers. Managed platform saves significant engineering time.',
estimatedEffort: '2-3 days integration',
platforms: [
{ name: 'Svix', pricing: 'Pay per delivery', features: ['Standard Webhooks', 'Retries', 'Dashboard'] },
{ name: 'Convoy', pricing: 'Open source / self-hosted', features: ['Open source', 'Self-hosted', 'Webhook gateway'] },
],
};
}
console.log(decideWebhookInfrastructure({
monthlyVolume: 500000,
subscribers: 200,
events: 15,
teamSize: 2,
}));
Expected output: Decision framework recommends managed platforms for high-volume systems (>100K/month), many subscribers (>50), or small teams. Custom solutions work for low-volume, simple use cases.
Common Mistakes
1. Not Using Standard Webhooks
Custom webhook formats require consumers to implement provider-specific Parsing. Standard Webhooks provides a universal format consumers already support. Adopting it reduces integration friction.
2. Managing Webhook Infrastructure In-House
Building reliable webhook delivery is hard. Retries, rate limiting, monitoring, and scaling require significant engineering investment. For most teams, managed platforms are more cost-effective.
3. Not Using Svix's Verification Library
Implementing Standard Webhooks verification manually is error-prone. Svix provides verified client libraries. Use them. Manual implementation may miss edge cases.
4. Ignoring Svix Dashboard
Svix provides a dashboard for delivery monitoring. Use it. It shows delivery attempts, failures, retry status, and endpoint health. Custom dashboards are unnecessary.
5. No Fallback for Managed Platform Outages
If Svix has an outage, your webhook delivery stops. Implement a fallback: queue messages locally, retry when Svix recovers, or use a secondary delivery mechanism.
Practice Questions
1. What is the Standard Webhooks specification?
A community specification defining a standard format for webhook payloads and headers. It standardizes message ID, event type, timestamp, signature verification, and idempotency for interoperability.
2. How does Svix simplify webhook delivery?
Svix manages webhook infrastructure: delivery, retries with exponential backoff, rate limiting, signature verification, delivery logging, monitoring dashboards, and webhook management APIs.
3. When should you use a managed webhook platform vs custom?
Use managed when: high volume (>100K/month), many subscribers (>50), multiple event types, or small team. Build custom when: low volume, few subscribers, simple needs, or full control required.
4. What are the benefits of Standard Webhooks for consumers?
Consumers can use a single verification library for all providers. Consistent payload format. Standard headers. No provider-specific parsing. Reduced integration time.
Challenge
Migrate a custom webhook system to Svix: create Svix application and endpoints, update provider code to send via Svix API, update consumer code to verify with Svix's Webhook class, set up dashboard monitoring and alerts, configure retry policy and rate limits, and validate delivery behavior matches the custom system.
FAQ
Mini Project: Svix Integration
Integrate Svix into an Express application: create application and endpoints via Svix API, send webhook messages on business events, verify incoming webhooks with Svix's verification library, build a custom dashboard using Svix's operational APIs, configure retry policy and rate limits, and set up Slack alerts for delivery failures.
What's Next
Now that you know about managed webhook platforms, review Webhook Best Practices to ensure your webhook system follows industry standards.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro