Calls

Call object fields

Calls are represented as JSON objects, which have the following keys:

Field Type Description
call_id UUID Unique call id
parent_call_id UUID This field is present only for some voip protocols.

For Avaya H.323 Passive recording, when call is put on hold and then resumed, the new call recording instance is created. This new instance links to the original call via parent_call_id field.

interaction_id UUID ID of interaction if this call is a part of multi-call interaction.
tenant_id UUID ID of tenant, which this calls is associated to
is_conference boolean If true, then this cal is a conference with more than 2 participants
recorder_id UUID Unique ID of the server, which recorded this call. In multi-site recording setup, this field allows to distinguish calls between locations
protocol_call_id string Uniq call id as provided by phone system.

For example, for SIP protocol this field is a "Call-Id" header in SIP INVITE message.

call_state integer Call state:

  • 1 - INITIATED - The caller sent invitation to the callee (e.g. SIP INVITE is sent)
  • 2 - ACCEPTED - The callee received invitation and confirmed this (e.g. SIP Trying is sent)
  • 3 - ALERTING - The callee started ringing (e.g. SIP 183 Session Progress is sent)
  • 4 - CONNECTED - The call is answered (e.g. SIP 200 OK is sent)
  • 5 - DISCONNECTING - One of parties initiated call disconnect (e.g. SIP BYE is sent)
  • 6 - DISCONNECTED - The call is completed (e.g. SIP BYE is confirmed with 200 OK)
  • 7 - HOLD - The call has been put on hold. For some voip protocols this call state is a final state, meaning that call recording is completed when call is put on hold. When call is resumed, a new call instance is started. For others protocols this state is an intermediate state, meaning that it will switch to CONNECTED state when call is resumed from hold.
  • 8 - TRANSFERRED - The call has been transferred to third party. Note, for some voip protocols even if the call has been transferred, it's call state is stored as DISCONNECTED rather than TRANSFERRED. This occurs because on protocol level the reason of call disconnect is not provided by phone system.

on_demand_state integer The state of on-demand recording:

  • 0 - DISABLED - On-demand triggers are not allowed for this call (e.g. call is configred as "always record")
  • 1 - KEEP_RECORDING - On-demand trigger was received and call will be kept
  • 2 - WAITING_TRIGGER - Waiting for on-demand trigger. If not received, then call will be deleted automatically upon completion

record_state integer Recording state:

  • 10 - ACTIVE - Call is in process of normal recording
  • 20 - LICENSE_OVERUSAGE - Call is recorded, but it is not possible to playback it due to license over-usage. In this case, the audio file is encrypted. Contact vendor to decrypt such files. This state is valid for both active calls and diconnected.
  • 30 - FINISHED - Call recording is finished normally
  • 40 - IGNORED - Call is ignored by recording filters. Only call metada is stored in database. The audio file is not created for such calls

voip_protocol integer Voip signaling protocol of the call:

  • 0 - UNKNOWN (not recognized protocol). Call is recorded from RTP packets only
  • 1 - SIP
  • 2 - H.323
  • 4 - SCCP (Cisco Skinny)
  • 5 - MGCP
  • 6 - Avaya (H.323 protocol with proprietary extensions)
  • 7 - Nortel UNISTIM
  • 8 - TAPI
  • 9 - MGCP PRI Backhaul (it is used between Cisco UCM and Voice Gateway)
  • 10 - Alcatel (proprietary protocol used by Alcatel OmniPCX - partially supported)
  • 11 - Avaya (passive RTP protocol)
  • 12 - Avaya TSAPI + passive RTP
  • 13 - SIPREC
  • 14 - Cisco Built-in-Bridge (active recording)
  • 15 - NEC SIP (proprietary protocol)
  • 16 - SIP ED137 radio (passive recording)
  • 17 - Cisco Built-in-Bridge (passive recording)

setup_time datetime Date/time when call was initiated.

Format is ISO8601 with timezone, for example 2014-06-10T13:45:51+0800

connect_time datetime Date/time when call was answered.

Format is ISO8601 with timezone.

disconnect_time datetime Date/time when call was disconnected.

Format is ISO8601 with timezone.

from_ip

to_ip

string

Ip-address of caller/called party.

Format is x.x.x.x, for example 192.168.0.10

from_port

