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

# Webhook security

Each webhook event sent by Orb includes two headers that let you check where it came from:

1. `X-Orb-Timestamp`: This header represents the time that the webhook was sent from Orb. You can check this timestamp and compare it to a configured threshold in your system, in order to prevent processing of the webhook event. This can be a mitigation against [replay attacks](https://en.wikipedia.org/wiki/Replay_attack) where webhook events are re-sent, causing downstream systems to behave unexpectedly.
2. `X-Orb-Signature`: The signature header (formatted as `v1=<signature>`) is a security header which can be used to confirm that the webhook event originated from Orb. We highly recommend verifying the signature, and only processing events where the header matches the signature you generate. Since each webhook endpoint is associated with a secret, your backend server should re-compute the signature by preparing the payload and subsequently computing an HMAC with the SHA 256 function.
   * The `payload` for the HMAC is the literal `"v1:"` followed by the ISO format `X-Orb-Timestamp` and finally the literal `:` followed by the event message body itself.
   * You should use the configured secret for the endpoint URL as the signing secret for the HMAC.
   * When comparing to your generated HMAC, you can either prefix the literal `v1=` to compare with `X-Orb-Signature` header directly, or extract the element after `v1=` in `X-Orb-Signature` to check against your generated value.

## Verifying signatures with the SDKs

In Python, TypeScript, Java and Kotlin, Orb's SDKs verify the signature as they parse a webhook event, with one parsing method per [payload style](/integrations-and-exports/webhooks/payload-styles). In Go, call `client.Webhooks.VerifySignature` before parsing. [Parsing payloads with the SDKs](/integrations-and-exports/webhooks/payload-styles#parsing-payloads-with-the-sdks) lists each SDK's methods.

## Verifying signatures yourself

Here's an example verification snippet implemented as a Flask endpoint:

```python theme={null}
from flask import Flask, request
import hmac
from hashlib import sha256

app = Flask(__name__)

@app.route('/webhook-handler', methods=['POST'])
def handle_webhook():
    # parse webhook JSON
    webhook_event = request.json

    if webhook_event is None:
        # could not parse request
        return ('Unable to parse notification.', 400)

    expected_signature = request.headers["X-Orb-Signature"]
    iso_format_delivery_time = request.headers["X-Orb-Timestamp"]

    secret_string = "<insert your secret string here>"
    secret = bytes(secret_string, "utf-8")

    # Prefix the beginning of the signature with `v1:<isoformat timestamp>`
    prefix = "v1:{0}:".format(iso_format_delivery_time)

    # Convert to bytes and append the body of the request
    message = prefix.encode("utf-8") + request.data

    # Generate an encode message based on the secret and the message string with sha256.
    hmac_object = hmac.new(secret, message, sha256)
    created_signature = "v1=" + hmac_object.hexdigest()

    if not hmac.compare_digest(expected_signature, created_signature):
        return ('Unable to verify webhook signature.', 400)

    # Handle based on webhook_event.type
    return ('Successfully processed webhook!', 200)
```


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