Skip to main content
Question

Needs Advice on List User Call Records API

  • 28 November 2023
  • 10 replies
  • 236 views

Hello Ring Central Community,

I am very new to getting data via API but I do have a working script that successfully retrieve our company's call data in the format I wanted. Now my next obstacle is that perPage parameter only allows a maximum of 250 records returned for Detailed view.

Is there a way to retrieve more than 250 records?

If there is no way to retrieve more than 250 records, what is the best practices from here? I reviewed Ring Central Data Archival but because we don't have a database, I am not sure what to do. We have AWS S3 but currently it is not being used for company reporting. Should we set up an S3 bucket for this?

I am also not sure how often the API supposed to be called? Do I need to figure out on average how many coming through every hour and schedule the script to retrieve and append data every hour? What if there is an influx of incoming call and there are more than 250 calls during that certain hour?

Thank you in advance for any help or guidance you can provide!

You can use the pagination value to navigate thru the pages (which each page contains 250 records).

Here is an example how to read the account call log using the RingCentral JS SDK

async function read_account_calllog(){
var queryParams = {
dateFrom: "2023-11-01T16:42:12.577Z",
dateTo: "2023-11-05T16:42:12.577Z",
view: "Detailed",
perPage: 250
}
try {
var resp = await platform.get('/restapi/v1.0/account/~/call-log', queryParams)

var jsonObj = await resp.json()

for (var record of jsonObj.records){
// parse record and save it to your db
console.log(JSON.stringify(record))
console.log("======= ^^^^^ ========")
}
// Check if there are next pages
var navigationObj = jsonObj.navigation
if (navigationObj.hasOwnProperty("nextPage")){
read_calllog_nextpage(navigationObj.nextPage.uri)
}else{
console.log("no next page. Done")
}
}catch(e){
console.log(e.message)
}
}

async function read_calllog_nextpage(url){
try {
var resp = await platform.get(url)
var jsonObj = await resp.json()
for (var record of jsonObj.records){
// parse record and save it to your db
console.log(JSON.stringify(record))
console.log("======= ^^^^^ ========")
}
// Check if there are next pages
var navigationObj = jsonObj.navigation
if (navigationObj.hasOwnProperty("nextPage")){
read_calllog_nextpage(navigationObj.nextPage.uri)
}else{
console.log("no more next page. Done")
}
} catch (e){
console.log(e.message)
}
}

You can combine the 2 functions into one and handle the queryParams accordingly.