to_port

integer Ip port of caller/called party
from_mac

to_mac

string Mac-address of caller/called party.

Format is XX-XX-XX-XX-XX-XX

from_number

to_number

from_name

to_name

from_id

to_id

string Number/name/id of caller/called party.

This value is provided by phone system.

For SIP protocol these values are extracted from the "From" and "To" headers of SIP INVITE message.

Example of SIP INVITE mesage:

INVITE sip:102@192.168.0.10 SIP/2.0
From: "John Smith" <sip:100@192.168.0.10>
To: "Emy" <sip:102@192.168.0.10>

In this case:

  • from_number = "100"
  • from_name = "John Smith"
  • from_id = "100@192.168.0.10"
  • to_number = "102"
  • to_name = "Emy"
  • to_id = "102@192.168.0.10"

Note, for SIP protocol, the values of these fields may be extracted from SIP headers "Remote-Party-ID" and "P-Asserted-Identity".

Example of SIP message:

INVITE sip:102@192.168.0.10 SIP/2.0
From: "John Smith" <sip:100@192.168.0.10>
To: "Emy" <sip:102@192.168.0.10>
Remote-Party-ID: "John" <sip:77@ex.com>;party=calling

In this case:

  • from_number = "77"
  • from_name = "John"
  • from_id = "77@ex.com"

transferred_from_number

transferred_from_name

transferred_from_id

string Number/name/id of phone, from which the call was transferred.

This value depends on voip signaling protocol.

For example, for Cisco Skinny protocol these fields are the same as "Last Redirecting Party Name/Number"

transferred_to_number

transferred_to_name

transferred_to_id

string Number/name/id of phone, to which the call was transferred.

This value depends on voip signaling protocol.

agent_id

agent_name

string For Avaya TSAPI protocol these fields are id and name of agent.
broadworks_user_id

broadworks_group_id

broadworks_sp_id

string Broadworks-specifid Ids for SIPREC protocol
metaswitch_user

metaswitch_group

metaswitch_system

string Metaswitch-specifid Ids for SIPREC protocol
cisco_nearend_guid

cisco_farend_guid

string Cisco near-end and far-end GUIDs for Cisco Built-in-Bridge recording
cisco_nearend_refci

cisco_farend_refci

string Cisco near-end and far-end REFCI values for Cisco Built-in-Bridge recording
cisco_phone_ip string IP-address of Cisco phone for Cisco Built-in-Bridge recording
cisco_nearend_partition

cisco_farend_partition

string Cisco near-end and far-end partition info for Cisco Built-in-Bridge recording
participants list A list of call participants. See object Participant.

Normally, there are only two participants of each call.

But for a conference call it may be more than 2 participants.

files list A list of audio files. See object File.

Normally, only one audio file exists per call instance.

But in some cases it may be multiple audio files per call:

  • When MiaRec is configured to detect log silence periods in a call, the recording is split on multiple audio files when silence is detected.
  • When there is license issue (not valid or not enough), then a part of call is encrypted. In this case, the call will have at least two audio files. First one will be relatively short (usually less than 15 seconds) and the second one will contain the remaing part of a conversation. The second file will be encrypted.

File object fields

Audio files are represented as JSON objects which have the following keys:

Field Type Description
file_id string Unique file id

It is unique only within a scope of this call instance.

start_time datetime Date/time when audio recording for this particular file has been started.

Format is ISO8601 with timezone, for example, 2014-06-10T13:45:51+0800

stop_time datetime Date/time when audio recording for this particular file has been stopped
file_size integer Size of audio file in bytes
file_path string Location of audio file on disk.
watermark string SHA1 hash of audio file content. It is used to validate data integrity

Participant object fields

Each call has at least 2 call participants (caller and called party). Conference calls may have more than 2 participants (such scenarios are not supported at the moment, but may be added in future).

Call participants are represented as JSON objects with the following attributes:

Field Type Description
participant_id string Unique participant id

It is unique only within a scope of this call instance.

join_time datetime Date/time when the participant joined the call.

Format is ISO8601 with timezone, for example, 2014-06-10T13:45:51+0800

leave_time datetime Date/time when the participant left the call
user_id string If such call participant is known to MiaRec, then user_id field points to existing MiaRec user account.

This is field can be null when participant is not know

