---
updatedAt: 2026-05-28T02:33:18.000Z
agentTools:
  projectIndex: https://checkout-docs.transfi.com/llms.txt
---

# Webhook Signature

All webhooks sent from TransFi are signed with a dedicated secret that is known only by TransFi and Customers. This ensures the integrity of the data contained in the webhook.

> <Callout icon="📘" theme="info">
>   **NOTE**
>
>   > Please connect with our tech support team to know your webhook dedicated secret key.
> </Callout>

We are using **HMAC (Hash-based Message Authentication Code)** as the authentication method using two keys:

* **HTTP Request Body**
* **Dedicated Secret Key**

## How does Webhook Signature work?

Use the following code snippet to generate the hash using **dedicated\_secret\_key + request\_body**

Compare the generated hash with the signature received in the following header:

* If the generated hash matches the value received from `X-Transfi-Hmac-Hash`, the webhook request is considered **valid**.
* If the values do not match, the webhook request should be treated as **invalid**.

<Callout icon="📘" theme="info">
  Customers can skip these events.
</Callout>

## Code Snippet

```node Node.js
const crypto = require('crypto');
const dedicatedSecret = <DEDICATED_SECRET>;
const body = req.body.toString('utf8');
const signature = req.headers['X-Transfi-Hmac-Hash'];
const hash = crypto.createHmac('sha256', dedicatedSecret).update(body).digest('hex');
return hash === signature;
```
```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class VerifyHmacSha256 { public static void main(String[] args) throws
NoSuchAlgorithmException, InvalidKeyException { String webhookSecret =
<DEDICATED_SECRET> // Assign with your secret key String receivedHash =
req.headers['X-Transfi-Hmac-Hash']; String receivedMessage = <STRINGIFIED_BODY>
// Stringified body

        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(webhookSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        sha256_HMAC.init(secret_key);

        byte[] calculatedHash = sha256_HMAC.doFinal(receivedMessage.getBytes(StandardCharsets.UTF_8));

        // Convert the calculated hash to a hexadecimal string
        StringBuilder hexCalculatedHash = new StringBuilder();
        for (byte b : calculatedHash) {
            hexCalculatedHash.append(String.format("%02x", b));
        }

        if (hexCalculatedHash.toString().equals(receivedHash)) {
            System.out.println("Hashes match, message is authentic.");
        } else {
            System.out.println("Hashes do not match, message may be tampered.");
        }
    }
}
```
```python
import hmac
import hashlib
import json
dedicated_secret = "<DEDICATED_SECRET>"  # Replace with your actual dedicated secret
body = request.get_json()  # Assuming you're using Flask or a similar framework
signature = request.headers.get('X-Transfi-Hmac-Hash')
# Generate HMAC hash
hash = hmac.new(
    dedicated_secret.encode('utf-8'), 
    json.dumps(body).encode('utf-8'), 
    hashlib.sha256
).hexdigest()
# Compare the generated hash with the signature
is_valid = hash == signature
```

<br />

<br />