Obtaining Timeline Call Business Analytics Data

Last updated: 2024-03-22Contributors
Edit this page

It is quite common to acquire and segment call data based on time related metrics for reporting and analysis. Call Timeline API provides data over multiple time intervals such as 'Hourly', 'Daily', 'Weekly' or 'Monthly'. This kind of information can provide key insights to the line of business managers, for instance, detect when peak call times are and if and when they should adjust their call staff shifts to manage those peak times.

Example Use Cases:

  • Get average 'Call Handle Time' for all calls daily.
  • Calculate the 'Average Time to Answer' for all calls hourly.

For more information, please refer to the overview section.

Composing a request using RingCentral API Reference

One can use our interactive API Reference to not only create an API Request but also run it interactively and see the response.

API Definition Guide

Controlling what to group data by

There are two options to group by. The groupBy element allows users to perform direct grouping. The groupByMembers element allows users to group by individual users with the selected option. All the data retrieved will represent the portion of the calls that involved the specified groupBy or groupByMember type. GroupBy types cannot be mixed in one request, there can only be one type. If this field is undefined or null, the response will contain one record with data aggregated by the whole company.

Direct Grouping (groupBy)

groupBy (API) Description
Company This grouping will return call data for the entire company.
CompanyNumbers This grouping will return call data for direct numbers set up under Phone Systems - > Phone Numbers on Admin Portal.
Users This grouping will return call data for individual mailboxes. When users are added to the grouping, the response provides call data aggregated at the user level.
Queues This grouping will return call data for Queue extensions.
IVRs This grouping will return call data for IVR extensions.
SharedLines This grouping will return Call data for the calls made to one phone number that can be answered by up to 16 phones within a designated group.
UserGroups This grouping will return call data for User Groups setup on Admin Portal.
Sites This grouping will return call data for Site extensions when an account is using the multi-site feature.
Departments This grouping will return call data for users labeled with the same Department on Admin Portal.

Group by Memebers (groupByMembers)

groupByMember (API) Description
Department This grouping will return call data for individual users under Departments. Specify Ids of departments along with this grouping which will provide aggregated call data for users under those departments.
UserGroup This grouping will return call data for individual users under User Groups. Specify Ids of user groups along with this grouping which will provide aggregated call data for users under those user groups.
Queue This grouping will return call data for individual users under Queues. Specify Ids of queues along with this grouping which will provide aggregated call data for users under those queues.
Site This grouping will return call data for individual users under Sites. Specify Ids of Sites along with this grouping which will provide aggregated call data for users under those Sites.

Example

"grouping": {
  "groupBy": "Users",
  "keys": []
}

or

"grouping": {
  "groupByMember": "Site",
  "keys": []
}

Setting the timeframe of the request

The timeSettings object contains the following important elements:

  • The timeZone will be used to determine the includeDays and includeHours specified in the advancedTimeSettings
  • The timeRange element allows users to specify the datetime range for which the calls will be aggregated and will be provided in set time intervals (for example day, week etc). The call is considered to be within time range if it was started within that range. This is similar to aggregate endpoint along with providing data at different timeframe splits.
  • The advancedTimeSettings gives you even more flexibility in including and excluding data from generated reports, including the ability to include/exclude weekdays and set the timezone and working hours.

In the below example, under advancedTimeSettings, the includeDays will allow users to add weekdays of choice, and includeHours will allow users to filter data for custom hours (format hh:mm) for specified date-time range under timeRange section. Further, they can add grouping as necessary to make sure that the data received is aggregated by counter & timer.

Example

"timeSettings": {
  "timeZone": "America/Los_Angeles",
  "timeRange": {
    "timeFrom": "2023-01-01T00:00:00.877Z",
    "timeTo": "2023-01-31T04:01:33.877Z"
  },
  "advancedTimeSettings": {
    "includeDays": [
      "Sunday"
    ],
    "includeHours": [
      {
        "from": "00:00",
        "to": "23:59"
      }
    ]
  }
}

Customizing Data Response

The responseOptions element allows users to specify call aggregation breakdown and its data aggregation types for API responses.

The counters element provides aggregation on Call volume by specified metrics for set Time Interval split. The metrics can be provided in the counter section under the responseOptions.

The timers element provides aggregation for time spent on the call. The metrics can be provided in the timer section under responseOptions which will provide duration details by specified metrics for set Time Interval splits.

Example

"responseOptions": {
  "counters": {
    "allCalls": true,
    "queueOpportunities": true,
    "callsByDirection": true,
    "callsByOrigin": true,
    "callsByResponse": true,
    "callsSegments": true,
    "callsByResult": true,
    "callsByCompanyHours": true,
    "callsByActions": true,
    "callsByType": true
  },
  "timers": {
    "allCallsDuration": true,
    "callsDurationByDirection": true,
    "callsDurationByOrigin": true,
    "callsDurationByResponse": true,
    "callsSegmentsDuration": true,
    "callsDurationByResult": true,
    "callsDurationByCompanyHours": true,
    "callsDurationByType": true
  }
}

Filtering your dataset further

The callFilters element allows users to filter out the data and specify the granular scope to call breakdown metrics for both counter and timer section. Detailed splits of these sections can be found in Data Dictionary below.

Filters list type Purpose
directions array[string] Specifies whether the call was inbound or outbound relative to the scope specified in the grouping object. Not applicable to internal calls with company scope (when grouping is not specified).
origins array[string] Specifies whether an external party was present in the initial segment of the call.
callResponses array[string] Aggregation of calls by the first response action.
callResults array[string] Aggregation of calls by the nature of call result.
callSegments array[object] Aggregation of calls by the presence of specific segment.
callActions array[object] Aggregation of calls by the presence of specific action.
companyHours array[string] Aggregation of calls by company's business hours or after hours.
callDuration object aggregation of calls based on the overall call length
timeSpent object aggregation of calls based on the time spent by the specified mailbox(es) on call.
extensionFilters.fromIds array[string] List of extension Ids from which users specified in groupBy received calls.
extensionFilters.toIds array[string] List of extension Ids to which users specified in groupBy placed calls.
calledNumbers array[string] The direct company numbers the caller called.
queueSla array[string] To get aggregate of calls that were either in or out of a particular queueSLA.
callTypes array[string] To get aggregate of calls based on how the call started from the callee perspective.

