Glossary

Payment Webhook

A payment webhook is an automated HTTP callback that notifies a merchant's server in real time when a payment event occurs.

Key Takeaways

  • A payment webhook is an HTTP POST callback that a payment processor sends to a merchant's server whenever a transaction event occurs, such as a successful charge, refund, or dispute.
  • Security is critical: webhook endpoints must verify HMAC-SHA256 signatures, validate timestamps for replay protection, and handle idempotency since providers guarantee at-least-once delivery, not exactly-once.
  • Bitcoin and Lightning payment webhooks differ from card network callbacks: on-chain transactions require multiple confirmation events over minutes, while Lightning invoice settlement fires near-instantly with no chargeback risk.

What Is a Payment Webhook?

A payment webhook is an automated server-to-server HTTP callback triggered by a payment event. When a customer completes a purchase, requests a refund, or disputes a charge, the payment gateway sends an HTTP POST request to a pre-registered URL on the merchant's server. The POST body contains a JSON payload describing the event type and the transaction data associated with it.

The term "webhook" was coined by Jeff Lindsay in 2007 to describe a pattern where one system pushes notifications to another via HTTP, rather than requiring the second system to repeatedly ask for updates. In payment processing, webhooks are sometimes called "callbacks," "notifications," or "IPNs" (Instant Payment Notifications, a legacy PayPal term). Regardless of name, the mechanism is the same: the payment provider tells your server what happened, so your server does not have to keep asking.

Webhooks are the foundation of event-driven payment architectures. Without them, merchants would need to poll the provider's API at regular intervals to check transaction status: a pattern that wastes bandwidth, burns API quotas, and introduces latency between when an event occurs and when the merchant learns about it.

How It Works

The webhook lifecycle follows a predictable sequence from registration through event delivery.

  1. The merchant registers an HTTPS endpoint URL with the payment provider, either through a dashboard or via API
  2. A payment event occurs in the provider's system (charge succeeds, refund is issued, dispute is opened)
  3. The provider constructs a JSON payload containing the event type, timestamp, and transaction data
  4. The provider signs the payload using HMAC-SHA256 and sends it as an HTTP POST to the registered endpoint
  5. The merchant's server verifies the signature, returns an HTTP 200 status code to acknowledge receipt, and processes the event asynchronously

If the merchant's server fails to return a 2xx status code, the provider retries delivery using exponential backoff. Stripe, for example, retries up to 25 times over 72 hours before disabling the endpoint entirely.

Webhook Payload Structure

A typical webhook payload wraps transaction data inside an event envelope. Here is an example from a payment processor:

{
  "id": "evt_1NG8Du2eZvKYlo2CUI79vXWy",
  "type": "payment_intent.succeeded",
  "created": 1686089970,
  "data": {
    "object": {
      "id": "pi_3NG8Du2eZvKYlo2C0ghnFaHN",
      "amount": 2000,
      "currency": "usd",
      "status": "succeeded"
    }
  }
}

The type field identifies what happened. The data.object field contains the full resource that changed. The id field serves as a unique event identifier used for idempotent processing.

Common Event Types

Payment providers emit dozens of event types. The most commonly handled ones fall into a few categories:

CategoryExample Events
Chargescharge.succeeded, charge.failed, charge.refunded
Disputescharge.dispute.created, charge.dispute.closed
Subscriptionsinvoice.paid, invoice.payment_failed
Payoutspayout.paid, payout.failed
Refundsrefund.created, refund.updated

Signature Verification

Every production webhook endpoint must verify the cryptographic signature included in the request headers. Without verification, an attacker could forge webhook payloads to trigger fraudulent order fulfillment or fake refund notifications.

The standard approach uses HMAC-SHA256. The provider computes a hash over the raw request body (combined with a timestamp) using a shared secret, then includes the result in a request header. The merchant's server recomputes the hash and compares the two values using constant-time comparison to prevent timing attacks.

// Node.js webhook signature verification
const crypto = require("crypto");

function verifyWebhookSignature(payload, signature, secret) {
  const timestamp = signature.split(",")[0].split("=")[1];
  const receivedSig = signature.split(",")[1].split("=")[1];

  const signedPayload = timestamp + "." + payload;
  const expectedSig = crypto
    .createHmac("sha256", secret)
    .update(signedPayload)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(receivedSig),
    Buffer.from(expectedSig)
  );
}

Different providers use different header names for the signature. Stripe uses Stripe-Signature, Square uses x-square-hmacsha256-signature, and PayPal uses certificate-based RSA verification via Paypal-Transmission-Sig. The emerging Standard Webhooks specification aims to unify this with a standard webhook-signature header and support for both HMAC-SHA256 and Ed25519 signing.

Retry Logic and Failure Handling

Webhook delivery uses at-least-once semantics: the provider guarantees it will try to deliver an event at least once, but it may deliver the same event multiple times. Retries use exponential backoff, doubling the delay between each attempt.

A typical retry schedule looks like this:

  1. Immediate retry on first failure
  2. 30-second delay
  3. 5-minute delay
  4. 30-minute delay
  5. 2-hour delay
  6. 24-hour delay (final retry)

HTTP status codes in the 2xx range signal success. Any 3xx redirect, 4xx client error, or 5xx server error triggers a retry. Connection timeouts (typically 10 to 30 seconds depending on the provider) also trigger retries. After all retries are exhausted, undeliverable events are logged or moved to a dead letter queue for manual investigation.

