Welcome to Data Connector API documentation!

Note

The is a RESTful implementation. Code is written in c#

Contents:

Before you start

To help your integration go as smooth and trouble free as possible we have compiled this section. Here we go into detail on those areas where we have received feedback on or have spent time working with our partners on questions posted via our Service Desk.

Please also review the Checklist we have compiled to assist you in making sure you have all your ducks lined up before completing the integration.

Data Connector

There are 2 essential properties you must code for in your Data Connector implementation. These are: Date Range and Limit. Their respective importance are explained below:

Date Range

An IntelliSearch profile will always pass a date range to the Data Connector. This range is based on 5 different period types: Daily, weekly, monthly, quarterly and custom. Custom is a user defined date range.

It is therefore critical that you accommodate for a date range from within your code. The most efficient way to do this via our Integration Tool by adding a date field in the Search Criteria panel and setting it’s condition to Range. With doing this and placing a breakpoint in VS, you will see the data structure that constitutes a date range.

A date range consists of 2 searchCriteria items. The Id of both items will be identical (this means both items are coupled) and the key will be the name you give to this field in the search criteria panel.

Limit

It is possible from within the Evaluation (~v6 Coach) to not supply a date range when searching for agent calls.

Without care, this will impact on your network bandwidth. All items (an item = row of data) will be returned to Coach if you do not restrict the amount of data being returned. This is why we include the Limit property. By using this Limit property you can restrict the number of items being returned to Coach.

Please be aware that the Limit increases in line with the period type (when used in conjunction with the IntelliSearch feature) and is static when used from the Evaluation Form. Do not use an arbitrary value here, please be sure to use our Limit value instead.

Background information on search process:

We do take care by not requesting unnecessary data. Let me give you an overview of the process. A search is requested and a request is passed to the Data Connector. The payload includes a limit, tenant code, list of agents and a list of search criteria. The Data Connector will process the search criteria and return a list of IDs that reference a call and adhering to the provided limitation of items per agent. Coach will then pipe this returned list through a randomisation algorithm. The product of the algorithm is a list of IDs (per agent) based on the max number of calls per agent (a) stipulated in the IntelliSearch Profile OR (b) 100 (via Evaluation form only). This list is then returned to the Data Connector. The Data Connector will then return the call information for each of these IDs as well as any additional metadata you wish to see in Coach.

Integration Tool

Our Integration Tool is accessible via our developer portal. It is not OSS and it cannot be installed locally [within your infrastructure]. The first task you’ll be invited to perform it to confirm connectivity to your hosted Data Connector - Test your Connector. You must enable a public facing IP address and port for the Integration Tool to be able to reach your Data Connector end-point. You will not be able to progress through the Integration Tool until it has confirmed connectivity with the Data Connector. Please note, this does not mean that you must have completed the development work at this point in time.

There are 1 of several outbound IP addresses the Integration Tool can use to communicate through so please add this list to your firewall:

  • 23.100.53.139
  • 23.100.53.152
  • 23.100.53.156
  • 23.100.58.69

If for security reasons you are unable to enable an IP and port then we suggest you deploy the Data Connector and your own Recorder repository to a cloud provider VM such as offer up by Azure or AWS.

Coach server environment

To help you quickly and without any effort configure your server, we have prepared a Chef script for your convenience. You will need to install Chef client version 12.2.1 first - https://downloads.chef.io/chef-client/windows/. You can find this here - Server deployment.

Checklist

Prior to integration

  • [✔] Watched all the videos for solid understanding of what’s involved
  • [✔] Read the Checklist section
  • [✔] Read the Checklist section
  • [✔] Subscribed to the Coach Service Desk
  • [✔] Obtained public facing IP address for the Integration Tool to test your Data Connector
  • [✔] Added port of Data Connector RESTful API before to firewall
  • [✔] Added this IP range (23.100.53.139,23.100.53.152,23.100.53.156,23.100.58.69) to your firewall so Integration Tool can reach your Data Connector

Server configuration

Coding

  • [✔] Downloaded Data Connector RESTful API from github
  • [✔] Downloaded QA Data Connector from github to look at sample implementation
  • [✔] Implemented Data range in both GetMediaForUserAsync and GetMediaForUsersAsync so results are filtered on a period
  • [✔] Incorporated the Limit property in and MediaForUserArgs and MediaForUsersArgs so as to not return potentially millions of rows of data
  • [✔] Received Email with link back to recorder configuration
  • [✔] Clicked on link included in Email and returned to recorder configuration
  • [✔] Tested users import in Integration Tool
  • [✔] Tested search criteria in Integration Tool

Post-coding

  • [✔] Completed Integration Tool and have received T-SQL script file Email attachment
  • [✔] Installed Coach

Support

  • [✔] Received training on Coach

Getting Started

Important

Please read the Getting Started section before continuing.

This is the place to start if you are the person who’s responsible for the integration of your recorder with Coach.

Here you will be shown how to download and confirm that the middleware is installed correctly.

