SignalWire RELAY | Call Control for NodeJS

Real-time Communications that don’t REST

Mar 14, 2019

By Erik Lagerway, VP of Product

REST (Representational State Transfer) has become rather prolific, with more than 70% of all public APIs being REST. The popularity comes from the fact that REST builds upon existing systems and features of HTTP, making it familiar to web developers everywhere.  REST was chosen over alternatives like SOAP, for its close coupling with JSON and web-friendly format, which web developers preferred when rapidly iterating web applications. That said, there are limitations to REST.

REST-based applications by nature are stateless, the state is managed by the client. Similarly, since HTTP doesn't have a mechanism to push notifications from the server to the client, it is difficult to implement any type of service where the server updates the client in real-time. At least not without the use of polling, web-sockets or another type of web-hook.

At SignalWire, we felt like we needed something a bit more modern, something where web microservices are intrinsic in the design from the start.


Introducing RELAY

RELAY is the next evolution in real-time communication APIs. Relay is a new real-time web service protocol that provides for persistent, asynchronous connections to the SignalWire network.

Our CEO, Anthony Minissale wrote an article recently “API in our DNA”, which also touches on Relay.

Relay brings advanced real-time capabilities like real-time event monitoring functionality to the developer, without the need for markup language interpretation or latent REST responses. This is a game-changer for developers.

System and billing events can be monitored and acted upon in real-time. In the past, doing something simple like intercepting call events for a voice call that shows the destination endpoint as offline, and then re-routing those calls automagically, was kludgy and didn’t produce elegant results. Many times the call would fail or the delays in call setup would drive the user to hang up themselves.


Step 1: Call Control


The first set of Relay functions that can be consumed via our new Relay JavaScript library is Call Control. This initial iteration of Relay Call Control will allow developers to programmatically manage voice calls in real-time using JavaScript. It’s the first step towards completing SignalWire’s real-time web services API and libraries. Be sure to check our developer website for a current list of supported programming languages.


Enabling RELAY Call Control via NodeJS

The first set of Relay functions that can be consumed via our new Relay JavaScript library is Call Control. This will allow developers to programmatically manage voice calls in real-time using NodeJS. It’s the first step towards completing SignalWire’s real-time web services API and libraries.

Developer Documentation for RELAY Clients:
https://docs.signalwire.com/topics/relay-clients/

Before getting started, be sure you have created your SignalWire account!


Let's create an outbound call using RELAY and NodeJS, using the following steps:

1. Install the package using NPM:

npm install @signalwire/node

2. In order to use the NodeJS client, you must get your host, project, and token from your SignalWire dashboard:

const host = "example.signalwire.com"
const project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
const token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

3. Use the SignalWire host, project, and token variables to then set up the Client:

const { RelayClient } = require('@signalwire/node')
const client = new RelayClient({ host, project, token })

4. You can then use the client to make a request to place a call:

async function main(numberToCall) {
  const call = await client.calling.newCall({ type: 'phone', from: '+18991112222', to: numberToCall })

  // Attach listeners for all events..
  call.on('created', call => {
    console.log(`The state has changed from ${call.prevState} to ${call.state}`, '\n')
  })
  .on('ringing', call => {
    console.log(`The state has changed from ${call.prevState} to ${call.state}`, '\n')
  })
  .on('answered', call => {
    console.log(`The state has changed from ${call.prevState} to ${call.state}`, '\n')
  })
  .on('ending', call => {
    console.log(`The state has changed from ${call.prevState} to ${call.state}`, '\n')
  })
  .on('ended', call => {
    console.log(`The state has changed from ${call.prevState} to ${call.state}`, '\n')
  })

  await call.begin() // Start the call!
}
main('+18991113333').catch(console.error)


5. Now, let's process an inbound call:

async function main() {
  const call = await client.calling.newCall({ type: 'phone', from: '+18991112222', to: '+18991113333' })

  // Attach listeners for all connect states..
  call.on('disconnected', call => {
    console.log('Call has been disconnected!')
  })
  .on('connecting', call => {
    console.log('Call is trying to connect..')
  })
  .on('connected', call => {
    console.log(`Call has been connected with ${call.peer.id}!`)
  })
  .on('failed', call => {
    console.log('Call failed to connect!')
  })
  .on('answered', async call => {
    await call.connect({ type: 'phone', to: '+18991114444' })
      .catch(error => {
        console.error('Error connecting call:', error)
      })
  })

  await call.begin() // Start the call!
}
main().catch(console.error)


Using the Dashboard

In the SignalWire dashboard, you will have the opportunity to see your Relay activity. Here we can see a few SIP calls and some that also touch the PSTN:

If we click on the call thread we can see more details on the conversation, including a summary, segments and events:

We can expand the segments and see the detail in each segment:

Let's have a look at the events. In this first example we see a Call Creation event:

Next is the Call Connection event:

Disruptive Pricing

Our fee structure is simple, we meter per minute / per call leg, we don’t charge for setting up calls programmatically nor do we charge for securing your calls, because security is a good thing.

Calling Rates
US Inbound $0.00255*
US Outbound $0.0065*
SIP In/Out $0.0007*

For all pricing check here.


Come and build something great on SignalWire!

RELAY documentation:

https://docs.signalwire.com/topics/relay/

Main developer documentation site:

https://docs.signalwire.com/

Friendly support can be found in our online community.

P.S. We always announce features to our community before bringing it to the general public, so sign up for your free SignalWire account today, receive $5 in credits and join our Community!

* Please check our pricing page for up to date pricing.