Voicemail Configuration Guide

Summary

Voicemail in Expertflow CX allows a customer to leave a recorded message when their private advisor is unavailable — on another call, in Not Ready state, logged out, or after ring-no-answer (RONA). The recording is stored on the media server and a VOICE_MAIL_ACTIVITY is posted to CX so the advisor can play it back from the Agent Desk voicemail mailbox.

Configuration overview:

  1. Conversation Studio — add the Condition Checker and Set Voicemail nodes; set the Voicemail DN.

  2. FusionPBX Dialplan — create the voicemail capture dialplan (e.g. 54544).

  3. Voicemail Internal DN — create the customer entry dialplan (e.g. 1122) and set isDidVoicemail.

  4. Enable Voicemail Application — make sure the FusionPBX Voicemail app is enabled and running.

  5. Enable Voicemail on Extensions — turn on voicemail for each advisor extension in FusionPBX.

  6. Keycloak — map each advisor to agentExtension or DID_number.

  7. Nginx Voicemail Route — expose the voicemail recording path over HTTPS.

  8. voicemail_end.lua — update the media server recording URL and CX connection details.

Configuration

1. Conversation Studio

Configure the voice flow so that when voicemail is enabled, the call is routed to the Voicemail DN. This DN must match the FusionPBX voicemail dialplan destination_number (e.g. 54544).

Open the Find Agent Subflow

  1. Open Conversation Studio at CX-FQDN/conversation-studio/ and log in.

  2. Double-click the Find Agent Subflow node (top left of the canvas).

  3. In the popup, click Edit Properties.

image-20260720-085453.png

Configure the Condition Checker node

The Condition Checker decides whether the call should take the voicemail path.

  1. In the left panel, open the Condition section.

  2. Drag the Condition Checker node from the Condition section onto the flow canvas.

  3. Double-click the Condition Checker node to open its properties.

  4. Configure the condition as follows:

    • Message / Field: select msg.

    • Value: payload.data.additionalDetails.isVoiceMailEnable

    • Condition: select is true from the dropdown.

  5. Save the Condition Checker node.

image-20260723-051932.png

Configure the Set Voicemail node

After the Condition Checker is configured, add and configure the Set Voicemail node.

  1. In the left panel, open the Actions section.

  2. Drag the Set Voicemail node from the Actions section onto the flow canvas.

  3. Double-click the Set Voicemail node to open its properties.

  4. Enter the Voicemail DN in the Voicemail DN input box (e.g. 54544). This value must match the FusionPBX dialplan in section 2.

  5. Save the Set Voicemail node.

image-20260720-085555.png

Connect the nodes and save

  1. Connect the nodes so that the true path of the Condition Checker leads to the Set Voicemail node. Use the completed flow diagram below as the reference.

  2. Save the subflow configuration.

The completed flow should look like this:

image-20260720-123504.png

2. FusionPBX Dialplan

Create a dialplan entry for voicemail capture. Voice Connector transfers calls to this DN when the advisor is unavailable.

  1. Open the FusionPBX web interface and log in.

  2. Go to DomainDialplanDialplan Manager.

  3. Click Add to create a new dialplan entry.

  4. Configure the dialplan using the table below and save.

image-20260720-075454.png

Order

Tag

Type

Data

Enabled

1

condition

destination_number

^54544$

true

2

action

set

agent_extension=${voicemail_agent_extension}

true

4

action

set

vm_caller_id=${sip_from_user}

true

6

action

set

vm_called_dn=${destination_number}

true

7

action

set

vm_domain=${domain_name}

true

30

action

set

api_hangup_hook=lua /usr/share/freeswitch/scripts/voicemail_end.lua ${uuid} ${vm_caller_id} ${vm_called_dn} ${vm_domain} ${agent_extension} ${strepoch()} AGENT_EXTENSION ${destination_number} ${sip_h_X-CALL-ID}

true

33

action

voicemail

default ${domain_name} ${agent_extension}

true

3. Voicemail Internal DN

Create a dialplan entry for the customer entry point into the voicemail flow. Calls to this DN execute vcApi.lua 'voicemail'.

The isDidVoicemail session variable controls which routing path runs:

  • isDidVoicemail=falseagent extension flow: customer is prompted to enter their advisor's extension.

  • isDidVoicemail=trueDID flow: call is routed using the advisor's dedicated DID number.

  1. Open the FusionPBX web interface and log in.

  2. Go to DomainDialplanDialplan Manager.

  3. Click Add to create a new dialplan entry.

  4. Configure the dialplan using the table below and save.

image-20260720-081034.png

Order

Tag

Type

Data

Enabled

1

condition

destination_number

^1122$

true

2

action

set

isDidVoicemail=false (extension flow) or isDidVoicemail=true (DID flow)

true

3

action

lua

vcApi.lua 'voicemail'

true

4. Enable Voicemail Application

On some FusionPBX installs the Voicemail application is disabled. If it is not running, mailboxes will not work even when dialplans and extensions are configured.

  1. Open the FusionPBX web interface and log in.

  2. Go to AdvancedApp Manager.

  3. Search for Voicemail.

  4. Confirm the Voicemail application status is Enabled. If it is disabled, enable it and save.

  5. Verify that AppsVoicemail is now visible in the FusionPBX menu.

If the Voicemail app was just enabled and settings look incomplete, run App Defaults:

  1. Go to AdvancedUpgrade.

  2. Select the App Defaults checkbox and execute.

5. Enable Voicemail on FusionPBX Extensions