Example

  "callFilters": {
    "directions": [ "Inbound", "Outbound" ],
    "origins": [ "Internal" ],
    "callResponses": [ "Answered" ],
    "callResults": [
      "Completed"
    ],
    "callSegments": [
      {
        "segment": "Ringing",
        "length": {
          "minSeconds": 0,
          "maxSeconds": 200
        }
      }
    ],
    "callActions": [
      {
        "callAction": "HoldOff"
      }
    ],
    "companyHours": "BusinessHours",
    "callDuration": {
      "minSeconds": 0,
      "maxSeconds": 200
    },
    "timeSpent": {
      "minSeconds": 0,
      "maxSeconds": 200
    },
    "extensionFilters": {
      "fromIds": [
        "123",
        "432"
      ],
      "toIds": [
        "345",
        "654"
      ]
    },
    "calledNumbers": [
      "+16505551212"
    ],
    "queueSla": [
      "InSla"
    ],
    "callTypes" : [
      "Direct"
    ]
  }

Pagination

Analytics can produce a lot of results so you may want to paginate your results to enable easier processing. Pagination is done with two additional query parameters: page and perPage. For timeline reports, you can also specify the interval as a query parameter.

Pagination (API) Description
page The page you wish to start with. For example, start on page 2.
perPage The number of results return on each page. For example, you want 10 results on the first page and an additional 10 on the second page. Note: timeline reports have a max limit of 20 per page.

Example

POST /analytics/calls/v1/accounts/~/timeline/fetch?interval=Week&page=2&perPage=10
Host: platform.ringcentral.com
Content-Type: application/json
Accept: application/json
Authorization: Bearer REPLACE_WITH_YOUR_VALID_ACCESS_TOKEN

Data dictionary

CounterResponseOptions (API) TimerResponseOptions (API) Description
allCalls allCallsDuration The combined total of all the calls involving the specified groupby dimension. Counter will return of total calls by time intervals. Timer will return call duration aggregation for total calls by time intervals.
queueOpportunites Not Applicable

The total number of times calls are presented to an extension.

QOpportunities is applicable for users grouping only.

callsByOrigin callsDurationByOrigin

Breaks down of calls that happened within or outside of the account.

  • Internal: Calls that originated inside the account.
  • External: Calls that originated outside the account.
Counter will return aggregation of calls for these breakdown by time intervals. Timer will return call duration aggregation for the same by time intervals.
callsByDirection callsDurationByDirection

Aggregates all the calls based on the direction of the call with reference to the specified row type.

  • Outbound: Calls made from extension are represented as "Outbound".
  • Inbound: Calls received on extension are "Inbound".
Counter will return aggregation of calls for these breakdown by time intervals. Timer will return call duration aggregation for same by time intervals.
callsByResponse callsDurationByResponse

Breakdown of the response to the calls by the selected dimension. Gives a higher level aggregation of how many were:

  • answered: Calls picked & answered by the user.
  • notanswered: Calls not answered by the user.
  • connected: Only applicable to outbound calls and aggregates all the calls that got connected to the called number.
  • notConnected: Only applicable to outbound calls and aggregates all the calls that did not get connected to the called number.
Counter will return aggregation of calls for these breakdowns by time intervals. Timer will return call duration aggregation for the same by time intervals.
callsByType callsDurationByType

Aggregation is based on the types of calls that are handled by users.

  • direct: Direct calls answered by the user.
  • fromQueue: Queue calls that are answered by the user.
  • parkRetrieval: Calls answered by the user after retrieving a parked call.
  • transferred: Transferred calls that were answered by the user.
  • outbound: Calls made from the extension numbers.
  • overflow: Total calls overflowed from an extension.
Counter will return aggregation of calls for these breakdown by time intervals. Timer will return call duration aggregation for same by time intervals.
CallsByActions Not Applicable

Aggregation of actions taken by the user on all the calls they handled.

holdson: Number of times the user placed the calls on hold.
  • holdsoff: Number of times the user removed calls from hold.
  • parkson: Number of times the user placed the calls on park location.
  • parksoff: Number of times the user retrieved calls from park location blindTransfer: Type of call transfer where a call is transferred to another agent without any prior information.
  • warmTransfer: Type of transfer where a call is transferred to another agent with prior information about the transfer.
  • dtmfTransfer: Type of transfer where a call is transferred vis dtmf sequence.
Counter will return aggregation of calls for these actions by time intervals. Not applicable for Timer.
CallsByResult callsDurationByResult

End result of the calls. Describes how the calls that came to specified Groupby ended.

For Answered:

  • Completed: Call ended normally after a live talk with the user. It is possible calls may not have ended at this level and got transferred or forwarded out or abandoned during the hold in which case even after calls were answered not all were completed.
  • Abandoned: The caller hung up before the user could answer or during the hold.
  • Voicemail: Call reached the voicemail of the user or group.

For Not Answered:

  • Missed: Calls that rang to max time/rings as per the setup and were not answered by the user
  • Accepted: Calls that were responded by a system such as automated response or VM and disconnected
  • Unknown: for outbound pstn calls, the result is unknown for calls connected/Not connected
Counter will return aggregation of total calls for these Results by time intervals. Timer will return call duration aggregation for the same calls by time intervals.
callsSegments callsSegmentsDuration

Aggregates the times spent by the caller in different stages of the call. These are the calls that came to the dimensions specified by GroupBy. The data received will be by time intervals split pre-applied (hour, day, week, month).

  • setup: It is when the phone system is connecting to callee's device. This is when the caller is calling via RC App and the system says "Please wait while I try to connect you" before the beeps start.
  • ringing: Duration for which calls spent ringing to the Extn/No & can be found under Timer. When selected under counter, it returns, the number of calls that had a ringing phase.
  • ivrPrompts: Duration for which calls are spent in IVR Prompt before reaching the Extn/No. When selected as “Calls” returns, the number of calls that had IVR Prompt phase.
  • livetalk: Duration for which callers were having a live talk with Extn/No & can be found under Timer. When selected under counter, it returns the number of calls that had a Live Talk phase.
  • holds: Duration for which callers were put on hold by Extn/No & can be found under Timer. When selected under counter, it returns, number of calls that had a Hold phase.
  • parks: Duration for which callers spent in a parked state after being parked by Extn/No & can be found under Timer. When selected under counter, it returns the number of calls that were parked by Extn/No.
  • transfers: Duration for which caller was being transferred by Extn/No & can be found under Timer. When selected under counter, it returns the number of calls that were transferred by Extn/No.
  • vmGreeting: Duration for which callers spent listening to VM greeting & can be found under Timer. When selected under counter, it returns the number of calls that had VM greeting phase.
  • voicemail: Duration for which callers spent in Voicemail & can be found under Timer. When selected under counter, it returns number of calls that had Voicemail Phase.