Webhooks vs. Polling

Polling is the alternative to webhooks: instead of waiting for the provider to push an event, the merchant's server periodically calls the provider's API to check for status changes.

AspectWebhooksPolling
LatencyNear real-timeEqual to polling interval
Server loadFires only on eventsConstant requests regardless of changes
API quota usageMinimalProportional to poll frequency
Network requirementsRequires inbound HTTPSOutbound-only (works behind firewalls)
ReliabilityDepends on endpoint uptimeClient controls timing
Event orderingNot guaranteedClient controls order

Most production systems use a hybrid approach: webhooks handle real-time event notification, while periodic API calls serve as a reconciliation fallback. If a webhook delivery fails or the endpoint experiences downtime, the polling mechanism catches any missed events during the next reconciliation pass.

Bitcoin and Lightning Webhooks

Payment webhooks in the Bitcoin ecosystem differ fundamentally from card network callbacks. Card payments follow a deterministic authorize-capture-settle flow, while Bitcoin transactions rely on probabilistic block confirmations and Lightning payments settle through HTLC preimage reveals.

On-Chain Confirmation Callbacks

When a customer pays with on-chain Bitcoin, the merchant's payment processor (such as BTCPay Server) fires webhooks at multiple stages:

  • Payment detected in the mempool (zero confirmations): the transaction is visible but not yet confirmed in a block
  • First block confirmation (~10 minutes): the transaction is included in a mined block
  • Threshold reached (1 to 6 confirmations depending on the merchant's risk tolerance): the payment is considered settled

This multi-stage confirmation model has no equivalent in card processing. A merchant receiving a $50 card payment gets a single authorization webhook. A merchant receiving 0.001 BTC gets a series of confirmation events spread over minutes, each reducing the probability of a double-spend. Six confirmations (~60 minutes) is the traditional threshold for high-value transactions, though many merchants accept one confirmation for typical amounts.

Lightning Invoice Settlement

Lightning invoice webhooks behave more like traditional payment webhooks in terms of speed. When a payer settles a BOLT 11 invoice, the payment completes in milliseconds as the preimage propagates back through the route. The merchant's Lightning node transitions the invoice from OPEN to SETTLED, and the webhook fires immediately.

Native Lightning node software (LND, Core Lightning) exposes invoice state changes through gRPC streams rather than HTTP webhooks. Payment processors like BTCPay Server and managed Lightning APIs from providers such as Lightspark translate these gRPC streams into standard HTTP webhook callbacks that web applications can consume.

A key advantage of Lightning webhooks over card webhooks: there are no chargebacks. Once a Lightning payment settles, it is final. The merchant never receives a dispute.created event because the payment protocol does not support reversals. This simplifies webhook handling for payment finality.

Use Cases

Order Fulfillment

The most common use case: a payment_intent.succeeded webhook triggers order fulfillment. The merchant's server creates a shipping label, sends a confirmation email, and updates inventory. Without webhooks, the merchant would need to poll for payment status after every checkout, adding latency and complexity.

Subscription Billing

Recurring billing depends heavily on webhooks. When a subscription renewal fails (invoice.payment_failed), the merchant's system can trigger dunning emails, retry the charge, or pause the subscription. When a payment succeeds, access is extended automatically.

Fraud Detection and Disputes

Dispute webhooks (charge.dispute.created) alert merchants the moment a customer files a chargeback. Early notification gives merchants time to gather evidence and respond within the dispute window, which is typically 7 to 21 days depending on the card network.

Multi-Rail Payment Orchestration

Payment orchestration platforms use webhooks to route events from multiple processors through a single integration point. A merchant accepting payments through Stripe, PayPal, and a Bitcoin processor can normalize webhook payloads from all three into a unified event format for their backend systems. See our research on API economy and payments infrastructure for a deeper look at how modern payment APIs compose.

Risks and Considerations

Duplicate Delivery

Because providers use at-least-once delivery, webhook handlers must be idempotent. A handler that creates a new database record every time it receives a charge.succeeded event will create duplicate records when the same event is delivered twice. The standard mitigation is to store processed event IDs and check for duplicates before executing side effects.

Out-of-Order Events

Webhook providers do not guarantee event ordering. A charge.refunded event might arrive before the corresponding charge.succeeded event, especially during retries. Webhook handlers must be resilient to this by checking the current state of the resource (via API call) rather than assuming a linear event sequence.

Endpoint Security

A webhook endpoint that does not verify signatures is an open door for payment fraud. An attacker who discovers the endpoint URL can send forged payloads to trigger order fulfillment without actual payment. Beyond signature verification, production endpoints should validate timestamps (rejecting events older than 5 minutes to prevent replay attacks), enforce HTTPS with TLS 1.2 or higher, and consider IP allowlisting as a defense-in-depth measure.

Processing Latency

Webhook handlers must respond within the provider's timeout window (typically 5 to 30 seconds) or the delivery is marked as failed. Long-running operations like sending emails, calling third-party APIs, or running database migrations should happen asynchronously after the endpoint returns a 200 response. A common pattern is to enqueue the event in a message queue and process it in a background worker.

Middleware Signature Pitfalls

Signature verification must run against the raw request body before any middleware parses or transforms it. JSON parsing, body decompression, or framework middleware that modifies whitespace will change the bytes and cause signature verification to fail. This is a frequent source of debugging confusion in frameworks like Express.js, where the body parser runs before the webhook handler by default.

This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.