Requests can be made without the use of an authorization mechanism or Basic Auth.
All requests must be made via HTTP/TLS with a cert issued from a trusted authority. Self Signed Certs are not supported at this time.
APIs are only available in JSON. All date and times will be in the ISO 8601 format.
Call Details
At the completion of each call, an outbound HTTP call can be made that will include the data about a given call. This includes general metadata captured with the call and details about what Tethr detected in the call.
Example of call details:
{ "callId" : "bbqfbbbow", "callUri" : "https://demo.Tethr.io/calls/bbqfbbbow", "utcStart" : "2014-04-30T17:01:42.65Z", "utcEnd" : "2014-04-30T17:02:35.29Z", "participants" : [{ "participantId" : 1, "refType" : "agent", "refId" : "adf3234", "phoneNumber" : "(222) 111-1010", "email" : "JDow@demo.comp", "firstName" : "John", "lastName" : "Dow", "isInternal" : true, "segments" : [{ "id" : "0f11c168-0762-4fc8-83c8-10a79b091847", "categoryId" : "UtteranceBreak", "categoryType" : "Sentence", "startMs" : 0, "endMs" : 2120 }, { "id" : "90e3f3b4-9691-49aa-8089-fd76a2d68640", "categoryId" : "UtteranceBreak", "categoryType" : "Sentence", "startMs" : 11770, "endMs" : 25020 }] }, { "participantId" : 2, "phoneNumber" : "(602) 555-0567", "isInternal" : false, "segments" : [{ "id" : "8af4cfce-5258-469f-8557-16c140d61792", "categoryId" : "UtteranceBreak", "categoryType" : "Sentence", "startMs" : 2090, "endMs" : 14400 }, { "id" : "559b54b8-caaf-4c22-b0eb-30672eea1fc9", "categoryId" : "UtteranceBreak", "categoryType" : "Sentence", "startMs" : 12970, "endMs" : 31040 }, { "id" : "a15ecdf9-3062-45ce-a336-75a9b515c1ea", "categoryId" : "8be93266-563a-4566-a3d7-9a532ad0c324", "categoryType" : "PhraseDetection", "categoryDisplayName" : "Misdirected: Mailing List", "startMs" : 15610, "endMs" : 16230, "value" : 0.8 }, { "id" : "ce3fcf54-06a1-4e74-ba2e-c482e50472d5", "categoryId" : "UtteranceBreak", "categoryType" : "Sentence", "startMs" : 49640, "endMs" : 101930 }] }] }
Linking to a Call
A web browser can be given a link directly to a given call by using the Call URI. If you would like that link to go to a specific point in time, you can add a query string parameter of transcript with a value of the time in the call in milliseconds (for example, https://demo.tethr.io/calls/bbqfbbbow?transcript=15610).
Example of data model in C#:
public class CallDetails { /// <summary> /// The Tethr Call ID /// </summary> public string CallId { get; set; } /// <summary> /// The Session Id from the originating audio ingestion system. /// </summary> /// <remarks> /// Can be used to cross reference this call with other systems that would also have this Id. /// </remarks> public string SessionId { get; set; } /// <summary> /// The URI to the Call in Tethr. /// </summary> /// <remarks> /// This URI can be used in a WebBrowser to open the Call Archive for this call. /// a query string parameter of “transcript” with a value of the time in the call in milliseconds (example https://demo.tethr.io/calls/bbqfbbbow?transcript=15610) /// </remarks> public string CallUri { get; set; } /// <summary> /// The start time of the call, in UTC time. /// </summary> public DateTime UtcStart { get; set; } /// <summary> /// The end time of the call, in UTC time. /// </summary> public DateTime UtcEnd { get; set; } /// <summary> /// The current display name of the Call Group in Tethr. /// </summary> public string CallDisplayName { get; set; } /// <summary> /// This is a concatenated list of call groups assigned to this call. /// </summary> /// <remarks> /// This may be obsolete in a future date /// </remarks> public string CallGroupId { get; set; } /// <summary> /// The IDs of the Call Groups in Tethr. /// </summary> public List<CallGroup> CallGroups { get; set; } /// <summary> /// A dynamic JSON object that contains all the extra metadata send along with the call, from the originating audio ingestion system. /// </summary> public JObject CallMetadata { get; set; } /// <summary> /// Any Classifications associated to this call by Tethr /// </summary> public List<CallClassification> Classifications { get; set; } /// <summary> /// Participant details for the call. /// </summary> public List<Participant> Participants { get; set; } /// <summary> /// Any SIP events captured and sent to Tethr from the originating audio ingestion system. /// </summary> public List<CallEvent> Events { get; set; } /// <summary> /// The phone number that was dialed that started the call. /// </summary> public string NumberDialed { get; set; } /// <summary> /// The direction of the call. /// </summary> public CallDirection Direction { get; set; } /// <summary> /// A call ID that may be shared between one or more calls, that together represent one complete calls. /// </summary> /// <remarks> /// Some call records will split a call into multiple calls when the caller is transferred or another participant is added. /// This master call ID can be used to tell Tethr that a set of call are really one call. /// /// This is actually a good thing in many cases, it allows us to treated each part of the call as own call, but still be able /// to link what happened in prior call to an event in this call, or even a future call. /// </remarks> public string MasterCallId { get; set; } /// <summary> /// The 3 letter language code (ISO 639-2 Alpha-3 Code) that this call is most likely/predominantly going to contain. /// </summary> /// <see cref="https://www.loc.gov/standards/iso639-2/php/code_list.php"/> public string Language { get; set; } /// <summary> /// The 3 letter country code (ISO 3166 ALPHA-3 Code) of the dialect most likely spoken on this call. /// </summary> /// <see cref="http://www.iso.org/iso/home/standards/country_codes.htm"/> /// <see cref="http://www.nationsonline.org/oneworld/country_code_list.htm"/> public string Country { get; set; } } public class CallGroup { public string Id { get; set; } public string DisplayName { get; set; } /// <summary> /// The type of call group. /// </summary> /// <example> /// Division, Location, Team, Skill, Campaign /// </example> public string Type { get; set; } } public class CallEvent { /// <summary> /// The time the event took place in Milliseconds from the Call start time. /// </summary> public int TimeMs { get; set; } /// <summary> /// A dynamic JSON object that contains all the extra metadata send along with the call, from the originating audio ingestion system. /// </summary> public JObject Metadata { get; set; } } public class CallClassification { /// <summary> /// A unique ID given to each instance of Classification. /// </summary> /// <remarks> /// This is only used for tracking a given instance in Tethr. /// </remarks> public string Id { get; set; } /// <summary> /// The Category Type of the Classifications /// </summary> /// <remarks> /// Category Types represent the sub system with-in Tethr that assigned the Classification to the call. /// </remarks> public string CategoryType { get; set; } /// <summary> /// The Category ID from the given sub system in Tethr that assigned the Classification /// </summary> /// <remarks> /// The any given ID will be unique to a given Category Type. /// </remarks> public string CategoryId { get; set; } /// <summary> /// The user friendly name of the Classification /// </summary> public string DisplayName { get; set; } /// <summary> /// The start time of the classification in Milliseconds from the start of the call. /// </summary> public int? StartMs { get; set; } /// <summary> /// The end time of the classification in Milliseconds from the start of the call. /// </summary> public int? EndMs { get; set; } /// <summary> /// A numerical value for the classification. /// </summary> /// <remarks> /// This value will represent a different metric for each Category Type. /// </remarks> /// <example> /// When looking at Text Classification, the value will be a scale from 1 to 0 representing how well it fit the model. /// </example> public double Value { get; set; } /// <summary> /// Indicates that this classification was required but not hit /// </summary> [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool Missed { get; set; } } public class Participant { /// <summary> /// The Id for this Participant with-in Tethr /// </summary> public byte ParticipantId { get; set; } /// <summary> /// The type for the external reference ID stored in "RefId" for this participant. /// </summary> /// <remarks> /// This represents the kind of or what external system the ID given to a /// participant is from. Reference Types are not pre-defined and are set per environment. /// Once created they can not be renamed, or deleted. They can be hidden and will no longer /// be assigned to participants. /// /// There can only be 1 primary reference type for a given customer, if more are needed, they /// can be placed in the Metadata. But the Reference Type is what's used in Tethr for grouping /// callers. /// </remarks> /// <example> /// Let's take an example of ACME Contact Center, they have out sourced their staffing, the our sourcing /// firm provided an ID for each of the agents answering the phones, for each of the Agents, we would have a /// RefType of "agent". However ACME Contact Center also has employees that supervise, and sometimes /// answer a call, for a call that an employee was on, RefType would be "employee" and RefId would contain /// their employee ID in ACME Contact Center's HR database. /// /// ACME Contact Center also has a CRM, and the Contact Center application used by the Agent, injects the /// customers ID from the CRM into the SIPRec data stream, Tethr detects that record, and would set the /// RefType to "customer" and the RefId to the Id from the CRM. /// /// Or if a customer is Asked to enter their account number in the IVR when they first connect. /// That customer Id number could be inserted here as well. /// </example> public string RefType { get; set; } /// <summary> /// The external reference ID corresponding to the system specified in the RefType field. /// </summary> public string RefId { get; set; } /// <summary> /// The unique ID give to this participant from the originating audio ingestion system. /// </summary> /// <remarks> /// If the call was injected via the archived call API, then this will be the channel /// of the participant in the original audio file. This can be 0 or 1 based. /// /// If the call was injected via the live call API, then this value will be determined /// by the ingestion system, but is often a SIP channel Id. /// </remarks> public string ContactId { get; set; } /// <summary> /// The phone number from the Caller ID for this participant. /// </summary> public string PhoneNumber { get; set; } /// <summary> /// The email address of the participant, if available. /// </summary> /// <remarks> /// It's very uncommon for Tethr to have the Email address of a participant. /// But if we have it, we will send it along. /// </remarks> public string Email { get; set; } /// <summary> /// The First Name of the participant. if available. /// </summary> public string FirstName { get; set; } /// <summary> /// The Last Name of the participant. if available. /// </summary> public string LastName { get; set; } /// <summary> /// A flag indicating this participant is inside the call center. /// </summary> /// <remarks> /// This is typically determined by what side of the Phone System the participant was /// connected to. E.g. If the participants connection was connected to the Call Centers PBX /// they are marked as Internal. It would be possible that if an agent called another agent /// via an internal extension both participants would be marked and Internal, but if the first /// agent called the second agent using an outside number, it's possible one of the agents wouldn't /// be marked an Internal. Actual results are very depended on how the contact centers phone /// and audio ingestion systems are configured. /// </remarks> public bool IsInternal { get; set; } /// <summary> /// The different elements Tethr detected on a call from this participant. /// </summary> public List<Segment> Segments { get; set; } /// <summary> /// The utterances and the words from this participant. /// </summary> /// <remarks>BETA FEATURE</remarks> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public List<Utterance> Utterances { get; set; } } public class Utterance { /// <summary> /// The start time of the utterance in Milliseconds from the start of the call. /// </summary> public int StartMs { get; set; } /// <summary> /// The end time of the utterance in Milliseconds from the start of the call. /// </summary> public int EndMs { get; set; } /// <summary> /// The words during this utterance. /// </summary> public List<Word> Words { get; set; } } public class Word { /// <summary> /// The start time of the word in Milliseconds from the start of the call. /// </summary> public int StartMs { get; set; } /// <summary> /// The end time of the word in Milliseconds from the start of the call. /// </summary> public int EndMs { get; set; } /// <summary> /// The text of the word at this time. /// </summary> public string Content { get; set; } /// <summary> /// The confidence score for the transcription. /// </summary> public float Confidence { get; set; } } public class Segment { /// <summary> /// A unique ID given to each instance of Classification. /// </summary> /// <remarks> /// This is only used for tracking a given instance in Tethr. /// </remarks> public string Id { get; set; } /// <summary> /// The Category Type of the Classifications /// </summary> /// <remarks> /// Category Types represent the sub system with-in Tethr that assigned the Classification to the call. /// </remarks> public string CategoryType { get; set; } /// <summary> /// The Category ID from the given sub system in Tethr that assigned the Classification /// </summary> /// <remarks> /// The any given ID will be unique to a given Category Type. /// </remarks> public string CategoryId { get; set; } /// <summary> /// The user friendly name of the Classification /// </summary> public string DisplayName { get; set; } /// <summary> /// The start time of the segment in Milliseconds from the start of the call. /// </summary> public int StartMs { get; set; } /// <summary> /// The end time of the segment in Milliseconds from the start of the call. /// </summary> public int EndMs { get; set; } /// <summary> /// A numerical value for the classification. /// </summary> /// <remarks> /// This value will represent a different metric for each Category Type. /// </remarks> /// <example> /// When looking at Text Classification, the value will be a scale from 1 to 0 representing how well it fit the model. /// </example> public double Value { get; set; } /// <summary> /// Where appropriate, the content will be part of the transcript that triggered the segments. /// </summary> public string Content { get; set; } } public enum CallDirection { /// <summary> /// Direction was not specified on the call /// </summary> Unknown, /// <summary> /// The caller was dialing from an out-side line. /// </summary> Inbound, /// <summary> /// The caller was dialing from an in-side line, calling an out-side number /// </summary> Outbound, /// <summary> /// Internal extention to extention call. /// </summary> Internal }
JSON Schema of Data Model:
{ "$id": "CallDetails", "definitions": { "CallClassification": { "$id": "CallClassification", "type": [ "object", "null" ], "properties": { "id": { "type": [ "string", "null" ] }, "categoryType": { "type": [ "string", "null" ] }, "categoryId": { "type": [ "string", "null" ] }, "displayName": { "type": [ "string", "null" ] }, "startMs": { "type": [ "integer", "null" ] }, "endMs": { "type": [ "integer", "null" ] }, "value": { "type": "number" }, "missed": { "type": "boolean" } }, "required": [ "id", "categoryType", "categoryId", "displayName", "startMs", "endMs", "value" ] }, "CallEvent": { "$id": "CallEvent", "type": [ "object", "null" ], "properties": { "timeMs": { "type": "integer" }, "metadata": {} }, "required": [ "timeMs", "metadata" ] }, "CallGroup": { "$id": "CallGroup", "type": [ "object", "null" ], "properties": { "id": { "type": [ "string", "null" ] }, "displayName": { "type": [ "string", "null" ] }, "type": { "type": [ "string", "null" ] } }, "required": [ "id", "displayName", "type" ] }, "Participant": { "$id": "Participant", "type": [ "object", "null" ], "properties": { "participantId": { "type": "integer" }, "refType": { "type": [ "string", "null" ] }, "refId": { "type": [ "string", "null" ] }, "contactId": { "type": [ "string", "null" ] }, "phoneNumber": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "firstName": { "type": [ "string", "null" ] }, "lastName": { "type": [ "string", "null" ] }, "isInternal": { "type": "boolean" }, "segments": { "$id": "List`1", "type": [ "array", "null" ], "items": { "$ref": "Segment" } }, "utterances": { "$id": "List`1", "type": [ "array", "null" ], "items": { "$ref": "Utterance" } } }, "required": [ "participantId", "refType", "refId", "contactId", "phoneNumber", "email", "firstName", "lastName", "isInternal", "segments" ] }, "Segment": { "$id": "Segment", "type": [ "object", "null" ], "properties": { "id": { "type": [ "string", "null" ] }, "categoryType": { "type": [ "string", "null" ] }, "categoryId": { "type": [ "string", "null" ] }, "displayName": { "type": [ "string", "null" ] }, "startMs": { "type": "integer" }, "endMs": { "type": "integer" }, "value": { "type": "number" }, "content": { "type": [ "string", "null" ] } }, "required": [ "id", "categoryType", "categoryId", "displayName", "startMs", "endMs", "value", "content" ] }, "Utterance": { "$id": "Utterance", "type": [ "object", "null" ], "properties": { "startMs": { "type": "integer" }, "endMs": { "type": "integer" }, "words": { "$id": "List`1", "type": [ "array", "null" ], "items": { "$ref": "Word" } } }, "required": [ "startMs", "endMs", "words" ] }, "Word": { "$id": "Word", "type": [ "object", "null" ], "properties": { "startMs": { "type": "integer" }, "endMs": { "type": "integer" }, "content": { "type": [ "string", "null" ] }, "confidence": { "type": "number" } }, "required": [ "startMs", "endMs", "content", "confidence" ] } }, "type": "object", "properties": { "callId": { "type": [ "string", "null" ] }, "sessionId": { "type": [ "string", "null" ] }, "callUri": { "type": [ "string", "null" ] }, "utcStart": { "type": "string", "format": "date-time" }, "utcEnd": { "type": "string", "format": "date-time" }, "callDisplayName": { "type": [ "string", "null" ] }, "callGroupId": { "type": [ "string", "null" ] }, "callGroups": { "$id": "List`1", "type": [ "array", "null" ], "items": { "$ref": "CallGroup" } }, "callMetadata": {}, "classifications": { "$id": "List`1", "type": [ "array", "null" ], "items": { "$ref": "CallClassification" } }, "participants": { "$id": "List`1", "type": [ "array", "null" ], "items": { "$ref": "Participant" } }, "events": { "$id": "List`1", "type": [ "array", "null" ], "items": { "$ref": "CallEvent" } }, "numberDialed": { "type": [ "string", "null" ] }, "direction": { "type": "string", "enum": [ "Unknown", "Inbound", "Outbound", "Internal" ] }, "masterCallId": { "type": [ "string", "null" ] }, "language": { "type": [ "string", "null" ] }, "country": { "type": [ "string", "null" ] } }, "required": [ "callId", "sessionId", "callUri", "utcStart", "utcEnd", "callDisplayName", "callGroupId", "callGroups", "callMetadata", "classifications", "participants", "events", "numberDialed", "direction", "masterCallId", "language", "country" ] }