Total Leads
β
Avg Response
β
seconds
Contacted <5 Min
β
Opt-Out Rate
β
Leads Per Day
Last 7 daysAvg Response Time
Seconds per dayNo lead data yet
Lead events will appear here once the Cloudflare Worker or your lead forms start posting to POST /api/lead-event.
Leads workspace
Unified list, two-way inbox, and conversion tracking will live here.
Lead list
Per-lead rows, filters, and actions (including block / mark as sold) will appear here.
Unified inbox
Threaded SMS conversations and quick replies from the dashboard β coming soon.
Won & ROI
Mark jobs as sold, attach value, and compare revenue to campaign cost β coming soon.
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. β | |||||
No reports yet
Weekly reports are generated every Monday morning and emailed to you automatically. They'll appear here too.
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?"
π‘ 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?"
π‘ 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β¦
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.
Backend β Create Client Account
Run seed-client.js to create their account
Open PowerShell, navigate to your backend folder, and run:
$env:DATABASE_URL="your_database_url"; node seed-client.js CLIENT_ID THEIR_PIN core client America/New_York +1XXXXXXXXXX +1XXXXXXXXXX trueπ‘ Args used here: tier, role=client, timezone, telnyx_number, forward_phone, active.
Set the client's follow-up timezone (used for 8am-9pm local quiet hours):
Then set their Telnyx number and forwarding phone in the DB:
UPDATE clients SET telnyx_number = '+1XXXXXXXXXX', forward_phone = '+1XXXXXXXXXX' WHERE client_id = 'CLIENT_ID';π‘ telnyx_number receives calls/SMS. forward_phone is the roofer's real cell for call forwarding.
UPDATE clients SET timezone = 'America/New_York' WHERE client_id = 'CLIENT_ID';π‘ Replace America/New_York with the value selected above (IANA timezone format).
Verify the client appears in Admin β Onboarding (or Ops directory)
Onboarding tab: confirm the submission row. Ops β Client directory: confirm the client_id exists and is active. If missing, the seed script may have failed β check your DATABASE_URL.
Test their login URL
Open this in an incognito window β it should auto-login and show their (empty) dashboard:
https://dashboard.responsepro.app?client=CLIENT_ID&token=THEIR_PINCloudflare Worker β Lead Intake
Get the Worker intake URL for this client
The intake endpoint is: https://responsepro-intake.bluediamondcart.workers.dev/{CLIENT_ID}. Replace {CLIENT_ID} with the exact client_id from Phase 1.
Set the Worker URL as the form action on their website
Point their website contact form's action URL to the Worker intake endpoint. The Worker accepts both JSON and form-urlencoded POST requests. Fields: name, phone, email, service, source.
Verify the Worker env vars are set in Cloudflare
Cloudflare Dashboard β Workers β responsepro-intake β Settings β Variables. Confirm: API_BASE (Render URL), API_SECRET (Bearer token), TELNYX_API_KEY, TELNYX_MESSAGING_PROFILE_ID.
Run a test submission end-to-end
Submit a test form with your own phone number. Confirm: (1) SMS arrives within 60 seconds, (2) a row appears in the dashboard Lead Analytics tab, (3) no errors in the Error Log tab.
Confirm the intake is live
The Worker runs 24/7 on Cloudflare's edge β no scenario to toggle. Once the form URL is set, every submission is automatically processed: normalized, deduped, SMS sent, owner alerted, follow-up queued.
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 opt-out and opt-in flows
Text STOP from your phone to their Telnyx number. Confirm the row appears in opted_out_phones and no further automated outbound SMS is sent to that number. Then text START β confirm the row is removed from opted_out_phones and a row appears in opt_in_events.
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
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)π‘ 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.
π‘ One-time setup value β same for all clients. The server handles missed call SMS directly via /api/voice/event (no external scenario needed).
Review the missed call SMS message text
Personalize with the client's business name. Must include "Reply STOP to opt out." Example: "Hi, you just called [Business Name] and we missed you. Still need a roofing estimate? Reply here and we'll get right back to you. Reply STOP to opt out."
Test by calling the Telnyx number and not answering
Call their Telnyx number from your cell. Let it ring out β don't answer. Wait ~30 seconds then check: (1) Missed Calls tab shows a new row, (2) SMS arrives on your phone, (3) error log is clean.
β If all three pass β voice is live. The missed call SMS flow is fully server-side, no external scenario to enable.
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 the follow-up cadence
The 4-step cadence is: 1 hour, 24 hours, 72 hours, 7 days after initial contact. Sequence stops on reply, opt-out (STOP), or all 4 steps sent. No per-client configuration needed β the cadence is the same for all clients.
Test follow-up sequence end-to-end
Trigger a test lead through the Worker intake. Confirm a row appears in follow_up_queue with step = 1 and a valid next_send_at. The first follow-up is scheduled ~1 hour after intake (not immediate). After send, confirm it advances/reschedules to the next step. Verify replying STOP cancels future sends.
β If queue rows schedule correctly and steps advance after sends, follow-ups are live. pg_cron handles execution automatically.
Client Handoff
Send the client their dashboard login URL
https://dashboard.responsepro.app?client=CLIENT_ID&token=THEIR_PINπ‘ Send via text or email. Tell them to bookmark it β that link logs them in automatically.
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 is set up
Make sure they've paid the setup fee (if applicable) and their first month is collected. Don't leave this step until billing is confirmed.
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.β