Guides
Handling Webhooks
Receive and verify webhook events from MUDBASE in your application.
1. Configure an endpoint
From Console → Webhooks, set the URL you want events delivered to and check the events you want to receive. Then generate a signing secret — copy it immediately, it's shown only once.
2. Verify every request
Read the raw request body (don't let a body-parsing middleware transform it first) and compare the HMAC against X-MUDBASE-Signature:
import express from "express";
import crypto from "crypto";
const app = express();
// express.raw (not express.json) so req.body is the exact bytes MUDBASE signed
app.post(
"/webhooks/mudbase",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.header("X-MUDBASE-Signature");
const expected = crypto
.createHmac("sha256", process.env.MUDBASE_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
const valid =
signature &&
crypto.timingSafeEqual(Buffer.from(signature, "hex"), Buffer.from(expected, "hex"));
if (!valid) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = JSON.parse(req.body.toString("utf8"));
// Respond fast — do the real work after acknowledging.
res.status(200).json({ received: true });
handleEvent(event).catch((err) => console.error("Webhook handler failed", err));
}
);
async function handleEvent(event) {
switch (event.event) {
case "collection.insert":
// ...
break;
case "kyc.completed":
// ...
break;
default:
break;
}
}import express from "express";
import crypto from "crypto";
const app = express();
// express.raw (not express.json) so req.body is the exact bytes MUDBASE signed
app.post(
"/webhooks/mudbase",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.header("X-MUDBASE-Signature");
const expected = crypto
.createHmac("sha256", process.env.MUDBASE_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
const valid =
signature &&
crypto.timingSafeEqual(Buffer.from(signature, "hex"), Buffer.from(expected, "hex"));
if (!valid) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = JSON.parse(req.body.toString("utf8"));
// Respond fast — do the real work after acknowledging.
res.status(200).json({ received: true });
handleEvent(event).catch((err) => console.error("Webhook handler failed", err));
}
);
async function handleEvent(event) {
switch (event.event) {
case "collection.insert":
// ...
break;
case "kyc.completed":
// ...
break;
default:
break;
}
}3. Respond quickly, process asynchronously
Acknowledge with a 2xx status as soon as the signature checks out — before you've finished handling the event. If your endpoint takes too long to respond, MUDBASE times out and retries the delivery, and you'll end up handling the same event twice.
Because retries can (and will) redeliver the same event, make your handler idempotent — key any side effect off X-MUDBASE-Delivery-ID or the event's own document ID so processing the same delivery twice is harmless.
See Webhooks (Concepts) for the full event list, payload format, and retry policy.