party_direction integer Participant direction:

  • 0 - UNKNOWN
  • 1 - CALLER
  • 2 - CALLED
party_type integer Participant type:

  • 0 - UNKNOWN
  • 1 - AGENT
  • 2 - GATEWAY
  • 3 - CONFERENCE_BRIDGE
party_number

party_name

party_caller_id

string Name, number and id of participant.

These values are provided by phone system

List and search calls

Get a list of all calls:

GET /api/v2/calls.json

Example of JSON response:

{  
    "next_url": null,
    "calls":[{
        "call_id": "e03f497d-bdff-1019-102b-f5caab54f081",
        "setup_time": "2013-10-12T16:32:22-0800"
        "from_number": "102",
        "to_number": "101",
        ...
    },{
        "call_id": "e03f497d-bdff-1019-1023-694f40413c84",
        "setup_time": "2013-10-12T18:45:02-0800"
        "from_number": "103",
        "to_number": "105",
         ...
    }]
}

Paging

Each response has next_url attribute like:

{
    "calls": [ ... ],
    "next_url": "/api/v2/calls.json?start=200"
 }

next_url is set to null if there are no more pages. Otherwise the client application should use this URL to sent retrieve next portion of records.

When requesting a list of objects, by default MiaRec returns 20 records per page. The client application may request up to 1000 items per page with URI parameter limit=X, for example:

/api/v2/calls.json?limit=500

Calculating a total number of records

A calculation of a total number of records matching to the search criteria can be very expensive operation. For optimization purposes, the MiaRec application doesn't calculate such value. The next_url attribute is used to signal if more data is available beyond the currently requested page. On the very last page, the application sets next_url attribute to null and includes the total attribute, which is equal to a total number of records of all pages.

The following example represents the last page of data, i.e. no more data is available:

{
    "calls": [ ... ],
    "next_url": null,
    "total": 513
 }

How does the application know that there is more data available beyond the current page?

It is quite easy. The application queries the database for limit+1 records. The last records, if available, is discarded, i.e. the application always returns up to limit records. A presence of the last record is a signal that more data is available beyond the currently requested page. Yet, it is not known if there is only 1 extra record available or a lot more.

The MiaRec web portal uses one trick to improve user experience when paginating data.

It shows a pagination counter like "0-20 of many" to signal that more data is available. Word "many" means that there are more than 1,000 records available beyond the current page, otherwise, it shows the pagination counter like "0-20 of 893" telling the end user that only 893 records are available in database. How does it do that?

Actually, the MiaRec web portal queries 1,000 records instead of the page size (limit attribute). For example, when end user wants to see the first 20 records, the application actually queries 1,000 records. It calculates a total number of the returned records. If it is less than 1,000, then it shows that exact number to end user (for example, 0-20 of 813), otherwise it shows "many" word telling that a lot more records are available (more than 1,000).

To replicate the same user experience in your application, you can pass the URI parameter max_total_calc to REST API. If max_total_calc is set to 1,000, then the application queries 1,000 records even if limit is set, for example, to 50.

A response still contains 50 or less records, but the total attribute will be set to a non-null value no more than 1,000 records available beyond the current page.

Note, for performance reasons, a maximum accepted value for max_total_calc parameter is limited to 1,000.

Example request:

/api/v2/calls.json?limit=50&max_total_calc=1000

Response:

{
    "calls": [ ... ],
    "next_url": "/api/v2/calls.json?start=50&limit=50&max_total_calc=1000"
    "total": 813
 }

In this example, the total attribute signals that only 813 records are available in DB (less than 1,000 beyond the currently requested page 0-50). Note, the next_url attribute is not null, i.e. more pages are available beyond page 0-50.

Search

The returned list of objects may be filtered to narrow the search results according to different attributes, like date range, user, group, search term etc.

Filtering parameters should be specified as URI parameters.

REST API supports two search engines:

  • Basic search
  • Advanced search

The Basic search supports filtering recordings by the most frequently used attributes.

The Advanced search supports more attributes for searching as well as various comparison operators like "ends with", "is empty", etc. This search capability is the same as available in the MiaRec web portal on Advanced Search tab.

Basic search

Basic search is activated when URI attribute advanced_search is missing or set to 0, like:

/api/v2/users.json?advanced_search=0

