Skip to content
Webhooks

Signed webhooks with retries

Add an endpoint URL and Formwire posts every new submission to it as JSON. A signature header lets you verify each request came from us, retries cover a flaky endpoint, and the delivery log shows what happened.

Start free Read the docs 250 free submissions per month.

A signed JSON payload

Each request carries a Formwire-Signature header: a timestamp and an HMAC-SHA256 of the body, keyed with the webhook's secret. Recompute it on your side and reject anything that doesn't match or is more than a few minutes old.

Retries that give up gracefully

A non-2xx answer, a timeout after 10 seconds or a redirect counts as a failure. Formwire retries up to six times, after 1, 5, 15, 60 and 240 minutes, then marks the delivery as gave up.

  • Five deliveries in a row that fail every retry switch the webhook off and email you.
  • Retry a delivery by hand from the submission's page.

Test before you trust it

Send a test payload from the dashboard and see the response status straight away. Test deliveries are marked test: true in the body so your endpoint can tell them apart.

Safe by default

Webhook URLs must be public HTTPS addresses: private networks and local hosts are refused. A webhook added with an API key or through MCP waits for someone to confirm it in the dashboard before it receives anything.

  • Rotate the signing secret any time.
How it works

The payload your endpoint receives

One JSON object per submission, with the fields exactly as your form posted them.

  1. 1

    Open the form's Settings, then Integrations, and add your endpoint URL. Copy the signing secret shown once.

  2. 2

    Verify Formwire-Signature on each request: HMAC-SHA256 of `<t>.<raw body>` with the secret.

  3. 3

    Answer with any 2xx within 10 seconds. Do the slow work after you've answered.

  4. 4

    Watch the delivery log on each submission, or send a test from the dashboard.

json formwire
POST https://hooks.acme.com/formwire
Formwire-Signature: t=1760400000,v1=5f1a…c3
Formwire-Delivery-Id: dlv_01J9…
Formwire-Event: submission.created

{
  "id": "dlv_01J9…",
  "type": "submission.created",
  "created_at": "2026-10-14T09:20:00.000Z",
  "data": {
    "submission_id": "sub_01J9…",
    "form_id": "frm_01J8…",
    "form_name": "Contact",
    "source": "form",
    "created_at": "2026-10-14T09:19:58.000Z",
    "page_url": "https://acme.com/contact",
    "fields": { "name": "Ada", "email": "ada@example.com", "message": "Hi" }
  }
}

Which plans include it

Webhooks, up to 5 per form, come with Pro.

See pricing
FAQ

Questions about webhooks

How do I verify the signature?

Take the t value from the Formwire-Signature header, compute HMAC-SHA256 of `<t>.<raw body>` with your webhook's secret, and compare it with v1 in constant time. Reject requests whose t is more than a few minutes old.

What counts as a failure?

Any status outside 200 to 299, no answer within 10 seconds, or a redirect. Formwire never follows redirects; point the webhook at the final URL.

Will the same submission be sent twice?

A retry sends the same payload with the same id and Formwire-Delivery-Id, so you can de-duplicate on it. A new submission always has a new id.

Can I post to a server on my own network?

No. Webhook URLs must resolve to public addresses, so Formwire can't be used to reach private networks. Use a tunnel or a public relay during development.