Internal Extension Dialing
Extension dialing lets one on-platform user call another by a short extension number (for example
1001) instead of a phone number, connecting two soft phones without routing through the PSTN. It also
supports adding an extension into an active call as a conference participant.
Like every other soft-phone operation, extension dialing is capability-gated: a provider offers it only when it can connect two of its own registered endpoints. A provider that cannot does not advertise the capability, the soft phone hides the control, and the server fails closed.
The extension registry
Extensions are a provider-neutral, tenant-scoped map from a dialed number to an Orchard user. This is the system of record: providers translate the resolved user into their own live endpoint, so the same extension keeps working if you switch providers.
Manage extensions under Interaction Center > Management > Extensions (requires the Manage telephony extensions permission). For a step-by-step walkthrough, see Extensions in the user manual. Each extension has:
| Field | Description |
|---|---|
| Extension number | Required. The number an agent dials, unique per tenant (for example 1001). |
| User | Required. The Orchard user the extension rings, picked from a searchable list of enabled users. |
| Display name | A name for the extension itself (for example Front desk). When left empty it defaults to the user name, which shows the user's own display name. |
The entry's name is generated from the extension number and the display name, so the list search matches either. Every saved extension is dialable; there is no enabled or disabled state. To stop an extension ringing, delete it.
In the list, each entry shows its extension number as a grey badge with a # icon, then the display name, then the
user name as a separate badge with a person icon, so the number never reads as part of the name.
Who an extension rings, by name
Wherever the soft phone shows an extension it also shows who it rings: the transfer panel offers Transfer to extension 2 · Jane Doe, the keypad names the person while an extension is typed, a call to an extension is shown as Jane Doe · ext 2, and so are extension calls in Recent. A colleague whose extension you ring sees your name on their ringing call.
The name is resolved on the server, in this order:
- The extension's own Display name, when it is set to something other than the user name.
- The user's display name, as the site shows users (the CrestApps Users display name settings, for example first and last name). Without the CrestApps Users feature this is the user name.
- The user name.
- The bare extension number.
The soft phone reads every extension's name in one request when it connects (the GetExtensionDirectory hub
method) and keeps the list, reading it again only after five minutes; nothing is looked up per keystroke. When the
provider has no directory of its own (Telnyx), the transfer panel lists these extensions, and picking one
transfers to it as an extension.
The transfer panel's field searches that list by name as well as by number, in either of its modes: type Test and the list narrows to Test 2 · Ext 2; when a name narrows it to one person, Enter transfers to them. Digits still offer Transfer to extension 2 · Test 2. In the phone-number mode the field keeps its country flag for numbers; in the extension mode it is a plain search box.
Your own extension
The directory a user reads leaves out their own extensions, and tells the soft phone which they are. Calling or
transferring to your own extension would only ring the phone you are using, so it is refused with
That's your own extension. — by the soft phone before anything is sent, and by the server for an extension
call (DialExtension), a blind or warm transfer through the provider, and an extension typed into a Contact Center
call's transfer panel. A Contact Center agent cannot pick themselves either: the agent list leaves them out, and
the Contact Center refuses a transfer to the agent already on the call.
Placing an extension call
On the soft phone, toggle Dial extension, enter the extension, and dial. The dialed value is sent verbatim (it is not canonicalized to E.164) and skips outbound compliance screening, because an internal extension is not consumer outreach.
In extension mode the keypad's field is a plain search box, like the transfer panel's: type part of a colleague's name and the extensions of the people it matches are listed under the field; pick one to call it, or press Enter when the name narrows the list to one person. Digits still call the extension they are. Your own extension is never listed. Recent calls an extension call back as that extension.
An extension call to you always rings with Answer and Decline. The phone answers a leg without ringing only for a call it placed itself or an offer the agent just accepted, and only that one leg: a leg the platform rings at you as somebody's destination never is.
The call is always resolved and bridged server-side — the browser cannot originate directly to a colleague because it does not know the target's ephemeral provider endpoint:
Soft phone (Dial extension) ──► TelephonyHub.DialExtension
│
▼
ITelephonyService resolves the extension → target user (fails closed if unknown)
│
▼
ITelephonyExtensionDialProvider (capability + contract checked together)
│
▼
Provider rings the caller, dials the target endpoint, and bridges the two legs
Voicemail on no answer
If the target does not answer within the ring window, the caller is routed to the target user's voicemail instead of the call simply ending. The recording is ingested into that user's existing voicemail inbox through the standard saved-recording pipeline, so it appears on their soft-phone Voicemail tab like any other message. A caller who hangs up before the target answers, or a normally completed call, is not treated as a no-answer and does not leave a message.
Adding an extension to a conference
While on a call, an extension can be added as a conference participant through
AddExtensionToConference. The provider rings the resolved target and joins their leg to the existing
conversation. This complements the existing merge operation, which conferences calls that are already
active.
After a merge the soft phone shows the calls as one conference, with each participant listed under it, and offers no second merge of them; it remembers the conference itself, because a provider such as Telnyx says nothing of it when the phone reads its calls again. A merge that names calls already in the conference changes nothing (Telnyx's "already joined" refusal is read as done). A merge of a Contact Center caller with an extension call is led by the extension call, which carries the agent into its own conference.
Each participant's row has its own hang-up, which ends that participant only. The extension call a conference was
made from is also the agent's own way into it, so its hang-up (Hangup with the conferenceParticipant request
metadata) hangs up the colleague's leg alone and answers with the call still up and participantLeft set; the phone
stops listing it. Once nobody is left, the agent's remaining legs are hung up. The main hang-up ends the whole
conference.
The provider contract
A provider implements ITelephonyExtensionDialProvider and advertises the matching capabilities:
| Operation | Capability | Method |
|---|---|---|
| Call an extension | ExtensionDial | DialExtensionAsync |
| Add an extension to a conference | ExtensionConference | AddExtensionToConferenceAsync |
TelephonyCapabilityContracts maps both capabilities to ITelephonyExtensionDialProvider, so advertising a
capability without implementing the contract — or implementing the contract without advertising the
capability — both fail closed, exactly like every other telephony operation.
The telephony service resolves the dialed extension to a target user id before invoking the provider; the provider is responsible only for turning that user into its own live endpoint and connecting the call.
Provider support
| Provider | Extension dialing | Notes |
|---|---|---|
| Telnyx | ✅ Supported | Both legs are Telnyx SIP-over-WebSocket registrations. Extension dialing reuses the same two-leg originate-and-bridge orchestration as browser-audio outbound calls, with a SIP target on both sides. Conference-add originates the participant leg and joins it to a Telnyx conference formed from the active call. |
| Asterisk | Not yet | Connecting two just-in-time WebRTC PJSIP browser endpoints over ARI is part of the same server-side originate/bridge wave that gates browser-agent connection, so Asterisk does not advertise the capability yet and the control is hidden for it. |
Exporting and importing extensions
Extensions travel between environments through the Telephony Extensions deployment step and the TelephonyExtension recipe step. A user's identifier is issued by the environment that created the account, so an imported extension finds the user it rings by user name and is stored with that user's identifier in the destination. An extension whose user name does not exist in the destination is reported and skipped, and so is one whose number another extension already holds.
{
"steps": [
{
"name": "TelephonyExtension",
"Extensions": [
{
"ItemId": "9vt3k7x1m5q2c8z4b6n0r3h7y",
"Number": "1001",
"UserName": "agent.smith",
"DisplayName": "Agent Smith"
}
]
}
]
}
When Name is omitted it is built from the number and the display name, and when DisplayName is omitted the user name is shown to callers.