Draft, review, and send WhatsApp outreach from one screen

By General Input

Pick your audience from HubSpot, let a background assistant write each WhatsApp message, then approve every one before it sends through Freshchat.

Integrations

  • Freshchat
  • HubSpot

Type

App

Categories

  • Marketing
  • Customer Support

Build me an app that my growth and support team opens whenever we run a WhatsApp outreach push through Freshchat. It has two tabs: an audience builder where I assemble the list, review drafts and send, and a sent log where I see what went out and who replied. Nothing runs on a schedule, a person opens the app and drives the push.

Audience builder tab. At the top I name the push and define the audience by picking a HubSpot contact search, for example customers in a given lifecycle stage, or contacts with a deal closed in the last 30 days. A handler runs HubSpot Search Contacts with those filters and pulls the fields I care about: first name, last name, email, phone, lifecycle stage, company, deal or close information, and owner. Show the results as a table, one row per contact.

Matching to Freshchat. For every contact in the audience, match to their Freshchat record with List Users, keyed on email and then phone. Important data path nuance: Freshchat has no account wide list-all-conversations operation, so any conversation data has to be assembled by walking users first. For each matched user call List User Conversations, take the most recent conversation, then call List Conversation Messages on that conversation to get the latest message and its timestamp. Each row should show: matched or unmatched, the last chat snippet, how long ago they spoke, and the status of that most recent conversation. Use the list pagination parameters page and items_per_page (message lists default to 20 and cap at 50) and only pull the newest page of messages, do not walk full history. Load the Freshchat enrichment progressively so the HubSpot rows render immediately and each row fills in as its conversation lookup completes.

Creating missing people. Rows with no Freshchat record get an "Add to Freshchat" action that calls Create User with the contact's name, email and phone so they can be messaged, plus a bulk version that does it for every unmatched row in the push. Freshchat create and update calls return 202 Accepted and are processed asynchronously, so the resource does not come back in the response: update the row optimistically, then refetch shortly after to confirm, and show a pending state in between rather than treating a 202 as a failure.

Eligibility rules, enforced in the app and not left to the user. Exclude anyone whose most recent Freshchat conversation is still open or unresolved, so we never talk over a live support thread. Exclude anyone who has already been sent to inside this same push, so nobody is messaged twice. Excluded rows stay visible, greyed out, with the exclusion reason spelled out on the row so I can see exactly who got skipped and why. Re-evaluate both rules at send time as well as at display time, since a conversation can open between building the list and pressing send.

The template. The app holds the configuration for a pre-approved WhatsApp template: its name, its language, and the ordered list of variables it expects, each with a short description of what belongs in it. Drafting fills those variables, it never produces free text, because only approved template content can go out.

"Draft messages" button and the background agent. Pressing it kicks off a background agent over the eligible rows. For each person, the agent reads their recent chat transcript (List User Conversations, then List Conversation Messages on the most recent one) plus that person's HubSpot fields from the audience search, and produces values for the configured template variables in a strict schema, along with a one line reason for the angle it chose. The agent writes each person's result back into the app as it goes, so rows populate live and I can watch progress rather than waiting on one big result at the end.

Review table. The drafts land in a review table showing the person, a rendered preview of the template with their variables substituted, the raw variable values, the agent's reason, and a status of pending, approved or rejected. I can edit any variable value inline (the preview updates as I type), reject a row, or approve it, with bulk approve and bulk reject for a filtered selection. Nothing is sendable until it is approved, and rejected rows are kept for the record rather than deleted.

Sending. A "Send approved" action sends each approved row with Send Outbound WhatsApp Message, passing the template and that person's variable values. Send sequentially with a short delay, watch the X-RateLimit-Remaining header that every Freshchat response carries, slow down as it drops and stop cleanly on a 429 so the remaining rows can be retried afterwards rather than lost. Show live progress with per-row outcome and timestamp, and mark each person as sent for this push the moment the send succeeds so the no-double-message rule holds even if I press send again.

CRM write back. After each successful send, create a note on that person's HubSpot contact with Create Note, associated to the contact id, recording which template went out, the rendered message text, and when it was sent, so the CRM shows the outreach alongside everything else on the record. Show the note status on the row and let me retry a failed note without resending the message.

Sent log tab. Build this from List Outbound Messages: one row per message showing who it went to (resolve the Freshchat user back to a name with Get User or Fetch Users by IDs, and link it to the HubSpot contact where we know it), which push and template it belonged to, when it was sent, its delivery status, and whether the person replied. Work out replies by checking that user's conversations for an inbound message after the send timestamp, again via List User Conversations and List Conversation Messages. Let me filter by push, by date range, and by replied versus no reply, and put a small summary strip at the top with sent, delivered, replied and reply rate.

Persistence. Store pushes, their audience rows, the drafts and their approval state, and the send outcomes in the app, so a push survives a reload, the sent log is accurate without refetching everything, and the never-twice rule is actually enforceable. Record which team member approved and which one sent each row, since growth and support share this app.

Related prompts

Explore more prompts
Turn Mailjet email clicks into ranked HubSpot follow-upsiMessage campaign console with pre-flight checks and delivery boardA searchable RFP answer library your bid team drafts fromSee which target accounts just started advertising on LinkedInAccount health board that puts product usage next to your CRMLook up a customer's full chat history mid conversationLusha prospecting workbench with credit-safe revealsWhich companies your LinkedIn ads reach, matched to your CRMLead response desk with a running clock on every new leadApprove Lusha enrichment field by field before HubSpot saves it