Skip to main content
When SendX sends webhooks to your endpoint, we include a secure HMAC-SHA256 signature. This allows you to verify that the webhook truly came from SendX and that the payload hasn’t been altered in transit. This article explains how SendX signs webhook requests and how you can verify them in your own server — with ready-to-use examples in Python and Node.js.

Why Signature Verification Matters

Webhook signature verification ensures:
  • ✅ The request is authentic (it came from SendX).
  • ✅ The payload has not been altered during transmission.
  • ✅ You can safely process the event data without risk of spoofing.

How SendX Signs Webhooks

Every webhook request sent from SendX includes a cryptographic signature in its HTTP headers. Here’s how the signature is generated:
  1. The webhook payload (JSON body) is taken as-is.
  2. SendX computes an HMAC-SHA256 hash of this body using your team’s unique API key as the secret.
  3. The result is hex-encoded and added to the request headers.
Example request headers:
Content-Type: application/json
X-SendX-Signature: 3e7bda1d2d3c74b5f8a5ce5e7e7efef2df...
X-SendX-Signature-Alg: hmac-sha256
X-SendX-Webhook-Id: 4b1b3f72-8e01-43aa-9cf9-5dc6a8e4e937
X-SendX-Webhook-Attempt: 1

How to Verify a Webhook on Your Server

When your server receives a webhook from SendX:
  1. Capture the raw body of the POST request (without parsing it).
  2. Retrieve the following headers:
    • X-SendX-Signature
    • X-SendX-Signature-Alg
  3. Recompute the HMAC using your SendX Team API Key.
  4. Compare the recomputed signature with the one in the header using a constant-time comparison.
If they match — the webhook is valid.

Example: Verification Script

import hmac
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)

# Replace with your actual Team API Key
TEAM_API_KEY = "YOUR_TEAM_API_KEY_HERE"

@app.route("/webhook", methods=["POST"])
def verify_webhook():
    raw_body = request.data
    received_sig = request.headers.get("x-sendx-signature", "")
    algo = request.headers.get("x-sendx-signature-alg", "")

    if algo.lower() != "hmac-sha256":
        return jsonify({"error": "unsupported signature algorithm"}), 400

    computed_sig = hmac.new(
        TEAM_API_KEY.encode("utf-8"),
        raw_body,
        hashlib.sha256
    ).hexdigest()

    if hmac.compare_digest(computed_sig, received_sig):
        print("✅ Webhook signature verified successfully!")
        return jsonify({"verified": True}), 200
    else:
        print("❌ Invalid webhook signature!")
        return jsonify({"verified": False}), 400

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Common Issues & Fixes

IssuePossible CauseSolution
Invalid SignaturePayload was modified or encoded incorrectlyMake sure to use the raw request body, not a parsed or re-serialized version
Missing headerEndpoint not receiving all headersEnsure your reverse proxy or framework doesn’t strip custom headers
Verification fails intermittentlyUsing the wrong API KeyConfirm you’re using your Team API Key, not a personal or project key
I