Webhooks enable real-time notifications for your Monieswitch integration, allowing your system to receive automatic updates about important events and transaction statuses.

Why Use Webhooks?

Instead of repeatedly checking for updates (polling), webhooks provide instant notifications when events occur in your Monieswitch account. This approach is:
  • More efficient than polling
  • Not subject to rate limits
  • Highly scalable
  • Real-time and reliable

Webhook Approach

  1. One-time webhook URL registration
  2. Automatic notifications when events occur
  3. Immediate updates
  4. More efficient communication

Traditional Polling

  1. Your server repeatedly requests updates
  2. Each request requires a response
  3. High number of API calls
  4. Potential delays in getting updates

Signature Validation

Events sent from Monieswitch carry the x-monieswitch-signature header. The value of this header is a HMAC SHA512 signature of the event payload signed using your secret key. Verifying the header signature should be done before processing the event.

Example

const crypto = require("crypto");
const secret = process.env.SECRET_KEY;

// Using Express
app.post("/webhook/url", function (req, res) {
  // Validate event
  const hash = crypto
    .createHmac("sha512", secret)
    .update(JSON.stringify(req.body))
    .digest("hex");
  if (hash == req.headers["x-monieswitch-signature"]) {
    // Retrieve the request's body
    const event = req.body;
    // Do something with event
  }
  res.send(200);
});

Implementation Guide

1. Creating Your Webhook Endpoint

Set up a POST endpoint on your server to receive webhook notifications. Your endpoint should:
  • Accept JSON payloads
  • Return a 200 OK response
  • Process events asynchronously
Example implementation:
app.post("/webhooks", function (req, res) {
  res.status(200).send();

  // Process the event asynchronously
  const event = req.body;
  processWebhookEvent(event);
});

2. Update Webhook URL in Dashboard

In your Monieswitch account settings, add your webhook URL to receive notifications. This URL should be publicly accessible and secure.

Event Types Reference

Payout Events

{
  "event": "payout.pending",
  "status": "PENDING",
  "amount": 500,
  "merchantId": "b7205b06-f71f-417f-8f5f-0245ca2d3787",
  "narration": "testing",
  "beneficiaryBankCode": "090197",
  "beneficiaryAccountNumber": "2034589705",
  "description": "โ‚ฆ500.00 transferred to SIMI MICHELLE",
  "beneficiaryAccountName": "SIMI MICHELLE",
  "charges": 10,
  "totalAmount": 510,
  "beneficiaryBankName": "ABU MICROFINANCE BANK",
  "originatorWalletId": "4fa8008a-5c42-4ce0-8727-acce575496b6",
  "originatorAccountName": "ID Stores",
  "originatorAccountNumber": "4475364845",
  "paidAt": "2025-05-07T12:40:32Z",
  "transactionId": "1ba0105a-76aa-4f10-ae49-f610aad45dab",
  "reference": "kSh1NfD0gfwz3xPzV0ApFLfcp5a2TGZwCkg0",
  "sessionId": "999270250507124032023825430717"
}

Static Account Funding Events

{
  "event": "static.account.payment.pending",
  "type": "CREDIT",
  "status": "PENDING",
  "mode": "SANDBOX",
  "walletId": "4fa8008a-5c42-4ce0-8727-acce575496b6",
  "amount": 100000,
  "paidAt": "2025-05-07T12:59:50.641Z",
  "sessionId": "999270250507125950030527152284",
  "reference": "l-m8KbrPKoYV128VPckeKkeXaeedAsqFyMyOHu",
  "merchantId": "b7205b06-f71f-417f-8f5f-0245ca2d3787",
  "charges": 1550,
  "settledAmount": 98450,
  "userId": "573186c9-61bf-41fd-9616-75e0be705625",
  "walletType": "STATIC",
  "channelCode": "2",
  "transactionReference": "l-m8KbrPKoYV128VPckeKkeXaeedAsqFyMyOHu",
  "narration": "Sandbox Account funding.",
  "beneficiaryBankName": "XpressWallet",
  "beneficiaryBankCode": "999270",
  "beneficiaryBankVerificationNumber": "",
  "beneficiaryAccountName": "ID Stores",
  "beneficiaryAccountNumber": "4475364845",
  "originatorBankCode": "999270",
  "originatorBankName": "Monieswitch Test Bank",
  "originatorAccountName": "Emmanuel",
  "originatorAccountNumber": "0167421242",
  "originatorBankVerificationNumber": "",
  "description": "โ‚ฆ100,000.00 received from Emmanuel",
  "transactionId": "ff7b7e39-e473-4250-8724-797d7820f0bd"
}

Virtual Account Collection Events

