Webhook Setup

5 min read

Webhooks let WittyForm send an HTTP POST request to your server every time a form is submitted. This is the most flexible way to integrate: you control the endpoint, the processing logic, and the destination of the data.

Adding a webhook URL

  1. Open your form and go to Settings → Integrations → Webhooks.
  2. Click Add webhook.
  3. Enter your endpoint URL (must be HTTPS in production).
  4. Optionally, give the webhook a label (e.g., "CRM sync").
  5. Click Save.

You can add multiple webhooks per form. Each one fires independently on every submission.

Payload format

WittyForm sends JSON via HTTP POST. Field answers are keyed by your form field IDs:

{
  "event": "form.submitted",
  "timestamp": "2026-01-15T10:30:00.000Z",
  "formId": "form-uuid",
  "data": {
    "formId": "form-uuid",
    "responseId": "response-uuid",
    "answers": {
      "field-id": "Jane Smith",
      "email-field-id": "[email protected]"
    },
    "displayAnswers": {
      "field-id": "Jane Smith"
    },
    "submittedAt": "2026-01-15T10:30:00.000Z",
    "form": { "id": "form-uuid", "title": "Contact Form" }
  }
}

HTTP method and headers

All webhooks use POST. These headers are included by default:

  • Content-Type: application/json
  • User-Agent: WittyForm-Webhook/1.0
  • X-Webhook-Event, X-Webhook-ID, and X-Webhook-Delivery-ID
  • X-Webhook-Timestamp
  • X-WittyForm-Webhook-Token (a stable per-webhook token for destination firewall rules)
  • X-Webhook-Signature: sha256=... (if signing is enabled)

Custom headers

You can add custom headers in the webhook configuration panel. Click Add header and enter a key-value pair. Common uses:

X-API-Key: your-secret-key-here
Authorization: Bearer your-token-here

Authentication

API key header

The simplest approach: add a custom header with a secret value that your server validates on every request. If the header is missing or wrong, reject the request with 401 Unauthorized.

HMAC signature verification

For stronger security, enable webhook signing. WittyForm generates an HMAC-SHA256 signature of the payload body using a shared secret and includes it in the X-Webhook-Signature header.

To verify on your server (Node.js example):

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your request handler:
const isValid = verifySignature(
  req.body,            // raw request body string
  req.headers['x-wittyform-signature'],
  process.env.WITTYFORM_WEBHOOK_SECRET
);

if (!isValid) {
  return res.status(401).json({ error: 'Invalid signature' });
}

Retry logic

If your endpoint returns a non-2xx status code (or times out after 10 seconds), WittyForm retries the delivery:

  • Attempt 1: immediate
  • Attempt 2: after 1 second
  • Attempt 3: after 5 seconds
  • Attempt 4: after 30 seconds
  • Attempt 5: after 5 minutes
  • Attempt 6: after 1 hour

Once a webhook exhausts its configured retry count, it is marked as failed in the integration log. You can manually retry from the dashboard.

n8n and Cloudflare setup

  1. Use the n8n production URL with /webhook/; do not save the temporary /webhook-test/ URL.
  2. Activate the n8n workflow before submitting a form.
  3. Use the WittyForm Send Test action to send a safe sample with your field IDs.
  4. For a Cloudflare-protected receiver, copy the webhook's Delivery Token and configure a WAF/rate-limit exception for X-WittyForm-Webhook-Token with an exact token match. WittyForm cannot modify the receiver's Cloudflare rules for you.

Debugging with webhook.site

Before pointing a webhook at your production server, use a debugging tool to inspect the payload:

  1. Go to webhook.site and copy your unique URL.
  2. Paste that URL as your webhook endpoint in WittyForm.
  3. Submit a test form entry.
  4. Check webhook.site to see the full request headers, body, and timing.

This is also useful for troubleshooting when your own server returns errors: compare the payload you expect with what WittyForm actually sends.

Common errors

ErrorCauseFix
Connection refusedEndpoint is not reachableCheck that your server is running and the URL is correct
SSL certificate errorInvalid or expired certificateRenew your SSL certificate or use a valid CA
Timeout (10s)Server takes too long to respondProcess the webhook asynchronously: return 200 immediately, then handle the data
401 UnauthorizedAuthentication failedVerify your API key header or HMAC secret matches

Ready to Build Forms That Actually Convert?

Get lifetime access for just $37. No subscriptions or recurring fees. Create beautiful forms and own the tool forever.

14-day money-back· Instant access
Webhook Setup