Webhook implementation best practices for reliability and security.
Webhook Best Practices
Follow these guidelines to build a robust and reliable webhook consumer.
Respond Quickly
- Return a
200status code as quickly as possible - Offload heavy processing to background jobs or queues
- If your endpoint doesn't respond within 30 seconds, we'll consider it a failure
// Good: Acknowledge immediately, process later
app.post('/webhooks', (req, res) => {
res.status(200).send('ok');
queue.add('process-webhook', req.body);
});
Idempotency
Webhooks may be delivered more than once. Make your handlers idempotent:
- Use
data.referenceordata.idto detect duplicate deliveries - Store processed event IDs and skip duplicates
- Design your logic so processing the same event twice has no side effects
app.post('/webhooks', async (req, res) => {
const { data } = req.body;
// Check if already processed
const existing = await db.webhookEvents.findOne({
reference: data.reference
});
if (existing) {
return res.status(200).send('already processed');
}
// Store and process
await db.webhookEvents.create({
reference: data.reference,
event: req.body.event,
processed_at: new Date()
});
// Process the event...
res.status(200).send('ok');
});
Verify Signatures
Always verify the webhook signature before processing any payload. Never trust unverified webhooks.
Use HTTPS
Your webhook endpoint must use HTTPS. We do not deliver webhooks to HTTP URLs.
Handle All Event Types
Your webhook handler should gracefully handle unknown event types:
switch (payload.event) {
case 'transaction.success':
handleSuccess(payload);
break;
case 'transaction.failed':
handleFailure(payload);
break;
case 'transaction.refunded':
handleRefund(payload);
break;
default:
console.log('Unhandled event type:', payload.event);
break;
}
Error Handling
| Your Response | Our Action |
|---|---|
200 - 299 | Delivery successful, no retry |
4xx | Will not retry (client error) |
5xx | Will retry with exponential backoff |
| Timeout (30s) | Will retry with exponential backoff |
Monitor Webhook Deliveries
- Check the Webhook Logs tab in your Developer Settings to monitor delivery status
- Set up alerts for consecutive delivery failures
- Log all incoming webhooks for debugging
Summary
| Practice | Why |
|---|---|
Respond with 200 quickly | Prevent timeout retries |
| Implement idempotency | Handle duplicate deliveries safely |
| Verify signatures | Prevent spoofed webhooks |
| Use HTTPS only | Encrypt data in transit |
| Handle unknown events | Future-proof your integration |
| Process asynchronously | Keep response times low |