Verifying webhook signatures
Perceive8 includes a signature header with every webhook delivery so you can verify that the request came from Perceive8 and was not tampered with.
Header: X-Perceive8-Signature
The signature is an HMAC-SHA256 hex digest of the raw request body, keyed with your webhook secret (returned when you create the webhook).
Verification example (Node.js)
import { createHmac } from "crypto";
function verifyWebhookSignature(rawBody, signature, secret) {
const expected = createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
// Use a timing-safe comparison
return expected === signature;
}
// Express handler
app.post("/webhooks/perceive8", (req, res) => {
const sig = req.headers["x-perceive8-signature"];
const rawBody = req.rawBody; // Ensure body parser preserves raw bytes
if (!verifyWebhookSignature(rawBody, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(rawBody);
console.log("Received event:", event.event);
res.status(200).send("OK");
});
Verification example (Python)
import hashlib
import hmac
from flask import Flask, request
app = Flask(__name__)
WEBHOOK_SECRET = b"your-webhook-secret"
@app.route("/webhooks/perceive8", methods=["POST"])
def webhook():
sig = request.headers.get("X-Perceive8-Signature", "")
raw = request.get_data()
expected = hmac.new(WEBHOOK_SECRET, raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
return "Invalid signature", 401
event = request.json
print("Received:", event["event"])
return "OK", 200
Important: Always validate the signature before processing the webhook payload. Reject requests with missing or invalid signatures.