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¶
- [✔] Installed Chef Client 12.2.1.
- [✔] Run Chef script on server to configure your server prior to Coach install
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
andGetMediaForUsersAsync
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:
Next, add these 2 projects. Your solution will look similar to this:
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:
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
:
You’ll see the breakpoint hit:
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
:
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.
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:
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.
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.
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
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.
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
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.
There is only one user passed in
Here we see a 4 criteria in the MediaForUsersArgs listed
Here we see a 4 criteria listed
Here we see a the data connector credentials
All criteria is expanded. Each criteria starts with an identifier, e.g. date_0
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 passingTrue
. - 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 isI
.
Stage 2¶
Here you see the second method’s breakpoint being hit:
Here is the list of media Ids being requested from the Data Connector after the randomization process has processed the original list:
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.
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:

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:
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.
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].
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.
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
- 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 purposesKey
is the id of the field that means something to your connect; e.g. recording_dateLabel
is the on-screen display name for this field when being prompted for a valueValue
is the value that is being passed to your connector for searches to be filter onDependency 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.
- DataTime
- Use when you require to filter on a combination of date and time.
- List
- Use this type when you want to filter on one or more explicit values.
- ListNumeric
- Use this type when you want to filter on an explicit value as well as a number.
- Numeric
- Use when you require to filter on a number.
- Textual
- Use this type when you want to filter on a textual value.
- Time
- Use when you require to filter on a time.
- See
Search Criteria Matrix
document for the data types and their conditions.
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