Example of basic search using daterange and search_term attributes (note, multiple filtering parameters can be specified at the same time):

/api/v2/calls.json?daterange=2014/11/01-2014/12/01&search_term=12345

The following table lists the attributes available for basic search.

Parameter Description
daterange Filter by date range. Format of daterange is either YYYY/MM/DD-YYYY/MM/DD or YYYY/MM/DD

For example, the following query will return all recordings from 2014/11/01 00:00:00 to 2014/12/01 24:00:00:

/api/v2/calls.json?daterange=2014/11/01-2014/12/01

The following query will return all recordings from 00:00:00 to 24:00:00 of 2014/11/01

/api/v2/calls.json?daterange=2014/11/01

Note, the query will be executed with REST API user's timezone. If user's timezone is not configured, then groups, tenants or system default timezone will be used.

user_id Filter by user.

The following query will return all recordings associated with the user identified by ID. user_id is a unique ID of user created in MiaRec:

/api/v2/calls.json?user_id=546340bf-7b47-11e4-85a4-e03f497dbdff

user_login Filter by user login.

The following query will return all recordings associated with the user identified by login:

/api/v2/calls.json?user_login=john.smith

group_id Filter by group.

The following query will return all recordings associated with the specified group:

/api/v2/calls.json?group_id=d1d83c40-eec7-11e4-8558-e03f497dbdff

tenant_id Filter by tenant.

The following query will return all recordings associated with the specified tenant:

/api/v2/calls.json?tenant_id=d1d83c40-eec7-11e4-8558-e03f497dbdff

search_term Search a text in the phone number, phone name and notes.

Example:

/api/v2/calls.json?search_term=1234

category_id Filter recordings by category.

Example:

/api/v2/calls.json?category_id=de8440f6-f291-11e4-9476-e03f497dbdff

broadworks_user_id Filter recordings by Broadworks User ID.

Example:

/api/v2/calls.json?broadworks_user_id=user@broadworks.com

broadworks_group_id Filter recordings by Broadworks Group ID.

Example:

/api/v2/calls.json?broadworks_group_id=GroupA

active_only Return active calls only.

Example:

/api/v2/calls.json?active_only=1

Advanced search

Advanced search is activated when URI attribute advanced_search is set to 1, like:

/api/v2/calls.json?advanced_search=1

To support various comparison operators like "ends with", "is not empty", the URI parameters should be formatted as:

[PARAM_NAME]__[OPERATOR]=[VALUE]

Where:

  • [PARAM_NAME] is an attribute name, like "user_id", "from_number", etc.
  • [OPERATOR] is a comparison operator, like "is_empty", "lower_than", etc.
  • [VALUE] is the value to compare the attribute to. Note, the value is always required, even for operators like "is_empty". In this case, supply 1 or any other value, which will be ignored in the end.

Note, two underscore characters (__) are used as a separator between attribute name and operator.

Example of the advanced search URI query:

/api/v2/calls.json?advanced_search=1&phone_number__includes=1234&user_name__equal_to=J%20Smith

This is equivalent to:

("phone_number"  INCLUDES  "1234")  AND  ("user_name"  EQUAL_TO  "J Smith")

Note, a space character is encoded with %20 in URI

Table 1. Supported operators

