> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rntor.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Verifying webhooks requests

> Learn how to verify RNTOR webhook requests

With every webhook request, RNTOR includes headers that you can use to verify the request.

* `svix-id`: the unique message identifier for the webhook message. This identifier is unique across all messages, but will be the same when the same webhook is being resent (for example, due to a previous failure).
* `svix-timestamp`: timestamp in seconds since epoch.
* `svix-signature`: the Base64 encoded list of signatures, separated by spaces.

Webhook signing secrets are used to validate the payload data sent to your application from RNTOR. You can find the signing secret on your webhooks management page.

There are two ways to verify webhook requests:

## 1. Using the Svix library

First, install the Svix library for your language. Then, use the following code to verify the request (example in JavaScript):

```javascript theme={null}
import { Webhook } from "svix";

const secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw";

// These were all sent from the server
const headers = {
  "svix-id": "msg_p5jXN8AQM9LWM0D4loKWxJek",
  "svix-timestamp": "1614265330",
  "svix-signature": "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=",
};
const payload = '{"test": 2432232314}';

const wh = new Webhook(secret);
// Throws on error, returns the verified content on success
const verifiedPayload = wh.verify(payload, headers);
```

The `payload` is the raw string body of the request, and the headers are the headers passed in the request.

## 2. Manually verifying the signature

### Constructing the signed content

The content to sign is composed by concatenating the ID, timestamp, and payload, separated by the full-stop character (`.`). In code, it looks like this:

```javascript theme={null}
const signedContent = `${svix_id}.${svix_timestamp}.${body}`;
```

### Determining the expected signature

RNTOR uses an HMAC with SHA-256 to sign its webhooks. To calculate the expected signature, HMAC the `signedContent` from above using the Base64 portion of your signing secret—the part after the `whsec_` prefix—as the key.

For example, given the secret `whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw`, use `MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw`.

This is how you can calculate the signature in Node.js:

```javascript theme={null}
const crypto = require("crypto");

const signedContent = `${svix_id}.${svix_timestamp}.${body}`;
const secret = "whsec_5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH";

// Base64 decode the secret
const secretBytes = Buffer.from(secret.split("_")[1], "base64");
const signature = crypto
  .createHmac("sha256", secretBytes)
  .update(signedContent)
  .digest("base64");

console.log(signature);
```

This generated signature should match one of the signatures sent in the `svix-signature` header. The header contains a space-delimited list of signatures and their corresponding version identifiers. The signature list most commonly contains one signature, though it can contain any number of signatures.
