Webhooks Reference

Receive real-time notifications when a form submission occurs.

Requires Team plan or higher.


How webhooks work

When someone submits a response to your form, forms.wtf sends a POST request to each enabled webhook URL configured for that form. Webhooks fire asynchronously and do not block the submission.

  • Delivery is fire-and-forget with a 5-second timeout

  • Only webhooks with enabled: true are fired

  • If a webhook secret is configured, the payload is signed with HMAC-SHA256


Payload format

Every webhook delivery sends a JSON body with this structure:

{
  "event": "form.submission",
  "formId": "clxyz...",
  "data": {
    "wallet": "0xabc...def",
    "ensName": "vitalik.eth",
    "answers": [
      {
        "questionId": "q_abc",
        "questionLabel": "What is your name?",
        "value": "Alice"
      },
      {
        "questionId": "q_def",
        "questionLabel": "Rate your experience",
        "value": "5"
      }
    ],
    "submittedAt": "2026-04-01T14:32:00.000Z"
  },
  "timestamp": "2026-04-01T14:32:01.000Z"
}

Payload fields

Field
Type
Description

event

string

Always "form.submission"

formId

string

The form's unique ID

data.wallet

string

Respondent's wallet address (or anon_<uuid>)

data.ensName

string | null

Resolved ENS name, if available

data.answers

array

Array of answer objects

data.answers[].questionId

string

Question ID

data.answers[].questionLabel

string

Question label text

data.answers[].value

string

The respondent's answer

data.submittedAt

ISO 8601

When the response was submitted

timestamp

ISO 8601

When the webhook was fired


Signature verification

If you set a secret on your webhook, forms.wtf signs the payload using HMAC-SHA256 and includes the signature in the X-Webhook-Signature header.

To verify:

  1. Read the raw request body (as a string)

  2. Compute HMAC-SHA256(secret, body) as a hex string

  3. Compare with the X-Webhook-Signature header value

Node.js example

Python example

If no secret is configured, the X-Webhook-Signature header is not sent.


Managing webhooks

Webhooks are managed per-form through the dashboard or the internal API.

In the dashboard

  1. Open a form in the dashboard

  2. Go to the Webhooks tab

  3. Click Add Webhook

  4. Enter your endpoint URL and an optional signing secret

  5. Toggle the webhook on or off as needed

Via the API

Webhook management uses session-based authentication (dashboard login), not API keys.

Create a webhook

Field
Type
Required
Description

url

string

Yes

A valid URL to receive POST requests

secret

string

No

HMAC-SHA256 signing secret

Response (201):

Update a webhook

All fields are optional — only include the fields you want to update.

Field
Type
Description

url

string

Updated endpoint URL

secret

string | null

Updated secret (set null to remove)

enabled

boolean

Enable or disable the webhook

Delete a webhook

Returns { "ok": true } on success.


Best practices

  • Always verify signatures in production to ensure requests are genuinely from forms.wtf

  • Respond quickly — return a 200 status as soon as possible, then process asynchronously. The webhook times out after 5 seconds.

  • Handle duplicates gracefully — in rare cases, a webhook may fire more than once for the same submission. Use the data.submittedAt and data.wallet fields to deduplicate.

  • Use HTTPS endpoints — avoid receiving webhook payloads over unencrypted connections

  • Monitor failures — if your endpoint is unreachable, webhook deliveries are not retried. Check your server logs if you're missing events.

Last updated

Was this helpful?