--- title: "How to configure direct extension dialling for users and groups" slug: "how-to-configure-direct-extension-dialling-for-users-and-groups" tags: ["Direct Dialing", "Direct Extension Calling", "Extension", "Extension Dialling", "Group and User Extension", "Routing Policy"] updated: 2026-06-18T16:00:53Z published: 2026-06-18T16:00:53Z canonical: "docs.natterbox.com/how-to-configure-direct-extension-dialling-for-users-and-groups" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.natterbox.com/llms.txt > Use this file to discover all available pages before exploring further. # How to configure direct extension dialling for users and groups This guide explains how to build a routing policy that allows callers to dial a known user or group extension directly. The policy plays a prompt, captures the caller's input, validates it against Salesforce, and connects the call if a match is found. ## Use case Direct extension dialling is ideal when your callers already know the extension of the person or team they want to reach. Rather than navigating menus or waiting in a queue, the caller simply enters the extension number and is connected immediately. Common scenarios include: - Internal staff dialling into a main line and routing themselves to a colleague's extension. - Repeat customers who have been given a direct extension for their account manager. - Partner organisations with pre-shared group extensions for specific departments. ## How it works The call flow follows this sequence: 1. The caller hears a prompt asking them to enter a 4-digit extension followed by the **#** key. 2. The system captures the input using an IVR pattern match. 3. A Salesforce query checks the `nbavs__User__c` object for a matching `nbavs__SipExtension__c` value. 4. If no user match is found, a second query checks the `nbavs__Group__c` object for a matching `nbavs__Extension__c` value. 5. If a match is found in either object, the call is connected to that extension. 6. If no match is found, the caller hears an error message and the script returns `false`, allowing the policy to continue to the next app or container. ## Prerequisites - User extensions assigned under each user's Extension field. - Group extensions assigned (if you want group dialling) under each group's Extension field. ## Policy Builder setup The extension dialling logic is handled entirely within a **Script Engine** app. You will need to place it inside an Action container within your routing policy. 1. Open your routing policy in the **Policy Builder**. 2. Add an **Action** container where you want the extension dialling to occur (for example, after a welcome greeting). 3. Inside the Action container, add a **Script Engine** app. 4. Name the app (e.g. "Extension Dialling"). 5. Paste the Lua script (below) into the script field. 6. Save the policy. ## The Lua script The script below handles the full extension dialling workflow — prompting the caller, validating input against Salesforce, and connecting the call. Expand the accordion to view the full script. **Full Lua script — direct extension dialling** ```lua enable_debug('email') function question(say, voice, timeout)    print("DEBUG: Starting IVR loop")        local ivr = {}    local FIRST = 1          ivr[FIRST] = {}    ivr[FIRST].name = 'Extension'        -- Using \\d to safely capture any 4 digits    ivr[FIRST].pattern = '^(\\d{4})#$'      local res = nil    while res == nil or res == false do        res = session.ivr(ivr, say, voice, timeout, 'myIVR')                if type(res) == "table" then        else            session.say(' Sorry that number is not a valid extension ')        end    end    return res['value'] end function checkExtension(extension)    local userSoql = "SELECT nbavs__SipExtension__c FROM nbavs__User__c WHERE nbavs__SipExtension__c = '"..extension.."'"    local userSfRes = connector.sf_query(connectorId, userSoql, 'UserExtension')    if userSfRes == false then    end    local FIRST = 1    if userSfRes ~= false and type(userSfRes) == "table" and userSfRes[FIRST] ~= nil then        return true    end        local groupSoql = "SELECT nbavs__Extension__c FROM nbavs__Group__c WHERE nbavs__Extension__c = '"..extension.."'"    local groupSfRes = connector.sf_query(connectorId, groupSoql, 'GroupExtension')        if groupSfRes == false then    end        if groupSfRes ~= false and type(groupSfRes) == "table" and groupSfRes[FIRST] ~= nil then        return true    end        return false end function connect(extension)    local dialString = {}    local FIRST = 1        dialString[FIRST] = {}    dialString[FIRST].method = "NUMBER"    dialString[FIRST].target = tostring(extension)    dialString[FIRST].start = 0    dialString[FIRST].timeout = 30    dialString[FIRST].screen = false    session.connect(dialString, 33) end local res = question(' Please Enter the Extension you wish to reach followed by the # Key', nil, 7000) if res and checkExtension(res) then    connect(res) else    session.say(' We are sorry, but that extension could not be found in the system. ')    return false end return true ``` ## Script breakdown The script is split into three core functions. Here's what each one does: **question() — capture caller input** This function plays the TTS prompt and listens for the caller to enter 4 digits followed by **#**. It uses a regex pattern (`^(\\d{4})#$`) to validate the input. If the input doesn't match (e.g. fewer than 4 digits or no # key), the caller hears an error message and is prompted again in a loop. Key parameters: - `say` — the TTS message played to the caller. - `voice` — the TTS voice to use (set to `nil` to use the account default). - `timeout` — how long (in milliseconds) to wait for input before re-prompting. **checkExtension() — validate against Salesforce** This function runs two SOQL queries via the Salesforce Connector: 1. First, it queries the `nbavs__User__c` object for a user with a matching `nbavs__SipExtension__c`. 2. If no user is found, it queries the `nbavs__Group__c` object for a group with a matching `nbavs__Extension__c`. If either query returns a result, the function returns `true`. Otherwise, it returns `false`. **connect() — route the call** This function builds a dial string targeting the matched extension number and connects the call using `session.connect()`. The call rings for 30 seconds before timing out. Key parameters in the dial string: - `method` — set to `"NUMBER"` to dial the extension directly. - `target` — the extension number to connect to. - `timeout` — ring duration in seconds (default: 30). - `screen` — set to `false` (no call screening). ## Customisation options | Parameter | Default value | Description | | --- | --- | --- | | Extension length | 4 digits | Change the pattern `\\d{4}` to `\\d{3}` for 3-digit extensions or `\\d{5}` for 5-digit extensions. | | Timeout (IVR) | 7000 ms | How long the system waits for the caller to enter digits. Increase for callers who may need more time. | | Timeout (ring) | 30 seconds | How long the destination extension rings before timing out. Adjust in the `dialString.timeout` value. | | TTS prompt | "Please Enter the Extension…" | Customise the spoken prompt in the `question()` function call at the bottom of the script. | | Error message | "We are sorry, but that extension could not be found…" | Customise the failure message in the final `session.say()` call. | ## Troubleshooting **The caller hears "not a valid extension" repeatedly** This means the IVR pattern is not matching the caller's input. Check that: - The caller is pressing exactly 4 digits followed by **#**. - The pattern in the script matches your extension length (default is 4 digits). - The timeout value (7000 ms) is long enough for the caller to finish typing. **The extension is valid but the call doesn't connect** Check the following: - The user/group extension field in Salesforce actually contains the value the caller entered (check for formatting differences). > 💡 > > **Tip:** Enable `enable_debug('email')` (already included at the top of the script) to receive debug output via email. This makes it much easier to trace issues in production. Just populate your email address in the designated field. ## What happens after the script If the script returns `true` (successful connection), the call ends naturally when either party hangs up. If the script returns `false` (extension not found), the call passes to the next app or container in your routing policy. You can use this to route failed attempts to a receptionist, queue, or voicemail. ## Related - [Connect a Call App](/connect-a-call-app.md) - [Get Info App](/get-info-app.md)