Samuel_Polgar | 2019-05-19 01:03:17 UTC | #1
Dear PureCloud developers
The performance views offer a great overview for reporting. I was wondering if it is possible, or considered, to be able to download these views from the API's?
This would give us the ability to automate this style of report.
tim.smith | 2019-05-20 14:01:38 UTC | #2
The Analytics APIs have endpoints for managing report schedules and exports.
Samuel_Polgar | 2019-05-20 22:45:39 UTC | #3
Hello Tim
Thank you very much for your response and guidance.
From an API work flow, would we create the export using POST /api/v2/analytics/reporting/exports and then use an account with credentials to download the most recent report from the GET /api/v2/analytics/reporting/exports?
I have been using the following settings to generate an export report and receiving a 400 error - The request could not be understood by the server due to malformed syntax.
Please may I ask for help to troubleshoot?
{ "name": "Test Export", "timeZone": { "displayName": "", "id": "Australia/Sydney", "dstsavings": 0, "rawOffset": 600 }, "exportFormat": "CSV", "interval": "2019-03-31T13:00:00.000Z/2019-04-29T14:00:00.000Z", "period": "P1M", "viewType": "QUEUEPERFORMANCESUMMARY_VIEW", "filter": { "mediaTypes": ["voice"], "queueIds": ["e37eda8d-aeab-44cb-b13d-f6282dxxxx"], "skillIds": [], "skillGroups": [], "languageIds": [], "languageGroups": [], "directions": [], "originatingDirections": [], "wrapUpCodes": [], "dnisList": [], "sessionDnisList": [], "filterQueuesByUserIds": [], "filterUsersByQueueIds": [], "userIds": [], "addressTos": [], "addressFroms": [], "outboundCampaignIds": [], "outboundContactListIds": [], "contactIds": [], "aniList": [], "durationsMilliseconds": [ { "gt": {}, "gte": {}, "lt": {}, "lte": {} } ], "evaluationScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "evaluationCriticalScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "evaluationFormIds": [], "evaluatedAgentIds": [], "evaluatorIds": [], "transferred": true, "abandoned": true, "messageTypes": [], "divisionIds": [], "surveyFormIds": [], "surveyTotalScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyNpsScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "showSecondaryStatus": true, "agentDurationSortOrder": "", "waitingDurationSortOrder": "", "interactingDurationSortOrder": "", "agentName": "", "skillsList": [], "languageList": [], "mos": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyQuestionGroupScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyPromoterScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyFormContextIds": [], "conversationIds": [], "sipCallIds": [], "isEnded": true, "isSurveyed": true, "surveyScores": [ { "gt": {}, "gte": {}, "lt": {}, "lte": {} } ], "promoterScores": [ { "gt": {}, "gte": {}, "lt": {}, "lte": {} } ], "isCampaign": true, "surveyStatuses": [], "conversationProperties": { "isWaiting": true, "isActive": true, "isAcd": true, "isScreenshare": true, "isCobrowse": true, "isVoicemail": true, "isFlagged": true, "filterWrapUpNotes": true, "matchAll": true }, "isBlindTransferred": true, "isConsulted": true, "isConsultTransferred": true, "remoteParticipants": [], "statusList": [], "flowIds": [], "flowOutcomeIds": [], "flowOutcomeValues": [], "flowDestinationTypes": [], "flowDisconnectReasons": [], "flowTypes": [], "flowEntryTypes": [], "flowEntryReasons": [], "flowVersions": [], "groupIds": [], "hasJourneyCustomerId": true, "hasJourneyActionMapId": true, "hasJourneyVisitId": true }, "read": true, "locale": "en-us" }
tim.smith | 2019-05-21 13:40:32 UTC | #4
Generally, the error response body will provide an error message about what's wrong with your request. Can you share the error body and the correlation ID from the response?
Samuel_Polgar | 2019-05-21 21:08:56 UTC | #5
Hello Tim
Once again, thank you very much for your help.
Please kindly find the response and correlation ID below:
{ "status": 400, "code": "bad.request", "message": "The request could not be understood by the server due to malformed syntax.", "contextId": "ad48654c-2edd-4bd8-b764-c7c22b6a8e51", "details": [], "errors": [] }
tim.smith | 2019-05-21 21:49:16 UTC | #6
It looks like the API docs aren't generating correctly for that field. The API expects a simple string like this: timeZone: "Australia/Sydney". I'll open an issue to get the docs corrected.
Samuel_Polgar | 2019-05-21 22:18:26 UTC | #7
Hello Tim
Thank you very much for your help.
I used the below body and received the error message, would it be possible to ask for your help to check the body format for any issues please?
{ "name": "Test Export", "timeZone": "Australia/Sydney", "exportFormat": "CSV", "interval": "2019-03-31T13:00:00.000Z/2019-04-29T14:00:00.000Z", "period": "P1D", "viewType": "QUEUEPERFORMANCESUMMARY_VIEW", "filter": { "mediaTypes": ["voice"], "queueIds": ["e37eda8d-aeab-44cb-b13d-f6282d56xxxxx"], "skillIds": [], "skillGroups": [], "languageIds": [], "languageGroups": [], "directions": [], "originatingDirections": [], "wrapUpCodes": [], "dnisList": [], "sessionDnisList": [], "filterQueuesByUserIds": [], "filterUsersByQueueIds": [], "userIds": [], "addressTos": [], "addressFroms": [], "outboundCampaignIds": [], "outboundContactListIds": [], "contactIds": [], "aniList": [], "durationsMilliseconds": [ { "gt": {}, "gte": {}, "lt": {}, "lte": {} } ], "evaluationScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "evaluationCriticalScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "evaluationFormIds": [], "evaluatedAgentIds": [], "evaluatorIds": [], "transferred": true, "abandoned": true, "messageTypes": [], "divisionIds": [], "surveyFormIds": [], "surveyTotalScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyNpsScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "showSecondaryStatus": true, "agentDurationSortOrder": "", "waitingDurationSortOrder": "", "interactingDurationSortOrder": "", "agentName": "", "skillsList": [], "languageList": [], "mos": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyQuestionGroupScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyPromoterScore": { "gt": {}, "gte": {}, "lt": {}, "lte": {} }, "surveyFormContextIds": [], "conversationIds": [], "sipCallIds": [], "isEnded": true, "isSurveyed": true, "surveyScores": [ { "gt": {}, "gte": {}, "lt": {}, "lte": {} } ], "promoterScores": [ { "gt": {}, "gte": {}, "lt": {}, "lte": {} } ], "isCampaign": true, "surveyStatuses": [], "conversationProperties": { "isWaiting": true, "isActive": true, "isAcd": true, "isScreenshare": true, "isCobrowse": true, "isVoicemail": true, "isFlagged": true, "filterWrapUpNotes": true, "matchAll": true }, "isBlindTransferred": true, "isConsulted": true, "isConsultTransferred": true, "remoteParticipants": [], "statusList": [], "flowIds": [], "flowOutcomeIds": [], "flowOutcomeValues": [], "flowDestinationTypes": [], "flowDisconnectReasons": [], "flowTypes": [], "flowEntryTypes": [], "flowEntryReasons": [], "flowVersions": [], "groupIds": [], "hasJourneyCustomerId": true, "hasJourneyActionMapId": true, "hasJourneyVisitId": true }, "read": true, "locale": "en-us" }
{ "status": 400, "code": "bad.request", "message": "The request could not be understood by the server due to malformed syntax.", "contextId": "8b8f3c7b-04cb-4e71-8b56-8f142894b8f9", "details": [], "errors": [] }
tim.smith | 2019-05-22 15:33:25 UTC | #8
I can't tell exactly what property is causing the error, but the error in the backend is JsonMappingException: Can not deserialize instance of java.math.BigDecimal out of START_OBJECT token. That means there's a property that's expecting a decimal value, but has a JSON object value ({...}).
I took a look at what the UI sends when exporting a view by inspecting the developer console in the browser. I'd guess that cutting out the empty stuff in your request will probably avoid the issue. Here's what I spied:
{
"name": "2019-05-22 Queue Performance Summary",
"viewType": "QUEUE_PERFORMANCE_SUMMARY_VIEW",
"timeZone": "America/Denver",
"exportFormat": "CSV",
"interval": "2019-05-22T06:00:00.000Z/2019-05-23T06:00:00.000Z",
"locale": "en-us",
"filter": {
"mediaTypes": [
"voice"
]
}
}
Samuel_Polgar | 2019-05-22 18:41:34 UTC | #9
Hello Tim
Great! That's working, thank you very much for your help.
One last thing please, to download this report would I use the Client Credentials Grant from the javascript SDK to call the GET /api/v2/analytics/reporting/exports and find the "downloadUrl": https://public-api-v2.ap-southeast-2.mypurecloud.com.au/api/v2/downloads/7f433ff4 and the authentication would be taken care of?
Thank you very much for your help!
tim.smith | 2019-05-22 20:40:38 UTC | #10
When you make the request to that URL to download the file, include the same authorization header you included on the previous API request. The response should redirect you to an AWS file resource with an AWS access token in the query string. Do not include the authorization header on the follow up request to the AWS resource. Most HTTP libraries will handle the redirect for you without issue. But I have seen some cases where either it doesn't follow the redirect or it sends the same headers as the original request, which will cause an issue when it sends the authorization header (AWS file authentication and PureCloud API authentication are different things and are not interchangeable).
Samuel_Polgar | 2019-05-24 08:01:31 UTC | #11
Hello Tim
Hope you are keeping well.
Thank you very much for your detailed response.
I am very sorry to continue hassling you, I am a junior programmer, and sincerely appreciate all your assistance very much.
May I please bother you again to ask if you could check my logic?
- POST to
/api/v2/analytics/reporting/exports to generate report - GET
/api/v2/analytics/reporting/exports to find the downloadUrl - Make Request (using for example npm request) to downloadUrl including the authorization header from 2.
Would this be a GET like https://github.com/request/request#http-authentication ?
- Should be redirected to AWS file resource with AWS access token in query string.
- Use this query string to download the file
- Make sure I do not include the authorization header in step 5.
Hope you have a good and restful weekend!
tim.smith | 2019-05-24 14:10:58 UTC | #12
Sounds correct except the request just needs to specify the header; http authentication is something else. You want to do something like this:
request({
uri: downloadUrlFromApi,
method: 'GET',
headers: {
authorization: `bearer ${auth_token}`
}
})
Samuel_Polgar | 2019-05-24 22:04:54 UTC | #13
Hello Tim
One again, thank you very much. I sincerely appreciate your help.
system | 2019-06-24 22:04:54 UTC | #14
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: 5186