callsByCompanyHours callsDurationByCompanyHours

Aggregates data by company "Business Hours" or "After Hours" as setup on the admin portal.

Counter will return aggregation of calls for Business Hours & After Hours by time intervals. Timer will return call duration aggregation for the same by time intervals.
callsByQueueSla callsDurationByQueueSla

Provides the count of calls and their duration details for calls answered within SLA for Queues grouping only. Not applicable for the rest of the groupby available.

  • inSla: Calls answered within SLA.
  • outOfSla: Calls answered outside of SLA.
Counter will return aggregation of calls for these metrics by time intervals. Timer will return call duration aggregation for the same by time intervals.

Full sample request for Analytics Timeline Report

{
  "grouping": {
    "groupBy": "CompanyNumbers",
    "keys": []
  },
  "timeSettings": {
    "timeZone": "America/Los_Angeles",
    "timeRange": {
      "timeFrom": "2022-03-01T05:52:17.745Z",
      "timeTo": "2022-05-01T05:52:17.745Z"
    },
    "advancedTimeSettings": {
      "includeDays": [
        "Sunday"
      ],
      "includeHours": [
        {
          "from": "00:00",
          "to": "23:59"
        }
      ]
    }
  },
  "callFilters": {
    "directions": [
      "Inbound"
    ],
    "origins": [
      "Internal"
    ],
    "callResponses": [
      "Answered"
    ],
    "callResults": [
      "Completed"
    ],
    "callSegments": [
      {
        "segment": "Ringing",
        "length": {
          "minSeconds": 0,
          "maxSeconds": 200
        }
      }
    ],
    "callActions": [
      "HoldOff"
    ],
    "companyHours": [
      "BusinessHours"
    ],
    "callDuration": {
      "minSeconds": 0,
      "maxSeconds": 200
    },
    "timeSpent": {
      "minSeconds": 0,
      "maxSeconds": 200
    },
    "callFilters": {
      "extensionFilters": {
        "fromIds": [],
        "toIds": []
      }
    },
    "calledNumbers": []
  },
  "responseOptions": {
    "counters": {
      "allCalls": {
        "aggregationType": "Sum"
      },
      "queueOpportunities": {
        "aggregationType": "Sum"
      },
        "callsByDirection": {
        "aggregationType": "Sum"
      },
      "callsByOrigin": {
        "aggregationType": "Sum"
      },
      "callsByResponse": {
        "aggregationType": "Sum"
      },
      "callsSegments": {
        "aggregationType": "Sum"
      },
      "callsByResult": {
        "aggregationType": "Sum"
      },
      "callsByCompanyHours": {
        "aggregationType": "Sum"
      },
      "callsByActions": {
        "aggregationType": "Sum"
      },
      "callsByType": {
        "aggregationType": "Sum"
      }
    },
    "timers": {
      "allCallsDuration": {
        "aggregationType": "Sum"
      },
      "callsDurationByDirection": {
        "aggregationType": "Sum"
      },
      "callsDurationByOrigin": {
        "aggregationType": "Sum"
      },
      "callsDurationByResponse": {
        "aggregationType": "Sum"
      },
      "callsSegmentsDuration": {
        "aggregationType": "Sum"
      },
      "callsDurationByResult": {
        "aggregationType": "Sum"
      },
      "callsDurationByCompanyHours": {
        "aggregationType": "Sum"
      },
      "callsDurationByType": {
        "aggregationType": "Sum"
      }
    }
  }
}

The following code samples show how to read analytics timeline data.

Call the Analytics Timeline API - Grouped by users

Running the code

  • If you have tried the SMS quick start, you can just copy all the functions below and add them to the quick start project then call the read_analytics_timeline_grouped_by_users() function. Otherwise, edit the variables in ALL CAPS with your app and user credentials before running the code.
  • If you run on your production account, remember to use app credentials for production and change the RingCentral server URL to "https://platform.ringcentral.com"
const RC = require('@ringcentral/sdk').SDK

// Instantiate the SDK and get the platform instance
var rcsdk = new RC({
    server: 'https://platform.devtest.ringcentral.com',
    clientId: 'SANDBOX-APP-CLIENTID',
    clientSecret: 'SANDBOX-APP-CLIENTSECRET'
});
var platform = rcsdk.platform();

/* Authenticate a user using a personal JWT token */
platform.login({ jwt: 'SANDBOX-JWT' })

platform.on(platform.events.loginSuccess, function(e){
    read_analytics_timeline_grouped_by_users()
});

/*
  Read timeline analytics data from a period of time, broken down by day time frames and grouped by users
*/
async function read_analytics_timeline_grouped_by_users(){
  try {
    let userIds = await read_users()
    let bodyParams = {
        grouping: {
            groupBy: "Users",
            keys: userIds,
        },
        timeSettings: {
          timeZone: "America/Los_Angeles",
          timeRange: {
            // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
            // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
            // your local time to UTC time!
            timeFrom: "2023-01-01T00:00:00.000Z",
            timeTo: "2023-02-15T23:59:59.999Z"
          },
          advancedTimeSettings: {
            includeDays: [ "Sunday" ],
            includeHours: [
              {
                from: "00:00",
                to: "23:59"
              }
            ]
          }
        },
        responseOptions: {
          counters: {
            allCalls: true
          }
        }
      }

    let queryParams = {
      interval: 'Day',
      perPage: 10
    }
    var endpoint = '/analytics/calls/v1/accounts/~/timeline/fetch'
    var resp = await platform.post(endpoint, bodyParams, queryParams)
    var jsonObj = await resp.json()
    console.log(jsonObj)
  }catch(e){
    console.log(e.message)
  }
}

