Skip to main content



Verto (VER-to) RTC is a FreeSWITCH endpoint that implements a subset of a JSON-RPC connection designed for use over secure websockets. The initial target is WebRTC to simplify coding and implementing calls from web browsers and devices to FreeSWITCH. This allows a web browser or other WebRTC client to originate a call using Verto into a FreeSWITCH installation and then out to the PSTN using SIP, SS7, or other supported protocol. This moves FreeSWITCH farther out onto the cutting edge of real-time communications technology while maintaining interoperability with SIP and other legacy protocols.

mod_verto is the signaling protocol. It depends on mod_rtc for secure media streaming services.

Sofia is a SIP stack used by FreeSWITCH.

Click to expand Table of Contents


Verto specifies a Javascript library to be used in the browser while speaking JSON to the server.

Provides a single library and signaling channel for session management, call control, text messaging, event messaging, and user data exchange.


Verto was named after the Latin root word for "communication" or "dissemination of information" as seen in the modern use of the verb "advertise". In this, Verto simplifies communications between modern devices.


Verto performs most of the processing for its signaling protocol which relieves the web developer of a huge burden. A relatively simple Javascript enables a web browser to participate in a conference call that displays the list of participants with near-real-time updates of who is speaking; the moderator could be provided with visual controls to mute or kick a particular conferee. Because Verto is designed to work hand-in-hand with WebRTC it avoids the complications of using SIP, instead preferring a command structure designed for the purpose.

To see demonstration Javascript code look at the FreeSWITCH source code tree on GitHub.


mod_verto implements a FreeSWITCH endpoint as a subset of a JSON-RPC connection designed for use over websockets.

mod_verto is the signaling protocol. It depends on mod_rtc for media streaming services.

mod_verto was introduced into the version 1.5 development branch of FreeSWITCH and is undergoing heavy development in the Master branch. Please see the Community page for ways to participate in the development and testing of this neat protocol.


WebRTC and WSS (secure web sockets) began life with security as a primary design goal, not an afterthought. In order for any WebRTC implementation to function you must install properly configured certificate(s) and have the correct A record(s) in your DNS pointing to your FreeSWITCH domain. The hacks previously available for SIP with force-registration-domain and related force- settings simply can not work in the WSS security model. This is a Good Thing.

Only proceed with the following instructions after you have properly installed your WSS certificates. Follow the directions on the WebRTC page under Install Certificates.


Create this sample file conf/autoload_configs/verto.conf.xml


<configuration name="verto.conf" description="HTML5 Verto Endpoint">
<param name="debug" value="10"/>
<param name="enable-presence" value="false"/>
<param name="detach-timeout-sec" value="120"/>
<profile name="mine">
<param name="bind-local" value=""/>
<param name="bind-local" value="" secure="true"/>
<param name="secure-combined" value="/usr/local/freeswitch/certs/wss.pem"/>
<param name="secure-chain" value="/usr/local/freeswitch/certs/wss.pem"/>
<param name="userauth" value="true"/>
<param name="context" value="public"/>
<param name="dialplan" value="XML"/>
<param name="mcast-ip" value=""/>
<param name="mcast-port" value="1337"/>
<param name="local-network" value=""/>
<param name="apply-candidate-acl" value=""/>
<param name="rtp-ip" value="$${local_ip_v4}"/>
<!-- <param name="ext-rtp-ip" value=""/> -->
<param name="outbound-codec-string" value="opus,vp8"/>
<param name="inbound-codec-string" value="opus,vp8"/>
<param name="timer-name" value="soft"/>
<!-- <param name="force-register-domain" value="$${domain}"/> -->

User Directory

You can specify verto-context and verto-dialplan on a per-user basis in the user directory config files.

This is a portion of an example user named 1000


<user id="1000">
<param name="password" value="$${default_password}"/>
<param name="vm-password" value="1000"/>
<param name="verto-context" value="public"/>
<param name="verto-dialplan" value="XML"/>


Permission to use Verto signaling can be granted to the entire user directory by entering the following lines into directory/default.xml

User Directory

<domain name="$${domain}">
<param name="jsonrpc-allowed-methods" value="verto"/>
<param name="jsonrpc-allowed-event-channels" value="demo,conference,presence"/>

Permission to use Verto signaling can be granted to an individual user by entering the following lines into directory/default/1000.xml (for example)

Individual Extension Permissions

<user id="1000">
<param name="jsonrpc-allowed-methods" value="verto"/>
<param name="jsonrpc-allowed-event-channels" value="demo,conference,presence"/>


To enable the livearray functionality that provides near-real-time updates on conference events, add the following to conf/autoload_configs/conference.conf.xml


<param name="conference-flags" value="livearray-sync"/>