Parameter Type (see Table 2) Description
date date Date of call recording
datetime datetime Date/Time of call recording
duration duration Duration of call recording
direction set Call Direction
voip_protocol set Voip Protocol
user_id set User ID
user_name string User Name
group_id set Group ID
tenant_id set Tenant ID
category_id set Category ID
client_id set Client ID
notes string Notes
notes_count number Notes Count
call_id string_exact Call ID
pbx_call_id string PBX Call ID
pbx_tracking_id string PBX Tracking ID
call_state set Call State
record_state set Recording State
phone_number string Phone Number
phone_number_from string Phone Number (FROM only)
phone_number_to string Phone Number (TO only)
phone_name string Phone Name
phone_name_from string Phone Name (FROM only)
phone_name_to string Phone Name (TO only)
phone_id string Phone ID
phone_id_from string Phone ID (FROM only)
phone_id_to string Phone ID (TO only)
orig_calling_number string Orig Calling Number
orig_dialed_number string Orig Dialed Number
acd_number string ACD Number
acd_name string ACD Name
acd_id string ACD ID
redirected_from_number string Redirected From Number
redirected_from_name string Redirected From Name
redirected_from_id string Redirected From ID
redirected_to_number string Redirected To Number
redirected_to_name string Redirected To Name
redirected_to_id string Redirected To ID
phone_ip_address string IP Address
phone_ip_address_from string IP Address (FROM only)
phone_ip_address_to string IP Address (TO only)
broadworks_sp_id string Broadworks SP ID
broadworks_group_id string Broadworks Group ID
broadworks_user_id string Broadworks User ID
cisco_phone_ip string Cisco Phone IP Address
cisco_refci string_exact Cisco xRefCi
cisco_ucce_agent_id set Cisco UCCE Agent
cisco_ucce_skill_group_id set Cisco UCCE Skill Group
cisco_ucce_recovery_key number Cisco UCCE Call ID
metaswitch_system string Metaswitch System Name
metaswitch_group string Metaswitch Group Name
metaswitch_user string Metaswitch User Name
metaswitch_extension string Metaswitch User Extension
agent_id string Avaya Agent ID
agent_name string Avaya Agent Name
evaluation_report_score number Evaluation Report Score
evaluation_report_status set Evaluation Report Status
evaluation_reports_count number Evaluation Reports Count
screen_recordings_count number Screen Recordings Count
file_path string File Path
encrypt_fingerprint string_exact Encrypt Fingerprint
confidential bool Confidential Flag

Table 2. Supported comparison operators

Parameter type Supported operators
string

  • equal_to - attribute's value matches exactly a text
  • not_equal_to - attribute's value doesn't match a text
  • starts_with - attribute's value starts with a text
  • ends_with - attribute's value ends with a text
  • includes - attribute's value includes a text
  • is_empty - attribute's value is an empty string or not specified
  • not_empty - attribute's value is not an empty string
  • pattern - attribute's value matches a simple pattern (similar to SQL LIKE) using _ symbol to match exactly one character and % symbol to match zero or more characters.
  • regex - attribute's value matches a Regular Expression pattern.

string_exact

  • is - attribute's value matches exactly a text
  • is_not - attribute's value doesn't match a text
  • is_empty - attribute's value is an empty string or not specified
  • not_empty - attribute's value is not an empty string

string_query

  • query - attribute's value matches to a query expression
  • is_empty - attribute's value is an empty string or not specified
  • not_empty - attribute's value is not an empty string

number

  • equal_to - attribute's value equals to a number
  • not_equal_to - attribute's value doesn't equal a number
  • greater_than - attribute's value is greater than a number
  • lower_than - attribute's value is lower than a number
  • between - attribute's value is between two numbers
  • is_empty - attribute's value is not available (NULL)
  • not_empty - attribute's value is available (NOT NULL)

date

  • equal_to - attribute's value equals to a date
  • older_than - attribute's value is before a date
  • newer_than - attribute's value is after a date
  • between - attribute's value is between dates, separated by " - "
  • older_than_days - attribute's value is older than a specified number of days (integer)
  • newer_than_days - attribute's value is newer than a specified number of days (integer)

Format of date is:

  • YYYY/MM/DD
  • YYYY/MM/DD - YYYY/MM/DD - a range of date values (note, the space characters around the separator '-' are not required)

datetime

  • older_than - attribute's value is before a date+time
  • newer_than - attribute's value is after a date+time
  • between - attribute's value is between two date+time values, separated by "/"
  • older_than_minutes - attribute's value is older than a specified number of minutes
  • newer_than_minutes - attribute's value is newer than a specified number of minutes

Format of datetime is ISO8601. Example values:

  • 2019-04-30T06:00:00.000Z
  • 2019-04-30T06:00:00.000Z/2019-04-30T06:30:00.000Z - a range of datetime values (note, a separator character is "/")

duration

  • greater_than - attribute's value is lower than a duration
  • lower_than - attribute's value is after a duration
  • between - attribute's value is between two duration values, separated by " - "

Format of duration is:

  • SS - a number of seconds
  • MM:SS - minutes + seconds
  • HH:MM:SS - hours + minutes + seconds
  • SS - SS or MM:SS - MM:SS or HH:MM:SS - HH:MM:SS - a range of duration values (note, the space characters around the separator '-' are not required)

