Skip to content

Verifying Signatures

Validate that webhook requests came from Vitable using HMAC-SHA512 signatures.

Every webhook request includes an HMAC-SHA512 signature so you can verify it came from Vitable. The signature is computed over the timestamp and payload using your webhook secret key.

To get your webhook secret key, reach out to our team. Each webhook subscription has its own secret key — store it securely and never expose it in client-side code.

X-Vitable-Signature: sha512=<signature>
X-Vitable-Timestamp: <unix_timestamp>
import hmac
import hashlib
import time
def verify_webhook(payload: str, signature_header: str, timestamp_header: str, secret_key: str) -> bool:
# Reject requests older than 5 minutes (prevents replay attacks)
timestamp = int(timestamp_header)
if abs(time.time() - timestamp) > 300:
return False
# Reconstruct the expected signature
message = f"{timestamp}.{payload}"
expected = "sha512=" + hmac.new(
secret_key.encode("utf-8"),
message.encode("utf-8"),
hashlib.sha512,
).hexdigest()
return hmac.compare_digest(signature_header, expected)
import crypto from "node:crypto"
function verifyWebhook(payload, signatureHeader, timestampHeader, secretKey) {
// Reject requests older than 5 minutes
const timestamp = parseInt(timestampHeader, 10)
if (Math.abs(Date.now() / 1000 - timestamp) > 300) {
return false
}
// Reconstruct the expected signature
const message = `${timestamp}.${payload}`
const expected =
"sha512=" +
crypto.createHmac("sha512", secretKey).update(message).digest("hex")
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expected)
)
}