Receiving webhooks

Once you’ve created the webhook you’ll need to set up your server to receive the HTTP POST requests at the endpoint you specified. There are just a few basic things that we expect from your endpoint

  1. It uses HTTPS on the standard 443 port
  2. It responds within 5 seconds with a 2xx status code

Retry policy

If we don’t receive an acceptable response when sending events we will continue retrying the request, with decreasing frequency for up to 15 mins. If it has been over 24 hours of not receiving acceptable responses, then we will send out an email to email address (if specified) associated with the webhook. If it has been over 120 hours of not receiving acceptable responses, then the webhook will be disabled and an email will be sent out to notify.

Data Integrity check

To ensure the requests you receive are coming from MoneyMoov, you need to verify the signature provided in the x-moneymoov-signature header. This contains the hash of the payload hashed using HMACSHA256 with your webhook signing key and base64 encoded. To ensure the data received at your endpoint is the same as the data sent from our API, you need to do the same with payload received in the body and match it with the header. If they are the same then it's a correctly signed payload. If the signature does not match the hashed payload it is an incorrectly signed payload.

Here's how you can calculate the payload hash:

using System.Security.Cryptography;
using System.Text;

public static string CalculatePayloadHash(string secret, byte[] payloadBytes)
{
    byte[] keyByte = Encoding.UTF8.GetBytes(secret);

    using (var hmac = new HMACSHA256(keyByte))
    {
        byte[] hashMessage = hmac.ComputeHash(payloadBytes);
        var hashMsg = Convert.ToBase64String(hashMessage);
        return Convert.ToBase64String(hashMessage);
    }
}
const crypto = require('crypto');

/**
 * Calculate the HMAC SHA256 hash of the payload
 * @param {string} secret - The secret key for HMAC
 * @param {Buffer} payloadBytes - The payload as a byte array
 * @returns {string} - The base64 encoded hash
 */
function calculatePayloadHash(secret, payloadBytes) {
    // Create a HMAC SHA256 hasher
    const hmac = crypto.createHmac('sha256', secret);

    // Update the hasher with the payload bytes and finalize the hash
    const hash = hmac.update(payloadBytes).digest('base64');

    return hash;
}

// Example usage
const secret = 'your-secret-key';
const payload = Buffer.from('your-payload-string', 'utf8');
const hash = calculatePayloadHash(secret, payload);

console.log('Hash:', hash);

import hmac
import hashlib
import base64

def calculate_payload_hash(secret, payload_bytes):
    """
    Calculate the HMAC SHA256 hash of the payload.
    
    :param secret: The secret key for HMAC as a string.
    :param payload_bytes: The payload as bytes.
    :return: The base64 encoded hash as a string.
    """
    # Convert the secret to bytes
    key_bytes = secret.encode('utf-8')

    # Create a HMAC SHA256 hasher
    hmac_hasher = hmac.new(key_bytes, payload_bytes, hashlib.sha256)

    # Compute the hash
    hash_bytes = hmac_hasher.digest()

    # Convert the hash to base64
    return base64.b64encode(hash_bytes).decode('utf-8')

# Example usage
secret_key = 'your-secret-key'
payload = 'your-payload-string'
payload_bytes = payload.encode('utf-8')

hash_result = calculate_payload_hash(secret_key, payload_bytes)
print('Hash:', hash_result)