V 2.0
Call Report
Introduction
This document provides comprehensive information about the Call Report API endpoints. These endpoints allow retrieving, filtering, and exporting call log reports in various formats (CSV, Excel, PDF). The API supports advanced filtering capabilities including date ranges, agent filtering, duration filters, call types, and custom call analysis fields.
Base URL
The base URL for this API endpoint is: v4-api.deepcall.com/api/v2/callreport
Authentication
Authentication is required for all endpoints. It can be done in two ways:
- Using
ssid(Session ID) - Using
userIdandtoken
Note: When userId and token are used, ssid should not be present in the request.
Common Error Codes
These error codes can be returned by any endpoint in this API. Endpoint-specific errors are documented in their respective sections.
Authentication & Authorization Errors
| Error Code | Error Message | Description | Solution |
|---|---|---|---|
| 1000 | Invalid parameters | Request validation failed or authentication invalid | Check all required parameters are provided |
| 1014 | Invalid token | Authentication token is expired or invalid | Generate a new token or use valid ssid |
| 1015 | Permission denied | User does not have LIST_CALL_LOG permission | Contact admin to grant required permissions |
| 1047 | Invalid Request Data | Request body is empty or malformed | Ensure request body is valid JSON |
System Errors
| Error Code | Error Message | Description | Solution |
|---|---|---|---|
| 1009 | Something went wrong | Unexpected server error occurred | Retry the request or contact support |
| 1010 | Error in DB connect | Database connection is not available | Check system status or retry after some time |
Common Error Response Format
All error responses follow this structure:
{
"status": "error",
"message": "Error description here",
"code": 1000
}
PDF Downlaod
Endpoint
- Method: POST
-
Path:
v4-api.deepcall.com/api/v2/callreport/downloadPdf
Description
The Download PDF endpoint downloads a previously generated PDF report. This endpoint is used to retrieve the actual PDF file after creating an export request. You need to provide the requestId that was returned when the export request was created. The endpoint downloads the PDF file directly from cloud storage and returns the file data as a binary stream.
Use Cases
- Downloading PDF files generated from export requests
- Generating printable call reports
- Creating professional reports for management
- Call documentation for compliance
- Sharing formatted reports with clients
- Archival and record-keeping
- Invoice and billing documentation
- Audit trail documentation
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes* | User ID for authentication (*required if ssid not provided) |
| token | string | Yes* | Authentication token (*required if ssid not provided) |
| ssid | string | Yes* | Session ID (*required if userId/token not provided) |
| requestId | string | Yes | Request ID from export request response |
Important Notes
-
Authentication: Either
ssidOR (userId+token) must be provided -
Permission Required:
LIST_CALL_LOGpermission required -
Request ID Required: The
requestIdmust be obtained from the export request endpoint response - File Storage: PDF files are stored in cloud storage (S3/MinIO)
- File Status: The export request must be in "completed" status before downloading
- Direct Download: The file is streamed directly to the client as binary data
- Wait Time: If the export was just created, wait a few seconds before attempting download
Request Examples
Example 1: Download PDF Report with Session ID
Endpoint: POST v4-api.deepcall.com/api/v2/callreport/downloadPdf
{
"ssid": "{{ssid}}",
"requestId": "{{objectid}}"
}
Description: Downloads a PDF report using session ID authentication. The requestId should be obtained from a previous export request.
Example 2: Download PDF with Token Authentication
Endpoint: POST v4-api.deepcall.com/api/v2/callreport/downloadPdf
{
"userId": "{{userid}}",
"token": "{{token}}",
"requestId": "{{objectid}}"
}
Description: Downloads a PDF report using userId and token authentication. This is useful for API integrations where token-based auth is preferred.
Example 3: Download PDF for Different Request
Endpoint: POST v4-api.deepcall.com/api/v2/callreport/downloadPdf
{
"ssid": "{{ssid}}",
"requestId": "{{objectid}}"
}
Description: Downloads a different PDF report by providing a different request ID. Each request ID corresponds to a unique export job.
Response Details
Success Response
Status Code: 200
Content-Type: application/pdf
The response contains the PDF file data as a binary stream for direct download. The file will be downloaded directly to the client.
Response Format: Binary file stream containing the PDF data.
Example Response Headers:
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="call_report.pdf"
Content-Length: [file size in bytes]
The PDF file will automatically download when the request is successful.
Error Handling
Error Response Examples
Error 1: Invalid Request ID
Status Code: 200
{
"status": "error",
"message": "Invalid parameter",
"code": 1000
}
When This Occurs: Request ID is not provided or is invalid/malformed.
Solution: Ensure the requestId parameter is included and contains a valid request ID from a previous export request.
Error 2: File Not Found
Status Code: 200
{
"status": "error",
"message": "File Not Exists",
"code": 1009
}
When This Occurs: The PDF file does not exist in storage or the request ID is incorrect.
Solution:
- Verify the request ID is correct
- Check if the export request has completed processing
- Ensure the file hasn't been deleted from storage
- Try regenerating the export request
Error 3: Permission Denied
Status Code: 200
{
"status": "error",
"message": "Permission denied",
"code": 1015
}
When This Occurs: User does not have the required LIST_CALL_LOG permission.
Solution: Contact your system administrator to grant the necessary permissions.
Error 4: Invalid Token
Status Code: 200
{
"status": "error",
"message": "Invalid token",
"code": 1014
}
When This Occurs: Authentication token is expired or invalid.
Solution: Generate a new authentication token or use a valid session ID.
Error 5: Invalid Request Data
Status Code: 200
{
"status": "error",
"message": "Invalid Request Data",
"code": 1047
}
When This Occurs: Request body is empty or malformed JSON.
Solution: Ensure the request body is valid JSON with all required parameters.
Error 6: Internal Server Error
Status Code: 200
{
"status": "error",
"message": "Something went wrong",
"code": 1009
}
When This Occurs: Unexpected server error occurred during file retrieval.
Solution: Retry the request. If the problem persists, contact support.
PDF Downlaod
var axios = require('axios');
var data = '{"ssid": "{{ssid}}","requestId": "{{objectid}}"}';
var config = {
method: 'post',
url: 'https://{{brand}}/api/v2/CallReport/downloadPdf',
headers: {
'Content-Length': ''
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
setUrl('https://{{brand}}/api/v2/CallReport/downloadPdf');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Length' => ''
));
$request->setBody('{"ssid": "{{ssid}}","requestId": "{{objectid}}"}');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}import http.client
conn = http.client.HTTPSConnection("{{brand}}")
payload = "{\"ssid\": \"{{ssid}}\",\"requestId\": \"{{objectid}}\"}"
headers = {
'Content-Length': ''
}
conn.request("POST", "/api/v2/CallReport/downloadPdf", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))var client = new RestClient("https://{{brand}}/api/v2/CallReport/downloadPdf");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
var body = @"{" + "\n" +
@" ""ssid"": ""{{ssid}}""," + "\n" +
@" ""requestId"": ""{{objectid}}""" + "\n" +
@"}";
request.AddParameter("text/plain", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);curl --location -g --request POST 'https://{{brand}}/api/v2/CallReport/downloadPdf' \
--data-raw '{
"ssid": "{{ssid}}",
"requestId": "{{objectid}}"
}'var request = http.Request('POST', Uri.parse('https://{{brand}}/api/v2/CallReport/downloadPdf'));
request.body = '''{\n "ssid": "{{ssid}}",\n "requestId": "{{objectid}}"\n}''';
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://%7B%7Bbrand%7D%7D/api/v2/CallReport/downloadPdf"
method := "POST"
payload := strings.NewReader(`{
"ssid": "{{ssid}}",
"requestId": "{{objectid}}"
}`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}POST /api/v2/CallReport/downloadPdf HTTP/1.1
Host: {{brand}}
Content-Length: 55
{
"ssid": "{{ssid}}",
"requestId": "{{objectid}}"
}OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "{\n \"ssid\": \"{{ssid}}\",\n \"requestId\": \"{{objectid}}\"\n}");
Request request = new Request.Builder()
.url("https://{{brand}}/api/v2/CallReport/downloadPdf")
.method("POST", body)
.addHeader("Content-Length", "")
.build();
Response response = client.newCall(request).execute();var myHeaders = new Headers();
myHeaders.append("Content-Length", "");
var raw = "{\n \"ssid\": \"{{ssid}}\",\n \"requestId\": \"{{objectid}}\"\n}";
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://{{brand}}/api/v2/CallReport/downloadPdf", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "https://%7B%7Bbrand%7D%7D/api/v2/CallReport/downloadPdf");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Length: ");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
const char *data = "{\n \"ssid\": \"{{ssid}}\",\n \"requestId\": \"{{objectid}}\"\n}";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
res = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
#import
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://%7B%7Bbrand%7D%7D/api/v2/CallReport/downloadPdf"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
NSDictionary *headers = @{
@"Content-Length": @""
};
[request setAllHTTPHeaderFields:headers];
NSData *postData = [[NSData alloc] initWithData:[@"{\n \"ssid\": \"{{ssid}}\",\n \"requestId\": \"{{objectid}}\"\n}" dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:postData];
[request setHTTPMethod:@"POST"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"%@", error);
dispatch_semaphore_signal(sema);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSError *parseError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(@"%@",responseDictionary);
dispatch_semaphore_signal(sema);
}
}];
[dataTask resume];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); open Lwt
open Cohttp
open Cohttp_lwt_unix
let postData = ref "{\n \"ssid\": \"{{ssid}}\",\n \"requestId\": \"{{objectid}}\"\n}";;
let reqBody =
let uri = Uri.of_string "https://%7B%7Bbrand%7D%7D/api/v2/CallReport/downloadPdf" in
let headers = Header.init ()
|> fun h -> Header.add h "Content-Length" ""
in
let body = Cohttp_lwt.Body.of_string !postData in
Client.call ~headers ~body `POST uri >>= fun (_resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body -> body
let () =
let respBody = Lwt_main.run reqBody in
print_endline (respBody)$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Length", "")
$body = "{`n `"ssid`": `"{{ssid}}`",`n `"requestId`": `"{{objectid}}`"`n}"
$response = Invoke-RestMethod 'https://{{brand}}/api/v2/CallReport/downloadPdf' -Method 'POST' -Headers $headers -Body $body
$response | ConvertTo-Jsonrequire "uri"
require "net/http"
url = URI("https://{{brand}}/api/v2/CallReport/downloadPdf")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Length"] = ""
request.body = "{\n \"ssid\": \"{{ssid}}\",\n \"requestId\": \"{{objectid}}\"\n}"
response = https.request(request)
puts response.read_body
printf '{
"ssid": "{{ssid}}",
"requestId": "{{objectid}}"
}'| http --follow --timeout 3600 POST 'https://{{brand}}/api/v2/CallReport/downloadPdf' \
Content-Length:import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
var semaphore = DispatchSemaphore (value: 0)
let parameters = "{\n \"ssid\": \"{{ssid}}\",\n \"requestId\": \"{{objectid}}\"\n}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://{{brand}}/api/v2/CallReport/downloadPdf")!,timeoutInterval: Double.infinity)
request.addValue("", forHTTPHeaderField: "Content-Length")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
Example Response
[{"key":"Date"
"value":"Sun
23 Nov 2025 11:29:40 GMT"}
{"key":"Content-Type"
"value":"application\/json; charset=utf-8"}
{"key":"Content-Length"
"value":"58"}
{"key":"Connection"
"value":"keep-alive"}
{"key":"Access-Control-Allow-Origin"
"value":"*"}
{"key":"Access-Control-Allow-Methods"
"value":"GET
PUT
POST
DELETE
OPTIONS"}
{"key":"Access-Control-Allow-Headers"
"value":"session-token
Authorization
Origin
Accept
Content-Type
DNT
Authorization
Keep-Alive
User-Agent
X-Requested-With
If-Modified-Since
Cache-Control
Content-Type
Content-Range
Range"}
{"key":"Access-Control-Allow-Credentials"
"value":"true"}
{"key":"Vary"
"value":"Origin"}
{"key":"ETag"
"value":"W\/\"3a-Hk3L\/tap5L1EXKsavffpKR6hbuU\""}
{"key":"Strict-Transport-Security"
"value":"max-age=15724800; includeSubDomains"}
{"key":"Access-Control-Max-Age"
"value":"1728000"}]
{
"status": "error",
"message": "File Not Exists",
"code": 1009
}