Architecture

Webhook Architecture

Patterns for reliable, secure and easy-to-debug webhook systems

What is a webhook and how is it different from a REST API?

In a REST API, you ask: your application makes a GET request and waits for the response. In a webhook, the system tells you: when something happens (payment approved, commit pushed, user registered), the server fires a POST to the URL you registered.

This inversion of control makes webhooks very efficient — no polling, no open connections — but also harder to test and debug.

Stripe / GitHub
Publisher
POST →
httpdrop
Inspector / Relay
Your API
Consumer

The 5 pillars of a robust webhook

  1. 1
    Asynchronous processing — Return 200 immediately and process the payload in the background (queue, worker). Never do slow operations before responding.
  2. 2
    Idempotency — The same event can arrive more than once (automatic retry). Use the eventId from the payload to deduplicate: if already processed, return 200 without reprocessing.
  3. 3
    HMAC signature verification — Validate the X-Signature header (HMAC-SHA256 of body + secret) before processing any payload.
  4. 4
    Retry with exponential backoff — If your API returns 5xx, the publisher should retry: 1min → 5min → 30min → 2h. 4xx errors should not trigger retries.
  5. 5
    Logs and alerts — Record each received event with: eventId, processing status, latency and retry count. Alert when the failure rate exceeds 5%.

Testing webhooks with httpdrop

httpdrop works as a temporary receiver endpoint to inspect real webhook payloads — and also as a sender for outbound webhooks from your test application.

🔍
Inspect real payloads — Use the httpdrop URL as the webhook URL in Stripe/GitHub during development and see the exact payload that will reach your API.
📤
Test outbound webhooks — Configure httpdrop as the destination for your application's webhooks and inspect whether the payload, headers and HMAC signature are correct.
🔄
Replay — Resend any captured webhook with one click to test again without having to retrigger the original event.
HMAC signature verification (Node.js)
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
⚠️
Security: Never expose your webhook URL in public logs or API responses. Treat it as a credential. Always use HTTPS and validate the signature before processing any data.
Ready to implement? Check the full technical documentation with API reference, code examples and detailed parameters.
View docs →