Webhooks Intro
title: "Introduction to Webhooks" description: "Learn what webhooks are, how they enable event-driven server-to-server communication, and why they are essential for modern API integrations." weight: 11 date: 2026-06-28 lastmod: 2026-06-28 tags: ["apis", "webhooks"]
Webhooks are user-defined HTTP callbacks that are triggered by specific events. When an event occurs, the source site makes an HTTP request to the URL configured for the webhook, enabling real-time server-to-server communication.
## What You'll Learn
- What webhooks are and how they work
- Webhooks vs polling
- Common webhook use cases
- Webhook architecture overview
- Security considerations
## Why It Matters
Webhooks are the backbone of modern API integrations. They enable real-time event notifications between services without polling, reducing latency and server load.
## Real-World Use
A SaaS platform uses webhooks to notify a customer's CRM when a new subscription is created. The CRM receives the subscription data via HTTP POST within seconds, triggering automated workflows without manual polling.
## Flow Chart
```mermaid
flowchart LR
A[Event Source] -->|Event Occurs| B{Webhook Trigger}
B --> C[HTTP POST to URL]
C --> D[Consumer Server]
D --> E[Process Event]
D --> F[Acknowledge 200 OK]
Code Examples
Example 1: Simple Webhook Server
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def handle_webhook():
data = request.json
# Validate webhook
event_type = request.headers.get('X-Event-Type')
signature = request.headers.get('X-Signature')
print(f"Received webhook: {event_type}")
print(f"Payload: {data}")
# Process the event
if event_type == 'order.created':
process_order(data)
elif event_type == 'payment.received':
process_payment(data)
# Acknowledge receipt
return jsonify({"status": "received"}), 200
def process_order(data):
order_id = data.get('id')
customer = data.get('customer')
# Process the order
print(f"Processing order {order_id} for {customer}")
def process_payment(data):
transaction_id = data.get('transaction_id')
amount = data.get('amount')
print(f"Processing payment {transaction_id}: ${amount}")
if __name__ == '__main__':
app.run(port=8080)
Expected output: Webhook server receives POST requests, validates headers, processes different event types, and returns 200 OK.
Example 2: Sending a Webhook from a Provider
const https = require('https');
async function sendWebhook(url, eventType, payload) {
const data = JSON.stringify({
event: eventType,
timestamp: new Date().toISOString(),
data: payload,
});
return new Promise((resolve, reject) => {
const req = https.request(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(data),
'X-Event-Type': eventType,
'X-Signature': generateSignature(data),
'X-Delivery-Attempt': '1',
},
timeout: 10000,
}, (res) => {
let body = '';
res.on('data', chunk => body += chunk);
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve({ success: true, statusCode: res.statusCode });
} else {
resolve({ success: false, statusCode: res.statusCode, body });
}
});
});
req.on('error', reject);
req.on('timeout', () => {
req.destroy();
reject(new Error('Request timeout'));
});
req.write(data);
req.end();
});
}
function generateSignature(payload) {
const crypto = require('crypto');
const secret = process.env.WEBHOOK_SECRET;
return crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
}
// Usage
sendWebhook(
'https://consumer.example.com/webhook',
'user.created',
{ id: 123, email: 'user@example.com' }
).then(console.log).catch(console.error);
Expected output: Provider sends signed webhook POST request and receives acknowledgment from consumer.
Example 3: Webhook Registration Flow
const express = require('express');
const app = express();
app.use(express.json());
// In-memory webhook subscriptions
const webhooks = [];
// Register webhook
app.post('/api/webhooks/register', (req, res) => {
const { url, events, secret } = req.body;
if (!url || !events || !Array.isArray(events)) {
return res.status(400).json({ error: 'url and events required' });
}
const webhook = {
id: generateId(),
url,
events,
secret: secret || generateSecret(),
status: 'active',
createdAt: new Date().toISOString(),
stats: { sent: 0, failed: 0, lastDelivery: null },
};
webhooks.push(webhook);
// Send test webhook to verify
sendTestWebhook(webhook);
res.status(201).json({
id: webhook.id,
secret: webhook.secret, // Return once
url: webhook.url,
events: webhook.events,
});
});
// List webhooks
app.get('/api/webhooks', (req, res) => {
res.json(webhooks.map(w => ({
id: w.id,
url: w.url,
events: w.events,
status: w.status,
stats: w.stats,
})));
});
// Delete webhook
app.delete('/api/webhooks/:id', (req, res) => {
const index = webhooks.findIndex(w => w.id === req.params.id);
if (index === -1) return res.status(404).json({ error: 'Not found' });
webhooks.splice(index, 1);
res.status(204).end();
});
function generateId() {
return Math.random().toString(36).substring(2, 15);
}
function generateSecret() {
const crypto = require('crypto');
return crypto.randomBytes(32).toString('hex');
}
app.listen(3000);
Expected output: REST API for registering, listing, and deleting webhook subscriptions with auto-generated secrets.
Common Mistakes
| Mistake | Explanation |
|---|---|
| Not verifying webhook signatures | Without signature verification, anyone can send fake events to your endpoint |
| Returning non-2xx for successful processing | Always return 200 OK to acknowledge receipt; non-2xx triggers retries |
| Processing webhooks synchronously for long tasks | Acknowledge immediately (200) and process asynchronously to avoid timeouts |
| Not handling webhook retries | Consumers should handle duplicate deliveries idempotently |
| Storing secrets insecurely | Webhook signing secrets must be stored encrypted, never in source code |
Practice Questions
- What is the difference between webhooks and polling?
- How does a webhook provider know where to send events?
- What HTTP method do webhooks typically use?
- What should a consumer return to acknowledge a webhook?
- Why are webhook signatures important?
Challenge
Build a webhook provider that allows users to register webhook URLs for specific events. When events occur, send signed POST requests to all registered URLs. Include a verification mechanism (challenge-response) when registering a webhook.
FAQ
Mini Project
Build a webhook provider service that allows users to register webhooks, sends signed HTTP POST requests on events, and provides delivery logs. Include a webhook simulator for testing consumer endpoints.
What's Next
Learn the differences between webhooks and polling
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro