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
GET /restapi/v093/import/auth Host: hostname:port apikey: D53B03F9-3A7D-4645-97E9-618FD38819A4 password: D87869A979DB0078521D5872944E966E username: user cache-control: no-cache
Request headers
Field | Description |
---|---|
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) |
password | The md5hash of the password for the Verba user (optional) |
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 Code | Description |
---|---|
200 | Successful authentication |
500 | Error during authentication |
Response headers
Field | Description |
---|---|
Date | The date and time of the request in EEE, DD MMM YYYY HH:MM:SS format
Type: String |
Content-Type | The 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!)" }
Field | Description |
---|---|
status | The result of the authentication, possible values are ok, errorType: String |
token | The 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:
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
Field | Description |
---|---|
apikey | The generated, unique GUID for the API key |
token | The token received in the authentication request body |
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 Code | Description |
---|---|
200 | Successful import |
500 | Error during import |
JavaScript Object Notation: application/json Object Member Key: status String value: ok Key: status Member Key: reason String value: imported Key: token
Response headers
Field | Description |
---|---|
Date | The date and time of the request in EEE, DD MMM YYYY HH:MM:SS format
Type: String |
Content-Type | The 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" }
Field | Description |
---|---|
status | The result of the authentication, possible values are ok, errorType: String |
reason | Verification 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.