Legacy Dev Forum Posts

 View Only

Sign Up

Error Download Recording File Using API

  • 1.  Error Download Recording File Using API

    Posted 06-05-2025 18:05

    Husein | 2019-11-06 14:42:24 UTC | #1

    Dear All

    We have follow this document => https://developer.mypurecloud.com/api/tutorials/recordings-downloader/index.html?language=csharp&step=1

    to download recording file from purecloud, And get this error in this step conversationsApi.PostAnalyticsConversationsDetailsQuery(new ConversationQuery(Interval: myinterval));

    Error => Message=Error calling PostAnalyticsConversationsDetailsQuery: The specified value is not a valid Host header string.

    We update this myinterval with = @"2019-10-29T01:00:00/2019-10-29T23:00:00"; Please advise

    Below the script that we use

    using PureCloudPlatform.Client.V2.Api; using PureCloudPlatform.Client.V2.Client; using PureCloudPlatform.Client.V2.Extensions; using PureCloudPlatform.Client.V2.Model; using PureCloudPlatform.Client.V2; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks;

    namespace Recordings { class Program { static void Main(string[] args) { Console.Write("Enter Client ID: "); //string clientId = Console.ReadLine(); string clientId = "ae930735-f5fc-43b4-835a-f622c2fc4146"; Console.Write("Enter Client Secret: "); //string clientSecret = Console.ReadLine(); string clientSecret = "W8gONrOy1yEss67Tu4wjD_p4nMz5ah4-3EwTISxWLlM";

    // Get the Date Interval Console.Write("Enter Date Interval (YYYY-MM-DDThh:mm:ss/YYYY-MM-DDThh:mm:ss): "); //string interval = Console.ReadLine(); string myinterval = @"2019-10-29T01:00:00.000Z/2019-10-29T23:00:00.000Z";

    Console.WriteLine("Working...");

    // Configure SDK Settings string accessToken = GetToken(clientId, clientSecret); PureCloudPlatform.Client.V2.Client.Configuration.Default.AccessToken = accessToken;

    // Instantiate APIs ConversationsApi conversationsApi = new ConversationsApi();

    // Create folder that will store all the downloaded recordings string path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); path = path.Substring(0, path.LastIndexOf("bin")); path = path + "\\Recordings"; System.IO.Directory.CreateDirectory(path + "\\Recordings");

    // Call conversation API, pass date inputted to extract conversationIds needed //conversationsApi.Configuration.Username = ""; //conversationsApi.Configuration.Password = ""; //conversationsApi.Configuration.UserAgent = ""; conversationsApi.Configuration.TempFolderPath = path; var query = new ConversationQuery(); query.Interval = myinterval; query.Order = ConversationQuery.OrderEnum.Asc; query.Paging = new PagingSpec(25, 1); var api = new AnalyticsApi(); conversationsApi.Configuration.AddDefaultHeader("Content-Type", "application/json"); conversationsApi.Configuration.AddDefaultHeader("Host", "https://api.mypurecloud.com.au"); AnalyticsConversationQueryResponse resp= api.PostAnalyticsConversationsDetailsQuery(query); //conversationsApi.Configuration.AddDefaultHeader() AnalyticsConversationQueryResponse conversationDetails = conversationsApi.PostAnalyticsConversationsDetailsQuery(query); // Pass conversation details to function //extractConversationDetails(conversationDetails);

    // Final Output Console.WriteLine("DONE");

    if (Debugger.IsAttached) { Console.ReadKey(); } }

    /// <summary> /// Format conversation details to object inside and array. Get every mediatype per conversation /// </summary> /// <param name="conversationDetails"></param> /// <returns></returns> private static void extractConversationDetails(AnalyticsConversationQueryResponse conversationDetails) { // Push all conversationId from conversationDetails to conversationIds foreach (var conversationDetail in conversationDetails.Conversations) { getRecordingMetaData(conversationDetail.ConversationId); } }

    /// <summary> /// Generate recordingId for every conversationId /// </summary> /// <param name="conversationId"></param> /// <returns></returns> private static void getRecordingMetaData(string conversationId) { RecordingApi recordingApi = new RecordingApi(); List<Recording> recordingsData = recordingApi.GetConversationRecordingmetadata(conversationId);

    // Pass recordingsMetadata to a function iterateRecordingsData(recordingsData); }

    /// <summary> /// Iterate through every result, check if there are one or more recordingIds in every conversation /// </summary> /// <param name="recordingsData"></param> /// <returns></returns> private static void iterateRecordingsData(List<Recording> recordingsData) { foreach (var iterateRecordings in recordingsData) { getSpecificRecordings(iterateRecordings); } }

    /// <summary> /// Plot conversationId and recordingId to request for batchDownload Recordings /// </summary> /// <param name="iterateRecordings"></param> /// <returns></returns> private static void getSpecificRecordings(Recording iterateRecordings) { List<BatchDownloadRequest> batchRequest = new List<BatchDownloadRequest>(); BatchDownloadRequest batchDownloadRequest = new BatchDownloadRequest(ConversationId: iterateRecordings.ConversationId, RecordingId: iterateRecordings.Id); batchRequest.Add(batchDownloadRequest);

    // Create the batch job with the request list BatchDownloadJobSubmission batchSubmission = new BatchDownloadJobSubmission(BatchDownloadRequestList: batchRequest);

    BatchDownloadJobSubmissionResult recordingBatchRequestId = new BatchDownloadJobSubmissionResult(); RecordingApi recordingApi = new RecordingApi(); recordingBatchRequestId = recordingApi.PostRecordingBatchrequests(batchSubmission);

    recordingStatus(recordingBatchRequestId); }

    /// <summary> /// Check status of generating url for downloading, if the result is still unavailble. The function will be called again until the result is available. /// </summary> /// <param name="recordingBatchRequestId"></param> /// <returns></returns> private static void recordingStatus(BatchDownloadJobSubmissionResult recordingBatchRequestId) { BatchDownloadJobStatusResult getRecordingBatchRequestData = new BatchDownloadJobStatusResult(); RecordingApi recordingApi = new RecordingApi(); getRecordingBatchRequestData = recordingApi.GetRecordingBatchrequest(recordingBatchRequestId.Id);

    if (getRecordingBatchRequestData.ExpectedResultCount == getRecordingBatchRequestData.ResultCount) { // Pass the getRecordingBatchRequestData to getExtension function getExtension(getRecordingBatchRequestData); } else { Thread.Sleep(5000); recordingStatus(recordingBatchRequestId); } }

    /// <summary> /// Get extension of every recordings /// </summary> /// <param name="getRecordingBatchRequestData"></param> /// <returns></returns> private static void getExtension(BatchDownloadJobStatusResult getRecordingBatchRequestData) { // Store the contentType to a variable that will be used later to determine the extension of recordings. string contentType = getRecordingBatchRequestData.Results[0].ContentType; // Split the text and gets the extension that will be used for the recording string ext = contentType.Split('/').Last();

    createDirectory(ext, getRecordingBatchRequestData); }

    /// <summary> /// Generate directory for recordings that will be downloaded /// </summary> /// <param name="ext"></param> /// <param name="getRecordingBatchRequestData"></param> /// <returns></returns> private static void createDirectory(string ext, BatchDownloadJobStatusResult getRecordingBatchRequestData) { Console.WriteLine("Processing please wait...");

    string conversationId = getRecordingBatchRequestData.Results[0].ConversationId; string recordingId = getRecordingBatchRequestData.Results[0].RecordingId; string url = getRecordingBatchRequestData.Results[0].ResultUrl;

    string path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); path = path.Substring(0, path.LastIndexOf("bin")); System.IO.Directory.CreateDirectory(path + "\\Recordings\\" + conversationId + "_" + recordingId);

    downloadRecording(url, ext, path + "\\Recordings\\" + conversationId + "_" + recordingId); }

    /// <summary> /// Download recordings /// </summary> /// <param name="url"></param> /// <param name="ext"></param> /// <param name="targetDirectory"></param> /// <returns></returns> private static void downloadRecording(string url, string ext, string targetDirectory) { // string downloadFile = conversationId + '_' + recordingId + '.' + ext; string filename = targetDirectory.Substring(targetDirectory.LastIndexOf('\\') + 1, 73);

    using (WebClient wc = new WebClient()) wc.DownloadFile(url, targetDirectory + "\\" + filename + "." + ext); }

    /// <summary> /// Request client credentials token from PureCloud /// </summary> /// <param name="clientId"></param> /// <param name="clientSecret"></param> /// <returns></returns> private static string GetToken(string clientId, string clientSecret) { Configuration.Default.ApiClient.RestClient.BaseHost = "https://api.mypurecloud.com.au"; Uri myUri = new Uri("https://api.mypurecloud.com.au", UriKind.Absolute); Configuration.Default.ApiClient.RestClient.BaseUrl = myUri;

    var accessTokenInfo = Configuration.Default.ApiClient.PostToken(clientId, clientSecret, "api.mypurecloud.com.au");

    string token = accessTokenInfo.AccessToken;

    return token; } } }


    tim.smith | 2019-11-06 15:10:32 UTC | #2

    Husein, post:1, topic:6426
    conversationsApi.Configuration.AddDefaultHeader("Host", "https://api.mypurecloud.com.au");

    I'm guessing the error is caused by that. You definitely shouldn't be setting the host header and generally shouldn't be manually setting any headers at all (including content-type). If you're trying to set the environment for the SDK, you should use the documented method: https://developer.mypurecloud.com/api/rest/client-libraries/dotnet/index.html#setting_the_environment


    fahmi | 2019-11-07 01:27:35 UTC | #3

    Hi Smith,

    I am Husein Team. I just want to make it clear, the header that I added because we get some error "The specified value is not a valid Host header string." that's why I added the header but the result is the same. Please advice to solve error "The specified value is not a valid Host header string." on that codes.

    besides that I set the interval string as "2019-10-29T01:00:00.000Z/2019-10-29T23:00:00.000Z" this is the valid format ?

    Thanks,

    Fahmi.


    tim.smith | 2019-11-07 16:01:15 UTC | #4

    Please remove the custom headers and try setting the environment and obtaining an auth token using the documented methods. The code above isn't doing either of those things correctly.


    tim.smith | 2019-11-07 16:02:18 UTC | #5

    fahmi, post:3, topic:6426
    besides that I set the interval string as "2019-10-29T01:00:00.000Z/2019-10-29T23:00:00.000Z" this is the valid format ?

    Looks right at a glance, but you should validate your query using the Analytics Query Builder https://developer.mypurecloud.com/developer-tools/#/analytics-query-builder


    Husein | 2019-11-12 08:57:39 UTC | #6

    Hi Smith

    Now we can download the recording file,

    Thanks

    Husein


    system | 2019-12-13 09:10:44 UTC | #7

    This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.


    This post was migrated from the old Developer Forum.

    ref: 6426