Sunday, February 3, 2019

InContact Custom Report API


Summary

This post will walk through the steps necessary to generate a custom report job on InContact's platform via API.  I'll show examples in Node.js (asynchronous) and Python (synchronous).

Overview of Steps


Get Token

Node.js

  1. getToken() {
  2. console.log('getToken()');
  3. const url = 'https://api.incontact.com/InContactAuthorizationServer/Token';
  4. const body = {
  5. 'grant_type' : 'password',
  6. 'username' : this.username,
  7. 'password' : this.password
  8. };
  9. return fetch(url, {
  10. method: 'POST',
  11. body: JSON.stringify(body),
  12. headers: {
  13. 'Content-Type' : 'application/json',
  14. 'Authorization' : 'basic ' + this.authCode
  15. },
  16. cache: 'no-store',
  17. mode: 'cors'
  18. })
  19. .then(response => {
  20. if (response.ok) {
  21. return response.json();
  22. }
  23. else {
  24. const msg = 'response status: ' + response.status;
  25. throw new Error(msg);
  26. }
  27. })
  28. .then(json => {
  29. if (json && json.access_token && json.resource_server_base_uri) {
  30. return json;
  31. }
  32. else {
  33. const msg = 'missing token and/or uri';
  34. throw new Error(msg);
  35. }
  36. })
  37. .catch(err => {
  38. console.error('getToken() - ' + err.message);
  39. throw err;
  40. });
  41. }

Python

  1. def getToken(self):
  2. print('getToken()')
  3. url = 'https://api.incontact.com/InContactAuthorizationServer/Token'
  4. header = {'Authorization' : b'basic ' + self.authCode, 'Content-Type': 'application/json'}
  5. body = {'grant_type' : 'password', 'username' : self.username, 'password' : self.password}
  6. resp = requests.post(url, headers=header, json=body)
  7. resp.raise_for_status()
  8. return resp.json()

Start Report Job

Node.js

  1. startReportJob(reportId, reportURL, token) {
  2. const url = reportURL + reportId;
  3. console.log('startReportJob() - url: ' + url);
  4. const body = {
  5. 'fileType': 'CSV',
  6. 'includeHeaders': 'true',
  7. 'appendDate': 'true',
  8. 'deleteAfter': '7',
  9. 'overwrite': 'true'
  10. };
  11. return fetch(url, {
  12. method: 'POST',
  13. body: JSON.stringify(body),
  14. headers: {
  15. 'Content-Type' : 'application/json',
  16. 'Authorization' : 'bearer ' + token
  17. },
  18. cache: 'no-store',
  19. mode: 'cors'
  20. })
  21. .then(response => {
  22. if (response.ok) {
  23. return response.json();
  24. }
  25. else {
  26. const msg = 'response status: ' + response.status;
  27. throw new Error(msg);
  28. }
  29. })
  30. .then(json => {
  31. return json.jobId;
  32. })
  33. .catch(err => {
  34. console.error('startReportJob() - ' + err.message);
  35. throw err;
  36. });
  37. }

Python

  1. def startReportJob(self, reportId, reportURL, token):
  2. url = reportURL + reportId
  3. print('startReportJob() - url: ' + url);
  4. body = {
  5. 'fileType': 'CSV',
  6. 'includeHeaders': 'true',
  7. 'appendDate': 'true',
  8. 'deleteAfter': '7',
  9. 'overwrite': 'true'
  10. }
  11. header = { 'Content-Type' : 'application/json', 'Authorization' : 'bearer ' + token}
  12. resp = requests.post(url, headers=header, json=body)
  13. resp.raise_for_status()
  14. return resp.json()['jobId']

Get File URL