Install API

Note

You will need Visual Studio 2013 and PostMan

Download RESTful API middleware

Create a blank solution, e.g. integrations. At the command line cd in the directory Visual Studio created.

Create a sub folder named src. cd into this folder.

You can clone the dataconnector git repository by:

git clone git@github.com:qualtrak/data-connector-api.git

Next, please clone our sample recorder connector:

git clone git@github.com:qualtrak/recorder-qa.git

This connector is what we use when we carry out our QA.

Your folder structure will now look like this:

sample solution

Next, add these 2 projects. Your solution will look similar to this:

sample solution

Hint

If you are prompted to restore packages from nuget, accept.

Build the solution

Select the solution name in the Solution Explorer, right-click and enable Nuget

Hint

If you get an nuget error at this stage, clear the nuget cache by:

Menu ‣ Tools ‣ Options ‣ Nuget Package Manager ‣ General ‣ Clear Package Cache

Now build the solution.

Next, navigate to the recorder-qa\bin\Debug folder and copy the QATestRecorder.dll binary then paste it into data-connector-api\bin folder.

Important

When you develop your own recorder you must update the mappings in the ninject.xml file. More on this later.

We don’t have to change the ninject.xml file now as the default contains the mappings to this QATestRecorder assembly.

Finally, rebuild the solution. You are now ready to run and serve up the DataConnector RESTful API.

Confirm middleware deployment works

Expand the Controllers folder in DataConnector project and open the ConnectorsController class. Place a brakepoint on the Get method.

Select the DataConnect project, right-click and Set as StartUp Project. Now run the solution.

Copy the address, in my example it is http://localhost:20908/api/connector, into PostMan and press Send:

alternate text

You’ll see the breakpoint hit:

alternate text

Well done!! You have successfully downloaded, restored the required nuget packages, built and run the data connector middleware and hit a breakpoint into the sample recorder connector.

Create your Connector

Here you will be shown how to build and test your connector.

How to create a connector

Add a new project to your Visual Studio solution. For ease, reuse the QATestRecorder code but remove all the code in the methods and leaving the method signatures in play.

I have created a new connector and called the project recorder-abc with the namespace of ABCRecorder:

alternate text

How to interpret method parameters

Important

When a Schedule is being processed the username and password parameters are those that have been configured for your recorder. When a search is run from the Evaluation Form, the username and password are those of the user that is currently logged in.

Connector methods:

IRecorderApiFacade

This interface must be implemented in your Data Connector. However, not all implementations require coding. For example, if you don’t need to implement an esoteric way of streaming your media to Coach then you don’t need to code the GetStreamAsync method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 public interface IRecorderApiFacade
 {
     Task<IEnumerable<Media>> GetMediaByIdsAsync(IEnumerable<string> ids, DataConnectorProperties properties);
     Task<IEnumerable<Media>> GetMediaForUserAsync(string userId, MediaForUserArgs args, DataConnectorProperties properties);
     Task<IEnumerable<MediaUser>> GetMediaForUsersAsync(MediaForUsersArgs args, DataConnectorProperties properties);
     Task<string> GetMediaUrlAsync(string id, string originalUrl, DataConnectorProperties properties);
     Task<Stream> GetStreamAsync(string url);
     Task<IEnumerable<RecorderUser>> GetUsersAsync(DataConnectorProperties properties);
     Task SendEvaluationScoreAsync(SendEvaluationScoreArgs args, DataConnectorProperties properties);
 }
GetUsersAsync

This method is to return a list of RecorderUser.

1
     public Task<IEnumerable<RecorderUser>> GetUsersAsync(DataConnectorProperties properties)
DataConnectorProperties
Describes the user credentials required for an authentication challenge by the Recorder.

Please return a IEnumerable of RecorderUser objects.

GetMediaForUsersAsync

This method is to return a list of MediaUser which is a minimum list of information that is required by our randomizer. Our randomizer chooses which recordings Coach will accept from the batch supplied.

1
     public Task<IEnumerable<MediaUser>> GetMediaForUsersAsync(MediaForUsersArgs args, DataConnectorProperties properties)
MediaForUsersArgs
Used to store all the information required by the Recorder to perform a search for recordings for a list of users.
DataConnectorProperties
Describes the user credentials required for an authentication challenge by the Recorder.

Please return a IEnumerable of MediaUser objects.

Additional information
SearchCriteria
The Search Criteria is a filter that is to be applied to your recordings. If called from the Evaluation form, it is possible that no filter is supplied. If however, it is called from the Schedule then there will always be at least 2 criteria.
GetMediaByIdsAsync

This method is to return a list of Media

1
     public Task<IEnumerable<Media>> GetMediaByIdsAsync(IEnumerable<string> ids, DataConnectorProperties properties)
IEnumerable<string>
A list of recording ids originating from the recorder. This list is shortened [normally] list of recordings that was originally returned by the GetMediaForUsersAsync call.
DataConnectorProperties
Describes the user credentials required for an authentication challenge by the Recorder.

