Voip.ms getCDR API – get all call detail records

Voip.ms is a reliable, affordable and customizable VoIP service.

Recently I wanted to get all of my Voip.ms telephone number call detail records (CDR). Voip.ms provides a nice UI to manually view these but I had 100’s of records that I wanted to analyse. So I turned to the Voip.ms REST/JSON API which turned out to be very easy to work with (link to API docs).

The API has a getCDR endpoint. To get started I downloaded one of the provided PHP examples (a link near the top of API documentation page downloads a zip file with code examples) that made it easy to quickly understand the endpoint’s requirements to get all of my telephone number’s call detail records. The API documentation page also includes list of endpoint parameters and response values for each endpoint.

The API requires that you enable the API before you can use it and to register the IP address(es) making the calls.

The API getCDR endpoint also limits the response to only 90 records per API call. This only required creating a loop through a date range starting with the date of my first CDR to current date getting 90 day’s CDR per call.

Each of the 90 day’s responses were appended into a dataset that was exported to a csv file.

Code is provided below. Note that the password used is not your Voip.ms account password but another API password you create in their API management form at the top of the API docs page.

Aside from the getCDR endpoint, VoIP.ms API has over 100 functions to help you integrate our services into your website.


    $user = "username";
    $pass = "api_password";  /* API pw diff from account pw */

    $currentDate = new DateTime(date("Y-m-d"));
    $startDate = new DateTime('2019-08-08');
    $endDate = clone $startDate;
    $endDate->modify('+90 days');
    $cdr = []; // Array to hold all records
    $filename = "path\\to\\your\\folder\\" . $currentDate->format('Y-m-d') . "-api-getcdr_response-data.csv"; // Specify your desired path and filename
    // Check if the file exists
    if (file_exists($filename)) {
        // Delete the existing file
    $handle = fopen($filename, 'w'); // Open file for writing
    while ($startDate < $currentDate) {
        // Set startDate to be the day after the last endDate
        $startDate = clone $endDate;
        $startDate->modify('+1 day');
        $endDate->modify('+90 days');
        // Check if the end date exceeds the current date
        if ($endDate >= $currentDate) {
            $endDate = clone $currentDate;
        // Fetch records
        $records = fetchRecords($startDate->format('Y-m-d'), $endDate->format('Y-m-d'));
        $cdr = array_merge($cdr, $records);
        echo $startDate->format('Y-m-d') . ", " . $endDate->format('Y-m-d') . ", " . $currentDate->format('Y-m-d') . "\n";
        // If endDate is the current date, break the loop
        if ($endDate == $currentDate) {
    function fetchRecords($from, $to) {
        global $user, $pass;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
        curl_setopt($ch, CURLOPT_URL, "https://voip.ms/api/v1/rest.php?api_username={$user}&api_password={$pass}&method=getCDR&date_from={$from}&date_to={$to}&answered=1&timezone=-5");
        $result = curl_exec($ch);
        if($response['status'] != 'success'){
            echo $response['status'];
            return [];
        return $response['cdr'];
    fputcsv($handle, array('Date', 'Caller ID', 'Destination', 'Description', 'Account', 'Disposition', 'Duration', 'Seconds', 'Rate', 'Total', 'Unique ID', 'Destination Type'));
    foreach ($cdr as $row) {
        fputcsv($handle, array(


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.