Jump to

Generic Webhook

Send notifications about new survey responses to any HTTP endpoint — your own server, n8n, Make, Zapier, Pipedream, or any other service that accepts JSON.

Setup

Step 1 — Prepare your endpoint

You need a URL that accepts POST requests with a JSON body. This can be:

  • your own server
  • a webhook URL in n8n, Make, Zapier, or Pipedream
  • any service with incoming webhook support

The endpoint must respond with a 2xx status — otherwise the delivery is considered failed and will be retried.

Step 2 — Connect the integration in ftools

  1. Open the survey and go to the Integrations tab.
  2. Click Add integration and select the type Webhook.
  3. In the Provider field select Generic.
  4. Paste your URL into the Webhook URL field.
  5. Optionally set a name for the integration.
  6. Click Save.

The integration will send a notification on every new survey response.

Step 3 — Done

Each new response will be delivered to your endpoint as a JSON payload with full response and survey data. See the payload format below.

Optional — Signature verification

If you want to verify that requests come from ftools, set a secret in the Secret field when creating the integration, or leave it blank to auto-generate one.

The secret can be rotated at any time via the Rotate secret button in integration settings.

Each request will include an X-Webhook-Signature: sha256=<signature> header. See Webhook signature verification for verification instructions.

Reference

Integration configuration

Comparison table
FieldValue
integration_typewebhook
providergeneric
event_types["survey.response"]
urlYour endpoint URL
secretHMAC signing secret (auto-generated if not provided)

Trigger

The survey.response event fires on every new survey response submitted through the public widget. Subscription requirement: ACTIVE or CANCELED. Delivery does not occur on PAYMENT_OVERDUE.

Retries

On failure: 30 s → 120 s → 600 s.

HTTP request

POST <url>
Content-Type: application/json
X-Webhook-Event: survey.response
X-Webhook-Signature: sha256=<hmac>
User-Agent: feedback-tools-webhook/1.0

Timeout: 10 seconds. A 2xx response is considered a success.

Payload format

{
  "event": "survey.response",
  "timestamp": "2026-05-07T10:15:01.000000+00:00",
  "data": {
    "response": {
      "id": 12345,
      "session_uuid": "b1e9c2d3-...",
      "value": 9,
      "text": "Love the new dashboard",
      "country": "PL",
      "rejected": false,
      "created_at": "2026-05-07T10:15:00+00:00",
      "metadata": {
        "user_id": "usr_abc",
        "email": "user@example.com",
        "plan": "pro",
        "mrr": 299
      }
    },
    "survey": {
      "uuid": "3b2a1c0d-...",
      "title": "Post-onboarding NPS",
      "survey_type": "nps_10",
      "scale_style": "numeric_10",
      "question": "How likely are you to recommend us?",
      "response_type": "text"
    }
  }
}

Fields

Envelope:

Comparison table
FieldTypeDescription
eventstringAlways survey.response
timestampISO 8601Time the webhook was sent (not the response time)
dataobjectEvent data

data.response:

Comparison table
FieldTypeDescription
idintegerResponse ID
session_uuidstringWidget session UUID
valueinteger | nullNumeric response value (score)
textstring | nullText comment
countrystring | nullCountry code (ISO 3166-1 alpha-2)
rejectedbooleanResponse was dismissed by the user
created_atISO 8601Time the response was created
metadataobjectArbitrary data passed by the widget (email, plan, mrr, etc.)

data.survey:

Comparison table
FieldTypeDescription
uuidstringSurvey UUID
titlestringSurvey title
survey_typestringType: nps_10, csat, emoji, etc.
scale_stylestringScale style
questionstringQuestion text
response_typestringResponse type: text, numeric, etc.

Note: the data.derived block (nps_bucket, has_text) is not included in the current version. You can compute the NPS bucket yourself: value ≤ 6 → detractor, 7–8 → passive, 9–10 → promoter (only for survey_type: nps_10).

Signature verification

See Webhook signature verification.

Delivery

Comparison table
FieldDescription
statuspending / success / failed
attempt_countAttempt number (1–4)
response_statusHTTP status returned by your endpoint
response_bodyResponse body (up to 2048 characters)
errorError description on network failure

Delivery history is available in the Integrations section on the survey page.