Form Webhooks: Forward Submissions to Any URL

Last updated: March 2026

FormWit webhooks let you forward form submissions to any URL in real-time. Every time someone submits your form, FormWit sends a POST request with the submission data as JSON to your configured endpoint. Use webhooks to pipe submissions into Slack, Discord, Zapier, a CRM, a database, or any custom API.

Webhooks are available on the Starter plan ($39/year) and above.

How form webhooks work

When a visitor submits your form, FormWit processes the submission, stores it, sends email notifications, and then queues a webhook delivery. Within seconds, your endpoint receives a POST request with the full submission data.

The flow:

  1. Visitor submits your HTML form
  2. FormWit validates, stores, and checks for spam
  3. FormWit sends a POST request to your webhook URL
  4. Your server receives the JSON payload and does whatever you need

Spam submissions are filtered out automatically. Your webhook only receives clean submissions.

Configure a webhook URL

In the FormWit dashboard, open your form and go to Settings → Webhooks. Enter your HTTPS endpoint URL and an optional signing secret.

Requirements:

  • Must be HTTPS (HTTP URLs are rejected)
  • Must respond within 10 seconds
  • Must return a 2xx status code

The signing secret is optional but recommended. It lets you verify that requests come from FormWit, not a third party.

Webhook payload format

FormWit sends a JSON POST request with Content-Type: application/json. The payload has three fields:

{
  "submissionId": "019d10a6-4208-7000-9878-0d96ca3604b4",
  "formId": "019d1056-0dec-7000-93fd-45df4895704d",
  "data": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "message": "I'd like to learn more about your services."
  }
}
FieldTypeDescription
submissionIdstringUnique ID for this submission
formIdstringThe form that received the submission
dataobjectKey-value pairs from the form fields

The data object contains exactly what the visitor submitted. Field names match your HTML form's name attributes. Honeypot fields and internal fields (like _gotcha) are stripped before delivery.

Headers sent with every webhook

Content-Type: application/json
X-Formwit-Timestamp: 2026-03-21T13:47:31.509Z
X-Formwit-Signature: sha256=a1b2c3... (only if a secret is configured)

Verify webhook signatures

If you set a webhook secret, FormWit signs every payload with HMAC-SHA256. This lets you verify that the request actually came from FormWit and hasn't been tampered with.

The signature is computed over ${timestamp}.${body} using your secret as the HMAC key. To verify:

  1. Read the X-Formwit-Timestamp and X-Formwit-Signature headers
  2. Compute HMAC-SHA256(secret, timestamp + "." + rawBody)
  3. Compare your computed signature with the one in the header
  4. Optionally, reject requests where the timestamp is more than 5 minutes old (replay protection)

Node.js verification example

import crypto from "node:crypto";

function verifyWebhook(req, secret) {
  const timestamp = req.headers["x-formwit-timestamp"];
  const signature = req.headers["x-formwit-signature"];
  const body = req.body; // raw string, not parsed JSON

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${body}`)
    .digest("hex");

  return signature === `sha256=${expected}`;
}

Webhook retry behavior

FormWit retries failed webhook deliveries automatically:

  • 2xx response: Success. No retry.
  • 4xx response: Client error. Marked as failed immediately. No retry (your endpoint rejected the request, retrying won't help).
  • 5xx response or timeout: Server error. Retried up to 3 times with exponential backoff.

After 3 failed retries, the delivery is marked as permanently failed. You can manually retry failed deliveries from the webhook delivery log in your dashboard under Settings → Webhooks.

Receive webhooks in Node.js

A minimal Express server that receives form submissions via webhook:

import express from "express";

const app = express();
app.use(express.json());

app.post("/webhook", (req, res) => {
  const { submissionId, formId, data } = req.body;

  console.log(`New submission ${submissionId} on form ${formId}`);
  console.log("Name:", data.name);
  console.log("Email:", data.email);
  console.log("Message:", data.message);

  // Save to database, send to CRM, trigger workflow, etc.

  res.status(200).json({ received: true });
});

app.listen(3000);

Deploy this to any Node.js host (Vercel, Railway, Render, your own server) and set the public URL as your webhook endpoint in FormWit.

Forward submissions to Slack

FormWit has built-in Slack support. When you configure a Slack incoming webhook URL in your form settings, submissions are automatically formatted as Slack Block Kit messages with field names, values, and a link to your dashboard.

To set it up:

  1. Create a Slack incoming webhook for your channel
  2. In FormWit, go to Settings → Webhooks and paste the Slack webhook URL in the Slack field
  3. Submit a test form. Your Slack channel receives a formatted message within seconds

"We built our site with AI and needed a form backend fast. FormWit was the easiest piece — connected it to Slack via webhooks and had leads flowing to our team in minutes." — Krishna, Founder, Adzep

Forward submissions to Discord

Similar to Slack, FormWit has native Discord support. Submissions are formatted as Discord embeds with your form data.

  1. In Discord, go to your channel's settings → Integrations → Create Webhook
  2. Copy the webhook URL (it starts with https://discord.com/api/webhooks/)
  3. In FormWit, paste it in the Discord field under Settings → Webhooks

Connect to Zapier or Make

Use FormWit's generic webhook to connect to automation platforms like Zapier or Make (formerly Integromat):

  1. In Zapier, create a new Zap with "Webhooks by Zapier" as the trigger
  2. Choose "Catch Hook" and copy the webhook URL Zapier gives you
  3. Paste that URL as your webhook endpoint in FormWit
  4. Send a test submission to map the fields in Zapier
  5. Add any action: Google Sheets, Mailchimp, HubSpot, Notion, Airtable, etc.

This lets you connect form submissions to 5,000+ apps without writing code.

Webhook delivery log

Every webhook delivery is logged in your dashboard. Go to Settings → Webhooks to see:

  • Delivery status (Sent, Failed, Pending)
  • HTTP response code from your endpoint
  • Timestamp of each attempt
  • Error details (hover the status badge for failed deliveries)
  • Manual retry button for failed deliveries

Tips for reliable webhooks

  • Respond fast. Return a 200 status immediately, then process the data asynchronously. FormWit times out after 10 seconds.
  • Handle duplicates. Use submissionId as an idempotency key. In rare cases (network issues, retries), you may receive the same payload twice.
  • Verify signatures. If you set a secret, always verify the X-Formwit-Signature header to prevent spoofed requests.
  • Use HTTPS. FormWit requires HTTPS for webhook URLs. This protects your submission data in transit.
  • Monitor the delivery log. Check for failed deliveries periodically. Common failures: endpoint down, SSL certificate expired, response too slow.

Related guides

Want to skip the setup?

FormWit gives you a form endpoint in 60 seconds. Free plan, no credit card.

Create Free Form

Need a form fast?

Build one visually with our free HTML form generator — no coding required.

Try the Form Generator →

Try webhooks free

Add a contact form to your site in 30 seconds. No backend code required.

Try FormWit Free