RingCentral SDK for Node JS
RingCentral Developers is a cloud communications platform which can be accessed via more than 70 APIs. The platform's main capabilities include technologies that enable: Voice, SMS/MMS, Fax, Glip Team Messaging, Data and Configurations.
API Reference and APIs Explorer.
Table of contents
- Key Benefits
- Installation
- Getting Started
- API Calls
- Server-side Subscriptions
- Advanced SDK Configuration & Polyfills
- Making telephony calls
- Call management using JavaScript
- SMS
- MMS
- Fax
- Page visibility
- Tracking network Requests And Responses
- Migration from previous releases
Key Benefits
- Automatically handles token lifecycle procedures in multi-tab environment
- Re-issues non-authorized requests
- Decrypts PUBNUB notification messages
- Parses multipart API responses
- Restores subscriptions from cache
- Automatically re-subscribes in case of subscription renewal errors
- Compatible with latest WhatWG
fetch()
spec (DOM Requests and Responses)
Installation
You will need to configure SDK instance with your unique application key & secret this is provided by RingCentral's developer relations team.
This instance will be used later on to perform calls to API.
You can also supply optional polyfills and dependency injections, please read the polyfills section of this readme.
SDK can be used in 3 environments:
Set things up in NodeJS
-
Install the NPM package:
npm install ringcentral --save -
Require the SDK:
var SDK = ;var rcsdk =server: SDKserversandboxappKey: 'yourAppKey'appSecret: 'yourAppSecret'redirectUri: '' // optional, but is required for Implicit Grant and Authorization Code OAuth Flows (see below);
Set things up for Browserify or Webpack
Follow installation steps for NodeJS. Don't forget to add target: 'web'
to your webpack.config.js
to tell Webpack to
pick proper PUBNUB
and fetch
implementations.
Set things up in Browser
Get the code
Pick the option that works best for you:
-
Use CDN Attention! Versions listed here may be outdated:
-
Download everything manually:
- ZIP file with source code
- Fetch, direct download: fetch.js
- ES6 Promise, direct download: es6-promise.js
- PUBNUB, direct download: pubnub.js
-
Use Bower, all dependencies will be downloaded to
bower_components
directory:bower install ringcentral --save
Add scripts to HTML page (if you are not using any module loaders)
The SDK is represented by the global RingCentral constructor. Your application must create an instance of this object:
Add the following to your HTML:
<!-- or ringcentral.min.js -->
If you use RequireJS in your project
// Add this to your RequireJS configuration filerequire; // Then you can use the SDK like any other AMD component;
Make sure that polyfills are added to the page before or together with the SDK. Make sure SDK is configured to use polyfills.
Getting Started
Read API documentation for more information.
Get the Platform object
var platform = rcsdkplatform;
Now that you have your platform object and the SDK has been configured with the correct server URL and API key, your application can now log in and access the features of this API.
Login
Login is accomplished by calling the platform.login()
method of the Platform object with certain parameters depending
on the type of auth flow. A Promise
instance is returned, resolved with an AJAX Response
object.
3-legged OAuth 2.0 Flows
SDK provides a set of helper functions to assist with 3-legged OAuth flow.
You can pick one of two available setups:
- Top Frame — user temporarily navigates away from the app to RingCentral login pages
- Popup — RingCentral login pages are opened in a popup
Both setups support Authorization Code and Implicit Grant flows.
Top Frame Setup
This setup is good when your app uses the entire browser window.
When login is required for your application, the app's login page needs to open a URL that can be generated by SDK:
var loginUrl = rcsdkplatform; // implicit parameter is optional, default falsewindowlocation; // or .replace()
Your application need to have a special landing page to handle OAuth Redirect URI. On this page you need to resume the flow:
var loginOptions = rcsdkplatform;rcsdkplatform;
The above mentioned flow assumes that login page will be rendered in the top frame, e.g. user will temporarily navigate away from the app to RingCentral login pages.
Popup Setup
This setup is good when your app is rendered as a widget on a third-party sites.
If you would like to simply open RingCentral login pages in a popup, you may use the following short-hand in your app's login page:
var platform = rcsdkplatform;var loginUrl = platform; // implicit parameter is optional, default falseplatform // this method also allows to supply more options to control window position ;
In this case your landing page (the one to which Redirect URI points) need to call the following code:
RingCentralSDK;
Difference between Authorization Code and Implicit Grant flows
If your app uses Implicit Grant you should not provide appSecret
when creating SDK instance. The resulting login
information will not have refresh_token
, which means that every time when access_token
expires, app should navigate
users to app login page and re-initiate login flow. Also your app will need to handle situations with refreshError
events properly, for instance, enter auth flow automatically without user intervention.
For dynamic apps with subscriptions Authorization Code should work better because it provides an ability to refresh
tokens automatically without affecting the state of the app, but it requires to expose appSecret
.
Password Flow
This flow to be used only for private backend apps that can protect user credentials. Client-side apps are not allowed to use this flow.
Login is accomplished by calling the platform.login()
method of the Platform object with username, extension
(optional), and password as parameters.
rcsdkplatform ;
Handling login success
Because the login process is asynchronous, you need to call the promise's then
method and pass your success handler as
the continuation function.
This function will be called once login has succeeded, which allows the application to then perform updates to the user interface, and then perform the next actions using the API to load account details for the user's account and such.
Handling login failure
Login can, of course, fail - a user can enter the incorrect password or mistype their user name.
To handle cases where login fails, you can provide an error handler function in a call to the Promise's catch
method.
To keep this example simple, a simple JavaScript alert is being used. In a real application, you will want to provide
a good UX in your login form UI.
Checking login state
To check in your Application if the user is authenticated, you can call the loggedIn
method of the platform
object:
rcsdkplatform;
Or you can call ensureLogedIn
method which works the same way as loggedIn
but rejects promise on failure:
rcsdkplatform;
The SDK takes care of the token lifecycle. It will refresh tokens for you automatically. It will also automatically pause and queue all new API requests while the token is being refreshed in order to prevent data loss or inconsistency between SDK instances in different tabs. Paused / queued API requests will then be automatically processed once the token has been refreshed. All apropriate events will be emitted during this process.
If you just need to check whether the user has a valid token, you can call the accessTokenValid
method:
rcsdkplatform; // returns boolean
Retrieving and setting auth information
You can retrieve save and set back the auth information:
var authData = rcsdkplatformdata;rcsdkplatform;
It can be useful on the server if SDK instances are created and disposed for every HTTP request.
Logout
Logging the user out is trivial - just call the logout
method on the platform object:
rcsdkplatform;
Events
The platform provides the following events:
loginSuccess
loginError
logoutSuccess
logoutError
refreshSuccess
refreshError
— application may listen to this error and show login pagerateLimitError
To listen on platform events, you should call the on
method of the platform object:
var platform = rcsdkplatform; platform;
The on
method accepts an event type as its first argument and a handler function as its second argument.
API calls
To perform an authenticated API call, you should use the one of the methods of the platform object:
rcsdkplatform ;
If your Promise
library supports global error handler it might be useful to log Requests and Responses there.
HTTP Verb shorthands
rcsdkplatform;rcsdkplatform;rcsdkplatform;rcsdkplatform;
Available API response methods
json()
— if response type is JSON returns a plain JS objecttext()
— returns text representationmultipart()
— forContent-Type: multipart/mixed
responses returns an array ofApiResponse
toMultipart()
— same asmultipart()
but when response is notContent-Type: multipart/mixed
it will return an array with one item instead of errorok()
—true
for all2xx
responses,false
otherwiseerror()
— error string if anyrequest()
— low-levelRequest
objectresponse()
— low-levelResponse
object
Binary downloads
If you need to download a binary file from API (call recording, fax attachment), you can do it as follows:
On NodeJS
var fs = ; // read as bufferrcsdkplatform; // read as streamrcsdkplatform;
See more here https://github.com/bitinn/node-fetch#usage.
In browser
rcsdkplatform;
See more here https://developer.mozilla.org/en-US/docs/Web/API/Response.
Generic
In any case you always can just add token to known URL of resource and download it using whatever library you want or
use directly as <img src="..."/>
:
var url = rcsdkplatform;
Rate Limiting
Platform class emits rateLimitError
if server returns 429
status. You may supply an option handleRateLimit
and
SDK will re-execute the failed request. Please keep in mind that your application should somehow delay/throttle other
subsequent requests in this case because otherwise all those requests will be postponed too.
Server-side Subscriptions
Subscriptions are a convenient way to receive updates on server-side events, such as new messages or presence changes.
Subscriptions are created by calling the getSubscription
method of the RingCentral instance created earlier on.
var subscription = rcsdk; subscription; subscription // a list of server-side events ;
Removing Subscriptions from server
Once a subscription has been created, the SDK takes care of renewing it automatically. To cancel a subscription, you can
call the subscription instance's remove()
method:
subscription;
Updating Subscriptions
You can add more or replace event filters in the existing subscription at any time, by calling the subscription methods
and then calling the register()
method to update it on the server:
subscription;subscription;
Subscription reset
To revert subscription instance to it's prestine state you can use its reset()
and off()
methods, this will close
PUBNUB channel, remove all timers, subscription data and all bindings:
subscription;
Subscriptions lifecycle
The number of active subscriptions is limited per account (about 20). This means that the application should dispose unused subscriptions in the following situations:
- Application should
reset()
subscriptions (on the server they are dead already):- the
Platform
instance emitslogoutSuccess
oraccessViolation
events so the app shouldreset()
all subscriptions
- the
- Application should
remove()
subscriptions or remove no longer needed event filters from them:- the user navigates away from the page or particular view
- a subscription becomes unused by the application, based upon the application's business logic
One of very useful techniques to limit the number of active subscriptions is to store subscription data in cache and share this data across Subscription instances in multiple tabs:
var cacheKey = 'some-custom-key';var subscription = rcsdk;var cachedSubscriptionData = rcsdk; if cachedSubscriptionData try // if subscription is already expired an error will be thrown so we need to capture it subscription; // use the cache catch e console; else subscription; // explicitly set required events subscription; subscription;
With this technique subscription remove request on window/tab closing is no longer needed.
In any case if application logic dictates that subscription is not used anymore by any of it's instances, subscription can be removed from the server to make sure application stays within limits.
Stale Subscriptions
There is a known bug when user awakes the computer: subscription tries to renew itself but fails because the expiration time has passed (JS was halted while computer was sleeping).
Recommendation is to listen to subscription.events.renewError
event and when it occurs reset and re-subscribe:
subscription;
This has to be done in all tabs, application must handle potential race conditions.
When SDK cannot automatically renew subscription it will fire an event automaticRenewError
so that application can do
some actions in order to have active subscription again:
subscription;
Multiple event filters in one Subscription
The best practice is to have only one subscription object with multiple event filters of different types (messages, presence, etc.) instead of having a separate subscription for each individual event filter.
In the notification event handler application may have a bunch of if's that will execute appropriate action based on
event
property of the incoming message:
subscription;
Shorthand
The above mentioned things are put together into CachedSubscription
class and its restore(cacheKey)
method:
var subscription = rcsdk; // use it as usualsubscription;
Advanced SDK Configuration & Polyfills
You can use any of your favourite fetch()
and Promise
polyfills. SDK tries to get them from global scope every
time new instance is created.
In rare case when SDK will not detect globals automatically you can set them as follows:
windowPromise = whatever;windowfetch = whatever;windowHeaders = whatever;windowRequest = whatever;windowResponse = whatever;
Also you can manually define SDK properties:
var rcsdk = localStorage: whatever PUBNUB: whatever Promise: whatever fetch: whatever Headers: whatever Request: whatever Response: whatever;
But taking into account the nature of polyfills, it's better to keep them global as described before.
In the NodeJS it might be useful to replace simple built-in storage with something persistent:
var sdk = localStorage: whatever;
SDK works with localStorage
as with a simple object.
If you need to use 2 or more RingCentral accounts simultaneously, you need to create an instance of SDK for each account
and provide some unique cachePrefix
to SDK constructor (otherwise instances will share authentication).
var rcsdk1 = cachePrefix: 'foo-'; var rcsdk2 = cachePrefix: 'bar-';
Making telephony calls
In RingCentral terminology, making telephony calls is named "RingOut".
This example demonstrates a way to create a flexible RingOut tracking procedure. This is the most complex example with maximum fine-tuning - it could be simplified to suit the business requirements.
The sequence of RingOut is as follows:
- Perform a POST with the RingOut data
- Poll the RingOut status (GET requests) every second or so
Please refer to the following example:
var platform = rcsdkplatform timeout = null // reference to timeout object ringout = {}; // this is the status object (lowercase) /** * @param */ { console; ; } { platform ; } /** * @param {function(number?)} next - callback that will be used to continue polling * @param */ { ; ; } /** * To stop polling, call this at any time */ { ; if ringoutstatus && ringoutstatuscallStatus !== 'InProgress' platform ; // Clean ringout = from: phoneNumber: '' to: phoneNumber: '' callerId: phoneNumber: '' // optional, playPrompt: true // optional ; } /** * Start the ringout procedure (may be called multiple times with different settings) */;
Call management using JavaScript
If you are integrating with a CRM or ERP system, use of the JavaScript SDK is highly recommended. Following is an example of a call management integration that includes monitoring of incoming calls and performing of RingOuts.
A call management integration usually consists of the following tasks:
- Track the telephony status
- View the list of active calls
- View the recent calls
Track the telephony status
First, you need to load the initial Presence status (you can use Underscore or Lodash to simplify things):
var accountPresence = {}; rcsdkplatform ;
In the meantime, you can also set up Subscriptions (you can use Underscore or Lodash to simplify things):
var subscription = rcsdk; subscription; subscription; return subscription;
View the list of active calls
rcsdkplatform ;
View the list of recent calls
rcsdkplatform ;
By default, the load request returns calls that were made during the last week. To alter the time frame, provide custom
query.dateTo
and query.dateFrom
properties.
SMS
In order to send an SMS using the API, simply make a POST request to /account/~/extension/~/sms
:
rcsdkplatform ;
Fax
Fax endpoint understands multipart/form-data
requests. First part must always be JSON-encoded information about the
fax. Other parts should have filename
defined in order to be correctly presented in Service Web.
Browser
Modern browsers have FormData
class which could be used for sending faxes.
var body = to: phoneNumber: '123' // see all available options on Developer Portal faxResolution: 'High' formData = ; // This is the mandatory part, the name and type should always be as followsformData; // Find the input[type=file] field on the pagevar fileField = document; // Iterate through all currently selected filesfor var i = 0 file; file = fileFieldfilesi; ++i formData; // you can also use file.name instead of 'attachment' // To send a plain textformData; // Send the faxrcsdkplatform;
MMS
As similar to the fax endpoint, MMS
understands multipart/form-data
requests. In order to send an MMS using the API, simply make a POST request to /account/~/extension/~/sms
:
var body = from: phoneNumber: '+12223334444' //// Your mms-enabled phone number to: phoneNumber: '123' // see all available options on Developer Portal faxResolution: 'High' formData = ; // This is the mandatory part, the name and type should always be as followsformData; // Find the input[type=file] field on the pagevar fileField = document; // Iterate through all currently selected filesfor var i = 0 file; file = fileFieldfilesi; ++i formData; // you can also use file.name instead of 'attachment' // Send the mmsrcsdkplatform;
MMS-Enabled Phone Number
In order to identify the MMS-Enabled phone numbers on an extension, simply make a GET request to /account/~/extension/~/phone-number
var mmsEnabledNumbers = ; platform ;
Further reading:
NodeJS
SDK is capable of sending FormData
objects created by form-data module.
First, you will need to install it:
npm install form-data
Then you can build your fax, but keep in mind that FormData API in NodeJS is slightly different from the browser:
var FormData = body = to: phoneNumber: '123' // see all available options on Developer Portal faxResolution: 'High' formData = ; // This is the mandatory part, the name and type should always be as followsformData; // To send a plain textformData; // To send a file from file systemformData; // Send the faxrcsdkplatform;
Further reading:
Page visibility
You can use any of the libraries that work with the Page Visibility API, such as visibility.js.
This allows tracking the visibility of the page/tab/window/frame so that the application can react accordingly. Following are some actions that the application may wish to take whenever it becomes visible:
- Check authentication
- Reload/resync time-sensitive information from the server
- Send heartbeats to the server
Another usage is to reduce the number of Call Log or Messages reloads when the application is not visible. The SDK does not require that any such optimizations be implemented in the application, but it is considered good practice.
Tracking network Requests And Responses
You can set up tracking for all network requests (for instance, to log them somewhere) by obtaining a Client
object
and registering observers on its various events:
var client = rcsdkplatform;client; // apiResponse does not have response at this pointclient;client;
Migration from previous releases
!!! Attention !!!
In SDK version 2.0 Helpers were moved to separate repository: ringcentral-js-helpers.
A lot of code improvements were implemented in order to make SDK compatible with WhatWG Fetch, DOM Requests & DOM Responses: see full list of migration instructions.