{
  "event": "virtual.account.payment.success",
  "merchantId": "b7205b06-f71f-417f-8f5f-0245ca2d3787",
  "status": "success",
  "amount": 2000,
  "paidAt": "2025-05-07T13:06:20.719Z",
  "reference": "l-dETwqrcxjwnAba2kbr4StCHuSndsl9sBq8mz",
  "narration": "Funding Virtual Account 4460895224 - ID Stores-Fast payment",
  "transactionId": "f5e81a9a-c55a-4b6e-a153-b3e513759ff6",
  "amountPaid": 2000,
  "settledAmount": 1970,
  "settlementCharge": 30,
  "customerReference": "o8Vq9vejST2hWf5WyLK85hAGBHMW7jBtZsaV",
  "hasActiveSubaccount": false,
  "originatorBankCode": "999270",
  "originatorBankName": "Monieswitch Test Bank",
  "originatorAccountName": "Emmanuel",
  "sessionId": "999270250507130620813261532358",
  "originatorAccountNumber": "0167421242",
  "beneficiaryBankCode": "999270",
  "beneficiaryBankName": "Xpresswallet",
  "beneficiaryAccountName": "ID Stores-Fast payment",
  "beneficiaryAccountNumber": "4460895224"
}

Wallet Debit

{
  "event": "debit.wallet",
  "paidAt": "2025-06-24T12:38:51Z",
  "reference": "4usHc2qro2X8UUNMjP3rypl2L33HpS74KVK8",
  "totalAmount": 9800,
  "charges": 0,
  "status": "SUCCESS",
  "amount": 9800,
  "merchantId": "b7205b06-f71f-417f-8f5f-0245ca2d3787",
  "walletId": "dc55f7ab-e750-41d2-8e04-288a2b3f0a1c",
  "narration": "Testing",
  "originatorBankName": "Xpresswallet",
  "originatorBankCode": "999270",
  "originatorAccountName": "EmmaBaba",
  "originatorAccountNumber": "4499466143",
  "beneficiaryBankCode": "999270",
  "beneficiaryBankName": "Xpresswallet",
  "beneficiaryAccountName": "ID Stores",
  "beneficiaryAccountNumber": "4475364845",
  "description": "โ‚ฆ9,800.00 debitted from EmmaBaba",
  "transactionId": "1061c238-30b3-4387-88f1-3df458372d1f"
}

Card Events

{
  "event": "card.settlement",
  "mode": "SANDBOX",
  "amount": 400,
  "merchantId": "3aed8fe9-2c60-48fe-bea4-71ea8c8f3c84",
  "settlementDate": "2025-08-28",
  "status": "SUCCESSFUL",
  "settlementId": "ad8ecbaa-13b9-46a5-a7b9-79b1f83a1afd",
  "category": "CARD_SETTLEMENT",
  "isAutoSettlementEnabled": false
}

Sandbox Funding

{
  "event": "sandbox.fund.success",
  "type": "CREDIT",
  "status": "SUCCESS",
  "mode": "SANDBOX",
  "walletId": "4fa8008a-5c42-4ce0-8727-acce575496b6",
  "amount": 10000,
  "paidAt": "2025-05-07T12:55:23Z",
  "merchantId": "b7205b06-f71f-417f-8f5f-0245ca2d3787",
  "sessionId": "25752448303645411876949004421594",
  "reference": "YDlKPE2W90ZPOCPZmqUsJmNw0cxrioYFnUtY",
  "charges": 0,
  "settledAmount": 10000,
  "channelCode": "2",
  "transactionReference": "YDlKPE2W90ZPOCPZmqUsJmNw0cxrioYFnUtY",
  "narration": "Sandbox Funding",
  "beneficiaryBankName": "Xpress Wallet",
  "beneficiaryBankCode": "999270",
  "beneficiaryBankVerificationNumber": "00000000001",
  "beneficiaryAccountName": "ID Stores",
  "beneficiaryAccountNumber": "4475364845",
  "originatorBankCode": "999270",
  "originatorBankName": "Monieswitch Test Bank",
  "originatorAccountName": "Monieswitch Test Funding",
  "originatorAccountNumber": "0987654321",
  "originatorBankVerificationNumber": "00000000001",
  "description": "โ‚ฆ10,000.00 received from Monieswitch Test Funding"
}

Status Code Reference

Event TypeStatus CodeMeaning
virtual.account.payment.successsuccessPayment confirmed and processed
virtual.account.payment.pendingpendingPayment initiated but not completed
virtual.account.payment.failedfailedPayment attempt failed
payout.successSUCCESSTransfer completed successfully
payout.pendingPENDINGTransfer initiated but not completed
payout.failedFAILEDTransfer failed to complete
static.account.payment.successSUCCESSStatic account funding successful
static.account.payment.pendingPENDINGStatic account funding pending
static.account.payment.failedFAILEDStatic account funding failed
debit.walletSUCCESSWallet debit transaction completed
sandbox.fund.successSUCCESSSandbox funding successful
card.settlementSUCCESSFULCard settlement completed

Best Practices

1. Event Handling

  • Always verify event type before processing
  • Implement idempotency checks using reference/transaction IDs
  • Handle each event type independently
  • Log all received events for audit purposes

2. Status Verification

  • Confirm both event type and status match
  • Check failure reasons for failed events
  • Implement appropriate error handling
  • Validate webhook signature before processing

3. Processing Order

  • Process pending events before success or failed
  • Store pending state for reconciliation
  • Update records for both success and failure events
  • Maintain event sequence for audit trails

4. Failure Handling

  • Implement retry logic where appropriate
  • Store failure reasons for analysis
  • Send appropriate notifications
  • Consider automated recovery flows

5. Security

  • Always validate webhook signatures
  • Use HTTPS for webhook endpoints
  • Implement proper authentication
  • Log security events for monitoring