IDCanopy Developers
Aletheia

Webhooks

HMAC signing for outbound results and inbound submissions

Aletheia's outbound result webhook is generic, any tenant that registers a callback URL and an outbound HMAC secret receives HMAC-signed deliveries with X-Forensic-Signature. Aletheia's inbound URL-fetch webhook is the push-style intake surface (see Submitting a case §5): a tenant enrolled for inbound push signs its POSTs with X-Inbound-Signature.

Both directions use HMAC-SHA256, emitted and verified as lowercase hexadecimal with no prefix (no sha256=), computed over the exact raw bytes of the request body, not a re-serialized or canonicalised form.

DirectionHeaderWho signs
Outbound, Aletheia to tenantX-Forensic-SignatureAletheia
Inbound, tenant to AletheiaX-Inbound-SignatureThe tenant

Verification is constant-time on both sides. The inbound check lowercases the received header before comparison, so an uppercase-hex inbound signature is also accepted, but emit lowercase hex for forward-compatibility. Base64 and sha256=-prefixed forms are not accepted.

Sign and verify the exact bytes on the wire. Do not pretty-print, re-key-order, or re-encode the JSON before hashing, capture the raw body and HMAC that, distinct from the parsed JSON.

Reference verifier (Python)

import hashlib, hmac

def verify(secret: str, raw_body: bytes, received_sig: str) -> bool:
    expected = hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, received_sig.strip().lower())

Reference verifier (Node.js)

const crypto = require('crypto');
function verify(secret, rawBody, receivedSig) {
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(receivedSig.trim().toLowerCase());
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

The outbound signed body is replayed unchanged on each retry attempt, so the signature is stable across retries. See also Guides / Webhooks for the cross-service overview.

On this page