Event types

Monnify supports webhooks for various events like card transactions, settlement and disbursement completion, and refunds. To implement webhooks on your Monnify integration, it is recommended to follow certain best practices such as validating transaction hash, whitelisting Monnify's IP address, checking for duplicate notifications, and processing complex logic after acknowledging receipt of the notification with a 200 HTTP status code. These practices ensure the integrity and security of the payload, prevent unauthorized requests, avoid redundant processing, and prevent time-out issues.

Monnify Webhook Events and Structure

As part of the Monnify integration, notifications are automatically sent to your system when certain actions are completed. These notifications trigger corresponding activities on your system, and you can specify URLs for certain activities on your integration. The notifications include an event-type property that indicates what action has taken place, as well as event data containing details of the event.


Supported notification event types on Monnify include


  1. Successful Collection (for successful payments made on your account)
    Sample Event Notification Structure
    1{
    2  "eventType": "SUCCESSFUL_TRANSACTION",
    3  "eventData": {
    4    "product": {
    5      "reference": "1636106097661",
    6      "type": "RESERVED_ACCOUNT"
    7    },
    8    "transactionReference": "MNFY|04|20211117112842|000170",
    9    "paymentReference": "MNFY|04|20211117112842|000170",
    10    "paidOn": "2021-11-17 11:28:42.615",
    11    "paymentDescription": "Adm",
    12    "metaData": {},
    13    "paymentSourceInformation": [
    14      {
    15        "bankCode": "",
    16        "amountPaid": 3000,
    17        "accountName": "Monnify Limited",
    18        "sessionId": "e6cV1smlpkwG38Cg6d5F9B2PRnIq5FqA",
    19        "accountNumber": "0065432190"
    20      }
    21    ],
    22    "destinationAccountInformation": {
    23      "bankCode": "232",
    24      "bankName": "Sterling bank",
    25      "accountNumber": "6000140770"
    26    },
    27    "amountPaid": 3000,
    28    "totalPayable": 3000,
    29    "cardDetails": {},
    30    "paymentMethod": "ACCOUNT_TRANSFER",
    31    "currency": "NGN",
    32    "settlementAmount": "2990.00",
    33    "paymentStatus": "PAID",
    34    "customer": {
    35      "name": "John Doe",
    36      "email": "[email protected]"
    37    }
    38  }
    39}
  2. Successful Disbursement (for disbursement transactions with a successful definite status)
    Sample Event Notification Structure
    1{
    2  "eventType": "SUCCESSFUL_DISBURSEMENT",
    3  "eventData": {
    4    "amount": 10,
    5    "transactionReference": "MFDS|20210317032332|002431",
    6    "fee": 8,
    7    "transactionDescription": "Approved or completed successfully",
    8    "destinationAccountNumber": "0068687503",
    9    "sessionId": "090405210317032336726272971260",
    10    "createdOn": "17/03/2021 3:23:32 AM",
    11    "destinationAccountName": "DAMILARE SAMUEL OGUNNAIKE",
    12    "reference": "ref1615947809303",
    13    "destinationBankCode": "232",
    14    "completedOn": "17/03/2021 3:23:38 AM",
    15    "narration": "This is a quite long narration",
    16    "currency": "NGN",
    17    "destinationBankName": "Sterling bank",
    18    "status": "SUCCESS"
    19  }
    20}
  3. Failed Disbursement (for failed disbursement transactions)
    Sample Event Notification Structure
    1{
    2  "eventType": "FAILED_DISBURSEMENT",
    3  "eventData": {
    4    "amount": 17100,
    5    "transactionReference": "MFDS10620240708214001015343FR7PL8",
    6    "fee": 20,
    7    "transactionDescription": "You do not have sufficient balance to process this request. Please fund your account and try again.",
    8    "destinationAccountNumber": "8088524531",
    9    "sessionId": "",
    10    "createdOn": "08/07/2024 9:40:02 PM",
    11    "destinationAccountName": "MARVELOUS BENJI",
    12    "reference": "MF240708214000166415",
    13    "destinationBankCode": "305",
    14    "completedOn": "08/07/2024 9:40:07 PM",
    15    "narration": "AOlifepurse1260077196647628800Transaction",
    16    "currency": "NGN",
    17    "destinationBankName": "OPAY",
    18    "status": "FAILED"
    19  }
    20}
  4. Reversed Disbursement (for reversed disbursement transactions)
    Sample Event Notification Structure
    1{
    2  "eventType": "REVERSED_DISBURSEMENT",
    3  "eventData": {
    4    "transactionReference": "MFDS33920240513211815009133P47MKU",
    5    "reference": "662d2dcf22132ea227db164e-1715631494637",
    6    "narration": "Fund Transfer",
    7    "currency": "NGN",
    8    "amount": 145708,
    9    "status": "REVERSED",
    10    "fee": 8,
    11    "destinationAccountNumber": "8088523251",
    12    "destinationAccountName": "Marvelous Benji",
    13    "destinationBankCode": "305",
    14    "sessionId": "090405240513211816637369129129",
    15    "createdOn": "13/05/2023 9:18:16 PM",
    16    "completedOn": "13/05/2023 9:18:19 PM"
    17  }
    18}
  5. Successful Refund (for successfully processed initiated refunds)
    Sample Event Notification Structure
    1{
    2  "eventType": "SUCCESSFUL_REFUND",
    3  "eventData": {
    4    "merchantReason":"defective goods",
    5    "transactionReference":"MNFY|20190816083102|000021",
    6    "completedOn":"14/04/2021 4:24:05 PM",
    7    "refundStatus":"COMPLETED",
    8    "customerNote":"defects",
    9    "createdOn":"14/04/2021 4:23:37 PM",
    10    "refundReference":"ref001",
    11    "refundAmount":10:00
    12  }
    13}
  6. Failed Refund (for failed initiated refunds)
    Sample Event Notification Structure
    1{
    2  "eventType": "FAILED_REFUND",
    3  "eventData": {
    4    "merchantReason":"defective goods",
    5    "transactionReference":"MNFY|20190816083102|000021",
    6    "completedOn":"14/04/2021 4:24:05 PM",
    7    "refundStatus":"FAILED",
    8    "customerNote":"defects",
    9    "createdOn":"14/04/2021 4:23:37 PM",
    10    "refundReference":"ref001",
    11    "refundAmount":10:00
    12  }
    13} 
  7. Settlement Completion (for successfully processed settlements to your bank account or wallet)
    Sample Event Notification Structure
    1{
    2  "eventType": "SETTLEMENT",
    3  "eventData": {
    4    "amount": "1199.00",
    5    "settlementTime": "11/11/2021 02:29:00 PM",
    6    "settlementReference": "LB8HG1PNZT4ATJGZXQBY",
    7    "destinationAccountNumber": "6000000249",
    8    "destinationBankName": "Fidelity Bank",
    9    "destinationAccountName": "Teamapt Limited234",
    10    "transactionsCount": 1,
    11    "transactions": [
    12      {
    13        "product": {
    14          "reference": "2134565wda",
    15          "type": "2134565wda"
    16        },
    17        "transactionReference": "MNFY|26|20211111142601|000001",
    18        "paymentReference": "MNFY|26|20211111142601|000001",
    19        "paidOn": "11/11/2021 02:26:02 PM",
    20        "paymentDescription": "Seg",
    21        "accountPayments": [
    22          {
    23            "bankCode": "000014",
    24            "amountPaid": "1234.00",
    25            "accountName": "Okeke Chimezie",
    26            "accountNumber": "******1070"
    27          }
    28        ],
    29        "amountPaid": "1234.00",
    30        "totalPayable": "1234.00",
    31        "accountDetails": {
    32          "bankCode": "000014",
    33          "amountPaid": "1234.00",
    34          "accountName": "Okeke Chimezie",
    35          "accountNumber": "******1070"
    36        },
    37        "cardDetails": {},
    38        "paymentMethod": "ACCOUNT_TRANSFER",
    39        "currency": "NGN",
    40        "paymentStatus": "PAID",
    41        "customer": {
    42          "name": "Segun Adeponle",
    43          "email": "[email protected]"
    44        }
    45      }
    46    ]
    47  }
    48}
  8. Completed Oflline Payments
    Sample Event Notification Structure
    1{
    2  "eventType": "SUCCESSFUL_TRANSACTION",
    3  "eventData": {
    4    "product": {
    5      "reference": "MNF-Tl9Noo0G48000890",
    6      "type": "OFFLINE_PAYMENT_AGENT"
    7    },
    8    "transactionReference": "MNFY|76|20230830171357|000252",
    9    "invoiceReference": "MNF-Tl9Noo0G48000890",
    10    "paymentReference": "MNF-Tl9Noo0G48000890",
    11    "paidOn": "30/08/2023 5:13:57 PM",
    12    "paymentDescription": "adron",
    13    "metaData":{
    14      "phoneNumber":"08088523241",
    15      "name":"Khalid"
    16    },
    17    "destinationAccountInformation": {},
    18    "paymentSourceInformation": {},
    19    "amountPaid": 15000,
    20    "totalPayable": 15000,
    21    "offlineProductInformation": {
    22      "amount": 15000,
    23      "code": "56417",
    24      "type": "INVOICE"
    25    },
    26    "cardDetails": {},
    27    "paymentMethod": "CASH",
    28    "currency": "NGN",
    29    "settlementAmount": 14990,
    30    "paymentStatus": "PAID",
    31    "customer": {
    32      "name": "David Customer",
    33      "email": "[email protected]"
    34    }
    35  }
    36}
  9. Notification for Rejected Payments
    Sample Event Notification Structure
    1{
    2  "eventType": "REJECTED_PAYMENT",
    3  "eventData": {
    4    "metaData": "{"name":"Marvelous","age":"90"}",
    5    "product": {
    6      "reference": "MNFY|PAYREF|GENERATED|1687798434397393735",
    7      "type": "WEB_SDK"
    8    },
    9    "amount": 100,
    10    "paymentSourceInformation": {
    11      "bankCode": "50515",
    12      "amountPaid": 40,
    13      "accountName": "MARVELOUS BENJI",
    14      "sessionId": "090405230626180003067844645188",
    15      "accountNumber": "5141901487"
    16    },
    17    "transactionReference": "MNFY|85|20230626175354|041855",
    18    "created_on": "2023-06-26 17:53:55.0",
    19    "paymentReference": "MNFY|PAYREF|GENERATED|1687798434397393735",
    20    "paymentRejectionInformation": {
    21      "bankCode": "035",
    22      "destinationAccountNumber": "7023576853",
    23      "bankName": "Wema bank",
    24      "rejectionReason": "UNDER_PAYMENT",
    25      "expectedAmount": 100
    26    },
    27    "paymentDescription": "lets pay",
    28    "customer": {
    29      "name": "Marvelous Benji",
    30      "email": "[email protected]"
    31    }
    32  }
    33}
  10. Mandate Status Change
    Sample Event Notification Structure
    1{
    2  "eventType": "MANDATE_UPDATE",
    3  "eventData": {
    4    "customerAddress": "Everywhere is an address",
    5    "endDate": "2024-12-31 08:00:00.0",
    6    "customerEmailAddress": "[email protected]",
    7    "customerAccountName": "SAMUEL DAMILARE OGUNNAIKE",
    8    "customerAccountNumber": "2191406799",
    9    "customerAccountBankCode": "057",
    10    "customerName": "Damilare Ogunnaike",
    11    "mandateDescription": "Testing Monnify Mandate",
    12    "externalMandateReference": "mfy-mandate-102",
    13    "mandateStatus": "CANCELLED",
    14    "mandateAmount": 100000,
    15    "autoRenew": false,
    16    "mandateCode": "MTDD|01J3GRJH8D58B20VNX1E6GSY1N",
    17    "contractCode": "626689863141",
    18    "customerPhoneNumber": "08166189142",
    19    "startDate": "2024-07-24 08:00:00.0"
    20  }
    21} 
  11. Wallet Activity Notification
    Sample Event Notification Structure
    1 {
    2  "eventType": "ACCOUNT_ACTIVITY",
    3  "eventData": {
    4    "accountType": "MAIN",
    5    "accountName": "Test01",
    6    "accountNumber": "8016472829",
    7    "accountNuban": null,
    8    "activityType": "TRANSACTION",
    9    "amount": 100,
    10    "currency": "566",
    11    "balanceBefore": 862.68,
    12    "balanceAfter": 962.68,
    13    "reference": "MFY_WTP_TRF_2MPT61CFP_1896839989128998912_CBA_CREDIT_0_CREDIT_0",
    14    "narration": " MFY-WT/#/TRF|2MPT61cfp|1896839989128998912_CBA_CREDIT_0/#/2025-03-04/#/VA-6927004623/#/From-Moniepoint Microfinance Bank/#/Test User/#/5744000051",
    15    "activityTime": "2025-03-04 10:27:AM"
    16  },
    17  "metaData": {
    18    "senderAccount": "Monnify Service",
    19    "sourceAccountName": null,
    20    "sourceAccountNumber": null,
    21    "sourceBankCode": null,
    22    "sourceBankName": null
    23  }
    24} 
  12. Low Balance Alert
    Sample Event Notification Structure
    1{
    2"eventType": "LOW_BALANCE_ALERT",
    3"eventData": {
    4  "transactionTime": "2025-09-01T23:13:19Z",
    5  "merchantCode": "99ZYAFM0F3CY",
    6  "walletAccountNumber": "8023759978",
    7  "walletBalance": 0,
    8  "lowBalanceThreshold": 2000,
    9  "currency": "NGN",
    10  "description": "Your wallet balance has dropped below the configured threshold. Please fund your account."
    11  }
    12}


