Slack & Webhooks
Get new feedback, status changes, and replies in Slack, or send signed JSON events to your own endpoint, Zapier, Make, or n8n.
TellTide can notify you outside the dashboard. Connect them in Settings → Integrations. Each account has one Slack connection and one webhook, and both receive events from every app you own.
Events
| Event | Fires when |
|---|---|
feedback.created | A user submits feedback through the widget or the API |
feedback.status_changed | You change an item's status or move it on the board |
feedback.replied | Someone comments on an item |
Pick which events each connection receives. Feedback you add from the dashboard does not trigger feedback.created.
Slack
- In Slack, add the Incoming Webhooks app and choose a channel.
- Copy the webhook URL (it starts with
https://hooks.slack.com/services/). - Paste it into Settings → Integrations → Slack and click Connect Slack.
- Click Send test to post a sample message.
Each message shows the app, the type, the message, who sent it, and a link that opens the item in your inbox.
Webhooks
TellTide sends a POST with a JSON body to your endpoint. Respond with any 2xx status within 8 seconds. Failed deliveries are not retried. The last result appears under the webhook in Settings.
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
X-TellTide-Event | The event name, e.g. feedback.created |
X-TellTide-Delivery | A unique event ID |
X-TellTide-Signature | t=<unix seconds>,v1=<hex HMAC-SHA256> |
Payload
{
"id": "evt_3f1c…",
"type": "feedback.status_changed",
"created_at": "2026-11-05T10:00:00.000Z",
"test": false,
"data": {
"app": { "id": "LUMIO", "name": "Lumio" },
"feedback": {
"id": "a1b2c3",
"type": "bug",
"status": "in_progress",
"roadmap_status": "building",
"title": null,
"message": "CSV export drops the timezone on the created_at column.",
"rating": null,
"severity": "Medium",
"submitter": { "name": "Marcus Lee", "email": "marcus@example.com" },
"url": "https://telltide.com/feedbacks?open=a1b2c3",
"created_at": "2026-11-04 09:12:00"
},
"change": { "from_status": "open", "to_status": "in_progress", "label": "In progress" }
}
}
change is present on feedback.status_changed, and reply ({ "id", "body" }) on feedback.replied. Send test sends a feedback.created event with "test": true.
Verify the signature
Your signing secret (whsec_…) is shown under the webhook in Settings. Compute an HMAC-SHA256 of <t>.<raw body> with the secret and compare it to v1. Reject requests older than five minutes.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyTellTideSignature(rawBody, header, secret) {
const t = /t=(\d+)/.exec(header)?.[1];
const v1 = /v1=([a-f0-9]+)/.exec(header)?.[1];
if (!t || !v1 || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return v1.length === expected.length && timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}
Use the raw request body, not re-serialised JSON. Disconnecting and reconnecting the webhook creates a new signing secret.