# Webhooks/Callbacks

You can verify the Message Authentication Code (MAC) of a given callback using the HMAC SHA-512 algorithm. \
The MAC ensures data integrity and authenticity by enabling the recipient to verify that the message has not been altered.

\
Header key:  nmac\
Message Value:  payReference (data\["payReference"])\ <br>

```json
Sample Header

{
 "nmac": "6377f9fae71eedb408f45b5fb2f70e5cdab8f415f993707aeb0e2f2484238f65fe788084b4c354fcf0b7113aa380b7f6fb9e024dc5c0f32b745bc3198350cbb9",
 "Content-Type": "application/json"
}
```

Method to Calculate HMAC SHA-512

Here is the method to compute the HMAC SHA-512, as provided:

Java Version

```java
public static String calculateHMACSHA512(String payReferenceString, String secretKey) {
    try {
        String algorithm = "HmacSHA512";
        Mac mac = Mac.getInstance(algorithm);
        SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm);
        mac.init(secretKeySpec);

        byte[] rawHmac = mac.doFinal(payReferenceString.getBytes());
        return bytesToHex(rawHmac);
    } catch (NoSuchAlgorithmException | InvalidKeyException ex) {
        System.out.println("Error Calculating SHA512 Mac");
    }
    return null;
}

private static String bytesToHex(byte[] bytes) {
    StringBuilder hexString = new StringBuilder();
    for (byte b : bytes) {
        String hex = Integer.toHexString(0xff & b);
        if (hex.length() == 1) hexString.append('0');
        hexString.append(hex);
    }
    return hexString.toString();
}


```

PHP Version&#x20;

```php
function calculateHMACSHA512(string $payReferenceString, string $secretKey): ?string {
    try {
        $hash = hash_hmac('sha512', $payReferenceString, $secretKey, true);
        return bin2hex($hash);
    } catch (Exception $ex) {
        error_log("Error Calculating SHA512 HMAC: " . $ex->getMessage());
        return null;
    }
}


// Example Use:

$key = "SK-l1vE-jhlajtbhttyytyhaho9883lta";
$payReferenceString = "PYDN-20250133222543502154838751243";

$hmac = calculateHMACSHA512($payReferenceString, $key);
echo "HMAC-SHA512: " . $hmac . PHP_EOL;


```

#### Javascript Version

```javascript
const crypto = require('crypto');

function calculateHMACSHA512(payReferenceString, secretKey) {
    try {
        const hmac = crypto.createHmac('sha512', secretKey);
        hmac.update(payReferenceString);
        return hmac.digest('hex');
    } catch (error) {
        console.error("Error Calculating SHA512 HMAC", error);
        return null;
    }
}

```

#### Verification Logic

1. **Compute the MAC:** Use the provided `calculateHMACSHA512` method to compute the MAC for the given message and secret key.
2. **Compare MACs:** Compare the computed MAC with the `providedMac` in a time-constant manner to prevent timing attacks.

**All our Webhook/Callback are sent via HTTP Method to the specified url provided by Merchant.**

**Payout  Webhook Event Types**

```bash
transfer.success
transfer.failed
transfer.reversal
transfer.wallet.credit
transfer.wallet.debit
```

**Payins Webhook Events**

```
success
failed
charge.success
charge.failed
fixed.payment.success
fixed.payment.failed
```

\
Sample Webhook Responses

<pre class="language-json"><code class="lang-json">PAYIN WEBHOOK PAYLOAD 

<strong>SUCCESSFUL BANK TRANSFER  (DYNAMIC ACCOUNT)
</strong>
{
  "event": "success",
  "data": {
    "accountNumber": "4570888889",
    "amount": 400,
    "amountPaid": 400,
    "channel": "BANKTRANSFER",
    "currency": "NGN",
    "customerEmail": "daniel@example.com",
    "customerName": "Daniel Joe",
    "sessionId": "10000425090098505125073703528",
    "fee": 50,
    "feeRatio": 1,
    "feeType": "Ratio",
    "stampDutyFee": 0,
    "appliedStampDutyFee": false,
    "payReference": "PYDN-20250019238832347115824786432",
    "created": "2025-01-07 18:12:34",
    "paymentCompletionDate": "2025-01-07 18:15:45",
    "paymentStartDate": "2025-01-07 18:12:34",
    "paymentStatus": "SUCCESSFUL",
    "reference": "4c6e83ae-4a91-4d45-bbc7-59e7c912f4f5",
    "vat": 0,
    "responseCode": "00",
    "narration": "Sample Narration",
    "payer": {
      "sourceAccountName": "SAM PAYER",
      "sourceAccountNumber": "8334497001"
    }
  }
}



SUCCESSFUL BANK TRANSFER  (FIXED ACCOUNT)

{
  "event": "fixed.payment.success",
  "data": {
    "accountReference": "19f3af87-8c91-4883-a3c8-04e8f522ca28",
    "accountNumber": "0083004524",
    "amount": 151200,
    "amountPaid": 151150,
    "channel": "BANKTRANSFER",
    "currency": "NGN",
    "customerEmail": "email@gmail.com",
    "customerName": "Sample CustomerName",
    "sessionId": "MI1849540961234",
    "fee": 3249.73,
    "feeRatio": 2,
    "feeType": "Ratio",
    "stampDutyFee": 50,
    "appliedStampDutyFee": false,
    "payReference": "PYDN-202501072099999514140085",
    "created": "2025-01-07 20:22:03",
    "paymentCompletionDate": "2025-01-07 20:22:03",
    "paymentStartDate": "2025-01-07 20:22:03",
    "paymentStatus": "SUCCESSFUL",
    "reference": "PYDN-202501072099999514140085",
    "vat": 0,
    "responseCode": "00",
    "fixedAccountNumber": "1183004511",
    "narration": "Transfer Narration",
    "payer": {
      "sourceBankName": "OPAY",
      "sourceAccountName": "SAMPLE OPAY CUSTOMER",
      "sourceAccountNumber": "****2866"
    }
  }
}

