The ExoVoiceAnalyze API can be used to derive the Transcript, Summary and Sentiment of a call. It can also be used to Categorise calls based on business-defined categories to help businesses bifurcate their calls (Inbound or Outbound) into the pre-defined categories.
This API can be used for calls that have been made using any Voice Product of exotel, including but not limited to: Click to Call API, Lead Assist, Campaigns, Dashboard Calls etc. The only underlying requirement is that the call_sid should have a call recording associated with it.
Note:- This is an Asynchronous API that accepts the request and provides the Insights via a WebHook hit in the form a POST method on the URL mentioned in the API request body.
This API is chargeable and is not accessible to all Exotel customers by default. Please reach out to your account manager to get this enabled.
http://<API_Key>:<API_Token>@api.exotel.com/v1/Accounts/<account_sid>/Calls/<call_sid>/ExoVoiceAnalyze.json
Parameter Name |
Mandatory/Optional |
Value / Description |
task_id |
Mandatory |
Customer defined identifier for the requested task. This can be any random string. This can be used to map the WebHook response against the request to uniquely identify the incoming POST hit on the WebHook. |
callback_url |
Mandatory |
The CallBack URL where the WebHook hit needs to be made. Only POST method will be used to hit this endpoint. |
categories |
Optional* |
The Business defined categories into which the call has to be categorised. |
insight_tasks |
Mandatory |
Set of AI Insights that can be requested for. Valid values are :-
Any one task or all the tasks can be requested for in a single request. |
*Mandatory only if the “categorise” insight_tasks is one of the tasks.
Note:- The sentiment task will produce only one of the three values of: Positive/Negative/Neutral.
curl --location --request POST 'http://<API_KEY>:<API_TOKEN>@api.exotel.com/v1/Accounts/<Account_SID>/Calls/<Call_SID>/ExoVoiceAnalyze.json' \ --header 'Content-Type: application/json' \ --data-raw '{ "callback_url": "https://WebHookURL.com", "insight_tasks": ["summarization","categorise","sentiment","transcript"], "task_id": "567664345678”, "categories": ["category 1","category 2","category 3","category 4","category 5"] }'
var axios = require('axios'); var data = JSON.stringify({ "callback_url": "https://WebHookURL.com", "insight_tasks": [ "summarization", "categorise", "sentiment", "transcript" ], "task_id": "testPRod", "categories": [ "summary", "insights", "sales" ] }); var config = { method: 'post', url: 'http://<API_KEY>:<API_TOKEN>@api.exotel.com/v1/Accounts/<Account_SID>/Calls/<Call_SID>/ExoVoiceAnalyze.json', headers: { 'Content-Type': 'application/json' }, data : data }; axios(config) .then(function (response) { console.log(JSON.stringify(response.data)); }) .catch(function (error) { console.log(error); });
<?php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'http://%3CAPI_KEY%3E:%3CAPI_TOKEN%3E@api.exotel.com/v1/Accounts/%3CAccount_SID%3E/Calls/%3CCall_SID%3E/ExoVoiceAnalyze.json', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS =>'{ "callback_url": "https://WebHookURL.com", "insight_tasks": ["summarization","categorise","sentiment","transcript"], "task_id": "testPRod", "categories": ["summary","insights","sales"] }', CURLOPT_HTTPHEADER => array( 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); echo $response;
import http.client import json conn = http.client.HTTPSConnection("api.exotel.com") payload = json.dumps({ "callback_url": "https://WebHookURL.com", "insight_tasks": [ "summarization", "categorise", "sentiment", "transcript" ], "task_id": "testPRod", "categories": [ "summary", "insights", "sales" ] }) headers = { 'Content-Type': 'application/json' } conn.request("POST", "/v1/Accounts/<Account_SID>/Calls/<Call_SID>/ExoVoiceAnalyze.json", payload, headers) res = conn.getresponse() data = res.read() print(data.decode("utf-8"))
package main import ( "fmt" "strings" "net/http" "io/ioutil" ) func main() { url := "http://%3CAPI_KEY%3E:%3CAPI_TOKEN%3E@api.exotel.com/v1/Accounts/%3CAccount_SID%3E/Calls/%3CCall_SID%3E/ExoVoiceAnalyze.json" method := "POST" payload := strings.NewReader(`{ "callback_url": "https://WebHookURL.com", "insight_tasks": ["summarization","categorise","sentiment","transcript"], "task_id": "testPRod", "categories": ["summary","insights","sales"] }`) client := &http.Client { } req, err := http.NewRequest(method, url, payload) if err != nil { fmt.Println(err) return } req.Header.Add("Content-Type", "application/json") res, err := client.Do(req) if err != nil { fmt.Println(err) return } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return } fmt.Println(string(body)) }
HTTP Response:
{ "request_id": "11a32b11dd8f4257a5d576b6b1719202", "method": "POST", "http_code": 200, "success": true, "reason": "", "ExoVoiceAnalyze": { "job_id": "71191de3-b59c-4485-8372-e7d8139976f2", "task_id": "56775457ABVFRT", "call_sid": "554739565cXXXX5ed17bt", "status": "queued" } }
{ "request_id": "1cb631cbf412481ab91407be29e73bd6", "method": "POST", "http_code": 400, "ResponseData": { "Code": 400, "Message": "Invalid parameter", "Description": "Invalid insight task" } }
Description of parameters mentioned in the above success/failure responses:
Parameter Name | Type & Value | ||||||||||||||||||||||||||
request_id
|
A unique ID for the API request being made. | ||||||||||||||||||||||||||
http_code
|
HTTP response code of your request.
|
||||||||||||||||||||||||||
success | true or false. This shows whether the request succeeded or not. | ||||||||||||||||||||||||||
reason |
Explanation for success / failure |
||||||||||||||||||||||||||
job_id |
The unique identifier that ties an API response to a WebHook hit. |
||||||||||||||||||||||||||
task_id
|
Customer defined string passed in the API request. |
||||||||||||||||||||||||||
call_sid
|
The Call SID for which the Insights are generated. |
||||||||||||||||||||||||||
status
|
The status of the request submitted. The immediate value will by default be “queued” |
{ "success": true, "reason": "", "task_id": "8765Abgt678", "job_id": "5d1ca6b6-4f9b-4f4f-b411-826fcc29cade", "callSID": "2c6050f9cc6eb7f9aee2abd761fe17c7", "summary": { "summary": "Jason, a fresher with a supply chain and analytics background, called looking for a job in logistics or supply chain. The employer mentioned they are currently hiring for logistics but only for experienced candidates. Jason thanked the employer and ended the call.", "confidence": 0.9 }, "sentiment": { "sentiment": "NEUTRAL", "confidence": 0.8 }, "category": { "category": "Jobseeker mentioned they will not be able to move forward", "confidence": 0.7 }, "transcript": "Hello, where do you go?\nHello.\nHi, this is Jason.\nActually, I got your number from India.\nHi, Jason.\nGo ahead and help.\nYeah, actually, I'm looking for a job.\nI did my supply chain and analytics from IIT.\nActually, I'm a fresher.\nI'm looking for a job in logistics or supply chain.\nSo if you have any openings, I'll be really happy for that.\nCurrently, we are hiring for logistics space, but we're looking for somebody who\nbut you can surely send us your updated CV on the email id resume at waytogoconsulting.com I'm sure it's on the post that you found the name send us your CV we can definitely connect with you in case we have anything that's open for freshers okay so you don't have anything right now?\nwe do but nothing for freshers but for experience only\nOh, okay, okay.\nThat's fine then.\nThank you.\nYeah, thanks for calling.\n" }
{ "success": false, "reason": "Forbidden to access recording url of call", "job_id": "d2102824-e353-6765-aa9e-6bde866f2422", "callSID": "91126f1b80XXX88104cc4717bl" }
Description of parameters mentioned in the above success/failure WebHook hits:
Parameter Name | Type & Value |
success | Indicates whether the request succeeded or not. |
reason |
Explanation for success / failure |
job_id |
The unique identifier that ties an API response to a WebHook hit. |
callSID |
The Call SID for which the Insights are generated. |
summary |
The Summary of the conversation |
confidence |
A confidence score from 0 to 1 representing the confidence of the LLM(/s) in the generated insight. |
transcript |
The word to word transcript of the call. Please note that multilingual conversations are supported but the output is always given in English by default. |
categorise |
The category into which the call falls into, based on a best-fit scenario. |
sentiment |
The sentiment of the call. Values are fixed: Positive, Negative or Neutral. |