Every TwiML application needs a friendly name (we called ours “Browser Dialer”) and either a Voice URL or a Messaging URL. Since we want our users to make phone calls, we used a URL to our application’s “/voice” route.

Note: When running the app locally, you can use a tool like ngrok to get a publicly accessible URL for your development environment.

Before our users can make any calls in their browsers, we need to create a capability token for them.

Capability tokens are your way to control exactly what your users can and can't do with Twilio Client. In this case, our server will provide all users with tokens that allow them to make outbound phone calls.

We use the Twilio Node Helper Library to generate and configure a capability token with the SID of our Twilio Application to allow outgoing calls.

Token Generation Route

index.js

The Twilio.js client needs credentials to be able to initiate calls as well as send messages, among other cool features. The Twilio.js client requests the token from the /token route, at which point the client is initialized and ready to start using Twilio API's. Next, let's set up the Twilio Device in the browser.

Now that Twilio Client is ready, our users can start making phone calls. They'll start by inputting the phone number they wish to call.

We massage that input before passing the number on to Twilio, adding a + sign, then a country code, and the actual number. This is called the E.164 format and is required by most parts of Twilio's API.

We then use Twilio.Device.connect to start the call. Twilio will send a request to the URL you specified in your Twilio Application configuration, looking for instructions on how to handle the call.

In this case, we include the phone number the user wishes to dial in our connect() call, and we then access it in our server-side code here.

App=Ember.Application.create();App.Router.map(function(){this.route('call',{path:'/call'});this.route('index',{path:'/'});});App.IndexController=Ember.Controller.extend({init:function(){varself=this;// Default valuesthis.set('countryCode','1');this.set('currentNumber','');this.set('muted',false);this.set('onPhone',false);this.set('validPhone',Ember.computed('currentNumber',function(){return/^([0-9]|#|\*)+$/.test(this.get('currentNumber').replace(/[-()\s]/g,''));}));this.set('fullNumber',Ember.computed('countryCode','currentNumber',function(){return'+'+this.get('countryCode')+this.get('currentNumber').replace(/\D/g,'');}));// Fetch Twilio capability token from our Node.js server$.getJSON('/token').done(function(data){Twilio.Device.setup(data.token);}).fail(function(err){console.log(err);self.set('logtext','Could not fetch token, see console.log');});Twilio.Device.ready(function(){self.set('logtext','Browser dialer is ready..')});// Configure event handlers for Twilio DeviceTwilio.Device.disconnect(function(){self.set('onPhone',false);self.set('logtext','Call ended.');});// Set countriesthis.set('countries',[{name:'United States',cc:'1',code:'us'},{name:'Brazil',cc:'55',code:'br'},{name:'Colombia',cc:'57',code:'co'},{name:'Ecuador',cc:'593',code:'ec'},{name:'Estonia',cc:'372',code:'ee'},{name:'Germany',cc:'49',code:'de'},{name:'Great Britain',cc:'44',code:'gb'},{name:'Hong Kong',cc:'852',code:'hk'},{name:'Ireland',cc:'353',code:'ie'},{name:'Mexico',cc:'52',code:'mx'},{name:'Singapore',cc:'65',code:'sg'},{name:'Spain',cc:'34',code:'es'},]);},actions:{// Handle country code selectionselectCountry:function(country){this.set('countryCode',country.cc);},// Handle mutingtoggleMute:function(){varmuted=this.get('muted');this.set('muted',!muted);Twilio.Device.activeConnection().mute(!muted);},// Handle numeric buttonssendDigit:function(digit){Twilio.Device.activeConnection().sendDigits(digit);},// Make an outbound call with the current number,// or hang up the current calltoggleCall:function(){if(!this.get('onPhone')){this.set('onPhone',true);this.set('muted',false);// make outbound call with current numbervarn=this.get('fullNumber');Twilio.Device.connect({number:n});this.set('logtext','Calling '+n);}else{// hang up call in progressTwilio.Device.disconnectAll();}}}});

public/dialer.js

The Mute Toggle

public/dialer.js

Now you have an idea of how simple it is to use the Twilio Client in the browser. There are much more features to explore. Next, let's allow the user to send DTMF tones, in case they are calling an automated phone system.