Please return a IEnumerable of Media objects.

Additional information
Metadata
You can also return other data to Coach that is outside of the original search filter.
GetMediaForUserAsync

This method is to return a list of Media.

1
     public Task<IEnumerable<Media>> GetMediaForUserAsync(string userId, MediaForUserArgs args, DataConnectorProperties properties)
userId
The Id of the user originating from the Recorder.
MediaForUsersArgs
Used to store all the information required by the Recorder to perform a search for recordings for a list of users.
DataConnectorProperties
Describes the user credentials required for an authentication challenge by the Recorder.

Please return a IEnumerable of Media objects.

Additional information
Metadata
You can also return other data to Coach that is outside of the original search filter.
SearchCriteria
The Search Criteria is a filter that is to be applied to your recordings. If called from the Evaluation form, it is possible that no filter is supplied. If however, it is called from the Schedule then there will always be at least 2 criteria.
GetMediaUrlAsync

This method will return a url that will be loaded into the media player. The url may need to undergo further amendments before it can get the recording and this is where you can programmatically perform such an operation.

1
public Task<string> GetMediaUrlAsync(string id, string originalUrl, DataConnectorProperties properties)
id
This is a unique identifier to the recording originating from your recorder.
originalUrl
This is the original url. This is to be returned if you do not wish to make any modifications to the original url.
DataConnectorProperties
Describes the user credentials required for an authentication challenge by the Recorder.

Please return either the originalUrl or a modified url.

GetStreamAsync

If you require some form of proxy intervention when getting a recording then this is programmatically the place to perform such an operations

1
public Task<Stream> GetStreamAsync(string url)
url
This is the url that will generate a stream and can be used as part of the url if you need to do something particular with the returned recording.

Please return a Stream

How can I use it?

An example of how you can use this API is here. You enter this

/data-connector/api/stream?url=

into the Recordings root folder input field when configuring a media player from within the Console. This will ensure that every url is pre suffix with this value first resulting the stream being loaded into the media player.

If your recordings need to satify a Basic Authentication challenge then please see our BasicAuthenticationGetMedia Handler instead

SendEvaluationScoreAsync

This method provides the mechanism to update your own data repository with Headline Scores assigned to an evaluation.

1
public Task SendEvaluationScoreAsync(SendEvaluationScoreArgs args, DataConnectorProperties properties)
SendEvaluationScoreArgs
This POCO is used to wrap the evaluation score information that is destined for the recorder.
DataConnectorProperties
Describes the user credentials required for an authentication challenge by the Recorder.

This does not return anything.

Metadata

You can also return other metadata. This metadata will be displayed in Coach, next to the evaluation information when in an evaluation. The format of this metadata must adhere to the following json schema:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
       metadata:
         [
           {
             "label" : "Policy No",
             "value" : "23126603039",
             "field" : "policy_no",
             "type" : "number"
           },
           {
             "label" : "Notes",
             "value" : "Caller said they were happy with resolution",
             "field" : "call_notes",
             "type" : "string"
           }
         ]
     }

The above metadata json must be inserted into the returning RecordingInfo.Metadata object property. There is no limitation on the amount of metadata you supply.

This is how the above looks in the Evaluation form:

alternate text

Important

When you have built your recorder, copy its binary and any other binary that is required into the data-connector-api\bin folder before you host the DataConnector

Danger

You must not forget this next step. Failing to do so will result in your Data Connector not being called by the RESTful API middleware.

We use an IoC container called Ninject. Ninject needs to know how to call into to your implementation. We use an xml file to provide this information to Ninject. This file is found in the root folder of DataConnector project and is called ninject.xml. You are required to change the to attribute. Here in this example we see that our namespace is ABCRecorder.RecorderApiFacade and the assembly name is ABCRecorder :

1
2
3
4
5
 <?xml version="1.0" encoding="utf-8" ?>
 <module name="RecorderConfigurationModule">
 <bind service="Qualtrak.Coach.DataConnector.Core.Recorder.IRecorderApiFacade, Qualtrak.Coach.DataConnector.Core"
      to="ABCRecorder.RecorderApiFacade, ABCRecorder" />
 </module>

Important

Now copy the ninject.xml file into the data-connector-api\bin folder before you host the DataConnector

Test your Connector

Here, we will walk you though how to test your connector when using our Integration Tool [1] . You will need to host this end point. You can do this though IIS and allowing port 80 through your firewall. Your IP address or domain name will be required by our Integration Tool.

alternate text

Next, you will be asked for the media player you wish to use.

Search Criteria Matrix

Within Coach you have several different input types data types available to you that best describes the data you want to filter on.

See Search Criteria Matrix document for the data types and their conditions.

For more information on these data types see Data Types.

Build search criteria

You can use our Integration Tool to construct your recorder’s search criteria.

Here, you will see that we have defined the search criteria as having 3 fields; Date Range, Part of campaign and Direction of call.

alternate text

Test Users

