Total Leads
—
Avg Response
—
seconds
Contacted <5 Min
—
Opt-Out Rate
—
Leads Per Day
Last 7 daysAvg Response Time
Seconds per dayNo leads yet.
Run a test submission to see data here. Check Error Log under More if automations fail.
Leads workspace
What’s live today: use Lead Analytics (Overview) for lead volume, response-time KPIs, and weekly charts. Use Missed Calls for call recovery and SMS status. Use Weekly reports (More) for saved reports, and Error log if automations fail. The tabs below group how we think about leads, SMS, and outcomes—some capabilities are still on the product roadmap.
Lead list
A sortable per-lead table (filters, quick actions, block number, mark as sold) is not in the dashboard yet. Aggregates and trends are available now on Lead Analytics.
For timelines and KPIs, open Overview. For call-specific rows and recovery SMS, open Missed Calls. If something breaks, check Error log under More.
Unified inbox
Two-way SMS from this dashboard is not available. Replies and live conversations happen on your business phone and your Telnyx-connected number; Response Pro still runs automated outbound, follow-ups, STOP/START/HELP, and compliance on the server side.
Use your phone for back-and-forth with leads; use Overview and Missed Calls here to see outcomes and delivery status.
Won & ROI
Closed-won tracking and in-app ROI (job value, revenue vs subscription or ad spend) are not available in Response Pro yet.
Track wins in your CRM, spreadsheets, or notes for now. If you use the partner Pipeline view, use stages and notes there for internal deal tracking.
Total Missed
—
SMS Sent
—
Recovery Rate
—
Conversations
—
Avg Reply Time
—
seconds
Missed Call Events
| Timestamp | Caller | Call Status | SMS Sent | SMS Status | Replied | Conv. ID |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Automation Error Log
| Occurred At | Event Type | Error | Module | Call UUID | Caller |
|---|---|---|---|---|---|
| No errors logged. | |||||
No reports yet
Weekly performance reports appear here after they’re generated for your account. Email delivery on a set schedule is on the roadmap; you can always view history in this tab.
Prospects
Local roofing & contractor companies in the Fredericksburg / Spotsylvania / Stafford corridor.
No prospects yet
Click + Add Prospect to log your first roofing company.
| Company | Phone | Website | Response Time | Status | Notes | Updated |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Call Script
Select a prospect to load their personalised script with real response-time data pre-filled.
Select a prospect above to load the script.
Objection Handler
Tap an objection during a live call to reveal the exact response to say.
"That's great — most of our clients had something before switching too. The difference is ResponsePro texts every lead in under 60 seconds, automatically, 24/7. Whatever you're using now, is it doing that? Most tools require someone to log in and follow up manually. This runs itself."
"Totally fair — can I ask one quick thing? When a lead fills out your website form at 9pm on a Saturday, what happens? If the answer is 'they wait until Monday,' that's revenue sitting on the table every weekend. That's the only problem we solve, and we do it completely hands-off for you."
"I get it — $397 a month sounds like a cost. But think about what one roofing job is worth to you — $8,000? $15,000? If this system recovers even one lead a month that you would have lost to a competitor who responded faster, it's paid for itself ten times over. The question isn't the cost, it's what it costs you to not have it."
"Of course — when's a better time? I'll put it in my calendar right now. I just want to make sure I actually reach you — would [specific day] morning or afternoon work better?"
Tip: Get a specific day/time before hanging up. "Later" without a time = lost lead.
"Respect — a lot of owners do at the start. But when you're on a roof or in the middle of a job, are you texting back every new inquiry within a minute? Because that's what it takes to win the lead. ResponsePro handles that the second a form comes in, so you can stay focused on the work and still never lose the lead."
"Happy to — and I will. But real quick: SMS has a 96% open rate, email is around 20%. That's actually the core reason ResponsePro uses text instead of email to contact your leads. Can I grab your best email address? And while I have you — is there a specific concern I can address right now so the email is actually useful to you?"
Tip: Sending email is fine, but don't let it replace the conversation. Get one real question answered first.
Pipeline
Prospects by stage. Projected MRR shown for Interested (50%) and Closed (100%) at Core pricing ($397/mo).
Loading pipeline…
Onboarding
Review submissions, flip accounts to active, and export rows when you need a spreadsheet.
Total Submissions
—
Active
—
Pending
—
Cancelled
—
Onboarding Submissions
| Business | Owner | Contact | Tier | Submitted | Client ID | Account | Status | Actions |
|---|---|---|---|---|---|---|---|---|
| Loading… | ||||||||
Ops & tools
Quick checks, client directory, and exports. PINs are never stored here—use secure channels only.
Connectivity
—
Client directory
| Pin | Client ID | Tier | Role | Active | Actions |
|---|---|---|---|---|---|
| Open this tab to load the directory. | |||||
Onboarding export
Downloads the same fields as the Onboarding table (browser download).
Runbook shortcuts
Follow these steps every time you onboard a new client. Check off as you go — progress saves in your browser.
Sales → Backend — Create the paying client
Customer completed onboarding.responsepro.app and paid in Stripe
They pick Core or Pro, accept TCPA language, submit the form, then get redirected to Payment Links ($500 setup + monthly). You get the admin email (Resend) and a row in Admin → Onboarding. Use their suggested client_id from the form email, or agree on a final ID before seeding.
Tip: Pricing on the public site is Core $397/mo and Pro $747/mo (plus setup). Match the tier in the seed command to what they paid.
Run seed-client.js to create their dashboard login
From api-backend (Render shell or local with DATABASE_URL):
$env:DATABASE_URL="your_database_url"; node seed-client.js CLIENT_ID THEIR_PIN core client America/New_York +1XXXXXXXXXX +1XXXXXXXXXX trueArgs: client_id, pin (their dashboard PIN), tier = core or pro, role = client, IANA timezone, telnyx_number, forward_phone, active. Replace core with pro when needed. Legacy growth still accepted in the script but is deprecated — map old customers to pro.
Timezone (follow-ups + intake SMS wording): choose IANA zone; it updates the seed snippet and SQL below.
If the client already exists from seeding, you can patch numbers only:
UPDATE clients SET telnyx_number = '+1XXXXXXXXXX', forward_phone = '+1XXXXXXXXXX' WHERE client_id = 'CLIENT_ID';telnyx_number = the Telnyx DID (calls + SMS). forward_phone = contractor cell for voice bridge in /api/voice/answer.
UPDATE clients SET timezone = 'America/New_York' WHERE client_id = 'CLIENT_ID';Quiet hours (automated follow-ups): nothing sends between 9 PM and 8 AM local for that timezone; due sends reschedule to 8 AM local. Intake “business hours” SMS uses a separate weekday window in the Worker (see docs/WORKER-API-PARITY.md).
Verify Admin → Onboarding and Ops → Client directory
Onboarding tab: their submission row. Ops: client_id appears, tier matches what they bought, active is correct. If missing, the seed failed — check DATABASE_URL and script output.
Test their login URL
Incognito: ?client= + &token= triggers POST /api/auth/login with that PIN and stores a JWT. Replace THEIR_PIN with the same PIN you hashed in seed-client.js:
https://dashboard.responsepro.app?client=CLIENT_ID&token=THEIR_PINCore vs Pro UI: the Missed tab is hidden for Core (missed-call SMS is Pro-only in code). They still see Overview, Leads, reports, etc.
Cloudflare Worker — Lead Intake
Give them the production intake URL
Production hostname: https://intake.responsepro.app/CLIENT_ID (POST). Workers dev URL for debugging: https://responsepro-intake.bluediamondcart.workers.dev/CLIENT_ID. Path segment must match clients.client_id exactly.
Point the website / Angi / Zapier webhook at that URL
POST JSON or application/x-www-form-urlencoded. Common fields: name, phone (required for SMS), email, service, source, city — the Worker normalizes aliases (see restless-tooth-94b4/src/index.js).
Cloudflare Worker secrets (Render parity)
Workers → responsepro-intake → Settings: plain var API_BASE = https://responsepro-api.onrender.com. Secret API_SECRET = same value as Render’s API_SECRET (Bearer for internal routes). Outbound SMS is not sent from the Worker anymore — it goes through POST /api/internal/outbound-sms on Render (caps + compliance). Remove TELNYX_API_KEY / TELNYX_MESSAGING_PROFILE_ID from the Worker if still present.
Full contract: docs/WORKER-API-PARITY.md.
Test intake end-to-end
POST a test lead (real phone). Confirm: SMS to lead + optional owner alert, a lead row on the Leads tab, and a row in follow_up_queue. Check Error Log if anything fails.
Confirm intake is live
Worker returns 200 {"received":true} immediately and finishes work in the background (dedup, opt-out check, lead-event, SMS via API, follow-ups enqueue). Tier limits: monthly lead/SMS caps apply on the API side.
Telnyx — Inbound SMS (Opt-out handling)
Set inbound webhook in Telnyx Messaging Profile
Telnyx Portal → Messaging → Messaging Profiles → find their profile → set the Inbound Webhook URL to: https://responsepro-api.onrender.com/api/sms/inbound (POST)
Set inbound webhook in Telnyx for their number
Telnyx Portal → Numbers → their number → Edit → set Messaging Webhook URL to the same URL: https://responsepro-api.onrender.com/api/sms/inbound. Method: POST.
Test STOP / START (authoritative suppression)
Text STOP to their Telnyx number. Confirm a row in opted_out_phones. Then text START — row removed, opt_in_events logged, confirmation SMS sent per API.
/api/internal/follow-ups/process; missed-call recovery SMS (Pro) is skipped in /api/voice/event when the caller is opted out. Inbound handlers won’t log that thread as a new “reply” if opted out. START restores normal automated sends (subject to tier caps).Test HELP reply
Text HELP from your phone to their Telnyx number. Confirm you receive the help response with support contact info. The server handles STOP/START/HELP automatically — no external scenario needed.
Telnyx Voice — Missed Call System
Pro tier only — missed-call recovery SMS
Core accounts do not get automated missed-call texts from /api/voice/event (tier gate in the API). Voice answer still bridges callers to forward_phone for all tiers. For Core clients, skip SMS expectations in tests below unless you upgrade their tier to pro.
Create a Telnyx Call Control Application
Telnyx Portal → Voice → Call Control → Create Application. Set:
Webhook URL: https://responsepro-api.onrender.com/api/voice/event (POST)
Answer URL: https://responsepro-api.onrender.com/api/voice/answer (POST)Tip: One Call Control Application covers all clients — you don't need a new one per client.
Link their Telnyx number to the Call Control Application
Telnyx Portal → Numbers → find their number → Edit → assign it to the Call Control Application you just created. This tells Telnyx to hit your webhook URL when that number receives a call.
Confirm env vars are set in Render
Render Dashboard → ResponsePro API → Environment → confirm this is set:
TELNYX_WEBHOOK_PUBLIC_KEY— your Ed25519 public key from Telnyx Portal → API Keys → Webhooks. Required — server rejects all voice webhooks without this.
Tip: One-time setup value — same for all clients. The server handles missed call SMS directly via /api/voice/event (no external scenario needed).
Optional — customize missed-call SMS copy
Production text is hard-coded in api-backend/server.js inside /api/voice/event (mentions client_id, TCPA line, rates). Change it there and redeploy if you want a different template per brand.
Test by calling the Telnyx number and not answering
Pro: Let it ring out (or timeout). Check Missed Calls tab, recovery SMS to the caller, clean Error Log. Core: call still bridges on answer; expect no auto missed-call SMS from the API.
/api/voice/answer returns a connect action to forward_phone (25s timeout) so inbound callers reach the contractor’s cell; no timezone logic on that bridge.
pg_cron — Follow-up Sequences
Verify pg_cron job is active in Supabase
Supabase Dashboard → SQL Editor → run: SELECT * FROM cron.job; Confirm there is a job that calls POST /api/internal/follow-ups/process every 5 minutes. This replaces the old Make.com follow-up scenario entirely.
Confirm cadence + tier step cap
Delays between steps (when running): ~1 hour, 24 hours, 72 hours, then 7 days. Pro runs all four steps. Core runs two steps only (API completes the sequence at tier cap). Stops when the lead texts your Telnyx number (logged in lead_replies), on STOP, after the last allowed step, or when monthly SMS caps block sends.
Test follow-up sequence end-to-end
Trigger a test lead via Worker. Confirm follow_up_queue row step = 1, first next_send_at ~1 hour out. After cron fires, step advances until Core cap or Pro completion. Text STOP to verify cancellation.
Orchestration is Supabase pg_cron + pg_net calling POST /api/internal/follow-ups/process with Bearer API_SECRET.
Client Handoff
Send the client their dashboard login URL
https://dashboard.responsepro.app?client=CLIENT_ID&token=THEIR_PINTip: Share over a secure channel — token is their raw PIN. Bookmarking logs them in via /api/auth/login.
Walk them through the dashboard (5 min)
Show them: Lead Analytics KPIs, the weekly chart, Missed Calls tab, and how to read response times. Keep it simple — they care about leads contacted and response speed.
Confirm billing in Stripe
They should have completed onboarding.responsepro.app → Stripe Payment Links ($500 setup + $397/mo Core or $747/mo Pro). Match Stripe Customer to their client_id in your records; rotate links in onboarding/script.js if you create new Products/Prices.
Update onboarding status to Active
Onboarding tab → find their row → click Active. This is your internal record that they're fully live.
Schedule 7-day check-in
Set a reminder to follow up in 7 days. Ask: Are they getting SMS alerts? Any issues? This is also your shot to get a testimonial early.
Create rep login
Give your hire their own dashboard login
They only see Prospects, Call Script, Objections, and Pipeline—so they can work leads without touching customer analytics or your admin tools.
Run in PowerShell from your backend folder (same as seeding a client; role is partner in the DB):
$env:DATABASE_URL="your_database_url"; node seed-client.js PARTNER_ID REP_PIN core partner America/New_York "" "" trueOne login per rep
Each salesperson should have their own ID and PIN so pipeline ownership and activity stay clear.
Assign prospects / territory
Point leads at this rep
In the database, each prospect row belongs to a rep by ID. Assign the territories or lists this hire should work so their Prospects tab fills in.
UPDATE prospects SET partner_id = 'PARTNER_ID' WHERE partner_id = 'default';Confirm they have enough accounts to call
Before go-live, sanity-check counts so the rep isn’t staring at an empty list.
SELECT partner_id, COUNT(*) FROM prospects WHERE status != 'deleted' GROUP BY partner_id ORDER BY COUNT(*) DESC;QA + handoff to the rep
Send them the login link
They sign in with the same dashboard URL you use—only the tabs change based on their role. Replace REP_PIN with their real PIN when you share (use a secure channel).
https://dashboard.responsepro.app?client=PARTNER_ID&token=REP_PINWatch them click through once
Have them open Prospects, move a stage, skim Call Script and Objections, and check Pipeline. Fix access issues before they’re solo on the phones.
Set expectations
Confirm how you want notes entered, stages used, and follow-ups logged. This CRM is internal—your process, your rules.
Short line you can repeat to a new hire: “Use the link I sent—bookmark it. You’ll see your territory in Prospects; Pipeline is where you track deals. Ping me if anything looks empty or broken.”