Skip to main content

Webhooks

Webhook notifications allow you to efficiently track payments/deposits states, and enable you to automate communication internally or with your customers.They are push notifications sent as webhook message to URLs you defined.

You can subscribe to the payments/deposit events. When one of these events is triggered, we send a request to a URL of your choice in a JSON format. Along with the event, data about the payment/deposit is included, which we refer to as the payload.

Supported event types

Event typeDescription
PAYMENTSubscribe the transaction of payment
DEPOSITSubscribe the transaction of deposit

Decrypting Webhook Payloads

To ensure the security of webhook notifications, all webhook payloads are encrypted using AES-256-CBC.

Step 1: Receive the Webhook

When a webhook is triggered, you'll receive a POST request with the following structure:

{
"iv": "c6407a24ca95deaec313786321ec1e39",
"encrypted": "encrypted_payload_here"
}

Step 2: Decrypt the Payload

Decrypt the payload using AES-256-CBC encryption.

Encryption Details
  • Algorithm: AES-256-CBC
  • Key Size: 32 bytes (256 bits)
  • IV Size: 16 bytes (128 bits)
  • Encoding: Hex for encrypted data and IV
const { createDecipheriv } = require("crypto");

function decryptWebhookPayload(encryptedData, secret, iv) {
// Create decipher with AES-256-CBC
const decipher = createDecipheriv(
"aes-256-cbc",
Buffer.from(secret, "utf-8"),
Buffer.from(iv, "hex")
);

// Decrypt the data
let decrypted = decipher.update(encryptedData, "hex", "utf8");
decrypted += decipher.final("utf8");

// Parse and return JSON
return JSON.parse(decrypted);
}

// Usage
const secret = "your_32_byte_secret_key_here"; // 32 characters for AES-256
const iv = "1234567890abcdef1234567890abcdef"; // 16 bytes in hex (32 chars)
const encryptedData = webhookData.data; // Hex encoded encrypted data

try {
const decryptedPayload = decryptWebhookPayload(encryptedData, secret, iv);
console.log("Decrypted payload:", decryptedPayload);
} catch (error) {
console.error("Decryption failed:", error.message);
}

Step 3: Process the Decrypted Data

Once decrypted, the payload will contain the complete event data:

{
"subscriptionId": "4e408b3d-5f70-423d-b940-f7192cd77252",
"eventType": "PAYMENT",
"eventStatus": "SCHEDULED",
"timestamp": "2025-12-08T05:53:17.372Z",
"eventObject": {
"id": "4e408b3d-5f70-223d-b940-f7192cd77252",
"clientId": "72644e73-21ee-4cd7-9c56-04e6a2a96465",
"referenceNo": "20251208-PTW122",
"currencyCode": "USD",
"chargeFee": 160,
"amount": 123,
"beneficiaryId": "649e7865-3f93-4940-bfa5-d4324b24316a",
"paymentReference": "INV-123",
"paymentDate": "2025-12-08",
"purposeCode": "GOODS",
"sourceOfFunds": "Salary",
"status": "SCHEDULED",
"createdTime": "2025-12-08T05:53:17.000Z",
"failureReason": null
}
}

Retry Policy

To ensure reliable webhook delivery, our system implements an automatic retry mechanism for failed webhook deliveries.

Retry Mechanism

  • Retry Trigger: Webhooks will be retried if your endpoint returns a non-2xx HTTP status code
  • Delivery Timeout: Each webhook delivery attempt has a timeout of 30 seconds
  • Maximum Retry Duration: The system will continue retrying for up to 1 hour
  • Exponential Backoff: The retry strategy uses exponential backoff:
    • Initial retry intervals are short after the first failure
    • Retry intervals gradually increase with each subsequent failure
    • This approach balances quick recovery with system stability

Troubleshooting

Common Issues

  • Decryption fails (Wrong encryption key)
    Check encryption key matches the one in your dashboard
  • Decryption fails (Wrong IV)
    Verify you're using the IV from the webhook payload
  • Invalid JSON (Padding issue)
    Ensure proper PKCS7 padding removal after decryption
  • Webhook not received (Firewall/Network)
    Ensure your endpoint is publicly accessible and accepts POST requests