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
- Open the survey and go to the Integrations tab.
- Click Add integration and select the type Webhook.
- In the Provider field select Generic.
- Paste your URL into the Webhook URL field.
- Optionally set a name for the integration.
- 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
| Field | Value |
|---|---|
integration_type | webhook |
provider | generic |
event_types | ["survey.response"] |
url | Your endpoint URL |
secret | HMAC 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.0Timeout: 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:
| Field | Type | Description |
|---|---|---|
event | string | Always survey.response |
timestamp | ISO 8601 | Time the webhook was sent (not the response time) |
data | object | Event data |
data.response:
| Field | Type | Description |
|---|---|---|
id | integer | Response ID |
session_uuid | string | Widget session UUID |
value | integer | null | Numeric response value (score) |
text | string | null | Text comment |
country | string | null | Country code (ISO 3166-1 alpha-2) |
rejected | boolean | Response was dismissed by the user |
created_at | ISO 8601 | Time the response was created |
metadata | object | Arbitrary data passed by the widget (email, plan, mrr, etc.) |
data.survey:
| Field | Type | Description |
|---|---|---|
uuid | string | Survey UUID |
title | string | Survey title |
survey_type | string | Type: nps_10, csat, emoji, etc. |
scale_style | string | Scale style |
question | string | Question text |
response_type | string | Response type: text, numeric, etc. |
Note: the
data.derivedblock (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 forsurvey_type: nps_10).
Signature verification
See Webhook signature verification.
Delivery
| Field | Description |
|---|---|
status | pending / success / failed |
attempt_count | Attempt number (1–4) |
response_status | HTTP status returned by your endpoint |
response_body | Response body (up to 2048 characters) |
error | Error description on network failure |
Delivery history is available in the Integrations section on the survey page.