---
ref: workflow:nps-detractor-rescue
title: Reach NPS detractors while the score is fresh
author: thedogwiththedataonit
tools: [tool:typeform/retrieve-responses, tool:hubspot/search-crm-records, tool:slack/post-message, tool:hubspot/create-note]
tags: [capability:collect-responses, capability:manage-crm, capability:route-alerts, channel:chat, channel:email, has:api, motion:retention]
updated: 2026-09-27
---

# Reach NPS detractors while the score is fresh

Set up the tools below, then run the steps in order for the user, carrying each step's results into the next.

## Inputs

Ask the user for these before you start.

- `form_id`: the Typeform NPS survey
- `score_field`: the ref of its 0 to 10 question, e.g. nps_score
- `comment_field`: the ref of its open question, e.g. nps_reason
- `email_field`: the ref of the email question, or the name of the hidden field that carries the email, e.g. email
- `lookback_days`: how far back to read responses, e.g. 7
- `cs_channel`: the Slack channel to post in, e.g. #customer-success

## Set up

### Retrieve responses (Typeform, tool:typeform/retrieve-responses)

Use the API.

- Base URL: https://api.typeform.com
- Endpoint: `GET /forms/{form_id}/responses`
- Auth: send the header `Authorization: Bearer $TYPEFORM_API_KEY`
- Get a key: https://admin.typeform.com/user/tokens

Note: Forms with more than 1,000 responses need narrower `since` and `until` ranges or the `before` and `after` cursors. Responses from the last 30 minutes or so may be missing: use a webhook for real-time leads.

### HubSpot (tool:hubspot/search-crm-records, tool:hubspot/create-note)

For each call, use the first option your agent supports that lists it.

Notes:

- Search CRM records: The MCP tool takes up to five groups of six filters and returns up to 200 records per page.
- Create a note: `hs_timestamp` is required; attach the note to existing records with an `associations` object.

#### MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

```json
{ "mcpServers": { "hubspot": { "url": "https://mcp.hubspot.com" } } }
```

- Search CRM records: call the MCP tool `search_crm_objects`

#### API (official)

- Base URL: https://api.hubapi.com
- Search CRM records: `POST /crm/objects/2026-09/{objectType}/search`
- Create a note: `POST /crm/objects/2026-09/notes`
- Auth: send the header `Authorization: Bearer $HUBSPOT_API_KEY`

Note: Use a service key or an app's static access token with the CRM scopes the calls need; paths carry a dated version such as `2026-09`.

### Post a message (Slack, tool:slack/post-message)

Use the first option your agent supports.

Note: Needs the `chat:write` scope. Over MCP it posts as the signed-in user; the API and CLI post as the app's bot.

#### MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

```json
{ "mcpServers": { "slack": { "url": "https://mcp.slack.com/mcp" } } }
```

Call the MCP tool `slack_send_message`.

#### CLI (official)

Install the command, then confirm it runs.

```sh
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash
slack --version
```

Run `slack api chat.postMessage`.

Set `$SLACK_BOT_TOKEN` in your environment first (get a key: https://api.slack.com/apps).

Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.

## Steps

1. **Pull detractors** with Retrieve responses (Typeform). Read the responses to `form_id` submitted in the last `lookback_days`. Keep those with a `score_field` of 6 or less, with the email from `email_field`, the score and the `comment_field` answer.
2. **Find their owner** with Search CRM records (HubSpot). Search contacts by each email. Keep the contact ID, company name and `hubspot_owner_id`; note the emails with no contact.
3. **Route it** with Post a message (Slack). Post one message per detractor to `cs_channel` with the score, the comment, the company and the owner ID.
4. **Write the reply** yourself. Draft a short plain-text reply for each detractor's owner to send that thanks them, restates their comment in one line and asks for 15 minutes. Show the drafts to the user.
5. **Log it** with Create a note (HubSpot). Add a note to each contact ID with the score, the comment and the approved reply.

## Done when

- Every detractor in the window has a Slack post and a drafted reply.
- Each matched contact has a note, and the user has the emails with no contact.

## Rules

- Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
- Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
- Never print API keys.