Transaction Hash Computation

As a security measure, Monnify computes a hash of the request body whenever it sends a notification and includes it in the request header with the key 'monnify-signature'. To ensure the notification is valid and authorized, you should also calculate the hash and compare it to the one sent by Monnify before accepting or acting on the notification.

To calculate the hash, you can use a SHA-512 encoding of your client secret key and the object of the request body. The formula is: SHA-512(client secret key + object of request body).



Javascript, PHP, Java Sample Codes:

Sample Client Key: 91MUDL9N6U3BQRXBQ2PJ9M0PW4J22M1Y

Sample Request:

Sample Event Data
1{
2  "eventData": {
3      "product": {
4          "reference": "111222333",
5          "type": "OFFLINE_PAYMENT_AGENT"
6      },
7      "transactionReference": "MNFY|76|20211117154810|000001",
8      "paymentReference": "0.01462001097368737",
9      "paidOn": "17/11/2021 3:48:10 PM",
10      "paymentDescription": "Mockaroo Jesse",
11      "metaData": {},
12      "destinationAccountInformation": {},
13      "paymentSourceInformation": {},
14      "amountPaid": 78000,
15      "totalPayable": 78000,
16      "offlineProductInformation": {
17          "code": "41470",
18          "type": "DYNAMIC"
19      },
20      "cardDetails": {},
21      "paymentMethod": "CASH",
22      "currency": "NGN",
23      "settlementAmount": 77600,
24       "paymentStatus": "PAID",
25      "customer": {
26          "name": "Mockaroo Jesse",
27          "email": "[email protected]"
28      }
29  },
30  "eventType": "SUCCESSFUL_TRANSACTION"
31}