/*
  Read users and create a list of user id
*/
async function read_users()
{
  var userIds = []
  var queryParams = {
          type: ["User"]
        }
  let endpoint = "/restapi/v1.0/account/~/extension/"
  var resp = await platform.get(endpoint, queryParams)
  let jsonObj = await resp.json()
  for (var record of jsonObj.records) {
    // You can filter out any user you don't want to read analytics data!
    userIds.push(String(record.id))
  }
  return userIds;
}
from ringcentral import SDK
import json

#
#  Read timeline analytics data from a period of time, broken down by day time frames and grouped by users
#
def read_analytics_timeline_grouped_by_users():
  userIds = read_users()
  try:
    bodyParams = {
      'grouping': {
        'groupBy': "Users",
        'keys': userIds
      },
      'timeSettings':{
        'timeZone': "America/Los_Angeles",
        'timeRange': {
          # Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
          # The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
          # your local time to UTC time!
          'timeFrom': "2023-01-01T00:00:00.000Z",
          'timeTo': "2023-02-15T23:59:59.999Z"
        },
        'advancedTimeSettings': {
          'includeDays': [ "Sunday" ],
          'includeHours': [
            {
              'from': "00:00",
              'to': "23:59"
            }
          ]
        }
      },
      'responseOptions': {
        'counters': {
          'allCalls': True
        }
      }
    }

    queryParams = {
      'interval': "Day",
      'perPage': 10
    }

    endpoint = '/analytics/calls/v1/accounts/~/timeline/fetch'
    resp = platform.post(endpoint, bodyParams, queryParams)
    jsonObj = resp.json_dict()
    print(json.dumps(jsonObj, indent=2, sort_keys=True))
  except Exception as e:
    print ("Unable to read analytics timeline. ", str(e))

#
#  Read users and create a list of user id
#
def read_users():
  userIds = []
  try:
    queryParams = {
          'type': ["User"]
    }
    endpoint = "/restapi/v1.0/account/~/extension/"
    resp = platform.get(endpoint, queryParams)
    jsonObj = resp.json()
    for record in jsonObj.records:
      # You can filter out any user you don't want to read analytics data!
      userIds.append(str(record.id))
  except Exception as e:
    print ("Unable to read users. ", str(e))
  return userIds


# Authenticate a user using a personal JWT token
def login():
  try:
    platform.login( jwt= "SANDBOX_JWT" )
    read_analytics_timeline_grouped_by_users()
  except Exception as e:
    print ("Unable to authenticate to platform. Check credentials." + str(e))

# Instantiate the SDK and get the platform instance
rcsdk = SDK("SANDBOX-APP-CLIENTID", "SANDBOX-APP-CLIENTSECRET", "https://platform.devtest.ringcentral.com")
platform = rcsdk.platform()

login()
<?php
require('vendor/autoload.php');

// Instantiate the SDK and get the platform instance
$rcsdk = new RingCentral\SDK\SDK( 'SANDBOX-APP-CLIENTID', 'SANDBOX-APP-CLIENTSECRET', 'https://platform.devtest.ringcentral.com' );
$platform = $rcsdk->platform();

/* Authenticate a user using a personal JWT token */
$platform->login(["jwt" => 'SANDBOX-JWT']);
read_analytics_timeline_grouped_by_users();

/*
  Read timeline analytics data from a period of time, broken down by day time frames and grouped by users
*/
function read_analytics_timeline_grouped_by_users() {
  global $platform;
  try{
    $userIds = read_users();
    $bodyParams = array(
      'grouping' => array (
        'groupBy' => "Users",
        'keys' => $userIds,
      ),
      'timeSettings' => array (
        'timeZone' => "America/Los_Angeles",
        'timeRange' => array (
          // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
          // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
          // your local time to UTC time!
          'timeFrom' => "2023-01-01T00:00:00.000Z",
          'timeTo' => "2023-02-15T23:59:59.999Z"
        ),
        'advancedTimeSettings' => array (
          'includeDays' => array ("Sunday"),
          'includeHours' => array (
            array ('from' => "00:00", 'to' => "23:59")
          )
        )
      ),
      'responseOptions' => array (
        'counters' => array (
          'allCalls' => true
        )
      )
    );

    $queryParams = array (
      'interval' => "Day",
      'perPage' => 10
    );

    $endpoint = '/analytics/calls/v1/accounts/~/timeline/fetch';
    $resp = $platform->post($endpoint, $bodyParams, $queryParams);
    print_r (json_encode($resp->json(), JSON_PRETTY_PRINT));
  }catch (\RingCentral\SDK\Http\ApiException $e) {
    print_r ('Error: ' . $e->getMessage() . PHP_EOL);
  }
}

/*
  Read users and create a list of user id
*/
function read_users()
{
  global $platform;
  $userIds = array();
  try{
    $queryParams = array (
          'type' => array ("User")
        );
    $endpoint = "/restapi/v1.0/account/~/extension/";
    $resp = $platform->get($endpoint, $queryParams);
    foreach ($resp->json()->records as $record) {
      // You can filter out any call queue you don't want to read analytics data!
      array_push($userIds, strval($record->id));
    }
    return $userIds;
  }catch (\RingCentral\SDK\Http\ApiException $e) {
    print_r ('Error: ' . $e->getMessage() . PHP_EOL);
  }
}
?>
require 'ringcentral'

#
#  Read timeline analytics data from a period of time, broken down by day time frames and grouped by users
#
def read_analytics_timeline_grouped_by_users()
  begin
    userIds = read_users()
    bodyParams = {
        'grouping':{
          'groupBy': "Users",
          'keys': userIds
        },
        'timeSettings':{
          'timeZone': "America/Los_Angeles",
          'timeRange':{
            # Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current datetime
            # The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
            # your local time to UTC time!
            'timeFrom': "2023-01-01T00:00:00.000Z",
            'timeTo': "2023-02-15T23:59:59.999Z"
          },
          'advancedTimeSettings': {
            'includeDays': [ "Sunday" ],
            'includeHours': [
              {
                'from': "00:00",
                'to': "23:59"
              }
            ]
          }
        },
        'responseOptions':{
          'counters':{
            'allCalls': true
          }
        }
      }
    queryParams = {
      'interval': "Day",
      'perPage': 10
    }
    resp = $platform.post('/analytics/calls/v1/accounts/~/timeline/fetch', payload: bodyParams, params: queryParams)
    puts JSON.pretty_generate(resp.body)
  rescue StandardError => e
    puts (e)
  end
