Webhooks
Receive a signed HTTP POST on every submission — the fastest way to stream form data into your own backend.
Create a webhook
Open Integrations → Webhooks in your workspace. Click New webhook, give it a URL, and pick which events you want to receive.
Payload structure
Every webhook POST body follows this shape:
json
{
"id": "sub_01H9Q...",
"event": "submission.created",
"form_id": "frm_01H9P...",
"created_at": "2026-04-12T10:15:30Z",
"data": {
"name": "Ada Lovelace",
"email": "[email protected]",
"message": "Interested in the Pro plan."
},
"meta": {
"ip_country": "TR",
"referrer": "https://example.com/pricing",
"utm": { "source": "google", "campaign": "q2-pricing" }
}
}Verifying signatures
Every webhook request includes a X-AnimationFunnel-Signature header with an HMAC-SHA256 of the raw body, signed with your workspace's webhook secret. Always verify this before trusting the payload.
typescript
import crypto from "node:crypto";
export function verify(body: string, signature: string, secret: string) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}Retries & delivery
We retry failed webhooks up to 5 times with exponential backoff (1m, 5m, 30m, 2h, 12h). Your endpoint must respond with a
2xx status code within 10 seconds.Was this page helpful?