Skip to Content
FeaturesWebhooks

Webhooks

Webhooks let Formtorch push submission data to your server the moment it arrives. For each event you subscribe to, Formtorch sends a signed POST request to your endpoint.

Webhooks are available on Starter and Pro plans.

Want a full implementation walkthrough? See Webhook Processing for working examples in Next.js and Express.

Setting up a webhook

Webhook endpoints are workspace-level: one endpoint can receive events from all your forms.

Open Webhooks settings

Go to Settings → Webhooks in the dashboard . Click Add Endpoint.

Enter your URL and choose events

Enter your endpoint URL (must be https://). Select the events you want to receive:

EventWhen it fires
form.submittedA real, non-spam submission is received
form.spamTorchWarden flags a submission as spam
form.testA test submission is sent (_test=true or via the Send Test button)

You can subscribe to one, two, or all three.

Copy the signing secret

After saving, the signing secret is shown exactly once. Copy it and store it as an environment variable. If you lose it, delete the endpoint and create a new one.

That’s it. Formtorch begins delivering events to your endpoint immediately.

Payload

Every event uses the same JSON envelope:

{ "event": "form.submitted", "timestamp": "2025-03-15T14:30:00.000Z", "delivery_id": "d3f456abc789", "form": { "id": "a1b2c3d4e5", "name": "Contact Form" }, "submission": { "id": "x9y8z7w6v5", "created_at": "2025-03-15T14:30:00.000Z", "data": { "name": "Alex", "email": "alex@example.com", "message": "Hello there" }, "is_test": false, "is_spam": false } }

submission.data contains all submitted fields except reserved _* fields (_redirect, _honeypot, _formName, _test), which are stripped before delivery.

Request headers

Each webhook request includes these headers:

HeaderDescription
Content-Typeapplication/json
X-FormTorch-SignatureHMAC-SHA256 signature: sha256=<hex>
X-FormTorch-EventEvent name, e.g. form.submitted
X-FormTorch-DeliveryUnique delivery ID (matches delivery_id in the body)
User-AgentFormTorch-Webhooks/1.0

Signature verification

Always verify X-FormTorch-Signature before processing a payload. This confirms the request came from Formtorch and the body was not tampered with.

lib/verify-webhook.ts
import { createHmac, timingSafeEqual } from "crypto"; export function verifyWebhookSignature( body: string, signature: string, secret: string ): boolean { const expected = `sha256=${createHmac("sha256", secret) .update(body) .digest("hex")}`; const a = Buffer.from(signature); const b = Buffer.from(expected); if (a.length !== b.length) return false; return timingSafeEqual(a, b); }

Read the raw request body as a string before parsing JSON. Parsing first changes the string representation and breaks the check.

For full examples in Node.js, Python, and PHP, see Signature Verification.

Retry behavior

Your endpoint must respond within 30 seconds with a 2xx status. If it returns a non-2xx response or times out, Formtorch retries the delivery automatically with exponential backoff, up to 6 total attempts (1 initial + 5 retries).

After all attempts are exhausted, the delivery is marked failed. You can retry it manually from the delivery log.

Return 200 OK immediately and process the payload asynchronously if your handler takes more than a few seconds to complete.

Delivery log and manual retry

The delivery log for each endpoint is visible in Settings → Webhooks. It shows the status, HTTP response code, and response time for recent deliveries. Failed deliveries can be retried individually with the Retry button.

Testing your endpoint

Use the Send Test button on any endpoint to fire a form.test event immediately without submitting an actual form. This is useful for verifying your integration and signature verification before going live.

Pausing an endpoint

Click the toggle on any endpoint to pause it. Paused endpoints do not receive deliveries. Queued jobs for a paused endpoint are dropped, not buffered. Unpause to resume delivery.

Last updated on