Voicemail-Only Configuration Guide
This guide covers implementing Voicemail Only - the base experience where callers go directly to voicemail recording without hold queues or callback options.
This is a base experience, not an add-on. Email notifications and transcription can be added to this experience. See Implementation Guide for the full architecture.
Choose Your Implementation Path
There are two ways to implement Voicemail Only:
| Path | When to Use | Deployment | Feature Directory |
|---|---|---|---|
| Dedicated Feature | New deployments, clean slate | Deploy voicemail-only-with-email/ | serverless-functions/src/functions/features/voicemail-only-with-email/ |
| Parameter Approach | Existing callback-and-voicemail-with-email deployed | Add ?voicemailOnly=true to URL | Uses existing deployment |
Decision Guide
┌─────────────────────────────────────────────────────────────────┐
│ Does the account already have callback-and-voicemail deployed? │
├─────────────────────────┬───────────────────────────────────────┤
│ NO │ YES │
├─────────────────────────┼───────────────────────────────────────┤
│ → Dedicated Feature │ → Parameter Approach │
│ (new deployment) │ (zero additional deployment) │
└─────────────────────────┴───────────────────────────────────────┘
Path A: Dedicated Feature
Use this path for new accounts or when you want a clean, dedicated voicemail-only deployment.
For Human Developers
Step 1: Prepare Environment
- Navigate to your account's serverless directory
- Copy the example environment file:
serverless-functions/.env.example → serverless-functions/.env - Update the following variables:
ACCOUNT_SID: Your Twilio Account SIDAUTH_TOKEN: Your Twilio Auth TokenTWILIO_FLEX_CALLBACK_WORKFLOW_SID: Your workflow SID (e.g.,WW...)MAILGUN_API_KEY: Your Mailgun sending API keyMAILGUN_DOMAIN: Your sending domain (e.g.,voicemail.yourorg.com)NOTIFICATION_EMAIL: Admin email for notifications
Step 2: Deploy Functions
- Open terminal in
serverless-functions/directory - Run deployment script for your account:
./deploy.sh <account-name> - Note the deployed domain (e.g.,
custom-flex-extensions-serverless-XXXX-dev.twil.io)
Step 3: Create Studio Flow
- Navigate to Twilio Console → Studio → Flows
- Click Create new Flow
- Name it descriptively (e.g., "H2H Voicemail Only Flow")
- Select Start from scratch
- Add the following widgets:
Widget 1: Say/Play (Welcome)
- Widget name:
welcome_message - Say: "Thank you for calling [Organization]. Please leave your message after the tone."
- Voice:
Polly.Joannaor preferred voice
Widget 2: TwiML Redirect (Send to Voicemail)
- Widget name:
send_to_voicemail - Widget type:
add-twiml-redirect(NOTtwiml-redirect) - URL:
https://[YOUR-DOMAIN]/features/voicemail-only-with-email/studio/voicemail-recording
- Connect: Trigger → welcome_message → send_to_voicemail
- Click Publish
Step 4: Configure Phone Number
- Navigate to Twilio Console → Phone Numbers → Manage → Active Numbers
- Click on your voicemail number
- Under Voice & Fax:
- Configure with: Webhooks, TwiML Bins, Functions, Studio, or Proxy
- A call comes in: Studio Flow → Select your new flow
- Click Save
Step 5: Test
- Call the voicemail number from another phone
- Verify:
- Welcome message plays
- Recording prompt plays
- You can leave a message
- Task appears in Flex
- Email is sent (if configured)
For AI Agents
Prerequisites Check
# Verify you're in the correct directory
pwd
# Expected: /path/to/connieRTC-basecamp
# Check account configuration
cat serverless-functions/.env | grep -E "ACCOUNT_SID|MAILGUN"
Step 1: Configure Environment
# Create environment file if needed
cp serverless-functions/.env.example serverless-functions/.env
# Edit with required values (use your editor of choice)
# Required variables:
# - ACCOUNT_SID
# - AUTH_TOKEN
# - TWILIO_FLEX_CALLBACK_WORKFLOW_SID
# - MAILGUN_API_KEY
# - MAILGUN_DOMAIN
# - NOTIFICATION_EMAIL
Step 2: Deploy Functions
See Account-Specific Deployment Guide for complete deployment protocol.
# CRITICAL: Use deploy.sh, not npm run deploy
cd serverless-functions
./deploy.sh <account-name>
# Capture the deployed domain
DEPLOYED_DOMAIN=$(twilio serverless:list --properties domainName -o json | jq -r '.[0].domainName')
echo "Deployed to: $DEPLOYED_DOMAIN"
Step 3: Create Studio Flow
# Create Studio Flow via API
# Note: You'll need to create a flow-definition.json first
twilio api:studio:v2:flows:create \
--friendly-name "Voicemail Only Flow" \
--status "published" \
--definition "$(cat flow-definition.json)"
flow-definition.json template:
{
"description": "Voicemail Only Flow",
"states": [
{
"name": "Trigger",
"type": "trigger",
"transitions": [
{
"event": "incomingMessage",
"next": "welcome_message"
},
{
"event": "incomingCall",
"next": "welcome_message"
}
],
"properties": {
"offset": {"x": 0, "y": 0}
}
},
{
"name": "welcome_message",
"type": "say-play",
"transitions": [
{
"event": "audioComplete",
"next": "send_to_voicemail"
}
],
"properties": {
"say": "Thank you for calling. Please leave your message after the tone.",
"voice": "Polly.Joanna",
"offset": {"x": 0, "y": 200}
}
},
{
"name": "send_to_voicemail",
"type": "add-twiml-redirect",
"transitions": [
{
"event": "return"
},
{
"event": "timeout"
},
{
"event": "fail"
}
],
"properties": {
"url": "https://YOUR_DOMAIN/features/voicemail-only-with-email/studio/voicemail-recording",
"method": "POST",
"offset": {"x": 0, "y": 400}
}
}
],
"initial_state": "Trigger"
}
Step 4: Configure Phone Number
# Get the Flow SID from the previous step
FLOW_SID="FW..."
# Update phone number configuration
twilio api:core:incoming-phone-numbers:update \
--sid PN... \
--voice-url "https://webhooks.twilio.com/v1/Accounts/AC.../Flows/$FLOW_SID"
Step 5: Verify Deployment
# List deployed functions
twilio serverless:list --properties functionSid,friendlyName
# Test the voicemail endpoint
curl -X POST "https://$DEPLOYED_DOMAIN/features/voicemail-only-with-email/studio/voicemail-recording" \
-d "CallSid=CA_test" \
-d "From=+15551234567"
Path B: Parameter Approach
Use this when callback-and-voicemail-with-email is already deployed and you want to add a voicemail-only line without additional deployment.
For Human Developers
Step 1: Create New Studio Flow
- Navigate to Twilio Console → Studio → Flows
- Click Create new Flow
- Name it (e.g., "H2H Voicemail Only - Parameter")
- Select Start from scratch
Step 2: Configure TwiML Redirect
Add a single widget:
Widget: TwiML Redirect
- Widget name:
voicemail_only - Widget type:
add-twiml-redirect - URL: Add
?voicemailOnly=trueparameter:https://[YOUR-EXISTING-DOMAIN]/features/callback-and-voicemail-with-email/studio/wait-experience?voicemailOnly=true
Connect: Trigger → voicemail_only
Step 3: Configure Phone Number
- Navigate to your voicemail phone number
- Set A call comes in to your new Studio Flow
- Save
Step 4: Test
The voicemailOnly=true parameter causes the function to:
- Skip all callback and hold queue logic
- Immediately prompt for voicemail recording
- Create ConnieRTC task with voicemail attributes
- Send email to configured admins (uses existing Mailgun setup)
For AI Agents
Step 1: Identify Existing Deployment
# Find existing callback-and-voicemail deployment
twilio serverless:list --properties domainName,friendlyName
# Expected output includes something like:
# custom-flex-extensions-serverless-XXXX-dev.twil.io
Step 2: Create Studio Flow with Parameter
# Create the flow definition with voicemailOnly parameter
cat > voicemail-only-param-flow.json << 'EOF'
{
"description": "Voicemail Only (Parameter)",
"states": [
{
"name": "Trigger",
"type": "trigger",
"transitions": [
{"event": "incomingCall", "next": "voicemail_only"}
],
"properties": {"offset": {"x": 0, "y": 0}}
},
{
"name": "voicemail_only",
"type": "add-twiml-redirect",
"transitions": [
{"event": "return"},
{"event": "timeout"},
{"event": "fail"}
],
"properties": {
"url": "https://YOUR_EXISTING_DOMAIN/features/callback-and-voicemail-with-email/studio/wait-experience?voicemailOnly=true",
"method": "POST",
"offset": {"x": 0, "y": 200}
}
}
],
"initial_state": "Trigger"
}
EOF
# Create the flow
twilio api:studio:v2:flows:create \
--friendly-name "Voicemail Only (Parameter)" \
--status "published" \
--definition "$(cat voicemail-only-param-flow.json)"
Step 3: Configure Phone Number
# Get new flow SID
FLOW_SID="FW..."
# Update phone number
twilio api:core:incoming-phone-numbers:update \
--sid PN... \
--voice-url "https://webhooks.twilio.com/v1/Accounts/AC.../Flows/$FLOW_SID"
How the Parameter Works
When voicemailOnly=true is passed to the wait-experience function:
// In wait-experience.protected.js
if (voicemailOnly === 'true' && (mode === 'initialize' || mode === undefined)) {
// Skip queue lookup and redirect directly to voicemail recording
twiml.redirect(
`${baseUrl}?mode=record-voicemail&CallSid=${CallSid}&enqueuedTaskSid=${voicemailOnlyTaskSid}&voicemailOnly=true`
);
return callback(null, twiml);
}
The parameter is preserved through all callbacks:
- Initial wait experience URL
- Recording action URL
- Transcription callback URL
- Submit voicemail URL
Enabling Add-ons
Both paths support the same add-ons:
Email Notifications
Dedicated Feature: Built-in, configure MAILGUN_* environment variables
Parameter Approach: Uses existing Mailgun configuration from callback-and-voicemail-with-email
See: Email Notifications Add-on
Transcription
Both Paths: Enable in the recording configuration:
const recordingConfig = {
transcribe: true,
transcription_callback: `https://${context.DOMAIN_NAME}/transcription-webhook`
};
See: Transcription Add-on
Troubleshooting
Caller Still Gets Hold Options
- Check: Parameter is exactly
voicemailOnly=true(case-sensitive) - Verify: URL includes the parameter after
? - Confirm: Using correct serverless domain
No Email Sent
- Check Mailgun dashboard for errors
- Verify
MAILGUN_API_KEYis a sending key, not the private API key - Confirm DNS records are verified
- Test Mailgun API directly:
curl -s -w "\nHTTP Status: %{http_code}\n" \
--user "api:$MAILGUN_API_KEY" \
https://api.mailgun.net/v3/$MAILGUN_DOMAIN/messages \
-F from="test@$MAILGUN_DOMAIN" \
-F to="admin@yourorg.com" \
-F subject="Test" \
-F text="Test message"
Task Not Created
- Check Twilio Function logs in Console
- Verify
TWILIO_FLEX_CALLBACK_WORKFLOW_SIDis correct - Ensure TaskRouter workspace is active
Studio Flow Widget Type Error
// WRONG - This type doesn't exist in Studio validation
"type": "twiml-redirect"
// CORRECT - Use add-twiml-redirect
"type": "add-twiml-redirect"
Multiple Voicemail-Only Lines
To add more voicemail-only numbers:
- Create new Studio Flow for each number
- Use the same parameter approach or dedicated feature URL
- All lines share the same email and transcription configuration
- No additional serverless deployments needed
Rollback
Remove Parameter (Instant)
- Edit Studio Flow
- Remove
?voicemailOnly=truefrom the URL - Save - reverts to normal callback/voicemail behavior
Restore Original Function (if modified)
# Restore from backup
cp wait-experience.protected.js.backup wait-experience.protected.js
./deploy.sh <account-name>
Related Documentation
- Implementation Guide - Architecture overview
- Callback + Wait Setup - Full queue experience
- Account-Specific Deployment - Deployment protocol
- Email Notifications - Email add-on
- Transcription - Transcription add-on