Import API

AVAILABLE IN 9.3 AND ABOVE

Overview

The Import API allows ingesting 3rd party or Verba data into the system. 

The primary goal of the interface is to enable ingesting records to the system using JSON or XML formatted metadata and the corresponding media file(s). The interface provides access to the Verba Import Service through a REST API. This API supports both the standard and the advanced (trader voice specific) database schemas: Data model for trader voice recordings.

The API can be reached at http(s)://media-repository-address:port/restapi/v093/import/<action>

 

Prerequisites

In order to utilize the API, the following configuration is needed in the Web Application: Prerequisite configuration for Import API

General guidelines

HTTP GET, POST

The functions of the API are available as simple HTTP GET and POST requests. For implementations, where HTTP POST is not available, you can use the HTTP GET method. The maximum length of the HTTP GET request is usually maximized either by the client or the server. The client should assume that the maximum length of a GET request is 4000 characters, although, some implementations may support longer URLs too.

URL encoding

All HTTP requests have to be URL encoded and all spaces and special characters have to be escaped and substituted with its URL encoded equivalent. For further information, see http://www.w3schools.com/TAGS/ref_urlencode.asp.

Response type

The API provides json formatted responses.

Security

The API provides the following mechanism to ensure that the communications between the external application and the recording system are secure:

    • Authentication
    • Token based sessions
    • Option to limit the access to the API from preset network addresses
    • Option to use SSL/HTTPS

Authentication

The Import API requires a valid session token to process import requests. The authentication expects an HTTP GET request to the auth action. The token generated after a successful authentication is valid for one hour after the last use. 

If the authentication fails, the system will return a 500 HTTP Status Response, and a description of the problem encountered during the authentication

Request 

Authentication request
GET /restapi/v093/import/auth
Host: hostname:port
apikey: D53B03F9-3A7D-4645-97E9-618FD38819A4
password: D87869A979DB0078521D5872944E966E
username: user
cache-control: no-cache

Request headers

FieldDescription

apikey

The generated, unique GUID for the API key
username

The username of the Verba user used to authenticate. This user must have the Conversation Import role. (optional)

passwordThe md5hash of the password for the Verba user (optional)

Response

Authentication response
HTTP/1.1 200 OK
Date: Thu, 09 Jan 2019 10:42:57 GMT
Content-Type: application/json
Content-Length: 70

Response codes

Response CodeDescription
200Successful authentication
500Error during authentication

Response headers

FieldDescription
Date

The date and time of the request in EEE, DD MMM YYYY HH:MM:SS format

 

Type: String

 
Content-TypeThe type of the HTTP content: application/json
Type: String
Content-Length The length of the HTTP content
Type: Number 

Response body

{
    "status" : "ok",
    "token" : "94557faa725211e980f300155d01545a"
}
{
    "status" : "error",
    "error_message" : "Internal Server Error. An unexpected error has occured while generating token: Bad token request. Provided userName and/or password is incorrect. (Note: password must be md5 hashed!)"
}
FieldDescription
status The result of the authentication, possible values are ok, error
Type: String
tokenThe token for the authenticated session
Only sent if status is ok
Type: String
error_message Description of the error encountered
Only sent if status is error
Type: String

Import request

Request

The type of the request should be multipart, the boundary, media and the CDR file are mandatory unless noted otherwise. After a successful request, the following reply will be sent:

Authentication request
POST /restapi/v093/import/conversation HTTP/1.1
Host: 10.110.78.29:12345
apikey: D29AC60E-5CC3-48AE-9787-29E60EC1892A
token: 9471f4019e5611e980f800155d001c23
cache-control: no-cache
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name=""; filename="C:\GenericImport\CDR.xml
Content-Disposition: form-data; name=""; filename="C:\GenericImport\teszt.wav

------WebKitFormBoundary7MA4YWxkTrZu0gW--

Request headers

FieldDescription

apikey

The generated, unique GUID for the API key

token

The token received in the authentication request body

Response

Authentication response
HTTP/1.1 200 OK
Date: Thu, 09 Jan 2019 10:42:57 GMT
Content-Type: application/json
Content-Length: 47

Response codes

Response CodeDescription
200Successful import
500Error during import
HTTP/1.1 201 OK
JavaScript Object Notation: application/json     
Object
	Member Key: status 
		String value: ok 
	Key: status         
	Member Key: reason 
		String value: imported
	Key: token


Response headers

FieldDescription
Date

The date and time of the request in EEE, DD MMM YYYY HH:MM:SS format

 

Type: String

 
Content-TypeThe type of the HTTP content: application/json
Type: String
Content-Length The length of the HTTP content
Type: Number 

Response body

{
    "status" : "ok",
    "reason": "imported"
}
{
    "status": "error",
    "error_message": " Bad request. Failed to process CDR: String to parse is too short: , current position: 0"
}
FieldDescription
status The result of the authentication, possible values are ok, error
Type: String
reasonVerification if the import is sucessful.
Only sent if status is ok.
Type: String
error_message Description of the error encountered
Only sent if status is error
Type: String