Hashed Value:

f04fb635e04d71648bd3cc7999003da6861483342c856d05ddfa9b2dafacb873b0de1d0f8f67405d0010b4348b721c49fa171d317972618debba6b638aedcd3c

Computing Hash in Nodejs

Computing Hash in Nodejs
1const { sha512 } = require("js-sha512");
2
3const DEFAULT_MERCHANT_CLIENT_SECRET = "91MUDL9N6U3BQRXBQ2PJ9M0PW4J22M1Y";
4
5/**
6* Computes the HMAC-SHA512 hash of the given request body.
7* @param {string} requestBody - The stringified request body (JSON payload).
8* @returns {string} - The computed hash as a hex string.
9*/
10const computeHash = (requestBody) => {
11return sha512.hmac(DEFAULT_MERCHANT_CLIENT_SECRET, requestBody);
12};
13
14// Sample request body payload
15const stringifiedRequestBody = JSON.stringify(
16{
17  eventData: {
18    product: {
19      reference: "111222333",
20      type: "OFFLINE_PAYMENT_AGENT",
21    },
22    transactionReference: "MNFY|76|20211117154810|000001",
23    paymentReference: "0.01462001097368737",
24    paidOn: "17/11/2021 3:48:10 PM",
25    paymentDescription: "Mockaroo Jesse",
26    metaData: {},
27    destinationAccountInformation: {},
28    paymentSourceInformation: {},
29    amountPaid: 78000,
30    totalPayable: 78000,
31    offlineProductInformation: {
32      code: "41470",
33      type: "DYNAMIC",
34    },
35    cardDetails: {},
36    paymentMethod: "CASH",
37    currency: "NGN",
38    settlementAmount: 77600,
39    paymentStatus: "PAID",
40    customer: {
41      name: "Mockaroo Jesse",
42      email: "[email protected]",
43    },
44  },
45  eventType: "SUCCESSFUL_TRANSACTION",
46},
47null,
482 // pretty-print spacing (optional)
49);
50
51const computedHash = computeHash(stringifiedRequestBody);
52console.log("Computed hash:", computedHash);
53