Each advisor extension that can receive voicemail must have voicemail enabled in FusionPBX. Without this, the dialplan action voicemail default ${domain_name} ${agent_extension} cannot store a message for that extension.

  1. Open the FusionPBX web interface and log in.

  2. Select the target Domain (e.g. expertflow).

  3. Go to AccountsExtensions.

  4. Open the advisor extension (for example, 1001).

  5. Set Voicemail Enabled to True.

  6. Optionally set a Voicemail Password if local mailbox access is required.

  7. Click Save.

  8. Repeat steps 4–7 for every advisor extension that should receive voicemail.

You can confirm the mailbox exists under AppsVoicemail.

6. Keycloak

Map each advisor in Keycloak so the system knows which agent handles which customer call. The attribute required depends on the voicemail routing path configured in section 3.

  1. Open the Keycloak admin console and log in.

  2. Select the target realm (e.g. efcx-dev2).

  3. Go to Users and open the advisor user.

  4. Open the Attributes tab.

  5. Add the attribute for the routing path:

Flow

Key

Value

Example

Agent extension

agentExtension

Advisor extension

1234

DID

DID_number

Advisor DID number

100

  1. Click Save.

Agent extension flow — assign agentExtension to the advisor:

image-20260720-093210.png

DID flow — assign DID_number to the advisor:

image-20260720-092954.png

7. Nginx Voicemail Route

Nginx must expose the FreeSWITCH voicemail storage path so Agent Desk can play recordings from the URL built by voicemail_end.lua (for example, https://<MEDIA-SERVER-IP>/voicemail/...).

  1. On the media server, open the FusionPBX Nginx site config:

    nano /etc/nginx/sites-available/fusionpbx
    
  2. Go to the HTTPS section (around line 198):

    listen [::]:443 ssl;
    listen 443 ssl;
    server_name fusionpbx;
    
  3. Inside that server { ... } block, find location / { and add the following block above it:

    location /voicemail/ {
        alias /var/lib/freeswitch/storage/voicemail/default/;
        add_header Content-Type audio/wav;
        add_header Accept-Ranges bytes;
    }
    
  4. (Optional but recommended) Add the same location /voicemail/ block in the listen 80 server (around line 66), also above its location /.

  5. Save the file and exit the editor.

  6. Test the Nginx configuration and reload:

    nginx -t
    systemctl reload nginx
    

After this change, a recording path such as /var/lib/freeswitch/storage/voicemail/default/expertflow/1001/msg_....wav is reachable at https://<MEDIA-SERVER-IP>/voicemail/expertflow/1001/msg_....wav.

8. voicemail_end.lua Script

The script is already deployed on the media server at /usr/share/freeswitch/scripts/voicemail_end.lua. It runs on call hangup (via the api_hangup_hook in section 2), looks up the recording, and posts a VOICE_MAIL_ACTIVITY to CX. For each deployment, update the media server URL and CX connection details as follows.

Update the media server recording URL

  1. Open /usr/share/freeswitch/scripts/voicemail_end.lua on the media server.

  2. Locate the VOICEMAIL_RECORDING_BASE_URL setting near the top of the script.

  3. Change it to your media server voicemail endpoint:

    local VOICEMAIL_RECORDING_BASE_URL = "https://<MEDIA-SERVER-IP>/voicemail"
    

    Example: https://192.168.1.17/voicemail

  4. Save the file.

Update the CX connection details

The script loads CX settings from an env file named:

cx_env-<domain>-<service_id>.lua

Here, service_id is the Voicemail DN (the voicemail triggering DN configured in Conversation Studio and matched by the FusionPBX dialplan in section 2 — e.g. 54544).

The dialplan hangup hook passes ${destination_number} as this value, so if your Voicemail DN is 54544 and the domain is expertflow, the env file name is:

cx_env-expertflow-54544.lua
  1. Open or create the env file on the media server under /usr/share/freeswitch/scripts/ using the Voicemail DN as the service identifier.

  2. Set the CX FQDN and authentication values for your environment. Example:

    local config = {
        cxFqdn = "https://<CX-FQDN>",
        auth_enabled = false,
        auth_realm = "expertflow",
        client_id = "cim",
        client_secret = "<CLIENT_SECRET>",
        username = "voice_auth",
        password = "<PASSWORD>"
    }
    
    return config
    
  3. Confirm the file ends with return config. Without this return, the script cannot load CX settings.

  4. Save the file. No FreeSWITCH restart is required; the next hangup hook picks up the changes.

Limitations

  • Let's say we have two Private Advisors, A and B, and a VIP Customer. That customer is mapped to Private Advisor A. If the customer enters the extension for Private Advisor B, the call routes to it if it is available; otherwise, voicemail is triggered.

  • During the active call, the agent can play the voicemail.

  • Let's assume Private Advisor A is assigned to VIP customer Zeeshan, and Private Advisor B is assigned to VIP customer Usama. When Private Advisor A logs in to the Agent Workspace, they are also able to view the voicemail interactions of Usama's customer. This is the current product behavior.

  • Provided that isVoicemailEnabled=false is configured in the Agent Desk Helm values, a user can still access the voicemail inbox by navigating to the /customers/voicemail endpoint appended to the application's FQDN.

  • Assume voicemail is initially enabled in Agent Desk and several voicemail interactions are created. If voicemail is later disabled and the user navigates to the Interactions page, the previously created voicemail interactions are still visible.

  • Real-time notification is not implemented yet.