XML description

The description of the Verba XML file can be found at Metadata XML fields. The id of the call is optional, if no ID is provided, the system will generate one.

Call example XML

<?xml version="1.0" encoding="utf-8"?>
<verbacdr state="1">    <!-- Finished Call State -->
<id>ff83f076-9e4e-11e9-80f8-00155d001c23</id>   
<recorded_cid>testuser@verbalabs.com</recorded_cid>
<start_time>2019.06.21 14:40:15.618</start_time>
<end_time>2019.06.21 14:40:57.768</end_time>
<destination_caller_id>kakas@verbalabs.com</destination_caller_id>
<source_caller_id>6010</source_caller_id>
</verbacdr>

SMS example XML

<?xml version="1.0" encoding="utf-8"?>
<verbacdr>
<source_caller_id>15198274350</source_caller_id>
<destination_caller_id>12038894142</destination_caller_id>
<start_time>2019.07.15 14:40:15.618</start_time>
<end_time>2019.07.15 14:40:15.618</end_time>
<modality_id>sms</modality_id>
<sms>test message</sms>
</verbacdr>

Trader voice example XML

The Turret data model does not require a one-to-one relationship between metadata and media, it is allowed to have multiple CDR for one media file, or multiple media files for one CDR. The link between the media and CDR is the media_record_ids field. The media is found based on the CDR record by searching for the matching media record IDs, then limiting the search for media end time before CDR start time, and media start time after CDR end time.

CDR record

<?xml version="1.0" encoding="utf-8"?>
<verbacdr state="1"> <!-- Finished Call State -->
 <type>1</type> <!-- CDR only -->
 <id>dd0f1fea-4004-11e9-81ba-005056ac1d2e</id>
 <rec_version>9.4.0 (Revision 5699r)</rec_version>
 <native_id>588_0000000000</native_id>
 <location>DEV-MR.VERBALABS.COM </location>
 <source_device>257</source_device>
 <source_caller_id>6001</source_caller_id>
 <source_name>Mark Goodall</source_name>
 <destination_caller_id>588</destination_caller_id>
 <destination_name>Lloyds</destination_name>
 <recorded_cid>6001</recorded_cid>
 <signaling_source>10.10.64.46</signaling_source>
 <start_time>2019.03.06 11:42:05.552</start_time>
 <call_start_time>2019.03.06 11:42:05.552</call_start_time>
 <end_time>2019.03.06 11:42:37.868</end_time>
 <video_codec_id>299</video_codec_id> <!-- Undefined -->
 <cause_id>0</cause_id> <!-- Normal -->
 <rec_provider>11</rec_provider> <!-- BT ITS -->
 <recorder_service_id>23</recorder_service_id> <!-- Unified Recorder -->
 <modality_id>voice</modality_id>
 <recorded_party>0</recorded_party> <!-- Source caller -->
 <record_failed>false</record_failed>
 <ondemand>false</ondemand>
 <rtp_count_valid>false</rtp_count_valid>
 <conference>false</conference>
 <keep>false</keep>
 <controlled>false</controlled>
 <voice_mail>false</voice_mail>
 <secondary>0</secondary> <!-- Primary -->
 <agent_id>6001</agent_id>
 <agent_name>Mark Goodall</agent_name>
 <platform_id>bt-its</platform_id>
 <media_record_ids>
 <id>BT_IPSI-6-1-3</id>
 </media_record_ids>
 <files>
 <file expected_url="2019\03\06\dd0f1fea-4004-11e9-81ba-005056ac1d2e_(20190306114205552).xml" original="1">2019\03\06\dd0f1fea-4004-11e9-81ba-005056ac1d2e_(20190306114205552).xml</file>
 </files>
 <markers>
 <marker>
 <comment>6002 left the call</comment>
 <user>1</user>
 <timestamp>2019.03.06 11:42:37.798</timestamp>
 <start_pos>32</start_pos>
 <end_pos>32</end_pos>
 <marker_pos>1</marker_pos>
 </marker>
 </markers>
 <participants>
 <participant>
 <callerid>6002</callerid>
 <role>conferee</role>
 <start_time>2019.03.06 11:42:05.552</start_time>
 <end_time>2019.03.06 11:42:37.798</end_time>
 <end_cause>0</end_cause>
 </participant>
 </participants>
 <metadata>
 <metadata_template type="bt-its" name="">
 <calltype>Call</calltype>
 <console>257</console>
 <consolename/>
 <consoletype>Netrix Button</consoletype>
 <deviceid>65</deviceid>
 <devicetype>Speaker</devicetype>
 <line>588</line>
 <linename>Lloyds</linename>
 <linetype>Private Wire Automatic</linetype>
 <phantomddi/>
 <recchannel>6-1-3</recchannel>
 <userName>Mark Goodall</userName>
 <vertical>1539</vertical>
 </metadata_template>
 </metadata>
 <media>
 <mediasegment id="0" start_time="2019.03.06 11:42:05.552" end_time="2019.03.06 11:42:37.868">
 <mediadescriptor>
 <destination ip="127.0.0.1" port="16384" protocol="udp" tipsupported="false" />
 <content type="main"/>
 </mediadescriptor>
 </mediasegment>
 </media>