Computing Hash in PHP

Computing Hash in Nodejs
1<?php
2
3class CustomTransactionHashUtil
4{
5  /**
6   * Computes an HMAC-SHA512 hash for a given JSON string and client secret.
7   *
8   * @param string $stringifiedData The stringified JSON payload.
9   * @param string $clientSecret    The merchant client secret.
10   *
11   * @return string The computed HMAC-SHA512 hash.
12   */
13  public static function computeSHA512TransactionHash(string $stringifiedData, string $clientSecret): string
14  {
15      return hash_hmac('sha512', $stringifiedData, $clientSecret);
16  }
17}
18
19$DEFAULT_MERCHANT_CLIENT_SECRET = '91MUDL9N6U3BQRXBQ2PJ9M0PW4J22M1Y';
20
21// Build the payload as an array (safer and more readable)
22$payload = [
23  "eventData" => [
24      "product" => [
25          "reference" => "111222333",
26          "type" => "OFFLINE_PAYMENT_AGENT",
27      ],
28      "transactionReference" => "MNFY|76|20211117154810|000001",
29      "paymentReference" => "0.01462001097368737",
30      "paidOn" => "17/11/2021 3:48:10 PM",
31      "paymentDescription" => "Mockaroo Jesse",
32      "metaData" => new stdClass(),
33      "destinationAccountInformation" => new stdClass(),
34      "paymentSourceInformation" => new stdClass(),
35      "amountPaid" => 78000,
36      "totalPayable" => 78000,
37      "offlineProductInformation" => [
38          "code" => "41470",
39          "type" => "DYNAMIC",
40      ],
41      "cardDetails" => new stdClass(),
42      "paymentMethod" => "CASH",
43      "currency" => "NGN",
44      "settlementAmount" => 77600,
45      "paymentStatus" => "PAID",
46      "customer" => [
47          "name" => "Mockaroo Jesse",
48          "email" => "[email protected]",
49      ],
50  ],
51  "eventType" => "SUCCESSFUL_TRANSACTION",
52];
53
54// Convert payload to JSON (stringified body)
55$stringifiedData = json_encode($payload, JSON_UNESCAPED_SLASHES);
56
57// Compute hash
58$computedHash = CustomTransactionHashUtil::computeSHA512TransactionHash(
59  $stringifiedData,
60  $DEFAULT_MERCHANT_CLIENT_SECRET
61);
62
63echo "Computed Hash: " . $computedHash . PHP_EOL;
64

