Your phone rings, you’re on a job site or stuck in a meeting, the call drops, and your CRM does nothing. Or worse: your generic auto-reply fires at 2:00 AM to a robo-caller, kicking off an infinite loop between two bots that drains your SMS credits by sunrise.
I’ve built and broken dozens of these setups across client accounts before landing on the exact guardrails that make them bulletproof. Here’s how to build a production-ready Missed Call Text Back (MCTB) workflow in GoHighLevel that respects business hours, kills spam loops, stays carrier-compliant, and alerts your team when a real lead is waiting.

1. Why the Native Sub-Account Toggle Fails
Head to Settings > Business Profile in any sub-account, and you’ll see a one-click toggle labeled “Missed Call Text Back.” It looks great on paper because you type one message, hit save, and don’t have to touch the workflow builder.
Turn it off. Seriously. Here’s why that native toggle will burn you:
- Zero schedule logic: It fires whether a lead calls at 2:00 PM on a Tuesday or 3:30 AM on a Sunday.
- No infinite loop defense: When an automated robodialer hits your line, HighLevel texts back. If the bot responds, both systems ping-pong until your Twilio or LC Phone balance hits zero.
- No deduplication: If a customer calls three times in five minutes due to spotty cell service, HighLevel fires three identical auto-texts right back at them.
- Context-blind: It sends the same “Hey, sorry I missed you!” script to new leads, open high-ticket pipeline deals, and angry vendors alike.
Disable that global toggle. We’ll build the logic in the workflow engine where we actually have control over every condition.
2. Setting Up the Call Status Trigger Correctly
Create a blank workflow and name it something clean, like System - Core - Missed Call Text Back. Don’t add actions yet—let’s get the trigger filters locked in first.
Add a new workflow trigger and pick Call Status. HighLevel gives you several filters here, and picking the wrong mix is the most common reason these flows fail in testing.
Set up the trigger with these filters:
- Call Direction:
Incoming - Call Status: Select
missed,busy, andno-answer. Do not selectcompletedorcanceled. - In Phone System: Select your specific tracked number or pool if you run multiple lines. Leave it blank if you want it running across all numbers on the sub-account.
If you’re using custom call routing or IVR phone menus, check the HighLevel Call Status trigger documentation to ensure your ring timeout durations pass the call state back to the workflow engine properly.
3. Anti-Loop Protection and Rate Limiting
Before dispatching an SMS, we need to check the contact record. If this caller already triggered this workflow in the last 60 minutes, we need to exit immediately without spamming them.
The cleanest way to handle this without dealing with complex math or webhooks is an If/Else condition combined with a temporary cooldown tag:
- Step 1: If/Else Action (Name: Check Recent MCTB)
- Branch 1 (Recent Run): Contact Tag includes
temp-mctb-recent - Branch 2 (Eligible): Contact Tag does not include
temp-mctb-recent
- Branch 1 (Recent Run): Contact Tag includes
- Step 2: Under Branch 1 (Recent Run): Add an internal notification or just let the branch end with no outgoing SMS.
- Step 3: Under Branch 2 (Eligible): Add the action Add Contact Tag:
temp-mctb-recent. - Step 4: Cooldown Removal: At the very end of your active path, add a Wait action set to 60 minutes, followed by Remove Contact Tag:
temp-mctb-recent.
This simple cooldown prevents rapid-fire duplicate texts. Also make sure you’re honoring opt-outs across all flows; check out our guide on automating SMS opt-out and DND compliance in HighLevel so you don’t blast DND contacts.
4. Implementing Business Hours and Quiet Windows
A missed call during lunch needs different handling than one at 11:00 PM. If you text an after-hours lead asking “How can I help right now?”, they reply, get silence for nine hours, and immediately call a competitor.
Add an If/Else action named Business Hours Check with two branches:
- Branch 1 (Open Hours): Current Date/Time matches your work schedule (e.g., Monday–Friday, 08:30 to 17:30).
- Branch 2 (After Hours): Current Date/Time is outside those hours.
If you’re handling callers across different time zones, review our breakdown on SMS quiet hours and sending windows in HighLevel to keep your numbers off carrier spam radars.
5. Drafting the SMS Copy with Merge Field Fallbacks
Keep these texts brief, casual, and human. Don’t sound like a corporate answering service. Ask a short question that invites an immediate text reply.
Open Hours Template
Hi { { contact.first_name | default: 'there' }
}, I was on the other line when your call came in. How can I help you today? - { { location.name }
}After Hours Template
Hi { { contact.first_name | default: 'there' }
}, we missed your call and our office is currently closed. What questions can I answer for you so we can get right on it first thing in the morning? - { { location.name }
}If someone calls from a brand-new number without an existing name in your CRM, an unhandled merge tag will print awkward gaps like Hi , I was on the line. Prevent blank variables by checking our guide on fallback default values for merge fields in HighLevel.
6. Building Team Notifications and Assigning Leads
Sending the text is only half the battle. Your team needs an immediate alert so they can jump in manually if the prospect doesn’t respond in a few minutes.
Stack these actions right after your outgoing SMS:
- Assign to User: Set the dedicated rep or route through a round-robin pool.
- Create Task: Title it
Callback: {{ contact.name }}, due in 15 minutes. - Internal Notification: Send an in-app or SMS alert to the assigned user with the contact’s phone number and the exact call timestamp.
7. Integrating External Webhooks for Live Alerts
If your team works out of Slack, Discord, or an internal dashboard instead of living inside the HighLevel app, push the missed call payload out using a Webhook action.
Add a Webhook action to the flow and POST this JSON payload to your endpoint:
Standard payload structure:
{ "event": "missed_call_received", "contact_id": "{{ contact.id }}", "contact_name": "{{ contact.name }}", "contact_phone": "{{ contact.phone }}", "call_direction": "inbound", "timestamp": "{{ date.now }}", "location_id": "{{ location.id }}"
}To catch and route this payload with a lightweight Node.js/Express service, here’s a clean receiver snippet:
Express listener example:
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhooks/ghl-missed-call', (req, res) => { const { event, contact_name, contact_phone, timestamp } = req.body; if (event !== 'missed_call_received') { return res.status(400).json({ status: 'ignored' }); } console.log(`[${timestamp}] Missed call from ${contact_name} (${contact_phone})`); // Dispatch internal alert to Slack or push service here return res.status(200).json({ received: true });
});
app.listen(3000, () => { console.log('Webhook server listening on port 3000');
});8. Troubleshooting: 4 Reasons Your Workflow Fails
If your MCTB flow isn’t firing during testing, check these four things first before tearing the workflow apart:
- A2P 10DLC Registration Is Incomplete or Rejected: US carriers drop unregistered business texts at the gateway. Look at Settings > Phone Numbers > Trust Center. If your brand or campaign registration is pending or unverified, HighLevel will show the step executed, but the message status will show
failedorundeliveredin your conversation logs. Walk through our guide on A2P 10DLC campaign registration to get approved, and double-check the rules in the CTIA Messaging Principles and Best Practices. - “Allow Re-entry” Is Switched Off: Click into the workflow’s Settings tab. If Allow Re-entry is off, a lead can only ever enter this workflow once in their life. If they miss you again three weeks later, nothing happens. Keep Allow Re-entry ON (our cooldown tag handles spam prevention).
- Call Timeout Mismatch: If your forward-to number rings a cell phone that takes 25 seconds to hit voicemail, but HighLevel’s timeout is set to 20 seconds, HighLevel marks the call as missed while the cell phone is still ringing in your hand. Sync your timeout limits under Settings > Phone Numbers.
- Both the Native Setting and the Workflow Are Running: If you built this workflow but forgot to disable the native toggle in Business Profile, contacts will receive two different text messages back-to-back. Turn the native toggle off.
Frequently Asked Questions
Can I trigger this workflow only for new leads and not existing contacts?
Yes. Add an If/Else step right after the trigger that checks Contact > Opportunity status or filters out contacts carrying an active-client tag. You can send cold leads down your fast-response track while routing current customers to a support branch.
Does this work if calls are forwarded to a cell phone?
Yes, as long as the incoming call passes through your HighLevel tracking number first. When a call dials your HighLevel line and forwards out to your cell, HighLevel monitors the connection state. If you don’t answer and the call drops or hits HighLevel voicemail, the workflow triggers as expected.
How do I test this without spending money or burning SMS credits?
Create a test contact with your personal number. Dial your HighLevel number from another phone, let it ring until it drops, and watch the Execution Logs tab inside the workflow builder. You’ll see the exact branch taken and every variable evaluated in real time.
Will this send texts to landline numbers?
HighLevel will attempt the send, but mobile carriers will reject delivery on landline routes. You’ll see an error icon in the conversation history noting SMS failure. If you want to keep logs completely clean, drop a Validate Phone Number action before your SMS step to filter out non-mobile numbers.
Next Steps
Once your missed call sequence is running smoothly, make sure your booking calendar is actually open to take appointments. Check our guide on how to fix GoHighLevel calendar availability issues so leads who click your booking links don’t run into blank scheduling pages.

