---
title: Verify Webhooks Requests
description: Learn how to use the signing secret to verify your webhooks.
---
> For the complete documentation index, see [llms-docs.txt](/llms-docs.txt) or the site index [llms.txt](/llms.txt). Full docs corpus: [llms-full-docs.txt](/llms-full-docs.txt). Prefer markdown URLs (append `.md`) for agent consumption. Product skill: [skill.md](/skill.md).


To ensure that webhook requests are authentic and coming from Reloop, verify the signature included in the request headers. This prevents unauthorized requests from reaching your application logic.

## Headers

Every delivery includes:

| Header | Description |
| --- | --- |
| `Reloop-Id` | Event id (`whev_…`), same as body `id` |
| `Reloop-Timestamp` | Unix timestamp (seconds) used in the signature |
| `Reloop-Signature` | `t=<timestamp>,v1=<hex hmac>` |

## Signature algorithm

1. Read the **raw** request body bytes (do not re-serialize JSON).
2. Read `Reloop-Timestamp` (or parse `t=` from `Reloop-Signature`).
3. Compute HMAC-SHA256 over the string `` `${timestamp}.${rawBody}` `` using your endpoint secret (`whsec_…`).
4. Compare the hex digest to the `v1=` value with a constant-time compare.
5. Reject if the timestamp is older than ~5 minutes (replay protection).

```typescript
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyReloopWebhook(input: {
  secret: string;
  rawBody: string;
  signatureHeader: string;
  toleranceSeconds?: number;
}): boolean {
  const parts = Object.fromEntries(
    input.signatureHeader.split(",").map((p) => {
      const [k, ...rest] = p.trim().split("=");
      return [k, rest.join("=")];
    }),
  );
  const timestamp = Number(parts.t);
  const v1 = parts.v1;
  if (!Number.isFinite(timestamp) || !v1) return false;

  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - timestamp) > (input.toleranceSeconds ?? 300)) return false;

  const expected = createHmac("sha256", input.secret)
    .update(`${timestamp}.${input.rawBody}`)
    .digest("hex");

  try {
    const a = Buffer.from(expected, "hex");
    const b = Buffer.from(v1, "hex");
    return a.length === b.length && timingSafeEqual(a, b);
  } catch {
    return false;
  }
}
```

## Payload shape

```json
{
  "id": "whev_01h…",
  "type": "email.delivered",
  "created_at": "2026-07-22T12:00:00.000Z",
  "data": {
    "email_id": "em_…",
    "from": "hello@example.com",
    "to": ["user@example.com"],
    "subject": "Welcome",
    "status": "delivered"
  }
}
```

## Why verify webhooks?

Verification is critical because it allows you to:

- Confirm the request was signed with your endpoint secret
- Reject forged events from third parties
- Detect and drop replayed requests outside the time window
