> For the complete documentation index, see [llms.txt](https://piqpay.gitbook.io/merchant-integration/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://piqpay.gitbook.io/merchant-integration/callback/callback-signature.md).

# Callback signature

To verify that callbacks come from PiqPay, use the signature provided in the X-Signature header. The signature is calculated using the HmacSha256 algorithm, using the “Secret” from the Subscriptions section (secretKey) and the body of the received callback in JSON String format (data). The calculated signature is then encoded in BASE64 format.

To find the "Secret", you should navigate to the "Merchant brands" tab in the Backoffice portal and click the necessary brand (each brand has its own Secret) and go the "Subscriptions" section.

<figure><img src="/files/e8bWNuqN00Qnqxd8Wq9l" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Important: for the signature to be correctly decoded, there must be no spaces in the callback body.
{% endhint %}

**Example calculation in Kotlin**

{% code overflow="wrap" %}

```kotlin
fun calculateBase64HmacSha256(secretKey: String, data: String): String {
   val secretKeySpec = SecretKeySpec(secretKey.toByteArray(), "HmacSHA256")
    val mac = Mac.getInstance("HmacSHA256").apply { init(secretKeySpec) }
    return Base64.getEncoder().encodeToString(mac.doFinal(data.toByteArray()))
}
```

{% endcode %}

&#x20;

**Example calculation in JS (NodeJS)**

{% code overflow="wrap" %}

```javascript
const crypto = require('crypto');
function hmacSha256Node(s, d) {
    const hmac = crypto.createHmac('sha256', s);
    hmac.update(d);
    // Get the hash in BASE64 format
    const hash = hmac.digest('base64');
    return hash;
  }
  let sig = hmacSha256Node(secretKey, data);
  console.log(sig);
```

{% endcode %}

To test the signature calculation algorithm, you can use the following data:

**data:**

{% code overflow="wrap" %}

```
'{"type":"PAYMENT_ORDER_CREATED","id":"25c9d5ab-c5df-4d87-adc6-c0dc7c75e6da","orderId":"9f7348d0-6522-48b2-8743-d89a0e0a5451","merchantId":"8481fd2a-16f3-45cf-8eb0-7de1285d518a","storeId":"d8440d52-25a5-4e8e-907d-3d73dd3763a8","clientId":"4d331ccdс73fft12fcfcr2","externalId":"davvcd17dd344d2ftfc3jrc1cdk","amount":{"minorAmount":500000,"currency":"PKR"},"createdAt":"2026-02-15T10:43:48.218Z","callbackUrl":"https://webhook.site/f2161c53-8364-4614-94b6-78c604250a4a"}'
```

{% endcode %}

**secretKey:**

`'qrswmtlc8f'`

**Signature:**&#x20;

`U7E+wLPCDLufYPJtFUY2ryWp1QSRp9rnmvdfaqfZOg8=`

We send callbacks from the following IP addresses. You can whitelist them on your server if needed.

| DEV  | 51.17.52.88                                               |
| ---- | --------------------------------------------------------- |
| PROD | <p>51.17.160.132</p><p>154.205.145.213<br>38.54.42.66</p> |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://piqpay.gitbook.io/merchant-integration/callback/callback-signature.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
