Slack integration
Receive notifications about new survey responses directly in a Slack channel.
Setup
Step 1 — Create an Incoming Webhook in Slack
- Go to api.slack.com/apps and click Create New App → From scratch.
- Give the app a name (e.g.
ftools) and select your workspace. - In the left menu select Incoming Webhooks and enable Activate Incoming Webhooks.
- Click Add New Webhook to Workspace, select the channel where notifications should appear, and click Allow.
- Copy the Webhook URL — it looks like this:
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
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 Slack.
- Paste the Webhook URL from step 1 into the Webhook URL field.
- Optionally set a name, e.g.
Slack — Product feedback. - Click Save.
The integration will send a notification to Slack on every new survey response.
Step 3 — Done
Messages will appear in the selected channel and look like this:
🟢 9 · Post-onboarding NPS
Love the new dashboard
user@example.com · pro · PL · 2026-05-07T10:15:00
- Emoji color: 🟢 promoter (9–10), 🟡 passive (7–8), 🔴 detractor (0–6) — NPS surveys only
- The context line includes email, plan, country, and time — if provided in the response metadata
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 | slack |
event_types | ["survey.response", "survey.response.updated"] |
url | Slack Incoming Webhook URL |
secret | HMAC signing secret (auto-generated if not provided) |
Trigger
The survey.response event fires on every new survey response: from the widget, the public API, a dashboard import or the MCP create_response tool.
The survey.response.updated event fires once when a text comment is added to a response that had none. This happens when the widget sends the score first and the comment later. The message has the same format, with "Text added" in the context line. So a two-step response shows up as two messages: the score, then the full response with the text.
Subscription requirement: ACTIVE, CANCELED or TRIAL. Delivery does not occur on any other status, including 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
Slack receives a Block Kit payload:
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "🟢 9 · Post-onboarding NPS",
"emoji": true
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "> Love the new dashboard"
}
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "user@example.com · pro · PL · 2026-05-07T10:15:00.123456+00:00"
}
]
}
]
}Formatting rules
Header: {emoji} {score} · {survey.title}
- Emoji is based on NPS bucket:
🟢promoter (9–10),🟡passive (7–8),🔴detractor (0–6) - Emoji only appears for
nps_10survey type; omitted for other types - Score is omitted if
valueis null - Maximum 150 characters (truncated)
Section (quoted text): only rendered if the response contains text (response.text). Maximum 2900 characters.
Context line: built from available fields in order: metadata.email · metadata.plan · response.country · response.created_at. Fields are skipped if missing or empty.
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 Slack |
response_body | Response body (up to 2048 characters) |
error | Error description: HTTP <code> for a non-2xx response, or the network error |
Delivery history is available in the Integrations section on the survey page.