Node.js

  1. getFileURL(jobId, reportURL, token, numTries=10) {
  2. console.log('getFileURL() - jobId: ' + jobId + ' numTries: ' + numTries);
  3. const that = this;
  4. const url = reportURL + jobId;
  5. return fetch(url, {
  6. method: 'GET',
  7. headers: {
  8. 'Content-Type' : 'application/x-www-form-urlencoded',
  9. 'Authorization' : 'bearer ' + token
  10. },
  11. cache: 'no-store',
  12. mode: 'cors'
  13. })
  14. .then(response => {
  15. if (response.ok) {
  16. return response.json();
  17. }
  18. else {
  19. const msg = 'response status: ' + response.status;
  20. throw new Error(msg);
  21. }
  22. })
  23. .then(json => {
  24. if (json.jobResult.resultFileURL) {
  25. return json.jobResult.resultFileURL;
  26. }
  27. else {
  28. if (numTries > 0) { //loop (recursive) up to the numTries parameter
  29. return new Promise((resolve, reject) => {
  30. setTimeout(() => {
  31. resolve(that.getFileURL(jobId, reportURL, token, numTries-1));
  32. }, 60000); //retry once per minute
  33. });
  34. }
  35. else {
  36. throw new Error('Maximum retries reached');
  37. }
  38. }
  39. })
  40. .catch(err => {
  41. console.error('getFileURL() - ' + err.message);
  42. throw err;
  43. });
  44. }

Python

  1. def getFileURL(self, jobId, reportURL, token):
  2. url = reportURL + jobId
  3. header = { 'Content-Type' : 'application/x-www-form-urlencoded', 'Authorization' : 'bearer ' + token }
  4. resp = requests.get(url, headers=header)
  5. fileURL = resp.json()['jobResult']['resultFileURL']
  6. numTries = 10
  7. while (not fileURL and numTries > 0):
  8. print('getFileURL() - jobId: ' + jobId + ' numTries: ' + str(numTries))
  9. time.sleep(60)
  10. resp = requests.get(url, headers=header)
  11. fileURL = resp.json()['jobResult']['resultFileURL']
  12. numTries -= 1
  13. return fileURL

Download Report

Node.js

  1. downloadReport(url, token) {
  2. console.log('downLoadReport() - url: ' + url);
  3. return fetch(url, {
  4. method: 'GET',
  5. headers: {'Authorization' : 'bearer ' + token},
  6. cache: 'no-store',
  7. mode: 'cors'
  8. })
  9. .then(response => {
  10. if (response.ok) {
  11. return response.json();
  12. }
  13. else {
  14. const msg = 'response status: ' + response.status;
  15. throw new Error(msg);
  16. }
  17. })
  18. .then(json => {
  19. return json.files.file;
  20. })
  21. .catch(err => {
  22. console.error('downloadReport() - ' + err.message);
  23. throw err;
  24. })

Python

  1. def downloadReport(self, url, token):
  2. print('downLoadReport() - url: ' + url)
  3. header = { 'Content-Type' : 'application/x-www-form-urlencoded', 'Authorization' : 'bearer ' + token }
  4. resp = requests.get(url, headers=header)
  5. return resp.json()['files']['file']

Output

Node.js

getReport() - reportId: 4477
getToken()
startReportJob() - url: https://api-c7.incontact.com/inContactAPI/services/v13.0/report-jobs/4477
getFileURL() - jobId: 825795 numTries: 10
getFileURL() - jobId: 825795 numTries: 9
getFileURL() - jobId: 825795 numTries: 8
getFileURL() - jobId: 825795 numTries: 7
downLoadReport() - url: https://api-C7.incontact.com/inContactAPI/services/V15.0/files?fileName=CustomReports%5cApiReports%5cService+Levels_20190203T054855.csv
Job Complete

Python

getReport() - reportId: 4477
getToken()
startReportJob() - url: https://api-c7.incontact.com/inContactAPI/services/v13.0/report-jobs/4477
getFileURL() - jobId: 825797 numTries: 10
getFileURL() - jobId: 825797 numTries: 9
getFileURL() - jobId: 825797 numTries: 8
downLoadReport() - url: https://api-C7.incontact.com/inContactAPI/services/V15.0/files?fileName=CustomReports%5cApiReports%5cService+Levels_20190203T055156.csv
Job Complete

Source

Full source w/comments - https://github.com/joeywhelan/reportdemo

Copyright ©1993-2024 Joey E Whelan, All rights reserved.