Open you connector code and place breakpoint just inside of the GetUsers method.

Whem you press the Test Users button you get presented with this modal and you press OK

alternate text

It now hits your breakpoint. You will see 1000 is being passed as the tenantCode. You will see null for both username and password as the Integration Tool is not passing values for those.

alternate text

Test Recordings

Whenever you call upon your Data Connector to return a list of recordings, the process sequences through 2 stages. The first stage requests a list of recordings with minimum data. This list is then processed by our randomizer. Once the randomizer has chosen which recordings it wants, it then calls the Data Connector a second time which is stage 2. Stage 2 returns all the medatata data associated with the recordings. These stages are shown next. I have placed a breakpoint at the top of each method.

Stage 1

Open your connector code and place breakpoint just inside of the GetRecordingsForUsers method.

When you press the Test Media button you get presented with this modal and you press OK

get recordings pre

It now hits your breakpoint. You first see a limit value. This is the maximum calls that Coach wants per agent. You will see 1000 is being passed as the tenantCode. Next you see that only 1 userId is passed. Following this, you see that 4 search criteria have been passed. You will see `` `` for both username and password as the Integration Tool is not passing values for those.

get recordings

There is only one user passed in

get recordings param user

Here we see a 4 criteria in the MediaForUsersArgs listed

get recordings param criteria

Here we see a 4 criteria listed

get recordings param criteria

Here we see a the data connector credentials

get recordings param criteria

All criteria is expanded. Each criteria starts with an identifier, e.g. date_0

get recordings param criteria expanded

This is a description of the critiera being passed to your method:

Date Range
The first 2 criteria here form the date range. These come with conditions of GreaterthanEqual and LessThanEqual. As these criteria share the same identifier date_0 this denotes they refer to the same data input.
Part of campaign
The next criteria identifier is is_campaign_0. Here we see that the condition is Equal and that we are passing a boolean value. In this case, the Integration Tool is passing True.
Direction of call
The last criteria that is passed has the identifier of call_direction_0. Again, this condition is Equal and the value being passed is I.
Stage 2

Here you see the second method’s breakpoint being hit:

get recordings

Here is the list of media Ids being requested from the Data Connector after the randomization process has processed the original list:

get recordings

Footnotes

[1]http://dev.qualtrak.com/Cit - Integration Tool in the developer portal

Generate SQL Script

The deployment of Coach requires a single MS T-SQL script file. This file is automatically generated by the Integration Tool after both the Agents and Recordings service calls return data.

Generate a T-SQL script required during the installation of Coach

After you have tested both the Users and Media, you will be prompted to provide your contact details.

An account will be created in our developer portal for you. You will receive an Email with details on how to log in.

The last part of this process is generating the T-SQL that is required during the deployment of the Coach product. The T-SQL will be generated and will describe to Coach everything that you have entered during this process. You will have been sent an Email through out this process containing a link that you can use to modify your recorder configuration.

You will see a Generate Sql button at the bottom of the progress bar, situated on the left side of the page. Please press this.

generate sql

Important

You will now receive one final Email. This Email will have an attachment. This attachment is the T-SQL script you need to place in the Database folder of the installation package.

Conceptual Overview

What is Coach?

Coach from Qualtrak is a high standard agent evaluation PLUS online learning solution which is tightly integrated with any call recorder (voice and screen) to create a seamless solution for contact centers of every size.

High Availability

Coach is available with HA. This infographic explains the configuration required for HA:

coach ha infographic

Middleware

The following sections talk you through the reason why we have done what have done in the way we have done it.

Why?

The Coach product has a dependency on user and recording metadata. In order for Coach to obtain this data it reaches out to the Recorder via Service Orientated Architecture SOA. The reason for this api documentation is to show and help you work through this process.

What problem does this solve?

When one computer application requires information from another, we generally create an API to make this possible. We have chosen to create a RESTful API to act as the intermeditary between our system and yours. This approach enables a decoupling between the two systems, removing your reliance on Qualtrak to bring any changes from your api into production.

How does it solve it?

We manage the decoupling programmatically through the use of the Inversion of Control IoC pattern.

IoC Container

In software engineering, inversion of control (IoC) [1] describes a design in which custom-written portions of a computer program receive the flow of control from a generic, reusable library. Martin Fowler walks you through an implementation [2] and compares IoC with DI here [3]. Dependency Injection (DI) is another programming pattern.

RESTful API

In computing, Representational State Transfer (REST) is a software architecture style for building scalable web services [4] .

In this section we talk in more detail about our RESTful api that acts as the conduit between the 2 respective systems:

RESTful implemetation

This illustration shows the relationship between the api and the deployment process of the Coach product:

alternate text

In the above illustration you see the Coach product. Coach calls on end points [e.g. users] to either pull or push data.

These end points in turn will call out to a recorder via a Connector implementation. The Connector implementation will be code that you specifically write to talk to your recorder. In this Connector you will (a) reference your own api and (b) interpret that data [e.g. search criteria] that is being passed from the RESTful end point.