SUCCESSFUL CARD PAYIN

{
  "event": "success",
  "data": {
    "amount": 420,
    "amountPaid": 420,
    "channel": "CARD",
    "currency": "NGN",
    "customerEmail": "john@example.com",
    "customerName": "John Joe",
    "sessionId": "500720102499",
    "fee": 6.32,
    "feeRatio": 1.4,
    "feeType": "Ratio",
    "stampDutyFee": 0,
    "appliedStampDutyFee": false,
    "payReference": "PYDCRD-2020014787128341837",
    "created": "2025-01-07 21:20:06",
    "paymentCompletionDate": "2025-01-07 21:21:05",
    "paymentStartDate": "2025-01-07 21:20:01",
    "paymentStatus": "SUCCESSFUL",
    "reference": "56bcab3a-f30e-4",
    "vat": 0,
    "responseCode": "00",
    "narration": "",
    "payer": {
      "sourceAccountName": "Sam Joe"
    }
  }
}








PAYOUT WEBHOOK PAYLOAD 


SUCCESSFUL PAYOUT 
{
  "event": "transfer.success",
  "data": {
    "id": "d3792d15-82b0-43ef-af32-5de5ef0c60a1",
    "transactionAmount": 26250,
    "transactionFee": 500,
    "transactionReference": "PYDPYT-0112202419563400003748598",
    "responseCode": "00",
    "sessionId": "09028624120118588872826970586",
    "responseMessage": "Approved or completed successfully",
    "reference": "56274935607",
    "currencyCode": "NGN",
    "narration": "November pay",
    "senderAccountNumber": "6010336866",
    "senderAccountName": "Sample Merchant",
    "senderBank": "SAFE HAVEN MFB",
    "senderBankCode": "090286",
    "beneficiaryAccountName": "SAMPLE RECEIVER",
    "beneficiaryAccountNumber": "8130024726",
    "beneficiaryBank": "Opay",
    "beneficiaryBankCode": "100004",
    "transactionStatus": "SUCCESSFUL",
    "transactionStatusVerified": "true",
    "lastTransactionRequeryTimestamp": "2024-12-01 19:56:42",
    "created": "2024-12-01 19:56:34"
  }
}


FAILED PAYOUT


{
  "event": "transfer.failed",
  "data": {
    "id": "eed7eadb-406b-48b-ca603b9ce675",
    "transactionAmount": 1012,
    "transactionFee": 50,
    "transactionReference": "PYDPYT-07012025202247199945449",
    "responseCode": "81",
    "responseMessage": "Transaction Failed",
    "reference": "250108777662261900",
    "currencyCode": "NGN",
    "narration": "fees",
    "senderAccountNumber": "0034521179",
    "senderAccountName": "SAMPLE MERCHANT",
    "senderBank": "VFD Bank",
    "senderBankCode": "100033",
    "beneficiaryAccountName": "SAMPLE RECEIVER",
    "beneficiaryAccountNumber": "9126491726",
    "beneficiaryBank": "NGN",
    "beneficiaryBankCode": "090405",
    "transactionStatus": "FAILED",
    "transactionStatusVerified": "true",
    "lastTransactionRequeryTimestamp": "2025-01-07 20:22:53",
    "created": "2025-01-07 20:22:47"
  }
}




SUCCESSFUL POS TERMINAL WEBHOOK

{
    "event": "success",
    "data": {
        "accountNumber": "4565721625",
        "terminalId": "2100KJIL",
        "amount": 100.0,
        "amountPaid": 100.0,
        "channel": "POS",
        "currency": "NGN",
        "customerName": "MasterCard 2100KJIL",
        "sessionId": "1700074004691",
        "fee": 8.6,
        "feeRatio": 1.5,
        "feeType": "Ratio",
        "stampDutyFee": 0,
        "appliedStampDutyFee": false,
        "payReference": "PYDPOS-202502281000000241444522",
        "created": "2025-02-28 11:54:17",
        "paymentCompletionDate": "2025-02-28 11:54:17",
        "paymentStartDate": "2025-02-28 11:54:17",
        "paymentStatus": "SUCCESSFUL",
        "reference": "1700074004691",
        "vat": 0.0,
        "responseCode": "00",
        "narration": ""
    }
}


{
    "event": "failed",
    "data": {
        "accountNumber": "4565721625",
        "terminalId": "2100KJIL",
        "amount": 100.0,
        "amountPaid": 0.0,
        "channel": "POS",
        "currency": "NGN",
        "customerName": "MasterCard 2100KJIL",
        "sessionId": "1700074004691",
        "fee": 8.6,
        "feeRatio": 1.5,
        "feeType": "Ratio",
        "stampDutyFee": 0,
        "appliedStampDutyFee": false,
        "payReference": "PYDPOS-202502281000000241444522",
        "created": "2025-02-28 11:54:17",
        "paymentCompletionDate": "2025-02-28 11:54:17",
        "paymentStartDate": "2025-02-28 11:54:17",
        "paymentStatus": "SUCCESSFUL",
        "reference": "1700074004691",
        "vat": 0.0,
        "responseCode": "01",
        "narration": ""
    }
}




</code></pre>


---

# Agent Instructions: 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://docs.paydestal.com/paydestal/webhooks-callbacks.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.