Do you have c# example for this code. special on this part.

 

    var resp = await platform.get(url)    var jsonObj = await resp.json()    for (var record of jsonObj.records){        // parse record and save it to your db        console.log(JSON.stringify(record))        console.log("======= ^^^^^ ========")    }

 

Thanks, Yihan


Do you have c# example for this code. special on this part.

 

    var resp = await platform.get(url)    var jsonObj = await resp.json()    for (var record of jsonObj.records){        // parse record and save it to your db        console.log(JSON.stringify(record))        console.log("======= ^^^^^ ========")    }

 

Thanks, Yihan

 

Here you are

static private async Task read_user_calllog()
{
try
{
var queryParams = new ReadUserCallLogParameters();
queryParams.dateFrom = "2024-01-01T00:00:00.000Z";
queryParams.dateTo = "2024-01-31T23:59:59.009Z";
queryParams.view = "Detailed";

var resp = await restClient.Restapi().Account().Extension().CallLog().List(queryParams);
foreach (CallLogRecord record in resp.records)
{
Console.WriteLine(JsonConvert.SerializeObject(record, Formatting.Indented));
}
}
catch (Exception ex)
{
Console.WriteLine("Cannot read user call log data. " + ex.Message);
}
}

 


Thank you, PhongVu!

 

I have questions for paging through all records after init API call, how do I use c# call the API with navigationObj.nextPage.uri 

// Check if there are next pages    var navigationObj = jsonObj.navigation    if (navigationObj.hasOwnProperty("nextPage")){      read_calllog_nextpage(navigationObj.nextPage.uri)    }else{        console.log("no next page. Done")    }

How do I make API call by navigationObj.nextPage.uri?

C# code for this part?

var resp = await platform.get(url)

var jsonObj = await resp.json()

for (

var record of jsonObj.records){ // parse record and save it to your db console.log(JSON.stringify(record)) console.log("======= ^^^^^ ========")

}

Thank you, Yihan


Thank you, PhongVu!

 

I have questions for paging through all records after init API call, how do I use c# call the API with navigationObj.nextPage.uri 

How do I make API call by navigationObj.nextPage.uri?

C# code for this part?

 

You can implement like this

static private async Task read_account_calllog(string page)
{
CallLogResponse resp = null;
if (page == "")
{
var parameters = new ReadCompanyCallLogParameters();
parameters.dateFrom = "2023-11-17T00:00:00.999Z";
parameters.view = "Detailed";
parameters.perPage = 250;
resp = await restClient.Restapi().Account().CallLog().List(parameters);
}
else
{
resp = await restClient.Get<CallLogResponse>(page);
}

// parse and do something with the response

if (resp.navigation.nextPage != null)
{
Console.WriteLine("Read the next page");
// Mind the API rate limit 10 requests per minute => cause some delay if there are more than 10 pages to read
await read_account_calllog(resp.navigation.nextPage.uri);
}
else
{
Console.WriteLine("No more page");
}
}

 


Thanks for help, PhongVu!!

I got runtime error when I make next page call by pass navigation.nextPage.uri

System.NullReferenceException: 'Object reference not set to an instance of an object.'
 

rcCallLogResponse = await rc.Get<CallLogResponse>(nextURL);

 

AnyIdea?

 

Here is my code.

CallLogResponse rcCallLogResponse = null;

            RestClient rc = new RestClient(
               Environment.GetEnvironmentVariable("RC_CLIENT_ID"),
               Environment.GetEnvironmentVariable("RC_CLIENT_SECRET"),
               Environment.GetEnvironmentVariable("RC_SERVER_URL")
           );

            if(nextURL == "")
            {
                // OPTIONAL QUERY PARAMETERS
                ReadCompanyCallLogParameters readCompanyCallLogParameters = new ReadCompanyCallLogParameters
                {

                    //page = nextIndex,
                    perPage = 500,
                    view = "Detailed",
                    type = voiceOnly,
                    dateFrom = fromDateTime
                };
                rc.Authorize(Environment.GetEnvironmentVariable("RC_JWT")).Wait();

                rcCallLogResponse = await rc.Restapi().Account(accountId).CallLog().List(readCompanyCallLogParameters);
            }
            else
            {
                rcCallLogResponse = await rc.Get<CallLogResponse>(nextURL);
            }

Do I need to get new Token for next page data call?

 rc.Authorize(Environment.GetEnvironmentVariable("RC_JWT")).Wait();

 

Thanks, Yihan


I don’t see your entire function so I don’t really know how to actually implemented and call the function.

Follow this getting started sample code and add the extra code to read next page accordingly. Remember that the getting started sample code shows how to read a user call log. The code I shared above shows how to read account call log. Modify them accordingly as what you want to read. No need to set the .Account(accountId)…

https://developers.ringcentral.com/guide/voice/call-log/quick-start#c#


Thank you so much for your help! I added token refresh event for next page API call. It is working.

Here is my function:


       

 private static async Task ReadCallLogNextPage(string nextURL)
        {

            // https://developers.ringcentral.com/my-account.html#/applications
            // Find your credentials at the above url, set them as environment variables, or enter them below

            // PATH PARAMETERS
            string accountId = "xxxxxxxxx";

            //start time
            var fromDateTime = DateTime.Now.ToString("yyyy-MM-dd") + "T00:00:00.000Z";

            string0] voiceOnly = new String>1];
            voiceOnlyc0] = "Voice";

            CallLogResponse rcCallLogResponse = null;


            RestClient rc = new RestClient(
               Environment.GetEnvironmentVariable("RC_CLIENT_ID"),
               Environment.GetEnvironmentVariable("RC_CLIENT_SECRET"),
               Environment.GetEnvironmentVariable("RC_SERVER_URL")
           );
            rc.Authorize(Environment.GetEnvironmentVariable("RC_JWT")).Wait();

            if (nextURL == "")
            {
                // OPTIONAL QUERY PARAMETERS
                ReadCompanyCallLogParameters readCompanyCallLogParameters = new ReadCompanyCallLogParameters
                {
                    perPage = 500,
                    view = "Detailed",
                    type = voiceOnly,
                    dateFrom = fromDateTime
                };
                

                rcCallLogResponse = await rc.Restapi().Account(accountId).CallLog().List(readCompanyCallLogParameters);
            }
            else
            {
                rcCallLogResponse = await rc.Get<CallLogResponse>(nextURL);
            }
           

            if (rcCallLogResponse != null)
            {
                // insert RingCentralCallLogs
                foreach (var item in rcCallLogResponse.records)
                {
                    RingCentralCallLog insertRCLog = new RingCentralCallLog()
                    {
                        // add ringcentral call logs

                    //insert call legs if RingCentralCallLog session id is not in table which means new record just added.
                    if (returnRCLog == null)
                    {
                        Console.WriteLine("insert new ringcentral call:" + "ID: " + insertRCLog.id + " NewCallLog exist? " + returnRCLog);

                        foreach (var rcLogLeg in item.legs)
                        {
                            //add legs
                        }
                    }
                }

                // Check if there are next pages
                var navigation = rcCallLogResponse.navigation;
                if (navigation != null)
                {
                    if (navigation.nextPage != null)
                    {
                        Console.WriteLine("next Page -------- " + navigation.nextPage.uri);

                        //call ReadCallLogNextPage again if CallLogResponse has next page
                        await ReadCallLogNextPage(navigation.nextPage.uri);                       
                    }
                    else
                    {
                        Console.WriteLine("no next page. Done");
                    }
                }
            }

        }

 


Don’t call the authorize() function every time you call that function. Do exactly as the getting started sample code shows. Otherwise, you will hit the API rate limit and your app will stop working.


Got it. Thank you for great support!!


Reply