Webhooks
Receive real-time notifications when someone submits your form
Webhooks allow you to send form submission data to any URL in real-time. This enables you to integrate Static Forms with thousands of services like Slack, Discord, Zapier, Make (Integromat), n8n, or your own custom applications.
Paid Feature
Webhooks are available on paid plans (Pro or Advanced). View pricing to unlock this feature.
How Webhooks Work
When a form is submitted, Static Forms sends an HTTP POST request to your webhook URL with the form data. Your endpoint receives the data in real-time and can process it however you want.
- 1User submits your form
- 2Static Forms processes the submission
- 3We send a POST request to your webhook URL
- 4Your endpoint receives and processes the data
Setting Up a Webhook
To configure webhooks for your account:
- Log in to your dashboard
- Navigate to Settings → Webhooks
- Click Add Webhook
- Enter your webhook URL
- Click Save
HTTPS Recommended
HTTPS is strongly recommended for security. HTTP URLs are supported but should be used only in trusted environments.
Webhook Payload
When a form is submitted, we send a POST request with the following JSON payload:
Payload Fields
| Field | Type | Description |
|---|---|---|
event | string | Event name (e.g., form.submitted) |
timestamp | number | Unix timestamp (seconds) |
data | object | Submission details (see below) |
data.submissionId | string | Unique submission ID |
data.formData | object | All form fields submitted by the user |
data.apiKey | string | API key associated with the submission |
data.recipientEmail | string | Email that receives the submission |
data.replyTo | string | Reply-to email (when available) |
data.attachments | array | File attachment metadata (if any) |
Webhook Security
We recommend verifying webhook requests to ensure they're coming from Static Forms. You can do this by:
- Checking
data.apiKeyin the payload matches your expected key - Using a secret token in your webhook URL (e.g.,
https://yoursite.com/webhook?token=SECRET) - Requiring a custom header or bearer token on your endpoint
Response & Retry Logic
Your webhook endpoint should respond with a 2xx status code (like 200 or 204) to indicate successful receipt. Static Forms delivers webhooks with retries:
- Timeout: 10 seconds per attempt
- Retries: Up to 3 attempts with exponential backoff
- Idempotency: We send an
Idempotency-Keyheader usingstaticforms:{event}:{submissionId} - Failure Scope: Downstream webhook failures do not fail the form submission itself
Best Practice
Return 200 quickly, process asynchronously, and make your endpoint idempotent using data.submissionId or Idempotency-Key.
Example Implementations
Node.js / Express
Next.js API Route
Python / Flask
Popular Integrations
Zapier
Connect to 5000+ apps with no code
Make (Integromat)
Visual automation platform
n8n
Self-hosted workflow automation
Slack
Send submissions to Slack channels
Testing Your Webhook
You can test your webhook configuration from the dashboard:
- Go to Settings → Webhooks
- Click Test Webhook next to your webhook URL
- We'll send a test payload to your endpoint
- Check your endpoint logs to verify it received the test
Webhook Logs
View webhook delivery attempts and debug issues in your dashboard under Settings → Webhook Logs. Logs include:
- Timestamp of each attempt
- HTTP status code returned
- Response time
- Error messages (if any)
Log Retention
Webhook logs are retained for 14 days and include each retry attempt so you can debug downstream endpoint failures.
Troubleshooting
Webhook Not Receiving Requests
- Verify your webhook URL is correct and uses HTTPS
- Check your webhook logs in the dashboard for errors
- Ensure your endpoint is publicly accessible (not localhost)
- Check firewall rules allow inbound traffic
Timeouts
- Return a 200 response within 10 seconds
- Process webhook data asynchronously if it takes longer
- Optimize database queries and external API calls
Duplicate Webhooks
- Implement idempotency using
data.submissionIdor theIdempotency-Keyheader - Store processed submission IDs to prevent duplicate processing
- Still return 200 even if you've seen the submission before