Learn to use RingCentral event data with subscriptions instead of long-polling.Start Tutorial
The tutorial's navigation controls are located above this text. Use to move to the next step of the tutorial. Use to move to the previous step of the tutorial (if there is one). Use to see an overview of all the steps in the tutorial.
Developers are able to configure this application to operate with either your RingCentral Sandbox or Production applications in the .env file by setting the RC_ENV value to either sandbox or production.
Developers can also set this application to use any of the RingCentral Subscription Notification Types (defaulby ts to all enabled) in your environment variables. Read the API Reference for Notification Event Types to understand more about these options.
Let's begin by addressing some prerequisites!
Please make sure you have access to the following required resources on-hand prior to running this source code locally or via deployment to Heroku
The first file we'll look at is
.env.tmpl. This contains configuration data for this tutorial to operate either locally, on Heroku, or on your favorite PaaS. This file acts as a template for you and provides developers with all settings.
If running locally or not on Heroku, Developers need to rename this file
mv .env.tmpl .env. Open the file for editing, and fill in these tutorial runtime configuration values:
PORT: number - defaults to 3000
RC_ENV: string - [sandbox, production] - tells the application which API endpoint to use - defaults to sandbox
RC_APP_KEY: string - <your_ringcentral_application_key> - Available from within the RingCentral Developer Portal, also known as client_id in OAuth2 nomenclature
RC_APP_SECRET: string - <your_ringcentral_application_secret> - Available from within the RingCentral Developer Portal, also known as client_secret in OAuth2 nomenclature
RC_USERNAME: string - <your_ringcentral_username> - Either phone number or email (depending upon your account settings) and must be an administrative user-level account for either sandbox or production respectively
RC_PASSWORD: string - <your_ringcentral_password> - The associated password for the
RC_USERNAMEprovided above. Must be an administrative user-level account for either sandbox or production respectively
RC_EXTENSION: string - <your_ringcentral_extension> - The extension number as a string, optional
EXTENSIONS_PER_PAGE: number - Quantity of extensions to fetch per page - defaults to 500
SUBSCRIBE_TO_EXTENSION_EVENTS: boolean - Flag to indicate if you want to subscribe to extension events - defaults to true
SUBSCRIBE_TO_PRESENCE_EVENTS: boolean - Flag to indicate if you want to subscribe to extension's presence events - defaults to true
SUBSCRIBE_TO_MESSAGE_STORE_EVENTS: boolean - Flag to indicate if you want to subscribe to extension's message store events - defaults to true
SUBSCRIBE_TO_PRESENCE_LINE_EVENTS: boolean - Flag to indicate if you want to subscribe to extension's presence line events - defaults to true
SUBSCRIBE_TO_INSTANT_MESSAGE_EVENTS: boolean - Flag to indicate if you want to subscribe to extension's instant message events - defaults to true
Now, let's take a look at the first file that contains the actual content of the tutorial,
Next we setup this application's dependencies:
http: Node.js http module, used to create a web server
util: Node.js Util module, used for unfolding JSON event data in the console logs
Once our dependencies are in place, we create the variable
rcServer which leverages the environment variables to define our API Base URI.
server: The web server for this application
platform: Cache the RingCentral Platform method to streamline our code later
subscription: Creates a subscription, which is just a placeholder for the time being and will be populated later
Now that our application has all the necessary base parts to operate, let's define the
login method which is used as a wrapper to the Promise-based RingCentral JS SDK.platform.login method which is used to obtain an access_token we will use in subsequent API requests. This code is built to operate with a private, back-end application which uses Password Flow.
Then we call the
login() method to execute that code. If the SDK resolves that request, we initialize the application (more on this a little later in the tutorial).
The SDK caches the token for developers and manages refreshing the token if it is expired during a later request. This sounds great, but what happens if the Promise is rejected due to some error such as a bad request?
The RingCentral Platform provides developers with the following events related to getting, refreshing, and revoking tokens:
The eventListeners and associated handlers we have defined really do not do much other than log the response or error, in a production environment you will need to address security concerns appropriately.
When RingCentral has responded with a valid
access_token, the core of the application starts when we call the
The first thing we do is define a closure for use with recursion to GET Extension List for every extension in your RingCentral account where
type === 'User' and
status === 'Enabled'. Since the RingCentral JS SDK returns Promises we have thenables.
Since the JS SDK returns Promises, we have thenables we can use to wait for the async code to resolve/reject accordingly.
init() must also return a Promise or throw an error, so we begin our async chain by calling
getExtensionsPage() (described in the previous step Get All User Enabled Extensions ).
Then we pass the response data to the
createEventFilter function requires a parameter be provided which is the full list of our account extensions.
First we setup a private variable
_eventFilters which type array (the data type required by the JS SDK for this property's value when we will later register the
Then we iterate over each extension in the list, cache the extension for reference while building the
eventFilters array elements.
Lastly we leverage our environment variables to generate the string for each Event Type respectively and append it to the
Finally, once all the eventFilters have been added, we return the
_eventFilters back to the Promise chain, which passes the array of eventFilters as an argument to the
It is a best practice to provide Multiple event filters in a single Subscription. You can see in this code that we leverage our environment variables to include
It is recommended that developers using the JS SDK read the full Subscriptions lifecycle.
Now that all the heavy lifting is completed, we call the
startSubscription function and pass it the eventFilters we created in the previous step.
The value this function returns first calls the
subscription method setEventFilters, and passes eventFilters through as an argument, and finally chains the JS SDK
subscription.register() method which sends the eventFilters set on the subscription to the RingCentral API. The eventFilters are evaluated. If the request is in good form, the response we receive will contain your Subscription Info Object.
Please note: If an event filter is duplicated then only one instance of it will be kept for that subscription. Therefore, the client will always get only a single notification per subscription per event if the subscription conforms to the event. Developers do not have to build their server-side subscription code as has been proposed here, you can also use the Shorthand version of creating and registering subscriptions.
The last thing this tutorial needs to do is be able to handle the inbound subscription events.
As a convenience to developers using the JS SDK it exposes Subscription Events. These Subscription Events are imilar Platform Events which can be used in eventListeners (discussed earlier in the tutorial):
notification: Fires only after
subscribeSuccessand before either
removeSuccess. This is your actual Notification data as dictated by the eventFilters set on the
removeSuccess: Fires only after a subscription has been removed
removeError: Fires if there is an error trying to remove a subscription
renewSuccess: Fires when a subscription has successfully been renewed - NOTE: Subscriptions in the RingCentral SDKs renew automatically
renewError: Fires if there is an error attempting to renew a subscriptionq NOTE: This is important to listen for in your applications, as this can result in lost data and creating a poor user experience with your application or integration
subscribeSuccess: Fires if the
subscription.register()method executes successfully. In production, your event consumers should be on the ready when you hear this event from RingCentral
subscribeError: Fires if there is an error attempting to execute
subscription.register()method and provides additional information
This is where the rubber meets the road for this tutorial, once you start the application and no errors have occurred, developers should see a console.log message 'SUBSCRIPTION CREATED SUCCESSFULLY'. This message is only displayed when our
subscription.register() method has successfully accepted our eventFilters and started the subscription.
The code shown here is the event consuming portion of the tutorial. To test that this is operating, you will need to take action using your RingCentral account with respect to the eventFilters you defined in the environment variables for the instance of this application. Let's try one that is pretty easy to test, we will test: SUBSCRIBE_TO_EXTENSION_EVENTS
type === Userand
status === Enabled
subscription.on(subscription.events.notification)eventListener was triggered and has called
handleSubscriptionNotification()and supplied the notification message as the argument (which is what we should see in the logs).