set

  • is - attribute's value equals to a text
  • is_not - attribute's value doesn't equal to a text

bool

  • is_true - attribute's value is TRUE
  • is_false - attribute's value is FALSE or not specified (NULL)

View one call

Request:

GET /api/v2/calls/<call-id>.json

Response is a JSON formatted object with call metadata:

{
  "call": {
     "call_id":          "e03f497d-bdff-1019-102d-68be3896f081",
     "parent_call_id":   "",
     "is_conference",    false,
     "recorder_id":      "27a7086c-f5c2-11e4-8cc5-e03f497dbdff",
     "protocol_call_id": "12345678-098765-765431",

     "call_state":       6,
     "on_demand_state":  0,
     "record_state":     30,
     "voip_protocol":    0,

     "setup_time":       "2013-10-12T16:32:22-0800"
     "connect_time":     "2013-10-12T16:32:22-0800"
     "disconnect_time":  "2013-10-12T16:38:56-0800",

     "from_ip":          "192.168.0.10",
     "from_port":        5060,
     "from_mac":         "11-22-33-44-55-66",
     "from_number":      "102",
     "from_name":        "User1",
     "from_id":          "102@192.168.0.10",

     "to_ip":            "192.168.0.5",
     "to_port":          5060,
     "to_mac":           "22-33-44-55-66-77",
     "to_number":        "101",
     "to_name":          "",
     "to_id":            "101@192.168.0.5",

     "redirected_from_number":  "",
     "redirected_from_name":    "",
     "redirected_from_id":      "",
     "redirected_to_number":    "",
     "redirected_to_name":      "",
     "redirected_to_id":        "",

     "broadworks_sp_id":     "",
     "broadworks_group_id":  "",
     "broadworks_user_id":   "",
     
     "cisco_nearend_guid":    "",
     "cisco_farend_guid":     "",

     "files": [{
        "file_id": "01",
        "start_time": "2013-10-12T16:32:22-0800",
        "stop_time": "2013-10-12T16:38:56-0800",
        "file_size": 132000,
        "file_path": "C:\Recordings\20131012\20131012163222-534346ad00000003.mp3",
        "encrypt_key": "",
        "encrypt_tag": ""
     }],

     "participants": [{
        "participant_id": "01",
        "join_time": "2013-10-12T16:32:22-0800",
        "leave_time": "2013-10-12T16:38:56-0800",
        "user_id": "546340bf-7b47-11e4-85a4-e03f497dbdff",
        "party_direction": 1,
        "party_type": 0,
        "party_number": "102",
        "party_name": "User1",
        "party_caller_id": "102@192.168.0.10"
     }, {
        "participant_id": "02",
        "join_time": "2013-10-12T16:32:22-0800",
        "leave_time": "2013-10-12T16:38:56-0800",
        "user_id": "",
        "party_direction": 2,
        "party_type": 0,
        "party_number": "101",
        "party_name": "",
        "party_caller_id": "101@192.168.0.10"
     }]
  }
}

Delete one call

Request:

DELETE /api/v2/calls/<call-id>.json

Response contains HTTP status code as shown in the following table.

Response Description
200 OK Call has been successfully deleted

403 Forbidden The request cannot be completed because API user has no permission to delete calls

Retrieve file for playback

The audio/video file could be delieved to end-user web browser using three different ways:

1) Your web appliation requests the signed file URL using MiaRec REST API, then it re-sends that URL to end-user web browser. The web-browser retrieves the file directly from MiaRec web portal using the signed file URL.

2) Your web application retrieves file using MiaRec REST API and resends the file back to end-user web browser.

3) Your web application retrieves call metadata using MiaRec REST API, then gets access to MiaRec file storage directly and streams the file to end-user web browser.

Method #1 (recommended)

Your web appliation requests the signed file URL using MiaRec REST API. The generated URL is returned to end-user web browser. The web-browser uses the signed URL to request the file directly from MiaRec web portal.

How it works