</verbacdr>

Media record

<?xml version="1.0" encoding="utf-8"?>
<verbacdr state="1"> <!-- Finished Call State -->
 <type>2</type> <!-- Media only -->
 <id>dd0f1fec-4004-11e9-81ba-005056ac1d2e</id>
 <rec_version>9.4.0 (Revision 5699r)</rec_version>
 <native_id>BT_IPSI-6-1-3</native_id>
 <location>DEV-MR.VERBALABS.COM</location>
 <source_device>257</source_device>
 <source_ip>10.10.69.35</source_ip>
 <source_caller_id>6001</source_caller_id>
 <source_name>Mark Goodall</source_name>
 <destination_device>257</destination_device>
 <destination_ip>10.10.69.35</destination_ip>
 <destination_caller_id>6001</destination_caller_id>
 <destination_name>Mark Goodall</destination_name>
 <recorded_cid>6001</recorded_cid>
 <start_time>2019.03.06 11:42:17.131</start_time>
 <call_start_time>2019.03.06 11:42:11.191</call_start_time>
 <media_start_time>2019.03.06 11:42:17.131</media_start_time>
 <end_time>2019.03.06 11:42:43.013</end_time>
 <audio_codec_id>2</audio_codec_id> <!-- G.711A 64 kbps -->
 <video_codec_id>299</video_codec_id> <!-- Undefined -->
 <cause_id>85</cause_id> <!-- Voice Inactivity -->
 <rec_provider>11</rec_provider> <!-- BT ITS -->
 <recorder_service_id>23</recorder_service_id> <!-- Unified Recorder -->
 <modality_id>voice</modality_id>
 <recorded_party>0</recorded_party> <!-- Source caller -->
 <record_failed>false</record_failed>
 <ondemand>false</ondemand>
 <rtp_count_valid>false</rtp_count_valid>
 <conference>false</conference>
 <keep>false</keep>
 <controlled>false</controlled>
 <voice_mail>false</voice_mail>
 <secondary>0</secondary> <!-- Primary -->
 <agent_id>6001</agent_id>
 <platform_id>bt-its</platform_id>
 <media_length>25</media_length>
 <media_record_ids>
 <id>BT_IPSI-6-1-3</id>
 </media_record_ids>
 <files>
 <file expected_url="2019\03\06\dd0f1fec-4004-11e9-81ba-005056ac1d2e_(20190306114211191).wav" size="42310" original="1">2019\03\06\dd0f1fec-4004-11e9-81ba-005056ac1d2e_(20190306114211191).wav</file>
 </files>
 <metadata>
 <metadata_template type="bt-its" name="">
 <console>257</console>
 <consolename/>
 <consoletype>Netrix Button</consoletype>
 <deviceid>65</deviceid>
 <devicetype>Intercom</devicetype>
 <recchannel>6-1-3</recchannel>
 <username>Mark Goodall</username>
 <vertical>1539</vertical>
 </metadata_template>
 </metadata>
 <media>
 <mediasegment id="0" start_time="2019.03.06 11:42:11.200" end_time="2019.03.06 11:42:43.027">
 <mediadescriptor>
 <destination ip="10.10.10.10" port="1003" protocol="udp" tipsupported="false" />
 <content type="main"/>
 <codecs>
 <codec name="PCMU" pt="0" clk="8000" />
 <codec name="PCMA" pt="8" clk="8000" />
 <codec name="G722" pt="9" clk="8000" />
 <codec name="G729" pt="18" clk="8000" />
 <codec name="G723" pt="4" clk="8000" />
 <codec name="GSM" pt="3" clk="8000" />
 </codecs>
 <statistics>
 <start_time>2019.03.06 11:42:11.201</start_time>
 <rtp total="1597" lost="0" duplicated="0" outoforder="0" outofbuffer="0" streamchange="1"/>
 <decoding ok="3194" error="0" skipped="0" outofbuffer="0" resync="12"/>
 <mixing normalwrite="0" solowrite="3194" silencewrite="0" latemedia="0" resync="0" silence_suppressed="595"/>
 </statistics>
 </mediadescriptor>
 </mediasegment>
 </media>
 <rec_quality total_score="100">
 <recording rtploss="100" srtp="100" dec="100" mixing="100"/>
 <media silence="100" noise="100" beep="100" amp_change="100" unnatural_silence="100" amp_envelope_variance="100" volume="100"/>
 </rec_quality>
</verbacdr>

Load Balancing

The Import API for import service is a single server solution with no built-in load balancing capabilities. If multiple servers are required for the volume of the calls imported, client-side load balancing can be set up, as each separate server needs a session token unique to the server.