Webhooks Explained Simply: Understand and Use Webhooks
A webhook is a mechanism that allows one system to automatically send data to another system whenever a specific event occurs. No repeated requests, no waiting: the information arrives on its own, in real time.
This guide covers how webhooks work technically, the differences with API polling, security best practices, and concrete implementations.
What is a webhook?
A webhook is a configurable URL that receives automatic HTTP requests when a specific event triggers in a source application. It's also called an "HTTP callback" or a "web push notification."
The principle is straightforward:
- Configuration: provide a receiving URL (endpoint) to a third-party service.
- Trigger: an event occurs on the source side (new order, payment completed, etc.).
- Delivery: the source service sends an HTTP request (usually POST) to the configured URL, containing the event data in JSON format.
- Processing: the receiving server processes the payload and executes the necessary actions.
Anatomy of a webhook
A typical webhook request consists of:
- HTTP method:
POSTin the vast majority of cases. - Target URL: the endpoint configured by the receiver.
- Headers: metadata like content type (
Content-Type: application/json), an event identifier, and a signature for verification. - Body (payload): the event data in JSON format.
Example payload:
{
"id": "evt_01HXYZ123",
"type": "payment.completed",
"timestamp": "2026-04-14T20:15:00Z",
"data": {
"amount": 99.99,
"currency": "EUR",
"customer_id": "cust_42"
}
}
Webhook vs API polling: what's the difference?
The fundamental difference lies in who initiates the communication.
API polling (repeated requests)
Polling involves regularly querying a server to check if new data is available.
# The client polls every 30 seconds
while true; do
curl -s https://api.example.com/orders?since=last_check
sleep 30
done
Problems with polling:
- Resource waste: most requests return empty data (no changes).
- Latency: the delay between the event and its detection depends on the polling interval. With a 30-second interval, average latency is 15 seconds.
- Server load: thousands of polling clients create unnecessary load on the source server.
- Rate limiting: APIs often limit request counts, forcing wider intervals between queries.
Webhooks (push notifications)
With a webhook, the source server pushes data to the client only when an event occurs.
Advantages of webhooks:
- Real-time: data arrives instantly after the event.
- Efficiency: no unnecessary requests, no empty responses.
- Scalability: load on the source server is proportional to actual events, not to the number of clients.
- Bandwidth savings: only useful data is transferred.
Comparison table
| Criteria | API Polling | Webhook |
|---|---|---|
| Initiator | Client | Source server |
| Real-time | No (latency = interval) | Yes (near instant) |
| Server load | High (constant requests) | Low (only on event) |
| Client complexity | Low (simple loop) | Medium (endpoint to maintain) |
| Reliability | Good (client controls) | Medium (retry, failure handling) |
| Best use case | Rarely updated data | Frequent, critical events |
Concrete webhook use cases
1. Payments and e-commerce
When a customer makes a payment on Stripe, PayPal, or another provider, a webhook notifies the order system:
payment.completed→ confirm the order and send the confirmation email.payment.failed→ cancel the reservation and notify the customer.refund.processed→ update inventory and accounting.
2. CI/CD integration
Platforms like GitHub, GitLab, or Bitbucket send webhooks on every push, pull request, or merge:
push→ trigger a build and test pipeline.pull_request.opened→ launch static code analysis.deployment.success→ notify the team on Slack.
3. SaaS and automation
Tools like Zapier, Make (Integromat), or n8n rely heavily on webhooks to connect services together:
- New lead on HubSpot → create a task in Notion.
- Email marked "important" in Gmail → SMS notification via Twilio.
- New row in Google Sheets → update a CRM.
4. Real-time notifications
Monitoring and alerting systems use webhooks for instant notifications:
- Server goes down → PagerDuty alert → automatic call to the on-call engineer.
- CPU threshold exceeded → Slack message.
- SSL certificate expiring soon → email to admin.
How to implement a webhook receiver
Create the endpoint
Here's an example in Node.js with Express:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
// Shared secret with the sender
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
app.post('/webhooks/payments', (req, res) => {
// 1. Verify the signature
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
const expectedSig = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expectedSig) {
return res.status(401).json({ error: 'Invalid signature' });
}
// 2. Process the event
const { type, data } = req.body;
switch (type) {
case 'payment.completed':
handlePaymentCompleted(data);
break;
case 'payment.failed':
handlePaymentFailed(data);
break;
default:
console.log(`Unhandled event: ${type}`);
}
// 3. Respond immediately (200 OK)
res.status(200).json({ received: true });
});
app.listen(3000, () => {
console.log('Webhook listener on port 3000');
});
Key implementation points
Respond quickly: the endpoint must return a 200 OK status as fast as possible. Heavy processing (sending emails, database updates) should be asynchronous (queue, worker).
Handle idempotency: the same webhook may be sent multiple times (retry). The system must be able to process a duplicate event without undesirable side effects. Use the event's unique ID (id) as a deduplication key.
Log everything: store every received webhook (payload, timestamp, processing status) for debugging and auditing.
How to implement a webhook sender
Sending architecture
async function sendWebhook(url, payload, secret, retries = 3) {
const timestamp = Date.now();
const signature = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${JSON.stringify(payload)}`)
.digest('hex');
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': signature,
'X-Webhook-Timestamp': String(timestamp),
'X-Webhook-ID': crypto.randomUUID(),
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(10000), // 10s timeout
});
if (response.ok) {
console.log(`Webhook sent successfully (attempt ${attempt})`);
return true;
}
console.warn(`Attempt ${attempt}: status ${response.status}`);
} catch (error) {
console.warn(`Attempt ${attempt} failed:`, error.message);
}
// Exponential backoff
if (attempt < retries) {
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt)));
}
}
console.error(`Webhook failed after ${retries} attempts`);
return false;
}
Retry strategy
- Exponential backoff: wait 1s, 2s, 4s, 8s between attempts.
- Maximum retries: 3 to 5 before giving up.
- Timeout: 5 to 10 seconds per attempt.
- Dead letter queue: store permanently failed webhooks for analysis and manual replay.
Webhook security
Signature verification
HMAC-SHA256 signature is the webhook security standard. The principle:
- Sender and receiver share a secret key.
- The sender generates an HMAC of the payload with this key.
- The receiver recalculates the HMAC and compares it with the received one.
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Use timingSafeEqual to prevent timing attacks.
Other security measures
- HTTPS mandatory: never use HTTP for webhooks in production.
- IP restriction: only accept webhooks from the sender's known IP ranges.
- Secret rotation: change the secret key periodically.
- Payload validation: verify the structure and data types of received payloads.
- Rate limiting: limit requests per IP to prevent DDoS.
- Logging: log all attempts (successful or failed) with the source IP.
Failure handling and reliability
Webhooks are not 100% guaranteed. Unstable network, server maintenance, timeouts — many causes can make a delivery fail.
Reliability architecture
- Message queue: never send a webhook directly from the main process. Route it through a queue (Redis, RabbitMQ, SQS).
- Retry with backoff: as described above.
- Monitoring: track delivery rates and alert on drops.
- Dashboard: interface to view sent webhooks, their status, and replay failures.
- Health check endpoint: verify the target URL is reachable before sending.
Verification endpoint (handshake)
Some providers implement a handshake during configuration:
- The provider sends a
GETrequest with a challenge token. - The receiver must respond with the hashed token.
GET /webhooks?challenge=ch_abc123
→ Response: ch_abc123 (or HMAC of the challenge)
This proves that the receiver actually controls the configured URL.
Popular tools using webhooks
Payment platforms
- Stripe: webhooks for payments, refunds, disputes, subscriptions.
- PayPal: IPN notifications and API v2 webhooks.
- Square: webhooks for transactions, inventory, customers.
Development and CI/CD
- GitHub: events for push, pull requests, issues, deployments.
- GitLab: system and project webhooks, pipeline trigger support.
- Jenkins: Generic Webhook Trigger plugin for triggering builds.
Communication
- Slack: incoming webhooks for posting messages in channels.
- Discord: webhooks for sending embeds and messages.
- Telegram: Bot API with webhook mode for chat bots.
Automation
- Zapier: connectors based on webhooks to link hundreds of services.
- Make (Integromat): automation scenarios triggered by webhooks.
- n8n: open-source automation tool with native webhook node.
Testing and debugging webhooks
Local tools
ngrok: exposes a public tunnel to localhost, ideal for testing webhooks during development.
ngrok http 3000
# → Forwarding https://abc123.ngrok.io → http://localhost:3000
Configure the ngrok URL as the webhook endpoint during development.
Webhook.site: free service that generates a unique URL and displays all received requests in real time. Perfect for inspecting payloads.
Testing best practices
- Log systematically: record the raw payload, headers, and response status.
- Mock server: use tools like Mockoon or WireMock to simulate an endpoint.
- Unit tests: write tests for each event type processed.
- Load tests: verify behavior under high volumes of simultaneous webhooks.
- Production monitoring: dashboard with the number of webhooks received, success rate, and average processing time.
FAQ
What is a webhook in simple terms?
A webhook is a URL that automatically receives data from another service whenever an event occurs. Instead of fetching the information (polling), the information comes on its own, like a push notification.
What's the difference between a webhook and a REST API?
A REST API works on demand: the client sends a request and receives a response. A webhook works in push mode: the server sends data to the client without the client needing to ask for anything. REST API is client-initiated, webhooks are server-initiated.
Are webhooks secure?
Yes, provided you follow best practices: use HTTPS, verify HMAC-SHA256 signatures, restrict source IPs, and validate received payloads. Without these measures, a webhook exposes a potentially vulnerable public endpoint.
What to do if a webhook doesn't reach its destination?
Implement a retry mechanism with exponential backoff, monitor delivery rates, and maintain a dead letter queue for permanent failures. Some providers also offer an API to relist missed events.
Can a webhook be sent multiple times?
Yes, and this is expected behavior. Senders implement automatic retries on non-response (timeout, 5xx errors). The receiver must be idempotent: processing the same event twice without undesirable side effects, typically using the event's unique ID as a deduplication key.