Developer Blog

Validating Webhook Payloads with SHA 256 Signatures

A webhook signature proves that the payload was created by a trusted sender and was not changed in transit. The server should compute the expected HMAC from the raw request body and compare it with the signature header safely.

Published May 13, 2026 By Netvibes Infotech Ltd.
webhook security SHA 256 HMAC API security backend validation
Quick Answer

A webhook signature proves that the payload was created by a trusted sender and was not changed in transit. The server should compute the expected HMAC from the raw request body and compare it with the signature header safely.

A webhook signature proves that the payload was created by a trusted sender and was not changed in transit. The server should compute the expected HMAC from the raw request body and compare it with the signature header safely.

Direct answer

Never trust a webhook just because it reaches your endpoint. Read the raw body, compute the expected HMAC using the shared secret, and compare it against the provider signature with a timing safe comparison.

After the signature is valid, use JSON Validator or JSON Formatter to inspect the payload during debugging. Do not validate formatted JSON as the signed body because formatting changes the byte sequence.

Python HMAC example

import hmac
import hashlib

def verify_signature(raw_body: bytes, secret: str, received_signature: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        raw_body,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(expected, received_signature)

This function expects the raw request body exactly as received. If you parse and re serialize JSON first, the signature may not match.

Common mistake

# Wrong idea for signature validation
payload = request.json()
raw_body = json.dumps(payload).encode("utf-8")

This can change spaces, key order, and escaped characters. Use the raw body supplied by the web framework.

Django style approach

def webhook_view(request):
    raw_body = request.body
    received_signature = request.headers.get("X-Signature", "")

    if not verify_signature(raw_body, settings.WEBHOOK_SECRET, received_signature):
        return HttpResponse(status=401)

    return HttpResponse(status=200)

Security checklist

  • Use HTTPS for webhook endpoints.
  • Verify the signature before trusting the payload.
  • Use timing safe comparison.
  • Reject old timestamps if the provider includes one.
  • Log event IDs, not full sensitive payloads.

FAQ

Can I format webhook JSON before verifying it?

No. Verify the raw body first. Formatting changes the payload bytes and can break signature matching.

Is SHA 256 encryption?

No. SHA 256 is a hash function. HMAC with SHA 256 uses a secret key to authenticate the message.

Useful ScriptZip tools for this workflow