Verifying webhook signature
Securely verify that the webhook events are from Cake capital
When Cake Capital sends a webhook event to your server, it's crucial to verify that the payload was indeed sent by us and not tampered with. To ensure this, we sign the payload using a secret key, and you can use this document to verify the signature.
Example webhook payload
Here's an example of a webhook payload sent by Cake Capital:
{
"id": "38e67b16-d477-43b9-921b-a40cebb3bf2a",
"created_at": 1714062202544,
"event_name": "transaction-created",
"entity" :{
"id": "32a603e8-fa60-4898-8b87-55b4caa202a1",
"type": "transaction"
},
"resource_url": "https://sandbox.cakecapital.com/api/v1/send/transactions/32a603e8-fa60-4898-8b87-55b4caa202a1/"
}
Headers sent with the webhook event
Along with the payload, the following headers are sent:
X-Timestamp: The timestamp (in seconds from epoch) when the payload was created.
X-Signature: The signature used to verify the authenticity of the payload.
Signature generation process
The signature is generated using the following process:
- Concatenate the payload.id, the string --cake--, and the X-Timestamp.
Example: 38e67b16-d477-43b9-921b-a40cebb3bf2a--cake--1714062202544
- Create an HMAC-SHA512 hash of this string using your secret key.
- The resulting hash is the signature, which you can compare against the X-Signature header to verify the payload.
Code examples for verifying the signature
const crypto = require('crypto');
function verifySignature(payload, secretKey, xTimestamp, xSignature) {
const payloadString = `${payload.id}-cake-${xTimestamp}`;
const hmac = crypto.createHmac('sha512', secretKey);
hmac.update(payloadString);
const generatedSignature = hmac.digest('hex');
return generatedSignature === xSignature;
}
// Example usage
const payload = {
id: "38e67b16-d477-43b9-921b-a40cebb3bf2a",
created_at: 1714062202544,
event_name: "transaction-created",
entity: {
id: "32a603e8-fa60-4898-8b87-55b4caa202a1",
type: "transaction"
},
resource_url: "https://sandbox.cakecapital.com/api/v1/send/transactions/32a603e8-fa60-4898-8b87-55b4caa202a1/"
};
const secretKey = "ccws_10b851dc46a248bc8b0602d8941";
const xTimestamp = "1714062202544";
const xSignature = "the_signature_from_header";
const isValid = verifySignature(payload, secretKey, xTimestamp, xSignature);
console.log("Signature is valid:", isValid);
import hmac
import hashlib
def verify_signature(payload, secret_key, x_timestamp, x_signature):
payload_string = f"{payload['id']}-cake-{x_timestamp}"
payload_bytes = payload_string.encode('utf-8')
secret_key_bytes = secret_key.encode('utf-8')
generated_signature = hmac.new(secret_key_bytes, payload_bytes, digestmod=hashlib.sha512).hexdigest()
return hmac.compare_digest(generated_signature, x_signature)
# Example usage
payload = {
"id": "38e67b16-d477-43b9-921b-a40cebb3bf2a",
"created_at": 1714062202544,
"event_name": "transaction-created",
"entity": {
"id": "32a603e8-fa60-4898-8b87-55b4caa202a1",
"type": "transaction"
},
"resource_url": "https://sandbox.cakecapital.com/api/v1/send/transactions/32a603e8-fa60-4898-8b87-55b4caa202a1/"
}
secret_key = "ccws_10b851dc46a248bc8b0602d8941"
x_timestamp = "1714062202544"
x_signature = "the_signature_from_header"
is_valid = verify_signature(payload, secret_key, x_timestamp, x_signature)
print("Signature is valid:", is_valid)
Updated 20 days ago