Skip to main content
Webhook notifications are automated messages sent from Klyme to a specific URL endpoint of your choice. Instead of constantly checking for updates (polling) via API, webhooks push real-time data to a designated URL endpoint as soon as an event occurs such as a payment status changing from PENDING to COMPLETED.

Key Points

  • Webhook notifications are encrypted using aes-256-ctr.
  • Encyption for webhook notifications is enabled by default. However, encryption can be disabled upon request.
  • A HTTP 200 response must be sent back from the client to mark the delivery of the webhook notification as successful.
  • You have 5 attempts to successfully receive a unique webhook notification and send back a HTTP 200 response.
  • If after 5 attempts a HTTP 200 response is not sent back, the notification will stop sending as a failsafe.
  • Unreceived webhook notifications are still recorded by Klyme and can be re-sent upon request.

How to decrypt webhook notifications

const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());

app.post('/webhooks', (req, res) => {
    const iv = Buffer.from(req.body.iv, 'hex');
    let encryptedText = Buffer.from(req.body.data, 'hex');
    let decipher = crypto.createDecipheriv('aes-256-ctr', Buffer.from(process.env.WEBHOOK_SECRET), iv);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);

    res.status(200).send();
});
$secret = getenv('WEBHOOK_SECRET');

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['REQUEST_URI'] === '/webhooks') {
    $iv = hex2bin($_POST['iv']);
    $encryptedText = hex2bin($_POST['data']);

    // Decrypt the data
    $decrypted = openssl_decrypt($encryptedText, 'aes-256-ctr', $secret, OPENSSL_RAW_DATA, $iv);

    if ($decrypted === false) {
        // Handle decryption error
        http_response_code(400);
        echo 'Decryption failed';
        exit;
    }

    // Send a 200 OK response
    http_response_code(200);
    echo 'OK';
} else {
    // Handle other requests
    http_response_code(404);
    echo 'Not Found';
}
{
    "processingTime": "2025-07-23 18:32:26",
    "uuid": "ce1797873467e1bbddda9f99c42f126a",
    "merchantUuid": "xfe3539cb23ad9731be57905b8a0c099",
    "amount": 10.00,
    "currency": "GBP",
    "reference": "1A2B3C4D",
    "result": {
        "status": 1,
        "statusCode": "ACCC",
        "description": "COMPLETED",
        "institution": "monzo_ob",
        "redirectUrl": "https://your-redirect-url.com"
    },
    "customer": {
        "firstName": null,
        "surname": null,
        "middleName": null,
        "email": "[email protected]",
        "mobile": null,
        "phone": null,
        "customerId": null,
        "dob": null,
        "gender": null,
        "address1": null,
        "address2": null,
        "city": "Manchester",
        "postcode": null,
        "country": "GB",
        "company": null,
        "ip": "16.126.433.250",
        "payerName": null,
        "payerIban": null,
        "payerAccNum": null,
        "payerSortCode": null
    },
    "cart": {
        "items": [],
        "affiliateId": null,
        "discountCode": null
    },
    "device": {
        "deviceOs": "iOS",
        "deviceOsVersion": "18.5",
        "deviceName": "iPhone",
        "deviceBrowser": "Mobile Safari",
        "deviceBrowserVersion": "18.5"
        "deviceToken": "nTW220MaiBjonNLoox2k",
        "deviceIsMobile": 1,
    },
    "customParameters": {
        "custom1": null,
        "custom2": null,
        "custom3": null,
        "custom4": null,
        "custom5": null,
        "customJson": null
    }
}