Developer API · updated 2026-08-22
Every webhook delivery is signed so your server can prove it came from Dumpster Controls and was not tampered with. Verification is a dozen lines of code in any language. Never process an unverified webhook.
Each delivery carries:
X-DC-Signature: t=1755900000,v1=a1b2c3...
t is the unix timestamp when we signed, and v1 is the hex HMAC-SHA256 of the string "<t>.<raw body>" computed with your endpoint secret (dcwh_...).
1. Read the RAW request body (before any JSON parsing; whitespace matters). 2. Parse t and v1 from the header. 3. Compute HMAC-SHA256(secret, t + "." + rawBody) and hex-encode it. 4. Compare with v1 using a constant-time comparison. 5. Reject if |now - t| is more than about 5 minutes (replay protection).
const crypto = require("crypto");function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
const expected = crypto.createHmac("sha256", secret)
.update(parts.t + "." + rawBody).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
const sig = Buffer.from(parts.v1 || "");
// timingSafeEqual THROWS on unequal lengths: guard first
return fresh && sig.length === 64 &&
crypto.timingSafeEqual(Buffer.from(expected), sig);
}import hmac, hashlib, time
def verify(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=") for p in header.split(","))
expected = hmac.new(secret.encode(),
f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
fresh = abs(time.time() - int(parts["t"])) < 300
return fresh and hmac.compare_digest(expected, parts["v1"])Parsing the JSON and re-serializing it before hashing (key order changes, verification fails): always hash the raw bytes. Using == instead of a constant-time compare. Skipping the timestamp check, which allows replays of old captured deliveries.
Still stuck? Talk to our team
Open a support ticket inside the app and our team will answer there.
Log in and open a support ticketThe software is 100% free with unlimited orders. No credit card, no demo, no contract.
Create your free account