# How OmniRoute Delivers Webhooks with HMAC Signing and Exponential Backoff Retry Logic

> Learn how OmniRoute secures webhook delivery with HMAC signing and implements robust retry logic using exponential backoff for reliable communication. Explore the implementation details.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-04

---

**OmniRoute implements secure webhook delivery in [`src/lib/webhookDispatcher.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/webhookDispatcher.ts) using HMAC-SHA256 payload signing and exponential backoff retry logic that waits 2ⁿ × 1 second between attempts.**

OmniRoute is an open-source routing platform that guarantees reliable webhook delivery through a robust dispatcher system. According to the diegosouzapw/OmniRoute source code, the implementation combines cryptographic payload verification with resilient retry mechanisms to ensure secure transmission to subscriber endpoints.

## Payload Signing with HMAC-SHA256

The webhook dispatcher uses the `signPayload` helper function to generate cryptographic signatures that recipients use to verify payload authenticity. When a `secret` is configured for the webhook endpoint, the system attaches the signature to the `X-Webhook-Signature` header before transmission.

In [`src/lib/webhookDispatcher.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/webhookDispatcher.ts) (lines 20‑22), the signing implementation creates a standard HMAC-SHA256 digest:

```typescript
function signPayload(payload: string, secret: string): string {
  return `sha256=${crypto.createHmac("sha256", secret).update(payload).digest("hex")}`;
}

```

The resulting header value follows the format `sha256=<hex_digest>`, enabling receivers to independently calculate the signature using their shared secret and compare it against the header value.

## Delivery and Exponential Backoff Strategy

The `deliverWebhook` function manages the HTTP POST transmission and implements the retry mechanism. It validates the target URL, constructs the JSON request body, conditionally injects the signature header when a secret is present, and executes the request with automatic retry logic.

The retry schedule follows an exponential backoff pattern calculated as **2ⁿ × 1 second**, where `n` represents the zero-indexed attempt number. This creates progressively increasing delays of 1 second, 2 seconds, 4 seconds, 8 seconds, and so on, up to the configured `maxRetries` limit.

The dispatcher iterates through delivery attempts using this structure:

```typescript
for (let attempt = 0; attempt <= maxRetries; attempt++) {
  try {
    const res = await fetch(url, {method: "POST", headers, body, signal});
    if (res.ok || res.status /* ... success handling ... */) {
      return;
    }
  } catch (error) {
    // Calculate backoff: 2^attempt * 1000ms
    const delay = Math.pow(2, attempt) * 1000;
    await new Promise(resolve => setTimeout(resolve, delay));
  }
}

```

## Configuration Requirements

To enable HMAC signing, configure a `secret` string when registering the webhook endpoint. The `maxRetries` parameter accepts an integer defining how many retry attempts occur after the initial failed delivery (total attempts = maxRetries + 1).

Receivers must extract the signature from the `X-Webhook-Signature` header and verify it against the raw request body using the same HMAC-SHA256 algorithm with the shared secret.

## Summary

- **HMAC-SHA256 signing** occurs in [`src/lib/webhookDispatcher.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/webhookDispatcher.ts) via the `signPayload` function, generating signatures in `sha256=<hex>` format for the `X-Webhook-Signature` header.
- **Exponential backoff** retries failed deliveries using a delay formula of 2ⁿ × 1 second, where `n` is the current attempt index.
- **Resilient delivery** is handled by `deliverWebhook`, which validates URLs, manages headers, and loops up to `maxRetries` times before failing permanently.
- **Security** depends on pre-shared secrets; webhooks without configured secrets transmit without signatures.

## Frequently Asked Questions

### How does OmniRoute sign webhook payloads?

OmniRoute signs payloads using the `signPayload` function in [`src/lib/webzap/webhookDispatcher.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/webzap/webhookDispatcher.ts), which applies HMAC-SHA256 using the configured secret and outputs a hex digest prefixed with `sha256=`. This value populates the `X-Webhook-Signature` header on outgoing requests.

### What retry schedule does OmniRoute use for failed webhooks?

The system implements exponential backoff with a base delay of 1 second. The delay between attempt `n` and `n+1` equals 2ⁿ × 1000 milliseconds, creating intervals of 1s, 2s, 4s, 8s, etc., up to the configured `maxRetries` limit.

### Where is the webhook delivery logic implemented in OmniRoute?

All webhook delivery logic resides in [`src/lib/webhookDispatcher.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/webhookDispatcher.ts), including the `signPayload` helper for HMAC generation and the `deliverWebhook` function that handles HTTP transmission, header construction, and retry looping.

### How can receivers verify OmniRoute webhook signatures?

Receivers should read the `X-Webhook-Signature` header, extract the hex digest after the `sha256=` prefix, and compute their own HMAC-SHA256 signature of the raw request body using the shared secret. Matching digests confirm payload authenticity and integrity.