Formstep

Signed JSON to your own endpoint

When the destination is your own backend, a serverless function or a tool with no native integration, a webhook is the integration. Each submission arrives as one JSON event, keyed by field key, signed so you can prove it came from Formstep, and retried until your endpoint says yes.

Updated

How it works

  1. Open the form’s Integrations, pick Webhook, and type the URL. Leave the mapping empty to send every field, or add rows to send only some, under the JSON keys you choose. See an example request shows the body change as you edit.
  2. Copy the signing secret, which starts with whsec_ and is shown once. Add up to five custom headers, such as an authorization token.
  3. Click Turn on Webhook, then Send a test event: a signed POST with sample answers and your headers, logged in the event log like a real delivery.

See the full guide

What arrives

One envelope for everything Formstep sends: id, type, createdAt, apiVersion, test and data. Under data: the form, the submission with its id, respondent email, time, language and PDF link, an answers object for code, keyed by field key, and a display object with the same keys as readable text. A choice answer is its option key in answers and its label in display; a file is a list with download URLs in one and file names in the other. A submission that answered a request adds a request block with your external id and metadata.

X-Formstep-Signature: t=TIMESTAMP,sha256=HEX

A form can have several webhooks; each fires for every submission and every later edit, told apart by type. Turn on Send the field list with every event if your receiver cannot call fields.list itself.

Retries

Any 2xx is a success. Formstep tries up to five times: at once, then after at least 1, 2, 4 and 8 minutes, so the last attempt comes about two hours after the first. 429, 5xx, timeouts and connection failures are retried, and a longer Retry-After is honoured. 401, 403 and 404 stop the integration at once and email the person who set it up. Deliveries that used all five attempts show in a banner on the integration; Retry all sends them again and turns a paused integration back on.

For local development, expose your dev server with ngrok or a Cloudflare tunnel and point the webhook at it. For unfinished public-link responses, create a submission_abandoned subscription with the REST API; the webhook you add here never fires for them.

A workflow tool with a webhook trigger, such as Make or Pipedream, can receive these too. If the receiver is a workflow waiting on one specific person, you want a request’s callback rather than a webhook: it fires once, for that request, with its outcome.

Questions about Formstep for Webhooks

Something else on your mind? The docs cover every setting, and we answer email.

Read the docs

A webhook belongs to the form and fires for every submission, from share links and requests alike. A callback belongs to one request: the URL you pass as callbackUrl when you create it, called once when that request ends. Both carry the same event envelope.

Each request has an X-Formstep-Signature header of the form t=TIMESTAMP,sha256=HEX: an HMAC-SHA256 of TIMESTAMP, a dot and the raw body, with your signing secret. Hash the body exactly as it arrived. The webhook reference has a snippet to copy.

The workspace owner can reveal it in the dashboard; other members see the rest of the webhook. It cannot be regenerated: for a new secret, delete the webhook and create a new one.

HTTPS on a public address, up to 2,048 characters, with no credentials in the URL. Plain http:// works for localhost during development. Formstep checks the hostname again before every delivery, so a DNS record later pointed at an internal address is still refused.

Collect information from anyone.

Publish a sample form, answer it as your recipient would, and watch the answers come back. No account needed.

Read the docs