MuxForms webhooks POST JSON to your HTTPS URL when a submission is stored. Each form has one endpoint and a whsec signing secret; verify the MuxForms-Signature header with HMAC-SHA256. Failed deliveries retry with backoff and appear in the dashboard log.
Docs
Push every new submission into your API, queue, or automation. Choose Custom URL on the form Integrations tab.
| Item | Value |
|---|---|
| Event | submission.created |
| Method | POST |
| Signature header | MuxForms-Signature (t=, v1=) |
| Retries | 3 attempts (0s, 2s, 5s backoff) |
| Configure | Dashboard → form → Integrations tab (Custom URL) |
Open a form in the dashboard, go to Webhooks, and save an HTTPS endpoint. MuxForms generates a signing secret (whsec_…) you verify on your server. Use http://localhost only for local testing.
MuxForms sends POST with Content-Type: application/json and User-Agent: MuxForms-Webhooks/1. The body is UTF-8 JSON:
Payload
{
"event": "submission.created",
"form": { "id": "…", "name": "…", "project": "…" },
"submission": {
"id": "…",
"createdAt": "…",
"payload": { "email": "jane@example.com", "message": "Hello" },
"origin": "https://yoursite.com",
"ip": "…",
"userAgent": "…"
}
}The MuxForms-Signature header is t=<unix>,v1=<hmac>. The HMAC is SHA-256 over {timestamp}.{rawBody} using your signing secret. Reject timestamps more than five minutes from the clock.
Node.js
// Verify MuxForms-Signature (Node.js)
const crypto = require("crypto");
function verifyMuxFormsWebhook(secret, rawBody, signatureHeader) {
const parts = Object.fromEntries(
signatureHeader.split(",").map((p) => p.trim().split("=")),
);
const timestamp = Number(parts.t);
const expected = parts.v1;
if (!timestamp || !expected) return false;
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const actual = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return actual === expected;
}In Express, read the raw body before JSON parsing so the signature matches the bytes MuxForms sent.
Non-2xx responses and network errors trigger up to three delivery attempts with backoff (immediate, then 2s, then 5s). Each run is recorded in the dashboard delivery log. Use Resend to replay a past submission payload to your current webhook URL.
Webhooks fire for submissions accepted through the embed and the submit API. Email notifications are independent—you can use both.
Slack, CRM, n8n, or a custom worker—one POST per lead.
Upgrade to Pro