The last [far right] part of this illustration explains how you test your implementation and what part this plays during the installation.

Plug your own (or other 3rd party) API into middleware

The RESTful API is the container that you use to hook into a connector. The connector has the bare minimum to manage the communication with the RESTful API. However, if the connector requires a new method then this is completely in your control. You have the freedom to modify the caller [RESTful API code base] as well as the callee [connector].

Target different deployments

This robust RESTful API approach not only offers you a way to quickly code transactions with your api but the other benefit is removes the complexity of using minor permutations of your api with different end-clients through the use of IoC.

Controllers

What follows is a short description of each of the RESTful API end points:

Connectors
Used to test connectivity
Users
A user from the Recorder
Recordings
Either a list of recordings or the url of a single recording
Score
Pass evaluated recording scores back to your recorder system
Stream
A proxy to download the recording to a media player
Handlers
BasicAuthenticationGetMedia Handler
A proxy to download the recording when needing to satisfy a Basic Authentication challenge

Footnotes

[1]https://en.wikipedia.org/wiki/Inversion_of_control - Wikipedia
[2]http://www.martinfowler.com/articles/injection.html - Martin Fowler
[3]http://martinfowler.com/bliki/InversionOfControl.html - Martin Fowler
[4]https://en.wikipedia.org/wiki/Representational_state_transfer - Wikipedia

Controllers

Controllers are the RESTful API end points. These controllers act as the conduit between Coach and your Connector implementation. These controllers should rarely change.

BaseController

All controllers inherit from this base Controller.

Namespace:

Qualtrak.Coach.DataConnector.Controllers

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class BaseApiController : ApiController
{
    private const string TenantCodeHeaderKey = "TenantCode";
    private const string UsernameHeaderKey = "Username";
    private const string PasswordHeaderKey = "Password";

    protected DataConnectorProperties GetDataConnectorProperties()
    {
        var result = new DataConnectorProperties();
        result.TenantCode = this.GetValueFromHeaderKey(TenantCodeHeaderKey);
        result.Username = this.GetValueFromHeaderKey(UsernameHeaderKey);
        result.Password = this.GetValueFromHeaderKey(PasswordHeaderKey);
        return result;
    }

    private string GetValueFromHeaderKey(string key)
    {
        if (this.Request.Headers.Contains(key))
        {
            return this.Request.Headers.GetValues(key).First();
        }

        return null;
    }
}

Connector

Get Connector

To be used to check that the connector is present. Used predominatley by the Integration Tool.

Namespace:

Qualtrak.Coach.DataConnector.Controllers

HTTP call:

GET api/connector

c# code:

1
2
3
4
public bool Get()
{
    return true;
}

RecorderUsers

Get list of users

To return a list of users from the recorder connector.

Namespace:

Qualtrak.Coach.DataConnector.Controllers.Recorder

HTTP call:

GET api/recorder/users

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 [DeflateCompression]
 [Route("recorder/users")]
 public async Task<IEnumerable<RecorderUser>> GetAsync()
 {
    var client = NinjectWebCommon.Kernel.Get<IRecorderApiFacade>();

    try
    {
        return await client.GetUsersAsync(this.GetDataConnectorProperties());
    }
    catch (Exception ex)
    {
        Trace.TraceError("connector : [{0}]", ex.Message);
    }

    return await Task.FromResult(new List<RecorderUser>());
 }

Dependency on:

RecorderUser
Describes a Recorder User.

RecorderMedia

Get recording url

To get the url of a recording from the recorder connector.

Namespace:

Qualtrak.Coach.DataConnector.Controllers.Recorder

HTTP call:

GET api/recorder/media?id=123abc&originalUrl=http://calls.recorder.com/recording.aspx?id=123abc

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Route("recorder/media")]
[HttpGet]
public async Task<string> GetAsync(string id, string originalUrl)
{
    var client = NinjectWebCommon.Kernel.Get<IRecorderApiFacade>();
    string result = string.Empty;

    try
    {
        result = await client.GetMediaUrlAsync(id, originalUrl, this.GetDataConnectorProperties());
    }
    catch (Exception ex)
    {
        Trace.TraceError("connector : [{0}]", ex.Message);
    }

    return result;
}

Get list of recordings

To get a list of recordings from the recorder connector for a specific {userId}.

Namespace:

Qualtrak.Coach.DataConnector.Controllers.Recorder

HTTP call:

POST api/recorder/media/{userId}

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 [DeflateCompression]
 [Route("recorder/media/{userId}")]
 [HttpPost]
 public async Task<IEnumerable<Media>> PostAsync(string userId, MediaForUserArgs args)
 {
   var client = NinjectWebCommon.Kernel.Get<IRecorderApiFacade>();
   try
   {
       return await client.GetMediaForUserAsync(userId, args, this.GetDataConnectorProperties());
   }
   catch (Exception ex)
   {
       Trace.TraceError("connector : [{0}]", ex.Message);
   }

   return await Task.FromResult(new List<Media>());
 }

