I would like to be able to record call dispositions in our CRM system upon call completion. I set up a subscription to receive call related notifications (/restapi/v1.0/account/~/extension/~/presence?detailedTelephonyState=true&sipData=true) which seems to work fine. However, I do not see a link between notifications and call log entries which have the final disposition information attached and/or potential link to the voicemail recording. I can: 1) link notification and call log entries by sessionId for connected calls (both inbound and outbound) I cannot: 1) link "Ringing" or "NoCall" final notification to a Missed (inbound) call 2) link "Ringing" or "NoCall" final notification to a Voicemail (inbound) call 3) related to #2, I am not able to fetch the recording id I see call log ids when I list calls but they do not appear in web-hook notifications. At the same time, sessionId listed on call logs related to case #1 and #2 does not seem to be related to the web-hooks received in those cases. Is there some other way to resolve this issue?
You can use NoCall events which have an associated "CallConnected" event (associated via the sessionId property) and a duration > 0 to determine when you need to go and fetch an associated CallLog for greater detail.
Using your example from above...I created a subscription with eventFilters for presence (with detailedTelephonyState=true) and eventFilters for message-store. Then I made a call into that number and left a voicemail. Here are the events I received:
NEW INBOUND CALL IS RINGING THE EXTENSION'S PHONE NUMBER...
{ uuid: '61fa2f05-5679-4c57-a1d4-4b8fab2d8254',
event: '/restapi/v1.0/account/133128004/extension/133165004/presence?detailedTelephonyState=true',
timestamp: '2016-10-26T16:44:49.441Z',
subscriptionId: 'a8d72076-a1ce-42b3-86d7-5835ce9df152',
body:
{ extensionId: 133165004,
telephonyStatus: 'Ringing',
activeCalls:
[ { id: '448115d0d81241fcaf4fc0d0b01c0ef9',
direction: 'Inbound',
from: '+14158905908',
to: '+16505819987',
telephonyStatus: 'Ringing',
sessionId: '14860368004' },
[length]: 1 ],
sequence: 107945,
presenceStatus: 'Available',
userStatus: 'Available',
dndStatus: 'DoNotAcceptDepartmentCalls',
allowSeeMyPresence: true,
ringOnMonitoredCall: false,
pickUpCallsOnHold: false } }
RINGING HAS ENDED RESULTING IN 'NoCall' AND IS CONSIDERED FINAL...
{ uuid: 'e159d749-c8ef-48ac-984f-4a9954bc438a',
event: '/restapi/v1.0/account/133128004/extension/133165004/presence?detailedTelephonyState=true',
timestamp: '2016-10-26T16:45:09.434Z',
subscriptionId: 'a8d72076-a1ce-42b3-86d7-5835ce9df152',
body:
{ extensionId: 133165004,
telephonyStatus: 'NoCall',
activeCalls:
[ { id: '448115d0d81241fcaf4fc0d0b01c0ef9',
direction: 'Inbound',
from: '+14158905908',
to: '+16505819987',
telephonyStatus: 'NoCall',
sessionId: '14860368004',
terminationType: 'final' },
[length]: 1 ],
sequence: 107946,
presenceStatus: 'Available',
userStatus: 'Available',
dndStatus: 'DoNotAcceptDepartmentCalls',
allowSeeMyPresence: true,
ringOnMonitoredCall: false,
pickUpCallsOnHold: false } }
1. You would want to subscribe to your extension's presence events (with detailedTelephonyStatus=true on the eventFilters) and message-store events...as you have done.
2. When NoCall events come through and voicemail has been engaged, we can see a new property on the 'activeCalls' object named "terminationType" and it is set to 'final'. The Call Log entry should be added within the next 5-10 minutes. This filtered event could trigger a request queue to fetch this data from Call Log (setting the query parameters: view=Detailed&dateFrom={{TIMESTAMP_OF_NOCALL_EVENT}}) to occur 10 minutes later. By setting the view to detailed we get to see each leg of the call, in this case 'FindMe' had a result of 'NoAnswer'. By setting the dateFrom to be the time of the 'NoCall' event timestamp, we should only receive call log data which has occurred in the appropriate timeframe. We can use the sessionId to match the NoCall event to the callLog record, in this case "14860368004".
The request URL: https://platform.devtest.ringcentral.com/restapi/v1.0/account/~/extension/~/call-log?view=Detailed&a...
The result should look like this:
{ "uri": "https://platform.devtest.ringcentral.com/restapi/v1.0/account/133128004/extension/133165004/call-log...;,
"records": [
{
"uri": "https://platform.devtest.ringcentral.com/restapi/v1.0/account/133128004/extension/133165004/call-log...;,
"id": "ATquN2QNuxfWhtk",
"sessionId": "14860368004",
"startTime": "2016-10-26T16:44:41.829Z",
"duration": 100,
"type": "Voice",
"direction": "Inbound",
"action": "Phone Call",
"result": "Voicemail",
"to": {
"phoneNumber": "+1650581XXXX",
"name": "Benno Dean"
},
"from": {
"phoneNumber": "+14158905908",
"name": "SAN FRANCSCO CA",
"location": "San Francisco (Juniper), CA"
},
"transport": "PSTN",
"lastModifiedTime": "2016-10-26T16:46:40.001Z",
"legs": [
{
"startTime": "2016-10-26T16:44:41.829Z",
"duration": 100,
"type": "Voice",
"direction": "Inbound",
"action": "Phone Call",
"result": "Voicemail",
"to": {
"phoneNumber": "+1650581XXXX",
"name": "Benno Dean"
},
"from": {
"phoneNumber": "+1415890XXXX",
"name": "SAN FRANCSCO CA",
"location": "San Francisco (Juniper), CA"
},
"transport": "PSTN",
"legType": "Accept",
"extension": {
"uri": "https://platform.devtest.ringcentral.com/restapi/v1.0/account/133128004/extension/133165004";,
"id": 133165004
}
},
{
"startTime": "2016-10-26T16:44:47.582Z",
"duration": 21,
"type": "Voice",
"direction": "Outbound",
"action": "FindMe",
"result": "No Answer",
"to": {
"phoneNumber": "+1317600XXXX",
"location": "Indianapolis, IN"
},
"from": {
"phoneNumber": "+1415890XXXX",
"name": "Benno Dean"
},
"transport": "PSTN",
"legType": "FindMe",
"extension": {
"uri": "https://platform.devtest.ringcentral.com/restapi/v1.0/account/133128004/extension/133165004";,
"id": 133165004
}
}
]
}
],
"paging": {
"page": 1,
"perPage": 100,
"pageStart": 0,
"pageEnd": 0
},
"navigation": {
"firstPage": {
"uri": "https://platform.devtest.ringcentral.com/restapi/v1.0/account/133128004/extension/133165004/call-log...;
}
}
}
3. If a caller leaves a voicemail for that extension, we will receive a subsequent message-store event of type "VoiceMail" when a voicemail has been created. You can wait for this event and see if extensionId matches and is within a reasonable amount of time delta from the NoCall event (max of 10 minutes should be reasonable). The extensionId value can be used to match the two events (although you are correct, the sessionId is not present in the message-store event).
CALLER LEFT A VOICEMAIL, NEW MESSAGE STORE EVENT RECEIVED...
{ uuid: 'bc8cfb3d-661e-4393-9210-f3ff5be73ebc',
event: '/restapi/v1.0/account/133128004/extension/133165004/message-store',
timestamp: '2016-10-26T16:46:29.437Z',
subscriptionId: 'a8d72076-a1ce-42b3-86d7-5835ce9df152',
body:
{ extensionId: 133165004,
lastUpdated: '2016-10-26T16:46:22.553+0000',
changes:
[ { type: 'VoiceMail', newCount: 1, updatedCount: 0 },
[length]: 1 ] } }
We can use this event to trigger a GET request to the event URI (message-store entry containing the voicemail), which will respond with the following type of data (below). We can use the from.phoneNumber and to.phoneNumber to match this data to the NoCall event we received.
[ {
"uri": "https://platform.devtest.ringcentral.com/restapi/v1.0/account/133128004/extension/133165004/message-...;,
"id": 2074108004,
"to": [
{
"phoneNumber": "+1650581XXXX",
"name": "(650) 581-9987 (Benno Dean)",
"location": "San Mateo, CA"
}
],
"from": {
"phoneNumber": "+1415890XXXX",
"name": "SAN FRANCSCO CA"
},
"type": "VoiceMail",
"creationTime": "2016-10-26T16:46:22.000Z",
"readStatus": "Unread",
"priority": "Normal",
"attachments": [
{
"id": 2074108004,
"uri": "https://media.devtest.ringcentral.com/restapi/v1.0/account/133128004/extension/133165004/message-sto...;,
"type": "AudioRecording",
"contentType": "audio/mpeg",
"vmDuration": 58
}
],
"direction": "Inbound",
"availability": "Alive",
"messageStatus": "Received",
"lastModifiedTime": "2016-10-26T16:46:22.553Z",
"vmTranscriptionStatus": "NotAvailable"
}
]
As far as answering your question about not being able to fetch the "recording" of a VoiceMail, I agree that can be confusing for developers, and here is why...
Call Recordings === Call Log.Recordings
VoiceMails === Message-Store.Entries of type "VoiceMail"
The disambiguation between Call Recordings and VoiceMail is:
Call Recordings are audio files which are created when a call is answered, and the agent either presses the "Record" button -or- the account has automatic call recording configured. Call recordings are ONLY saved when the length of the call recording > 30 seconds. These audio call recording files (and related metadata for these audio call recordings) are accessible from the Call Log API resource.
VoiceMails are audio files which are created when a call is NOT answered. These audio voice mail files (and related metadata) are accessible from the Message-Store API resource.
I know there is a lot to consume here, but after reading it...does all this make sense to you and answer your questions?
Reply
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.