MiaRec REST API - get file #3

  • Step 1. The end-user web browser connects to your web application and requests a playback of particular call. For example, you could render the following HTML web page to end-user:

    <audio controls>
        <source src="https://YOUR-WEB-SERVER/recordings/CALL-ID" type="audio/mpeg">
    </audio>
    
  • Step 2. Your web appliation sends the "Generate File URL" request to MiaRec web server using REST API:

    /api/v2/calls/{call-id}.json/file_url.json?expires=3600
    

    The expires query parameter specifies for how long the URL should be valid (in seconds). The end-user will not be able to access the URL after expiration.

    Optionally, you can pass file_id query parameter to retrieve the particular file instance of the call:

    /api/v2/calls/{call-id}.json/file_url.json?expires=3600&file_id=01
    

The call may have multiple files in cases when automatic silence detection is enabled. In these cases, the recording is split on multiple files at silence periods. By default, silence detection is disabled. If the file_id is missing, then MiaRec web portal automatically concatenates multiple files into one on flight.

  • Step 3. MiaRec web portal returns JSON-formatted response containing the secure signed URL, like:

    {
       "signed_url": "https://miarec.example.com/calls/file/e03f497d-bdff-11e7-2790-4b6ab9967d89/signed?expires=1493100525&sign=NMxBcIFB6t2M...<TRUNCATED>"
    }
    

    The URL is signed by MiaRec web server using encryption methods. MiaRec validates the signature when it receives such URL back from the end-user (see step 5). If signature is invalid, then the URL is rejected. The signature protects the important URL parameters from modification (call-id, expires, host name, etc.). I.e. this URL is valid only for particular call and only for a limited permiod of time (see expires parameter above).

  • Step 4. Your web application needs to return URL to the end-user web browser, for example, inside HTTP Location header, like:

    HTTP/1.1 302 Found
    Location: https://miarec.example.com/calls/file/e03f...<TRUNCATED>
    

    Caution!

    You may generate the signed URL in advance when generating HTML web page (not recommended), like:

    <audio>
        <source src="https://miarec.example.com/calls/file/e03f...<TRUNCATED>" type="audio/mpeg">
    </audio>
    

    We do not recommend to do that because it creates unecessary load on MiaRec web server. In this example, URL has to be generated for each HTML page display even if the user doesn't playback the call. If you display 50 call recordings on page (in table, for example), then you need to request 50 Signed URLs in advance from MiaRec web server. It is time consuming because you need to send 50 HTTP requests to MiaRec.

    Better solution is to route file requests to your own web application first and then redirect to MiaRec web server when necessary, like:

    <audio controls>
        <source src="https://YOUR-WEB-SERVER/recording/CALL-ID" type="audio/mpeg">
    </audio>
    

    This URL should point to your web application. If end-user clicks "play" button in media player, then his/her web-browser automatically opens that URL. On your web application side you receive such request, parse "call-id", validate user's permissions and then ask MiaRec web portal to generate the signed URL for that particular call (see step 2).

  • Step 5. When web-browser receives HTTP 302 Found response with Location header, it automatically tries to open the returned URL (for user it is transparent).

  • Step 6. The MiaRec web portal verifies the signature and expiration parameters. If everyting is ok, then it connects to database and reads the file location from there.

  • Step 7. MiaRec web portal reads the file from the file storage.

  • Step 8. The file content is streamed directly to the end-user web browser.

Things to consider

  • It is a responsibility of your web application to check user permissions. You should verify user's role/group and credentials before you return the signed URL to user. MiaRec web portal gracefully generate signed URLs for any call that is accessible by your REST API account. Although, on MiaRec side you could limit access rights for your REST API account, i.e. you could grant your web application permissions only to particular recordings identified by tenant/group/user.

  • If both MiaRec web-portal and your web application are located in the same private network, then you could use HTTP (non-encrypted) protocol for REST API connection for optimization purposes. But for end-user to MiaRec web-portal communication, you need to use HTTPS (encrypted) protocol, i.e. you should deploy appropriate SSL certificate on MiaRec web server.

Method #2

Your web application retrieves file using MiaRec REST API. The your web application resends the file to end-user web browser.

How it works

MiaRec REST API - get file #1

  • Step 1. The end-user web browser connects to your web application and requests playback of particular call.

  • Step 2. Your web appliation sends the "Get file" request to MiaRec web server using REST API:

    /api/v2/calls/{call-id}.json/file
    

    Optionally, you can pass file_id query parameter to retrieve a particular file instance within the call:

    /api/v2/calls/{call-id}.json/file?file_id=01
    
  • Step 3. MiaRec web portal reads the file location from own database.

  • Step 4. MiaRec web portal reads the file from the file storage

  • Step 5. MiaRec web portal streams the file to your web application in a response to the request in step 2. Normally, at this moment, your web application should store temporary the file locally before it can pass that file further to end-user.

  • Step 6. Your web application streams the file to the web browser in a response to the request in step 1.