end

#
#  Read users and create a list of user id
#
def read_users()
    userIds = []
    queryParams = {
            'type': ["User"]
          }
    endpoint = "/restapi/v1.0/account/~/extension/"
    resp = $platform.get(endpoint, queryParams)
    jsonObj = resp.body
    for record in jsonObj['records'] do
      # You can filter out any user you don't want to read analytics data!
      userIds.append(record['id'].to_s)
    end
  return userIds
end

# Authenticate a user using a personal JWT token
def login()
  begin
    $platform.authorize( jwt: "SANDBOX_JWT" )
    read_analytics_timeline_grouped_by_users()
  rescue StandardError => e
    puts ("Unable to authenticate to platform. Check credentials." + e.to_s)
  end
end

# Instantiate the SDK and get the platform instance
$platform = RingCentral.new( "SANDBOX-APP-CLIENTID", "SANDBOX-APP-CLIENTSECRET", "https://platform.devtest.ringcentral.com" )

login()
using System;
using System.IO;
using System.Threading.Tasks;
using System.Collections.Generic;
using RingCentral;
using Newtonsoft.Json;

namespace TimeLineByUsers {
  class Program {
    static RestClient restClient;

    static async Task Main(string[] args){
      // Instantiate the SDK
      restClient = new RestClient("SANDBOX-APP-CLIENT-ID", "SANDBOX-APP-CLIENT-SECRET", "https://platform.devtest.ringcentral.com");
      // Authenticate a user using a personal JWT token
      await restClient.Authorize("SANDBOX-JWT");

      await read_analytics_timeline_grouped_by_users();
    }
    /*
      Read timeline analytics data from a period of time, broken down by day time frames and grouped by users
    */
    static private async Task read_analytics_timeline_grouped_by_users()
    {
      try
      {
        var bodyParams = new TimelineRequest();
        bodyParams.grouping = new Grouping();
        bodyParams.grouping.groupBy = "Users";
        bodyParams.grouping.keys = await read_users();

        bodyParams.timeSettings = new TimeSettings();
        bodyParams.timeSettings.timeZone = "America/Los_Angeles";
        bodyParams.timeSettings.advancedTimeSettings = new AdvancedTimeSettings();
        bodyParams.timeSettings.advancedTimeSettings.includeDays = new String[] { "Monday", "Tuesday", "Wednesday" };
        var hrInterval = new HoursInterval { from = "00:00", to = "23:59" };
        bodyParams.timeSettings.advancedTimeSettings.includeHours = new HoursInterval[] { hrInterval };
        bodyParams.timeSettings.timeRange = new TimeRange();
        // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
        // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
        // your local time to UTC time!
        bodyParams.timeSettings.timeRange.timeFrom = "2023-01-01T00:00:00.000Z";
        bodyParams.timeSettings.timeRange.timeTo = "2023-02-15T23:59:59.999Z";

        bodyParams.responseOptions = new TimelineResponseOptions();
        bodyParams.responseOptions.counters = new TimelineResponseOptionsCounters();
        bodyParams.responseOptions.counters.allCalls = true;
        bodyParams.responseOptions.counters.callsByDirection = true;
        bodyParams.responseOptions.counters.callsByOrigin = true;

        var queryParams = new AnalyticsCallsTimelineFetchParameters();
        queryParams.perPage = 10;
        queryParams.interval = "Day";

        var response = await restClient.Analytics().Calls().V1().Accounts("~").Timeline().Fetch().Post(bodyParams, queryParams);
        Console.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
    }
    /*
      Read users and create a list of user id
    */
    static private async Task<String[]> read_users()
    {
      List<String> list = new List<String>();
      try
      {
        var queryParams = new ListExtensionsParameters();
        queryParams.type = new String[] { "User" };
        var resp = await restClient.Restapi().Account().Extension().List(queryParams);
        foreach (var record in resp.records)
        {
          // You can filter out any call queue you don't want to read analytics data!
          list.Add(record.id.ToString());
        }
      }catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      var userIds = (String[])list.ToArray();
      return userIds;
    }
  }
}
package TimeLineByQueues;

import java.io.IOException;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;

import com.ringcentral.*;
import com.ringcentral.definitions.*;

public class TimeLineByQueues {
    static RestClient restClient;

