> ## Documentation Index
> Fetch the complete documentation index at: https://nango-khaliq-nan-660-add-support-for-personio-apis-to-nango.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify webhooks from Nango

> Step-by-step guide on how to verify the signatures of webhooks from Nango.

Validate webhook provenance by looking at the `X-Nango-Signature` header.

It's a SHA-256 hash generated using the secret key found in the *Environment Settings* in the Nango UI.

The webhook signature can be generated with the following code:

<Tabs>
  <Tab title="Javascript/Typescript">
    ```typescript
    import crypto from 'crypto';

    const secretKeyDev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
    const signature = `${secretKeyDev}${JSON.stringify(payload)}`;
    const hash = crypto.createHash('sha256').update(signature).digest('hex');
    ```
  </Tab>

  <Tab title="Python">
    ```python
    import hashlib
    import json

    secret_key_dev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
    signature = f"{secret_key_dev}{json.dumps(payload)}"
    hash = hashlib.sha256(signature.encode('utf-8')).hexdigest()
    ```
  </Tab>

  <Tab title="Java">
    ```java
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import javax.xml.bind.DatatypeConverter;

    public class Main {
        public static void main(String[] args) throws NoSuchAlgorithmException {
            String secretKeyDev = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
            String payloadString = // convert payload to JSON string
            String signature = secretKeyDev + payloadString;

            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(signature.getBytes("UTF-8"));
            String hash = DatatypeConverter.printHexBinary(hashBytes).toLowerCase();
        }
    }
    ```
  </Tab>

  <Tab title="Ruby">
    ```ruby
    require 'json'
    require 'digest'

    secret_key_dev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
    signature = "#{secret_key_dev}#{payload.to_json}"
    hash = Digest::SHA256.hexdigest(signature)
    ```
  </Tab>

  <Tab title="Go">
    ```go
    package main

    import (
        "crypto/sha256"
        "encoding/hex"
        "encoding/json"
    )

    func main() {
        secretKeyDev := "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        payloadString, _ := json.Marshal(payload) // Handle error in real code
        signature := secretKeyDev + string(payloadString)

        hash := sha256.Sum256([]byte(signature))
        hexHash := hex.EncodeToString(hash[:])
    }
    ```
  </Tab>

  <Tab title="Rust">
    ```rust
    use sha2::{Sha256, Digest};
    use serde_json::json; // Assuming use of serde_json for JSON serialization

    let secret_key_dev = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
    let signature = format!("{}{}", secret_key_dev, serde_json::to_string(&payload).unwrap());
    let mut hasher = Sha256::new();
    hasher.update(signature.as_bytes());
    let hash = format!("{:x}", hasher.finalize());
    ```
  </Tab>

  <Tab title="PHP">
    ```php
    <?php
    $secretKeyDev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
    $signature = $secretKeyDev . json_encode($payload);
    $hash = hash('sha256', $signature);
    ?>
    ```
  </Tab>
</Tabs>

Only accept a webhook if the `X-Nango-Signature` header value matches the webhook signature.
