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

# Verify Webhook Signatures

> Validate Zentra webhook deliveries before processing them

Every webhook delivery must be authenticated before you trust or process the payload.

## Verification Inputs

To verify a webhook, use:

* the raw request body exactly as received
* the signature header sent by Zentra
* the webhook secret returned when the endpoint was created

<Warning>
  Do not JSON-parse and then re-serialize the payload before verification. Use the raw body bytes.
</Warning>

## Recommended Flow

1. Read the raw request body
2. Extract the Zentra signature header
3. Compute the expected signature with your stored webhook secret
4. Compare signatures in constant time
5. Reject invalid payloads with `401` or `400`
6. Only then parse and process the event

## Example

```javascript theme={null}
import crypto from "crypto";

function verifyZentraWebhook(rawBody, signatureHeader, webhookSecret) {
  const expected = crypto
    .createHmac("sha256", webhookSecret)
    .update(rawBody)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}
```

## Reliability Requirements

* Make processing idempotent because deliveries may be retried
* Store delivery or event identifiers before applying business effects
* Return `2xx` only after the event is durably accepted by your system
* Keep delivery handling fast; move heavy work to async jobs

## Related Pages

<CardGroup cols={2}>
  <Card title="Configure Webhooks" icon="gear" href="/api-reference/webhooks/configure">
    Create endpoints and store webhook secrets
  </Card>

  <Card title="Handling Webhooks" icon="map" href="/guides/handling-webhooks">
    Full implementation guide with retry-safe patterns
  </Card>
</CardGroup>