    public static void main(String[] args) {
      var obj = new TimeLineByQueues();
      try {
        // Instantiate the SDK
        restClient = new RestClient("SANDBOX-APP-CLIENT-ID", "SANDBOX-APP-CLIENT-SECRET", "https://platform.devtest.ringcentral.com");

        // Authenticate a user using a personal JWT token
        restClient.authorize("SANDBOX-JWT");
        obj.read_analytics_timeline_grouped_by_queues();
      } catch (RestException e) {
        System.out.println(e.getMessage());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    /*
      Read timeline analytics data from a period of time, broken down by day time frames and grouped by call queues
    */
    public void read_analytics_timeline_grouped_by_users() throws RestException, IOException {
      try {
        var bodyParams = new TimelineRequest();
        bodyParams.grouping = new Grouping();
        bodyParams.grouping.groupBy = "Users";
        bodyParams.grouping.keys = read_users();

        bodyParams.timeSettings = new TimeSettings();
        bodyParams.timeSettings.timeZone = "America/Los_Angeles";
        bodyParams.timeSettings.advancedTimeSettings = new AdvancedTimeSettings();
        bodyParams.timeSettings.advancedTimeSettings.includeDays = new String[] { "Sunday" };
        var hrInterval = new HoursInterval();
        hrInterval.from = "00:00";
        hrInterval.to = "23:59";

        bodyParams.timeSettings.advancedTimeSettings.includeHours = new HoursInterval[] { hrInterval };
        bodyParams.timeSettings.timeRange = new TimeRange();

        // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
        // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
        // your local time to UTC time!
        bodyParams.timeSettings.timeRange.timeFrom = "2023-01-01T00:00:00.000Z";
        bodyParams.timeSettings.timeRange.timeTo = "2023-02-15T23:59:59.999Z";

        bodyParams.responseOptions = new TimelineResponseOptions();
        bodyParams.responseOptions.counters = new TimelineResponseOptionsCounters();
        bodyParams.responseOptions.counters.allCalls = true;
        bodyParams.responseOptions.counters.callsByDirection = true;
        bodyParams.responseOptions.counters.callsByOrigin = true;

        var queryParams = new AnalyticsCallsTimelineFetchParameters();
        queryParams.perPage = 10l;
        queryParams.interval = "Day";

        var resp = restClient.analytics().calls().v1().accounts("~").timeline().fetch().post(bodyParams, queryParams);
        String jsonStr = new Gson().toJson(resp, new TypeToken<Object>(){}.getType());
        System.out.println(jsonStr);
      }catch (RestException e){
        System.out.println(e.getMessage());
      }
    }
    /*
        Read call queues and create a list of call queue id
    */
    private String [] read_users() throws RestException, IOException {
      List<String> list = new ArrayList<>();
      try {
        var queryParams = new ListExtensionsParameters();
        queryParams.type = new String [] { "User" };
        var resp =  restClient.restapi().account().extension().list(queryParams);
        for (var record : resp.records) {
          // You can filter out any call queue you don't want to read analytics data!
          list.add(record.id.toString());
        }
      }catch(RestException e) {
        System.out.println(e.getMessage());
      }
      var userIds = (String[]) list.toArray(new String[list.size()]);
      return userIds;
    }
}

Call the Analytics Timeline API - Grouped by call queues

Running the code

  • If you have tried the SMS quick start, you can just copy all the functions below and add them to the quick start project then call the read_analytics_timeline_grouped_by_queues() function. Otherwise, edit the variables in ALL CAPS with your app and user credentials before running the code.
  • If you run on your production account, remember to use app credentials for production and change the RingCentral server URL to "https://platform.ringcentral.com"
const RC = require('@ringcentral/sdk').SDK

// Instantiate the SDK and get the platform instance
var rcsdk = new RC({
    server: 'https://platform.devtest.ringcentral.com',
    clientId: 'SANDBOX-APP-CLIENTID',
    clientSecret: 'SANDBOX-APP-CLIENTSECRET'
});
var platform = rcsdk.platform();

/* Authenticate a user using a personal JWT token */
platform.login({ jwt: 'SANDBOX-JWT' })

platform.on(platform.events.loginSuccess, function(e){
    read_analytics_timeline_grouped_by_queues()
});

/*
  Read timeline analytics data from a period of time, broken down by day time frames and grouped by call queues
*/
async function read_analytics_timeline_grouped_by_queues(){
  try {
    let callQueueIds = await read_call_queues()
    let bodyParams = {
        grouping: {
            groupBy: "Queues",
            keys: callQueueIds,
        },
        timeSettings: {
          timeZone: "America/Los_Angeles",
          timeRange: {
            // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
            // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
            // your local time to UTC time!
            timeFrom: "2023-01-01T00:00:00.000Z",
            timeTo: "2023-02-15T23:59:59.999Z"
          },
          advancedTimeSettings: {
            includeDays: [ "Sunday" ],
            includeHours: [
              {
                from: "00:00",
                to: "23:59"
              }
            ]
          }
        },
        responseOptions: {
          counters: {
            allCalls: true
          }
        }
      }

    let queryParams = {
      interval: 'Day',
      perPage: 10
    }
    var endpoint = '/analytics/calls/v1/accounts/~/timeline/fetch'
    var resp = await platform.post(endpoint, bodyParams, queryParams)
    var jsonObj = await resp.json()
    console.log(jsonObj)
  }catch(e){
    console.log(e.message)
  }
}

/*
  Read call queues and create a list of call queue id
*/
async function read_call_queues()
{
  var callQueueIds = []
  var queryParams = {
          type: ["Department"]
        }
  let endpoint = "/restapi/v1.0/account/~/extension/"
  var resp = await platform.get(endpoint, queryParams)
  let jsonObj = await resp.json()
  for (var record of jsonObj.records) {
    // You can filter out any call queue you don't want to read analytics data!
    callQueueIds.push(String(record.id))
  }
  return callQueueIds;
}
from ringcentral import SDK
import json

#
#  Read timeline analytics data from a period of time, broken down by day time frames and grouped by call queues
#
def read_analytics_timeline_grouped_by_queues():
  callQueueIds = read_call_queues()
  try:
    bodyParams = {
      'grouping': {
        'groupBy': "Queues",
        'keys': callQueueIds
      },
      'timeSettings':{
        'timeZone': "America/Los_Angeles",
        'timeRange': {
          # Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
          # The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
          # your local time to UTC time!
          'timeFrom': "2023-01-01T00:00:00.000Z",
          'timeTo': "2023-03-27T23:59:59.999Z"
        },
        'advancedTimeSettings': {
          'includeDays': [ "Sunday" ],
          'includeHours': [
            {
              'from': "00:00",
              'to': "23:59"
            }
          ]
        }
      },
      'responseOptions': {
        'counters': {
          'allCalls': True
        }
      }
    }

    queryParams = {
      'interval': "Day",
      'perPage': 10
    }

    endpoint = '/analytics/calls/v1/accounts/~/timeline/fetch'
    resp = platform.post(endpoint, bodyParams, queryParams)
    jsonObj = resp.json_dict()
    print(json.dumps(jsonObj, indent=2, sort_keys=True))
  except Exception as e:
    print ("Unable to read analytics timeline", str(e))

#
#  Read call queues and create a list of call queue id
#
def read_call_queues():
  callQueueIds = []
  try:
    queryParams = {
          'type': ["Department"]
    }
    endpoint = "/restapi/v1.0/account/~/extension/"
    resp = platform.get(endpoint, queryParams)
    jsonObj = resp.json()
    for record in jsonObj.records:
      # You can filter out any call queue you don't want to read analytics data!
      callQueueIds.append(str(record.id))
  except Exception as e:
    print ("Unable to read call queues. ", str(e))
  return callQueueIds


# Authenticate a user using a personal JWT token
def login():
  try:
    platform.login( jwt= "SANDBOX_JWT" )
    read_analytics_timeline_grouped_by_queues()
  except Exception as e:
    print ("Unable to authenticate to platform. Check credentials." + str(e))

# Instantiate the SDK and get the platform instance
rcsdk = SDK("SANDBOX-APP-CLIENTID", "SANDBOX-APP-CLIENTSECRET", "https://platform.devtest.ringcentral.com")
platform = rcsdk.platform()

login()
<?php
require('vendor/autoload.php');

// Instantiate the SDK and get the platform instance
$rcsdk = new RingCentral\SDK\SDK( 'SANDBOX-APP-CLIENTID', 'SANDBOX-APP-CLIENTSECRET', 'https://platform.devtest.ringcentral.com' );
$platform = $rcsdk->platform();

/* Authenticate a user using a personal JWT token */
$platform->login(["jwt" => 'SANDBOX-JWT']);
read_analytics_timeline_grouped_by_queues();

/*
  Read timeline analytics data from a period of time, broken down by day time frames and grouped by call queues
*/
function read_analytics_timeline_grouped_by_queues() {
  global $platform;
  try{
    $bodyParams = array(
      'grouping' => array (
        'groupBy' => "Queues",
        'keys' => array ("62284876016") ),
      'timeSettings' => array (
        'timeZone' => "America/Los_Angeles",
        'timeRange' => array (
          // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
          // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
          // your local time to UTC time!
          'timeFrom' => "2023-01-01T00:00:00.000Z",
          'timeTo' => "2023-02-15T23:59:59.999Z"
        ),
        'advancedTimeSettings' => array (
          'includeDays' => array ("Sunday"),
          'includeHours' => array (
            array ('from' => "00:00", 'to' => "23:59")
          )
        )
      ),
      'responseOptions' => array (
        'counters' => array (
          'allCalls' => true
        )
      )
    );

    $queryParams = array (
      'interval' => "Day",
      'perPage' => 10
    );

    $endpoint = '/analytics/calls/v1/accounts/~/timeline/fetch';
    $resp = $platform->post($endpoint, $bodyParams, $queryParams);
    print_r (json_encode($resp->json(), JSON_PRETTY_PRINT));
  }catch (\RingCentral\SDK\Http\ApiException $e) {
    print_r ('Error: ' . $e->getMessage() . PHP_EOL);
  }
}

/*
  Read call queues and create a list of call queue id
*/
function read_call_queues()
{
  global $platform;
  $callQueueIds = array();
  try{
    $queryParams = array (
          'type' => array ("Department")
        );
    $endpoint = "/restapi/v1.0/account/~/extension/";
    $resp = $platform->get($endpoint, $queryParams);
    $jsonObj = $resp->json();
    foreach ($jsonObj->records as $record) {
      // You can filter out any call queue you don't want to read analytics data!
      $callQueueIds->push($record->id);
    }
    return $callQueueIds;
  }catch (\RingCentral\SDK\Http\ApiException $e) {
    print_r ('Error: ' . $e->getMessage() . PHP_EOL);
  }
}
?>
require 'ringcentral'

#
#  Read timeline analytics data from a period of time, broken down by day time frames and grouped by call queues
#
def read_analytics_timeline_grouped_by_queues()
  begin
    callQueueIds = read_call_queues()
    bodyParams = {
            "grouping":{
              "groupBy": "Queues",
              'keys': callQueueIds
            },
            "timeSettings":{
              "timeZone": "America/Los_Angeles",
              "timeRange":{
                # Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
                # The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
                # your local time to UTC time!
                "timeFrom": "2023-01-01T00:00:00.000Z",
                "timeTo": "2023-02-15T23:59:59.999Z"
              },
              "advancedTimeSettings": {
                "includeDays": [ "Sunday" ],
                "includeHours": [
                  {
                    "from": "00:00",
                    "to": "23:59"
                  }
                ]
              }
            },
            "responseOptions":{
              "counters":{
                "allCalls": true
              }
            }
          }

    queryParams = {
        'interval': "Day",
        'perPage': 10
      }

    endpoint = '/analytics/calls/v1/accounts/~/timeline/fetch'
    resp = $platform.post(endpoint, payload: bodyParams, params: queryParams)
    puts JSON.pretty_generate(resp.body)
  rescue StandardError => e
    puts (e)
  end
end

#
#  Read call queues and create a list of call queue id
#
def read_call_queues()
  callQueueIds = []
  queryParams = {
            'type': ["Department"]
          }
  endpoint = "/restapi/v1.0/account/~/extension/"
  resp = $platform.get(endpoint, queryParams)
  jsonObj = resp.body
  for record in jsonObj['records'] do
    # You can filter out any user you don't want to read analytics data!
    callQueueIds.append(record['id'].to_s)
  end
  return callQueueIds
end

# Authenticate a user using a personal JWT token
def login()
  begin
    $platform.authorize( jwt: "SANDBOX_JWT" )
    read_analytics_timeline_grouped_by_queues()
  rescue StandardError => e
    puts ("Unable to authenticate to platform. Check credentials." + e.to_s)
  end
end

# Instantiate the SDK and get the platform instance
rcsdk = SDK("SANDBOX-APP-CLIENTID", "SANDBOX-APP-CLIENTSECRET", "https://platform.devtest.ringcentral.com")
platform = rcsdk.platform()

login()
using System;
using System.IO;
using System.Threading.Tasks;
using System.Collections.Generic;
using RingCentral;
using Newtonsoft.Json;

namespace TimeLineByUsers {
  class Program {
    static RestClient restClient;

    static async Task Main(string[] args){
      // Instantiate the SDK
      restClient = new RestClient("SANDBOX-APP-CLIENT-ID", "SANDBOX-APP-CLIENT-SECRET", "https://platform.devtest.ringcentral.com");

      // Authenticate a user using a personal JWT token
      await restClient.Authorize("SANDBOX-JWT");

      await read_analytics_timeline_grouped_by_queues();
    }
    /*
      Read timeline analytics data from a period of time, broken down by day time frames and grouped by call queues
    */
    static private async Task read_analytics_timeline_grouped_by_queues()
    {
      try
      {
        var bodyParams = new TimelineRequest();
        bodyParams.grouping = new Grouping();
        bodyParams.grouping.groupBy = "Queues";
        bodyParams.grouping.keys = await read_call_queues();

        bodyParams.timeSettings = new TimeSettings();
        bodyParams.timeSettings.timeZone = "America/Los_Angeles";
        bodyParams.timeSettings.advancedTimeSettings = new AdvancedTimeSettings();
        bodyParams.timeSettings.advancedTimeSettings.includeDays = new String[] { "Monday", "Tuesday", "Wednesday" };
        var hrInterval = new HoursInterval { from = "00:00", to = "23:59" };
        bodyParams.timeSettings.advancedTimeSettings.includeHours = new HoursInterval[] { hrInterval };
        bodyParams.timeSettings.timeRange = new TimeRange();
        // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
        // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
        // your local time to UTC time!
        bodyParams.timeSettings.timeRange.timeFrom = "2023-01-01T00:00:00.000Z";
        bodyParams.timeSettings.timeRange.timeTo = "2023-02-15T23:59:59.999Z";

        bodyParams.responseOptions = new TimelineResponseOptions();
        bodyParams.responseOptions.counters = new TimelineResponseOptionsCounters();
        bodyParams.responseOptions.counters.allCalls = true;
        bodyParams.responseOptions.counters.callsByDirection = true;
        bodyParams.responseOptions.counters.callsByOrigin = true;

        var queryParams = new AnalyticsCallsTimelineFetchParameters();
        queryParams.perPage = 10;
        queryParams.interval = "Day";

        var response = await restClient.Analytics().Calls().V1().Accounts("~").Timeline().Fetch().Post(bodyParams, queryParams);
        Console.WriteLine(JsonConvert.SerializeObject(response));
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
    }
    /*
      Read call queues and create a list of call queue id
    */
    static private async Task<String[]> read_call_queues()
    {
      List<String> list = new List<String>();
      try
      {
        var queryParams = new ListExtensionsParameters();
        queryParams.type = new String[] { "Department" };
        var resp = await restClient.Restapi().Account().Extension().List(queryParams);
        foreach (var record in resp.records)
        {
          // You can filter out any call queue you don't want to read analytics data!
          list.Add(record.id.ToString());
        }
      }catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      var callQueueIds = (String[])list.ToArray();
      return callQueueIds;
    }
  }
}
package TimeLineByQueues;

import java.io.IOException;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;

import com.ringcentral.*;
import com.ringcentral.definitions.*;

public class TimeLineByQueues {
    static RestClient restClient;

    public static void main(String[] args) {
      var obj = new TimeLineByQueues();
      try {
        // Instantiate the SDK
        restClient = new RestClient("SANDBOX-APP-CLIENT-ID", "SANDBOX-APP-CLIENT-SECRET", "https://platform.devtest.ringcentral.com");

        // Authenticate a user using a personal JWT token
        restClient.authorize("SANDBOX-JWT");
        obj.read_analytics_timeline_grouped_by_queues();
      } catch (RestException e) {
        System.out.println(e.getMessage());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    /*
      Read timeline analytics data from a period of time, broken down by day time frames and grouped by call queues
    */
    public void read_analytics_timeline_grouped_by_queues() throws RestException, IOException {
      try {
        var bodyParams = new TimelineRequest();
        bodyParams.grouping = new Grouping();
        bodyParams.grouping.groupBy = "Queues";
        bodyParams.grouping.keys = read_call_queues();

        bodyParams.timeSettings = new TimeSettings();
        bodyParams.timeSettings.timeZone = "America/Los_Angeles";
        bodyParams.timeSettings.advancedTimeSettings = new AdvancedTimeSettings();
        bodyParams.timeSettings.advancedTimeSettings.includeDays = new String[] { "Sunday" };
        var hrInterval = new HoursInterval();
        hrInterval.from = "00:00";
        hrInterval.to = "23:59";

        bodyParams.timeSettings.advancedTimeSettings.includeHours = new HoursInterval[] { hrInterval };
        bodyParams.timeSettings.timeRange = new TimeRange();

        // Change the "timeFrom" value accordingly so that it does not exceed 184 days from the current date and time
        // The specified time is UTC time. If you want the timeFrom and timeTo your local time, you have to convert
        // your local time to UTC time!
        bodyParams.timeSettings.timeRange.timeFrom = "2023-01-01T00:00:00.000Z";
        bodyParams.timeSettings.timeRange.timeTo = "2023-02-15T23:59:59.999Z";

        bodyParams.responseOptions = new TimelineResponseOptions();
        bodyParams.responseOptions.counters = new TimelineResponseOptionsCounters();
        bodyParams.responseOptions.counters.allCalls = true;
        bodyParams.responseOptions.counters.callsByDirection = true;
        bodyParams.responseOptions.counters.callsByOrigin = true;

        var queryParams = new AnalyticsCallsTimelineFetchParameters();
        queryParams.perPage = 10l;
        queryParams.interval = "Day";

        var resp = restClient.analytics().calls().v1().accounts("~").timeline().fetch().post(bodyParams, queryParams);
        String jsonStr = new Gson().toJson(resp, new TypeToken<Object>(){}.getType());
        System.out.println(jsonStr);
      }catch (RestException e){
        System.out.println(e.getMessage());
      }
    }
    /*
        Read call queues and create a list of call queue id
    */
    private String [] read_call_queues() throws RestException, IOException {
      List<String> list = new ArrayList<>();
      try {
        var queryParams = new ListExtensionsParameters();
        queryParams.type = new String [] { "Department" };
        var resp =  restClient.restapi().account().extension().list(queryParams);
        for (var record : resp.records) {
          // You can filter out any call queue you don't want to read analytics data!
          list.add(record.id.toString());
        }
      }catch(RestException e) {
        System.out.println(e.getMessage());
      }
      var callQueueIds = (String[]) list.toArray(new String[list.size()]);
      return callQueueIds;
    }
}