Computing Hash in Java

Computing Hash in Java
1import javax.crypto.Mac;
2import javax.crypto.spec.SecretKeySpec;
3import java.nio.charset.StandardCharsets;
4import java.security.InvalidKeyException;
5import java.security.NoSuchAlgorithmException;
6import java.security.SignatureException;
7import java.util.Formatter;
8
9public class TransactionHashUtil {
10
11  private static final String HMAC_SHA512 = "HmacSHA512";
12
13  /**
14   * Converts a byte array to a lowercase hex string.
15   *
16   * @param bytes The byte array to convert.
17   * @return The hex string.
18   */
19  private static String toHexString(byte[] bytes) {
20      try (Formatter formatter = new Formatter()) {
21          for (byte b : bytes) {
22              formatter.format("%02x", b);
23          }
24          return formatter.toString();
25      }
26  }
27
28  /**
29   * Computes an HMAC-SHA512 hash for the given payload using the merchant client secret.
30   *
31   * @param data                 The stringified JSON payload.
32   * @param merchantClientSecret The merchant client secret.
33   * @return The computed HMAC-SHA512 hash as a lowercase hex string.
34   *
35   * @throws SignatureException       If signature computation fails.
36   * @throws NoSuchAlgorithmException If HmacSHA512 algorithm is not available.
37   * @throws InvalidKeyException      If the provided key is invalid.
38   */
39  public static String computeHMAC512TransactionHash(String data, String merchantClientSecret)
40          throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
41
42      SecretKeySpec secretKeySpec = new SecretKeySpec(
43              merchantClientSecret.getBytes(StandardCharsets.UTF_8),
44              HMAC_SHA512
45      );
46
47      Mac mac = Mac.getInstance(HMAC_SHA512);
48      mac.init(secretKeySpec);
49
50      byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
51      return toHexString(rawHmac);
52  }
53
54  // Example usage
55  public static void main(String[] args) {
56      String clientSecret = "91MUDL9N6U3BQRXBQ2PJ9M0PW4J22M1Y";
57      String requestBody = "{"eventData":{"product":{"reference":"111222333","type":"OFFLINE_PAYMENT_AGENT"},"transactionReference":"MNFY|76|20211117154810|000001","paymentReference":"0.01462001097368737","paidOn":"17/11/2021 3:48:10 PM","paymentDescription":"Mockaroo Jesse","metaData":{},"destinationAccountInformation":{},"paymentSourceInformation":{},"amountPaid":78000,"totalPayable":78000,"offlineProductInformation":{"code":"41470","type":"DYNAMIC"},"cardDetails":{},"paymentMethod":"CASH","currency":"NGN","settlementAmount":77600,"paymentStatus":"PAID","customer":{"name":"Mockaroo Jesse","email":"111222333@ZZAMZ4WT4Y3E.monnify"}},"eventType":"SUCCESSFUL_TRANSACTION"}";
58
59      try {
60          String hash = computeHMAC512TransactionHash(requestBody, clientSecret);
61          System.out.println("Computed Hash: " + hash);
62      } catch (Exception e) {
63          e.printStackTrace();
64      }
65  }
66}
67

Rate this page

How would you rate your experience?

Copyright © 2025 Monnify
instagramfacebookicon