Feedback conversations
Support tickets tell you what is broken. Feedback conversations tell you how customers actually feel. Ask a customer for feedback (a feedback request), or record feedback your app collected — either way you get an ongoing conversation with an optional 1–5 rating and explanation, kept separate from your support queue. Available on Pro and above.
Request feedback (the "tickle")
A feedback request emails the customer a built-in, project-branded message with a one-click respond link — no form, no login. The request tracks its funnel: sent → opened (they clicked the link) → responded(they answered), so you always know whether a nudge landed. Perfect for "you signed up but never created a project — what stopped you?" automations driven from your own app.
import { HelmdeskClient } from '@helmdesk/sdk'
const helmdesk = new HelmdeskClient({ apiKey: process.env.HELMDESK_API_KEY! })
// e.g. from a lifecycle job: user signed up 3 days ago, no project yet
await helmdesk.feedback.requests.create({
title: 'How is your FireScraper setup going?',
message:
'Hi! We noticed you signed up but have not created a scraping session yet. ' +
'Did something get in the way? Reply and tell us — we read every answer.',
customerEmail: 'jane@example.com',
customerName: 'Jane',
})
// Later: check the funnel
const { requests } = await helmdesk.feedback.requests.list({ status: 'sent,opened' })The email subject is the request title. When the customer responds, a conversation is created from their answer and linked back to the request.
Link-only requests — send it yourself
Sometimes the ask belongs inside your email — a coupon, a renewal notice, a personal note from the founder. Pass channel: 'link' and Helmdesk sends nothing: the created request comes back with respondUrl, the public respond link, for you to embed wherever you like. The request starts as created instead of sent, and the funnel still tracks opened and responded exactly the same way.
// Create the link — no Helmdesk email goes out
const request = await helmdesk.feedback.requests.create({
title: 'How was your first month?',
message: 'Tell us how the first month went — the good and the bad.',
customerEmail: 'jane@example.com',
customerName: 'Jane',
channel: 'link',
// Staff-only context — the customer never sees this
internalNote: 'Sent $50 coupon WELCOME50 alongside this link',
})
// Put request.respondUrl inside your own coupon email
await sendMyCouponEmail({
to: 'jane@example.com',
couponCode: 'WELCOME50',
feedbackLink: request.respondUrl,
})
// The funnel still tracks it: created -> opened -> respondedThe optional internalNote works on both channels — use it to remember why a request went out ("sent $50 coupon"). It is visible to your team in the dashboard and API, never to the customer.
Record feedback from your app
If you collect feedback inside your own product (an in-app form, an NPS widget), push it to Helmdesk so everything lives in one place:
const conversation = await helmdesk.feedback.conversations.create({
title: 'In-app feedback',
body: 'Love the new export feature, but PDF rendering is slow on big jobs.',
customerEmail: 'jane@example.com',
rating: 4,
ratingComment: 'Great overall, exports need work',
})Reply and close
Conversations are two-way. When you reply — from the dashboard, API, or an AI assistant via MCP — the customer gets an email with a link back to the thread. A customer reply to a closed conversation reopens it.
// List open conversations with low ratings — who is unhappy?
const { conversations } = await helmdesk.feedback.conversations.list({
status: 'open',
rating: '1,2,3',
})
// Read the full thread
const thread = await helmdesk.feedback.conversations.get(conversations[0].id)
// Reply (the customer is emailed) and close
await helmdesk.feedback.conversations.reply(thread.id, 'Thanks — PDF speedup ships next week!')
await helmdesk.feedback.conversations.update(thread.id, { status: 'closed' })Scopes & environments
feedback:read— list and view conversations and requests.feedback:write— create requests, create conversations, reply, close/reopen, set ratings.- Requests created with an
sk_sandbox_…key are sandbox data: no real email is sent, and the data stays in the sandbox plane — ideal for integration tests. See Sandbox.
Endpoints
| Endpoint | Purpose |
|---|---|
| GET/POST /v1/feedback/conversations | List (filter by status, rating, customer, date) / create |
| GET/PATCH /v1/feedback/conversations/:id | Full thread / close, reopen, set rating |
| POST /v1/feedback/conversations/:id/messages | Reply (emails the customer) |
| GET/POST /v1/feedback/requests | List with funnel status / create + send the email |
| GET /v1/feedback/requests/:id | One request incl. opened/responded timestamps |
The MCP server exposes the same surface as tools (request_feedback, list_feedback_conversations, reply_to_feedback, …) — see MCP Server.