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

# Verify signatures

> Check that an event really comes from Groovin before you act on it.

Anyone who finds your webhook address can call it. A signature proves that an event comes from Groovin and was not changed on the way.

> [!WARNING]
>
> If your automation acts on events, such as replying to a message, verify the signature. Otherwise, anyone who knows the address can trigger it.

Every request is signed with the [Standard Webhooks](https://www.standardwebhooks.com/) scheme, using your **signing secret**. It starts with `whsec_`, and you find it in **Settings → MCP and API → Webhooks**. Both of your addresses share it: only point them at services you control.

## With a library

Use any Standard Webhooks library, such as the `standardwebhooks` package for Node.js or Python. In Node.js:

```js theme={null}
import { Webhook } from "standardwebhooks";

const webhook = new Webhook(process.env.GROOVIN_WEBHOOK_SECRET);

// rawBody must be the exact text you received, before any JSON parsing.
const event = webhook.verify(rawBody, {
  "webhook-id": request.headers["webhook-id"],
  "webhook-timestamp": request.headers["webhook-timestamp"],
  "webhook-signature": request.headers["webhook-signature"],
});
```

`verify` throws an error when the signature is wrong or too old.

## By hand

```text theme={null}
signed_content = "{webhook-id}.{webhook-timestamp}.{raw request body}"
signature      = base64(HMAC-SHA256(base64decode(secret without "whsec_"), signed_content))
webhook-signature: v1,<signature>
```

* Verify the **raw** body, before parsing it.
* Reject requests whose `webhook-timestamp` is more than 5 minutes old.

## After rotating the secret

After you rotate the secret, Groovin signs with both the new and the old one for 24 hours. The header then carries two signatures separated by a space, and a request is valid when one of them matches.

## Several Groovin users on one server

Give each user their own address, for example with an id in the path, so you know which signing secret to use.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.