---
title: Manually Verifying Webhook Signatures | PostGrid
description: How to manually verify PostGrid webhook signatures using HMAC-SHA256 when receiving payloads as JSON rather than JWT.
---

PostGrid supports sending webhook payloads in two separate formats: a [JSON web token](https://jwt.io/) (JWT) and regular JSON. Verifying the JWT with your webhook’s secret is [straightforward ](https://jwt.io/libraries)and automatically ensures that the payload was sent by PostGrid and is [recent enough](https://en.wikipedia.org/wiki/Replay_attack).

However, you may prefer to receive the payload as JSON since this is typically easier to integrate into existing codebases/tools. If you choose to do this, it is up to you to verify the request is sent by PostGrid.

You will have to:

1. Get the raw body of the request
2. Extract the signature header value
3. Calculate the HMAC of the raw body using the SHA-256 hash function and the secret; and
4. Compare the calculated HMAC with one sent in the `PostGrid-Signature` header, making sure that both values use the same encoding.

## Verifying the webhook signature

PostGrid will make the request to your webhook endpoint with a `PostGrid-Signature` header. Here’s an example of what that will look like:

```
PostGrid-Signature: t=1718932335515,v1=e888f596cf2db26b2f58631cb28d620882022c5727a8f5a558f328f8d886e11d
```

This signature begins with the timestamp (unix milliseconds) that PostGrid made the request, and is followed by a hash-based message authentication code ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) using [SHA-256](https://en.wikipedia.org/wiki/SHA-2).

**Step 1: Extract the timestamp and signatures from the header**

1. Split the header using the `,` character. This gets a list of elements consisting of the timestamp `t`, and the corresponding signature `v1`.
2. Split each element using the `=` character as the separator. This gives a prefix and value pair for both the timestamp, `t` and signature `v1`.

**Step 2: Prepare the`signedPayload` string**

The `signedPayload` string is created by concatenating

- The timestamp, `t` (as a string) +
- A period `.` +
- The raw body of the request (JSON with no whitespace)

**Step 3: Determine the expected signature**

Compute the HMAC of the the`signedPayload` (message/**expected signature**) by using the SHA256 algorithm and secret key (*found in the ‘Additional Information’ of the ‘Webhook Details’ section in the dashboard*)

**Step 4: Compare the signatures**

Compare the signature, `v1` from the header, to the newly calculated **expected signature**. If they do not match the webhook event should be rejected.

To prevent timing attacks, use a constant-time-string comparison to compare the expected signature with each of the received signatures.
