Skip to content
English
  • There are no suggestions because the search field is empty.

Verify the signature

Technical details and Node.js and Python code for verifying the X-Empath-Signature HMAC on every Empath webhook request.

Technical details of how to check that a request really came from Empath, with working code.

What is signed?

Empath computes an HMAC-SHA256 with your webhook's signing secret over this exact string:

{X-Empath-Timestamp}.{raw request body}

It sends the result as X-Empath-Signature: sha256= .

  • The timestamp is the decimal string from X-Empath-Timestamp (seconds, no milliseconds).
  • The body is the exact bytes received. Verify before parsing, never against re-serialised JSON.
  • Use a constant-time comparison.

Node.js

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyEmpathWebhook({ secret, timestamp, rawBody, signatureHeader }) {
  const expected = 'sha256=' + createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader ?? '');
  if (a.length !== b.length) return false;
  return timingSafeEqual(a, b);
}

Python

import hashlib, hmac

def verify_empath_webhook(secret: str, timestamp: str, raw_body: bytes, signature_header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

Good to know

  • Replay protection is up to you. Empath doesn't enforce a time limit. We recommend rejecting requests whose timestamp is more than 5 minutes from your clock.
  • Reject any request whose signature header doesn't start with sha256=.
  • Every retry is signed again with a new timestamp, so a retry's signature differs from the first attempt's.

Still need help?

Reach out to your Partner Success Manager, or email us at support@empathmsp.com. We’re happy to help!

Related articles

  • Request format: method, headers and timeouts
  • Create a webhook: Review & test and the signing secret
  • Build a receiver: the recommended pattern