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 200 status 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.reference or data.id to 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 ResponseOur Action
200 - 299Delivery successful, no retry
4xxWill not retry (client error)
5xxWill 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

PracticeWhy
Respond with 200 quicklyPrevent timeout retries
Implement idempotencyHandle duplicate deliveries safely
Verify signaturesPrevent spoofed webhooks
Use HTTPS onlyEncrypt data in transit
Handle unknown eventsFuture-proof your integration
Process asynchronouslyKeep response times low