Dependency on:

Media
Used to describe a recording from a Recorder.
MediaForUserArgs
Used to describe a filter to be applied by the Recorder when requests recordings.

Get a list of Ids from arguments

Get the minimum inforation required by our randomizer for it to choose what recordings will eventually be used by Coach.

Namespace:

Qualtrak.Coach.DataConnector.Controllers.Recorder

HTTP call:

POST api/recorder/media

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 [DeflateCompression]
 [Route("recorder/media")]
 [HttpPost]
 public async Task<IEnumerable<MediaUser>> PostAsync(MediaForUsersArgs args)
 {
   var client = NinjectWebCommon.Kernel.Get<IRecorderApiFacade>();
   try
   {
       return await client.GetMediaForUsersAsync(args, this.GetDataConnectorProperties());
   }
   catch (Exception ex)
   {
       Trace.TraceError("connector : [{0}]", ex.Message);
   }

   return await Task.FromResult(new List<MediaUser>());
 }

Dependency on:

MediaUser
Used to describe the relationship between a recording and a recorder user.
MediaForUsersArgs
Used to describe the search filter to be applied by the Recorder for recordings from a list of users.

Get a list of Media from list of media Ids

Get recordings from the Recorder from the supplied list of Ids.

Namespace:

Qualtrak.Coach.DataConnector.Controllers.Recorder

HTTP call:

POST api/recorder/media/full

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
  [DeflateCompression]
  [Route("recorder/media/full")]
  [HttpPost]
  public async Task<IEnumerable<Media>> PostAsync(MediaByIds args)
  {
       var client = NinjectWebCommon.Kernel.Get<IRecorderApiFacade>();
       try
       {
           var response = await client.GetMediaByIdsAsync(args.ids, this.GetDataConnectorProperties());
           return response;
       }
       catch (Exception ex)
       {
           Trace.TraceError("connector : [{0}]", ex.Message);
       }

       return await Task.FromResult(new List<Media>());
  }

Dependency on:

Media
Used to describe a recording from a Recorder.
MediaByIds
Used to contain a list of recording Ids for the Recorder to process.

Score

Push Score

To be used you want Evaluation headline scores to be persisted by the Recorder repository.

Namespace:

Qualtrak.Coach.DataConnector.Controllers.Recorder

HTTP call:

POST api/recorder/evaluationscore

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
  [Route("recorder/evaluationscore")]
  public async Task PostAsync(SendEvaluationScoreArgs args)
  {
      var client = NinjectWebCommon.Kernel.Get<IRecorderApiFacade>();

      try
      {
         await client.SendEvaluationScoreAsync(args, this.GetDataConnectorProperties());
      }
      catch (Exception ex)
      {
          Trace.TraceError("connector : [{0}]", ex.Message);
      }
  }

Dependency on:

SendEvaluationScoreArgs
Contains the Headline Score of an Evaluation that is to be persisted by the Recorder.

Stream

Stream recording

To be used to obtain a recording stream.

Namespace:

Qualtrak.Coach.DataConnector.Controllers.Recorder

HTTP call:

GET api/recorder/stream

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 [Route("recorder/stream")]
 public async Task<HttpResponseMessage> GetAsync(string url)
 {
   var client = NinjectWebCommon.Kernel.Get<IRecorderApiFacade>();
   try
   {
       var stream = await client.GetStreamAsync(url);
       bool match = false;

       var output = this.Request.CreateResponse(HttpStatusCode.OK);
       output.Content = new StreamContent(stream);
       output.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

       foreach (var item in this._listOfMediaFileTypes)
       {
           if (url.Contains(item.Ext))
           {
               output.Content.Headers.ContentType = new MediaTypeHeaderValue(item.MimeType);
               output.Content.Headers.ContentDisposition.FileName = "recording" + item.Ext;
               match = true;
               break;
           }
       }

       if (!match)
       {
           output.Content.Headers.ContentType = new MediaTypeHeaderValue("audio/x-wav");
           output.Content.Headers.ContentDisposition.FileName = "recording.wav";
       }

       return output;
   }
   catch (Exception ex)
   {
       Trace.TraceError("connector : [{0}]", ex.Message);
   }

   return new HttpResponseMessage(HttpStatusCode.NotFound);
 }

Plain old class objects

These are the classes the the RESTful implementation depends on. These classes can be used to pass information to the RESTful API or used to wrap data being returned from the RESTful API.

Important

When returning the FileName of the media back to Coach, you must only include the filename.ext (e.g. agent201506211015.wav) and not the absolute filepath or url. Coach generates the url from the information provided in the Recorder Media configuration page

RecorderUser

Describes a Recorder User.

Namespace:

Qualtrak.Coach.DataConnector.Core.Recorder

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 [DataContract()]
 public class RecorderUser
 {
     [DataMember]
     public string AccountId { get; set; }

     [DataMember]
     public string FirstName { get; set; }

     //The Automatic Call Distributor ID uniquely identifies an agent with a device; device being the equipment the call is directed to.  This ID identifies this user
     [DataMember]
     public string LastName { get; set; }

     //This is the unique identifier of a user account within the recorder
     [DataMember]
     public string Mail { get; set; }

     //This is the password of the user’s account.
     [DataMember]
     public string Password { get; set; }

     [DataMember]
     public string UserId { get; set; }

     [DataMember]
     public string Username { get; set; }
 }

Media

Used to describe a recording from a Recorder.

Namespace:

Qualtrak.Coach.DataConnector.Core.Recorder

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
 [DataContract]
 public class Media
 {
     [DataMember]
     public string Id { get; set; }

     [DataMember]
     public string FileName { get; set; }

     //The name of the file that uniquely identifies the recording
     [DataMember]
     public string RecorderUserId { get; set; }

     [DataMember]
     public DateTime? Date { get; set; }

     [DataMember]
     public string Metadata { get; set; }
 }

MediaForUserArgs

Important

Please read the Limit and Date Range sections before continuing.

Used to describe a filter to be applied by the Recorder when requests recordings.

Namespace:

Qualtrak.Coach.DataConnector.Core.Recorder.Args

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 [DataContract]
 public class MediaForUserArgs
 {
     [DataMember]
     public int Limit { get; set; }

     [DataMember]
     public List<SearchCriteria> SearchCriteria { get; set; }

     [DataMember]
     public string TimeZone { get; set; }
 }

MediaUser

Used to describe the relationship between a recording and a recorder user.

Namespace:

Qualtrak.Coach.DataConnector.Core.Recorder

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 [DataContract]
 [Serializable]
 public class MediaUser
 {
     //The code that uniquely identifies the recording, this could be a compound key
     [DataMember(Name = "id")]
     public string MediaId { get; set; }

     [DataMember(Name = "userId")]
     public string RecorderUserId { get; set; }
 }

Important

The RecorderUserId is a string and not an integer (number). For example, ‘009’ does not equal 9

MediaForUsersArgs

Important

Please read the Limit and Data Range sections before continuing.

Used to describe the search filter to be applied by the Recorder for recordings from a list of users.

Namespace:

Qualtrak.Coach.DataConnector.Core.Recorder.Args

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 [DataContract]
 public class MediaForUsersArgs
 {
     [DataMember]
     public int Limit { get; set; }

     [DataMember]
     public List<SearchCriteria> SearchCriteria { get; set; }

     [DataMember]
     public string TimeZone { get; set; }

     [DataMember]
     public IEnumerable<string> UserIds { get; set; }
 }

MediaByIds

Used to contain a list of recording Ids for the Recorder to process.

Namespace:

Qualtrak.Coach.DataConnector.Core.Recorder.Args

c# code:

1
2
3
4
5
6
 [DataContract]
 public class MediaByIds
 {
     [DataMember]
     public IEnumerable<string> ids { get; set; }
 }

SearchCriteria

Used to describe one search filter.

Namespace:

Qualtrak.Coach.DataConnector.Core.Shared

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
 [DataContract]
 public class SearchCriteria
 {
     DataMember]
     public string Id { get; set; }

     [DataMember(Name = "key")]
     public string Key { get; set; }

     [DataMember(Name = "label")]
     public string Label { get; set; }

     [DataMember(Name = "value")]
     public string Value { get; set; }

     [DataMember(Name = "condition")]
     public SearchCondition Condition { get; set; }

     [DataMember(Name = "dataType")]
     public System.TypeCode DataType { get; set; }
 }

Notes:

Id is an identifier used by Coach for mapping purposes
Key is the id of the field that means something to your connect; e.g. recording_date
Label is the on-screen display name for this field when being prompted for a value
Value is the value that is being passed to your connector for searches to be filter on

Dependency on:

SearchCondition
Enum of all possible conditions.

SendEvaluationScoreArgs

Contains the Headline Score of an Evaluation that is to be persisted by the Recorder.

Namespace:

Qualtrak.Coach.DataConnector.Core.Recorder.Args

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
 [DataContract]
 [Serializable]
 public class DataConnectorEvaluationScore : IDataConnectorEvaluationScore
 {
     [DataMember]
     public string EvaluationId { get; set; }

     [DataMember]
     public string ExtraScore { get; set; }

     [DataMember]
     public string HeadlineScore { get; set; }

     [DataMember]
     public string MediaId { get; set; }

     [DataMember]
     public string UserId { get; set; }
 }

DataConnectorProperties

Describes the user credentials required for an authentication challenge by the Recorder.

Namespace:

Qualtrak.Coach.DataConnector.Core.Shared

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 [DataContract]
 [Serializable]
 public class DataConnectorProperties : IDataConnectorEvaluationScore
 {
     [DataMember]
     public string Password { get; set; }

     [DataMember]
     public string TenantCode { get; set; }

     [DataMember]
     public string Username { get; set; }
 }

Enums

SearchCondition

Namespace:

Qualtrak.Coach.DataConnector.Core.Enums

c# code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 public enum SearchCondition
 {
     GreaterThan = 0,
     GreaterThanEqual = 1,
     LessThan = 2,
     LessThanEqual = 3,
     Equal = 4,
     NotEqual = 5,
     Any = 6,
     NotContains = 7,
     Contains = 8,
     StartsWith = 9,
     EndsWith = 10
 }

Server Deployment

Chef

Important

You will need to install Chef client version 12.2.1 first - https://downloads.chef.io/chef-client/windows/.

Note

Minimum requirements are Windows Server 2012 R2, SQL Server 2014 and IIS 8

The following is a chef script. Its purpose is to help you quickly preconfigure the server where Coach will be deployed:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# Cookbook Name:: coach_chef_web
# Recipe:: default
#
# Copyright (c) 2015 Qualtrak Solutions Ltd, All Rights Reserved.
powershell_script 'Install IIS' do
  code 'Add-WindowsFeature Web-Server'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name Web-Server).Installed"
end

powershell_script 'Install NET-Framework-45-Core' do
  code 'Add-WindowsFeature NET-Framework-45-Core'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name NET-Framework-45-Core).Installed"
end

powershell_script 'Install Web-Asp-Net45' do
  code 'Add-WindowsFeature Web-Asp-Net45'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name Web-Asp-Net45).Installed"
end

powershell_script 'Install Web-WebSockets' do
  code 'Add-WindowsFeature Web-WebSockets'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name Web-WebSockets).Installed"
end

powershell_script 'Install NET-WCF-HTTP-Activation45' do
  code 'Add-WindowsFeature NET-WCF-HTTP-Activation45'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name NET-WCF-HTTP-Activation45).Installed"
end

powershell_script 'Install Windows Auth' do
  code 'Add-WindowsFeature Web-Windows-Auth'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name Web-Windows-Auth).Installed"
end

powershell_script 'Install IIS Mgmt Console' do
  code 'Add-WindowsFeature Web-Mgmt-Console'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name Web-Mgmt-Console).Installed"
end

powershell_script 'Install IIS Mgmt Service' do
  code 'Add-WindowsFeature Web-Mgmt-Service'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name  Web-Mgmt-Service).Installed"
end

powershell_script 'Install IIS Application Initialization' do
  code 'Add-WindowsFeature Web-AppInit'
  guard_interpreter :powershell_script
  not_if "(Get-WindowsFeature -Name  Web-AppInit).Installed"
end

service 'w3svc' do
    action [:enable, :start]
end

Cut & paste the above code into a file called setup.rb. Open a command console as Administrator and enter:

1
c:\chef-apply setup.rb

This will now install all the server features required to host Coach on this server.

Release History

1.0.1 (2016-04-11)

  • Added a Checklist page (found under the Important section) to help remind Integration Engineers on the important / key stages & actions required during the integration
  • Added list of outbound IP addresses the Integration Tool uses to communicate through.
  • Added a new Before you start page (found under the Important section) to focus on key payload properties that you as a Integration Engineer must implement during the integration development

1.0.0 (2015-11-16)

  • Official 1.0 release
  • Included extra content based on feedback from partners

0.1.0 (2015-08-17)

  • Initial release as an OSS project with Coach 6.0

Qualtrak

Who we are

Qualtrak was initially founded in 1998 as Europe’s first specialist consulting business helping contact centers of all sizes to implement an effective Quality Monitoring and Coaching program or to renew their quality program.

What we do

Working with clients of all sizes, and using all of the major QM products, provided us with valuable lessons in what makes an effective QM/coaching solution.

Qualtrak is the only vendor to supply a ‘white-labelled’ high standard Agent Evaluation and Online Learning solution to OEM call recording vendors (on-prem and cloud), cloud based contact center Service Providers and OEM contact center vendors (on-prem and cloud). Qualtrak’s Coach can be integrated with any call recorder (API required) using Qualtrak’s SDK.

You can find more information by clicking here.

License

The MIT License (MIT)

Copyright (c) [2015] [Qualtrak Solutions Ltd]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Appendix

Data Types

Boolean
Use when the data you want to filter on requires True & False or 1 & 0.
boolean datatype
DataTime
Use when you require to filter on a combination of date and time.
datatime datatype
List
Use this type when you want to filter on one or more explicit values.
list datatype
ListNumeric
Use this type when you want to filter on an explicit value as well as a number.
list datatype
Numeric
Use when you require to filter on a number.
numeric datatype
Textual
Use this type when you want to filter on a textual value.
textual datatype
Time
Use when you require to filter on a time.
time datatype

The Getting Started section is the best place to start if you are a developer tasked with the job of integrating your recorder with Coach.

In this Getting Started section you will be guided through how to:

  • obtain the RESTful api middleware
  • confirm that the middleware deployment is correct
  • build search criteria with our Integration Tool
  • create your connector
  • test your search criteria with your new middleware
  • generate an artefact required during the installation of Coach