This would enable the kind of event reporting that allows a web page to display who is talking on the conference at the moment, for example.

To receive livearray data in JSON format, also enable the livearray-json-status flag:


<param name="conference-flags" value="livearray-sync|livearray-json-status"/>


To test if a call originated from a Verto client, test in your dialplan for the variable Caller-Source to equal mod_verto in a condition. There is also the variable Other-Leg-Source if the current leg is using SIP or SS7 and the connected leg might be a Verto call.

<extension name="verto call" continue="true">
<condition field="caller-source" expression="mod_verto">
<action application="log" data="INFO ***** Verto WebRTC Call ***** "/>

Bridging from WebRTC (mod_verto) to PSTN/ITSPs

WebRTC is slow to establish media. So we need to provide SDP asap.

We can do this by answering and sending some silent packets, instead of waiting for normal call setup:


<extension name="itsp_send_call">
<condition field="destination_number" expression="^(\d+)$">
<action application="answer"/>
<action application="playback" data="silence_stream://2000"/>
<action application="set" data="effective_caller_id_number=333444555"/>
<action application="set" data="effective_caller_id_name=ciaociaociao"/>
<action application="bridge" data="{absolute_codec_string=pcmu}sofia/gateway/itsp/$1"/>


To call a Verto endpoint from FreeSWITCH™ you have 3 choices:

Choice 1

Usage: ${verto_contact ${dialed_user}@${dialed_domain}}

Use this format of Verto dial string alone in a bridge command to call a known Verto endpoint, or append this template to the end of the sip dial-string currently in your directory/default.xml to include Verto endpoints on all outbound calls, or add it to an individual user's dial-string in the user directory, such as directory/default/1000.xml for example.

Verto Dial Strings

<!-- Add Verto to an extension in your dialplan to call WebRTC users directly -->
<action application="bridge" data="${verto_contact ${dialed_user}@${dialed_domain}}"/>

<!-- Append the Verto dial-string to the generic dial-string in directory/default.xml
to call WebRTC users along with SIP users simply by calling the user/xxxx endpoint -->
<param name="dial-string" value="{^^:sip_invite_domain=${dialed_domain}:presence_id=${dialed_user}@${dialed_domain}}${sofia_contact(*/${dialed_user}@${dialed_domain})},${verto_contact ${dialed_user}@${dialed_domain}}"/>

<!-- Create a custom dial-string for individual Verto users (e.g. in directory/default/1000.xml)
to call this particular user via Verto instead of SIP -->
<param name="dial-string" value="${verto_contact ${dialed_user}@${dialed_domain}}"/>

Choice 2

Usage: verto.rtc/

Use this in the bridge command the same way that you currently call "user/1000" for example. This is a nested originate, so don't put this form in the user directory dial-string because it will add a level of nesting in the code and duplicate effort.

If you already happen to know the uuid of the channel you can also call verto.rtc/u:<uuid> but verto_contact already looks up the connection uuid for you.

Choice 3

Usage: verto_contact api func

Use this form in an API call to originate a connection to a Verto user.

Client Side Samples

GitHub contains JavaScript sample code for your perusal.

These could stop working at any time, but anyone running Firefox can press Ctrl-U to view the page source and discover these very same links.

Verto Live Array

From a post to the freeswitch-users mailing list dated 2016.03.28 12:02 EDT the following JavaScript code snippet reveals the basics of how to get raw conference events using $.verto.livearray() from the Verto library:


var la = new $.verto.liveArray(verto, data.pvtData.laChannel, data.pvtData.laName,
{subParams: {callID: dialog ? dialog.callID : null}, "onChange": function (obj, args) {

la.onChange = function (obj, args) {
console.error("The change", args);

You can build on this template in your own JS code.


At this moment (July 2014) a bunch of handwork is involved in getting mod_verto working after building everything from source from the latest master tree. I wanted it to run in my LAN from a Mac desktop to the Freeswitch server, both behind the same NAT with a self signed certificate… not the easiest way. This assumes that you’ve installed Freeswitch, freeswitch-music and freeswitch-sounds. Many thanks to bkw for all the info.

First things first; it is mandatory that you use mod_verto with the client over https on a complete domainname without certificate warnings. Otherwise it WILL NOT work. This means you need the parts of one set of ca cert/key/cert in a few places; FreeSWITCH and the web server (Apache probably) as well as the client need to know about them.

You will need a wss.pem file in the right place. You also need the crt in the tls directory. Under here is a script (of course you can create certs yourself, there's lots of howtos), but before that, some tips.

- The required directories certs & tls do not exist by default, they need to be created (the script fixes that)

- The documentation says you will need a chain certificate. Because you are your own ca, you don’t need the chain certificate.

When running the script you must enter the fields correctly when asked (FQDN for example). Run as root, this assumes CONFDIR is /etc/freeswitch, change FQDN as well. You can change the defaults in the .sh scripts used also if you don't want to enter them during execution.

mkdir $CONFDIR/certs
mkdir $CONFDIR/tls
chown freeswitch:freeswitch $CONFDIR/certs $CONFDIR/tls
tar zxfv
perl -i -pe 's/md5/sha1/g' *.sh
perl -i -pe 's/2048/2048/g' *.sh
./ $FQDN
./ $FQDN
cat $FQDN.crt $FQDN.key > $CONFDIR/certs/wss.pem
cat $FQDN.crt > $CONFDIR/tls/dtls-srtp.crt
chown freeswitch:freeswitch $CONFDIR/certs/wss.pem $CONFDIR/tls/dtls-srtp.crt

After this, make sure you have installed and enabled at least the following modules (conf/autoload_configs/modules.conf.xml): mod_verto, mod_rtc, mod_opus

You can also follow this link on how to generate your certs:

Enable the following lines in conf/directory/default.xml:

     <param name="jsonrpc-allowed-methods" value="verto"/>
<param name="jsonrpc-allowed-event-channels" value="demo,conference,presence"/>

Enable the following line in conf/autoload_configs/conference.conf.xml:

<param name="conference-flags" value="livearray-sync"/>

Now, copy the certificate authority file you’ve created (/root/ to your client and install it. Also, add the host.domain to your hosts file or DNS to resolve it, if that isn’t ready yet.

Apache on the server has to know about the certs too, assuming you’ve installed it and enabled ssl, change this in default-ssl (probably in /etc/apache2/sites-available) and restart it:

SSLCertificateFile    $CONFDIR/certs/wss.pem
SSLCertificateKeyFile $CONFDIR/certs/wss.pem

As stated before, in my setup everything was behind the same NAT, and with a stun/turn server on the internet this causes trouble. You need to install your own stun/turn server behind the NAT. This is required because using at least one server is mandatory in WebRTC. My choice is . Look on the site how to do it.

Then, create a symlink on the server in the apache directory to the mod_verto demo for the client in the FreeSWITCH sources:

ln -s /usr/src/freeswitch/html5/verto/demo /var/www/verto

You will need to change the stun and turn server settings in verto-min.js in there too, just remove the defaults (including credentials) and change them to host.domainname:3478

Now, if everything is done correctly you can use chrome to surf to:

https://host.domain/verto/ and then you should be able to call the default conference at 3000 or 9386 for funny prompts.

If not; take a look at the Freeswitch console. If you can’t find, enable debugging in verto.conf.xml.

You can test if the SSL certs are correctly installed in the webserver with:

openssl s_client -connect host.domain:443

See Also

Verto is not just for call signaling


gorilla_opening_gifts.jpg (image/jpeg)
mod_verto.png (image/png)
mod_verto.png (image/png)


Where can i find Javascript library and documentation for mod_verto? Posted by at Jun 16, 2014 15:47
Very cool developers well done! Posted by at Jun 19, 2014 21:56 Posted by antonio at Jul 25, 2014 04:04
I'm trying to use the for checking a webrtc call from a Chrome browser on a mac. I have been able to log in and place a call from one extension to the other, however I do not see any voice path. After troubleshooting on my mac and the freeswitch server i noticed something different, On my mac there are multiple IP interfaces one with the IP address 172.26.x.x and another with the IP Address 10.65.x.x, the signaling is happening on the correct interface (10.65.x.x) but the chrome browser (chrome://webrtc-internals) establishes a RTCPeerConnections for both interfaces. What i further notice on the Freeswitch server is that it is trying to send the RTP stream to the 172.26.x.x address rather than the 10.64.x.x ip address.Is it possible to limit the RTCPeerConnection to only the 10.65.x.x address on my chrome browser, is this a configuration driven by the verto-min.js or something to be done on the chrome browser. Unfortunately I can't disable the 172.26.x.x IP Address on my mac laptop, this the wireless IP and the 10.65.x.x is the IP address assigned to my vpn client. Posted by h247v at Sep 29, 2015 17:02
Found the answer to my question. I overlooked the basic ICE peer identification process. Posted by h247v at Oct 01, 2015 20:18
Verto Phone for Chrome browser - step-by-step guide Posted by kovalyshyn at Sep 29, 2016 14:56
To send custom variables on incoming call to verto end point set variable with name prefix verto_h_ (since 1.6.16) Posted by Pechen at Apr 17, 2017 12:22
This is wonderful job ! Posted by livem at Mar 28, 2019 02:16
Verto is not just for call signalingThe link had move. Where can I find this somewhere ? Posted by livem at May 07, 2019 23:34