Things to consider:

  • The network connection between end-user and your web application may be significantly slower than the connection between your web app and MiaRec server(s). This means that the file streaming operation (step 6) may time out eventually, especially on big files. Your web application should support resumable file download using HTTP Range headers.

  • If your web application and MiaRec web portal are located in different datacenters, then such solution incurs additional bandwidth usage. For each file, your web application has to download it first from MiaRec web portal (inbound traffic), then re-transfer it to the end-user (outbound traffic).

Method #3

Your web application retrieves call metadata using MiaRec REST API. The call metadata contains the file path. This file path is used to access the file directly on MiaRec file storage and stream it to end-user web browser.

How it works

MiaRec REST API - get file #2

  • Step 1. The end-user web browser connects to your web application and requests playback of particular call.

  • Step 2. Your web appliation sends the "Get Call Metadata" request to MiaRec web server using REST API:

    /api/v2/calls/{call-id}.json
    
  • Step 3. MiaRec web portal reads call metadata from own database.

  • Step 4. Your web application receives JSON-formatted response from MiaRec containing call metadata like:

    {
    "call": {
     "call_id":          "e03f497d-bdff-1019-102d-68be3896f081",
     "from_number":      "102",
     "to_number":        "101",
     ...
     "files": [{
        "file_id": "01",
        "start_time": "2013-10-12T16:32:22-0800",
        "stop_time": "2013-10-12T16:38:56-0800",
        "file_size": 132000,
        "file_path": "/var/recordings/20131012/20131012163222-534346ad00000003.mp3",
     }]
    }
    

    The call metadata conteins the file location. In the example above, the file_path attribute is /var/recordings/20131012/20131012163222-534346ad00000003.mp3.

  • Step 5. Your web application needs to access the file directly on MiaRec storage.

    Note, the file_path in JSON response points to the file location accessible from the MiaRec servers. In order to access these files from your own server, you could use NFS file sharing, i.e. mount the local directory /var/recordings to remote NFS share. Instructions of how to configure NFS is out of scope of this document. Alternatively, you could use SSHFS instead of NFS.

  • Step 6. Your web application streams the file to the web browser in a response to the request in step 1.

Things to consider:

  • You need to have physical access and appropriate permissions to the MiaRec file storage in order to enable NFS file sharing there.

  • The NFS traffic is not encrypted. This means, that you could use NFS only within your private network only. You probably, could use VPN connection between your web app and MiaRec file storage, but this complicates the overall architecture. If a secure file transmission is required between your web application and MiaRec file server, then you should consider other methods described in this document.

  • This solution doesn't works with encrypted files. MiaRec may optionally encrypt the files on storage. When you access file storage directly from your web application, then the resulting audio/video files are not playable (they are kept in encrypted format). Other methods do support on-flight decryption (see below).

Advantages:

  • Resumable download is easier to achieve comparing to the previous method, because you can use your web server capabilities to serve files directly. It is a responsibility of the web-server to handle HTTP Range header, i.e. you do not need to worry about processing Range header.

Compatibility with file encryption

Methods 1 and 2 do support file encryption. The file is automatically decrypted on flight by MiaRec web portal during file streaming. The REST API account credentials are used to decrypt the file. This means that your REST API account has to be granted access to the appropriate file encryption key.

In method 3 (when your web application does access file storage directly), the read file remains encrypted (obviously). If you use this method, then you need to disable file encryption in MiaRec.

Pause and resume recording

Pause recording (mute):

POST /api/v2/calls/<call-id>.json/muting?action=mute

Resume recording (unmute):

POST /api/v2/calls/<call-id>.json/muting?action=unmute

Response contains HTTP status code as shown in the following table.

Response Description
200 OK Call recording has been paused/resumed successfully

403 Forbidden The request cannot be completed because API user has no permission to pause/resume recording. Verify role permissions.
404 Not Found Call recording with such ID is not found.