Incremental Exports
You can use the Incremental Exports API to export a complete list of information on inbound and outbound calls from your Zendesk Talk instance, then periodically (incrementally) fetch items that have been created or updated since the previous fetch.
See the Support API Incremental Export documentation for general information on Zendesk incremental APIs, including detailed usage notes and examples.
Request Parameters
The incremental export endpoints take a required start_time
parameter expressed as a Unix epoch time. Example:
GET /api/v2/channels/voice/stats/incremental/calls?start_time=1547635159
Pagination and Polling
For both pagination (during the initial export) and polling (periodic requests for new data), use the next_page
URL.
The next_page
URL contains start_time
parameter that matches the end_time
of the previous response, but it is recommended that this URL be treated as an opaque string. This is similar to the Incremental Export API in Zendesk Support, which also uses start_time
and end_time
.
Unlike other endpoints that return null as the value of next_page
when reaching the last page of the result set, these endpoints return the URL that should be used for the next export. You should use the count property to determine whether more items are available immediately.
Rate limits
You can make up to 10 requests per minute to these endpoints.
The rate limiting mechanism behaves identically to the one described in Rate Limits in the Support API introduction. We recommend using the Retry-After
header value as described in Catching errors caused by rate limiting.
If you find yourself bumping into the rate limit when testing the API, see Incremental Sample Export below to test the API without getting throttled continuously.
JSON format
Incremental Exports are represented as JSON objects with the following properties:
Name | Type | Read-only | Mandatory | Description |
---|---|---|---|---|
count | integer | true | false | The number of results returned for the current request |
end_time | integer | true | false | The most recent time present in this result set in Unix epoch time. This is used as the start_time in the next_page URL |
next_page | string | true | false | The URL that should be called to get the next set of results |
Incremental Calls Export
GET /api/v2/channels/voice/stats/incremental/calls?start_time={start_time}
Allowed For
- Admins
- Agents with
Can manage channels
permission
Fields
The exported items are represented as JSON objects with the following properties.
Name | Type | Description |
---|---|---|
agent_id | integer | The id of the first agent who picked up the call |
call_charge | string | Total charge for the call. String representation of a decimal number with six decimal places. Example: "1.230000". Null if no charge was received from Twilio |
call_group_id | integer | The id number of the group the call was last placed in before completion. |
call_recording_consent | string | Call recording consent value configured for the phone number. Allowed values are "always", "opt_in", "opt_out" or "never" |
call_recording_consent_action | string | Call recording consent option selected by the caller. Allowed values are "caller_opted_in", "caller_opted_out" or "null" |
call_recording_consent_keypress | string | Keypress the caller chose to give their call recording consent option. Allowed values are "3" or "null" |
callback | boolean | True if the call was initiated by a callback request from the customer |
callback_source | string | The source of the callback request. Allowed values are "null", "queue" or "web_widget" |
completion_status | string | Status of the call. Allowed values are "completed", "abandoned_in_queue", "abandoned_in_ivr", "abandoned_in_voicemail", "abandoned_on_hold", "pending_voicemail", or "failed" |
consultation_time | integer | Sum of how long in seconds agents consulted with each other while the customer was on hold |
created_at | date | When the call object was created |
customer_requested_voicemail | boolean | The customer requested to be directed to voicemail instead of waiting for an agent to answer |
default_group | boolean | The call was answered by an agent who is a member of the call's default group, if group routing is used |
direction | string | Inbound or outbound. The agent or customer who initialized the call |
duration | integer | Call duration in seconds |
exceeded_queue_time | boolean | The customer exceeded the maximum queue wait time and did not speak with an agent |
hold_time | integer | Sum of how long in seconds the customer was placed on hold by an agent(s) |
id | integer | Call id |
ivr_action | string | Menu action that was used by the caller in the IVR menu selection. Possible values: "null" (if IVR is not used), "menu", "voicemail", "group", "phone_number", "textback", "invalid" (returned for an invalid keypress) |
ivr_destination_group_name | string | Name of the group that received the call through IVR routing. null if IVR is disabled |
ivr_hops | integer | How many menu options the customer went through in IVR before talking to an agent. null if IVR is disabled |
ivr_routed_to | string | Phone number where call was routed to by IVR. Example: "+1311123456789". null if IVR is disabled |
ivr_time_spent | integer | How long in seconds the customer spent in IVR. Null if IVR is disabled |
minutes_billed | integer | Minutes billed |
not_recording_time | integer | How long in seconds spent not recording on the call. |
outside_business_hours | boolean | The call was received outside business hours |
overflowed | boolean | True if the call overflowed |
overflowed_to | string | The phone number that the call overflowed to. null if overflowed is false |
phone_number | string | Talk phone associated with the call. If this a digital line, the digital line nickname. Example: "+1311123456789". If this a SIP line, the SIP line address. Example: "[email protected]" |
phone_number_id | integer | Talk phone number id |
quality_issues | array | A summary of the call's quality issues related to the call provided to Zendesk from Twilio. Until the information is made available by Twilio, the array contains "information_not_available". If there are no issues, the array contains "none". Other possible values: one or more of "silence", "high_jitter", "high_packet_loss", "high_pdd", "high_latency" |
recording_control_interactions | integer | The amount of times agents have paused or resumed a recording on the call. |
recording_time | integer | How long in seconds spent recording on the call |
talk_time | integer | Sum of how long in seconds the customer was in conference with an agent(s). If a call is not accepted by an agent this will be 0 |
ticket_id | integer | The id of the ticket related to the call |
time_to_answer | integer | How long in seconds the customer waited for an agent to answer after hearing the Available agents greeting |
updated_at | date | When the call object was last created |
voicemail | boolean | If true, the call was a voicemail |
wait_time | integer | How long in seconds the customer was in the call before an agent answered |
wrap_up_time | integer | Sum of how long in seconds the agent(s) spent in wrap up |
call_channel | string | Channel the call came in. Allowed values are "phone", "mobile-sdk", "web-widget", "messaging-widget", "messaging-mobile-sdk", or "sip" |
line_type | string | Type of line the call originated from. Allowed values are "phone", "digital", or "sip" |
post_call_transcription_created | boolean | If true, the post call transcription has been created |
post_call_summary_created | boolean | If true, the post call summary has been created |
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
start_time | integer | Query | true | The time of the oldest Talk call you're interested in. The call can be inbound or outbound. Returns Talk calls modified on or since this time. |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/v2/channels/voice/stats/incremental/calls.json?start_time=1547635159
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/v2/channels/voice/stats/incremental/calls?start_time=1547635159"
method := "GET"
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Basic <auth-value>") // Base64 encoded "{email_address}/token:{api_token}"
client := &http.Client {}
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
Java
import com.squareup.okhttp.*;
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://support.zendesk.com/api/v2/channels/voice/stats/incremental/calls")
.newBuilder()
.addQueryParameter("start_time", "1547635159");
String userCredentials = "your_email_address" + "/token:" + "your_api_token";
String basicAuth = "Basic " + java.util.Base64.getEncoder().encodeToString(userCredentials.getBytes());
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", basicAuth)
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://support.zendesk.com/api/v2/channels/voice/stats/incremental/calls',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic <auth-value>', // Base64 encoded "{email_address}/token:{api_token}"
},
params: {
'start_time': '1547635159',
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
from requests.auth import HTTPBasicAuth
url = "https://support.zendesk.com/api/v2/channels/voice/stats/incremental/calls?start_time=1547635159"
headers = {
"Content-Type": "application/json",
}
email_address = 'your_email_address'
api_token = 'your_api_token'
# Use basic authentication
auth = HTTPBasicAuth(f'{email_address}/token', api_token)
response = requests.request(
"GET",
url,
auth=auth,
headers=headers
)
print(response.text)
Ruby
require "net/http"
require "base64"
uri = URI("https://support.zendesk.com/api/v2/channels/voice/stats/incremental/calls")
uri.query = URI.encode_www_form("start_time": "1547635159")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
email = "your_email_address"
api_token = "your_api_token"
credentials = "#{email}/token:#{api_token}"
encoded_credentials = Base64.strict_encode64(credentials)
request["Authorization"] = "Basic #{encoded_credentials}"
response = Net::HTTP.start uri.hostname, uri.port, use_ssl: true do |http|
http.request(request)
end
Example response(s)
200 OK
// Status 200 OK
{
"calls": [
{
"agent_id": 10011,
"call_charge": "0.025",
"call_recording_consent": "opt_in",
"call_recording_consent_action": "caller_opted_in",
"call_recording_consent_keypress": "3",
"callback": false,
"callback_source": null,
"completion_status": "completed",
"consultation_time": 0,
"created_at": "2019-01-16T10:36:56Z",
"customer_id": 10032,
"customer_requested_voicemail": false,
"default_group": false,
"direction": "inbound",
"duration": 76,
"exceeded_queue_wait_time": false,
"hold_time": 0,
"id": 10217,
"ivr_action": null,
"ivr_destination_group_name": null,
"ivr_hops": null,
"ivr_routed_to": null,
"ivr_time_spent": null,
"line": "+13308828232",
"line_id": 10062,
"line_type": "phone",
"minutes_billed": 2,
"not_recording_time": 5,
"outside_business_hours": false,
"overflowed": false,
"overflowed_to": null,
"phone_number": "+13308828232",
"phone_number_id": 10062,
"post_call_summary_created": true,
"post_call_transcription_created": true,
"quality_issues": [
"high_pdd",
"high_jitter"
],
"recording_control_interactions": 5,
"recording_time": 25,
"talk_time": 15,
"ticket_id": 5,
"time_to_answer": 60,
"updated_at": "2019-01-16T10:39:19Z",
"voicemail": false,
"wait_time": 35,
"wrap_up_time": 0
}
],
"count": 1,
"end_time": 1547635159,
"next_page": "https://subdomain.zendesk.com/api/v2/channels/voice/stats/incremental/calls.json?start_time=1547635159"
}
Incremental Call Legs Export
GET /api/v2/channels/voice/stats/incremental/legs?start_time={start_time}
A call leg is a logical connection between two voice gateways or between a gateway and an IP telephony device.
Allowed For
- Admins
- Agents with
Can manage channels
permission
Fields
Legs are a subsection of calls and return information specific to each agent that interacted with the call, or any action the system took on the call.
Name | Type | Description |
---|---|---|
agent_id | integer | Id of the agent associated with this part of the call. When agent_id is positive, then user_id must be 0 and the type is "agent_leg" |
available_via | string | Ways the agent is available for incoming calls. It can be null on customer leg. Allowed values are "browser" or "phone" |
call_charge | string | Call charge on the leg. String representation of a decimal number with six decimal places. Example: "1.230000" |
call_id | integer | Call id |
completion_status | string | Completion status of the leg. Allowed values are "agent_declined", "agent_missed", "agent_transfer_declined", "customer_hang_up" or "completed" |
conference_from | integer | id of agent who initiated the third-party conference |
conference_time | integer | Time that agent spent in third-party conference (if call has multiple conferences we will sum the conference time) |
conference_to | integer | id of user or agent who joined the third-party conference |
consultation_from | integer | id of the agent who requested the consultation |
consultation_time | integer | How long the agent consulted with another agent while the customer was on hold. null if there was no consultation |
consultation_to | integer | The id of the agent who received and accepted the consultation request. null if there was no transfer |
created_at | date | When the leg object was created |
duration | integer | How long in seconds the leg existed |
forwarded_to | string | Phone number the call was forwarded to. Example: "+1311123456789". It can be null on customer leg |
hold_time | integer | How long in seconds the leg existed |
id | integer | Leg id |
minutes_billed | integer | Minutes billed |
quality_issues | array | A summary of the call's quality issues related to the call provided to Zendesk from Twilio. Until the information is made available by Twilio, the array contains "information_not_available". If there are no issues, the array contains "none". Other possible values: one or more of "silence", "high_jitter", "high_packet_loss", "high_pdd", "high_latency" |
talk_time | integer | How long in seconds the agent was in conference with the customer for this leg |
transferred_from | integer | The id of the agent who initialized the transfer. This value must be 0 on the first agent's leg. null if there was no transfer |
transferred_to | integer | The id of the agent who received and accepted the transfer request |
type | string | The type of the leg. Allowed values are "customer", "agent", "external" or "supervisor" |
updated_at | date | When the leg object was last updated |
user_id | integer | Id of the customer or user associated with this part of the call. When user_id is positive then agent_id must be 0 and the type is customer_leg |
wrap_up_time | integer | How long in seconds the leg was in wrap up. It can be null on customer leg |
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
start_time | integer | Query | true | The time of the oldest Talk call you're interested in. The call can be inbound or outbound. Returns Talk calls modified on or since this time. |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/v2/channels/voice/stats/incremental/legs.json?start_time=1547635159
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/v2/channels/voice/stats/incremental/legs?start_time=1547635159"
method := "GET"
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Basic <auth-value>") // Base64 encoded "{email_address}/token:{api_token}"
client := &http.Client {}
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
Java
import com.squareup.okhttp.*;
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://support.zendesk.com/api/v2/channels/voice/stats/incremental/legs")
.newBuilder()
.addQueryParameter("start_time", "1547635159");
String userCredentials = "your_email_address" + "/token:" + "your_api_token";
String basicAuth = "Basic " + java.util.Base64.getEncoder().encodeToString(userCredentials.getBytes());
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", basicAuth)
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://support.zendesk.com/api/v2/channels/voice/stats/incremental/legs',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic <auth-value>', // Base64 encoded "{email_address}/token:{api_token}"
},
params: {
'start_time': '1547635159',
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
from requests.auth import HTTPBasicAuth
url = "https://support.zendesk.com/api/v2/channels/voice/stats/incremental/legs?start_time=1547635159"
headers = {
"Content-Type": "application/json",
}
email_address = 'your_email_address'
api_token = 'your_api_token'
# Use basic authentication
auth = HTTPBasicAuth(f'{email_address}/token', api_token)
response = requests.request(
"GET",
url,
auth=auth,
headers=headers
)
print(response.text)
Ruby
require "net/http"
require "base64"
uri = URI("https://support.zendesk.com/api/v2/channels/voice/stats/incremental/legs")
uri.query = URI.encode_www_form("start_time": "1547635159")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
email = "your_email_address"
api_token = "your_api_token"
credentials = "#{email}/token:#{api_token}"
encoded_credentials = Base64.strict_encode64(credentials)
request["Authorization"] = "Basic #{encoded_credentials}"
response = Net::HTTP.start uri.hostname, uri.port, use_ssl: true do |http|
http.request(request)
end
Example response(s)
200 OK
// Status 200 OK
{
"count": 2,
"end_time": 1547635159,
"legs": [
{
"agent_id": 0,
"available_via": null,
"call_charge": "0.019",
"call_id": 10217,
"completion_status": "completed",
"conference_from": null,
"conference_time": null,
"conference_to": null,
"consultation_from": null,
"consultation_time": null,
"consultation_to": null,
"created_at": "2019-01-16T10:36:56Z",
"duration": 76,
"forwarded_to": null,
"hold_time": 0,
"id": 10402,
"minutes_billed": 2,
"quality_issues": [
"high_pdd"
],
"talk_time": 15,
"transferred_from": null,
"transferred_to": null,
"type": "customer",
"updated_at": "2019-01-16T10:39:19Z",
"user_id": 10032,
"wrap_up_time": null
},
{
"agent_id": 10011,
"available_via": "browser",
"call_charge": "0.003",
"call_id": 10217,
"completion_status": "completed",
"conference_from": null,
"conference_time": null,
"conference_to": null,
"consultation_from": null,
"consultation_time": null,
"consultation_to": null,
"created_at": "2019-01-16T10:37:30Z",
"duration": 109,
"forwarded_to": null,
"hold_time": 0,
"id": 10407,
"minutes_billed": 2,
"quality_issues": [
"none"
],
"talk_time": 14,
"transferred_from": null,
"transferred_to": null,
"type": "agent",
"updated_at": "2019-01-16T10:39:19Z",
"user_id": 0,
"wrap_up_time": 0
}
],
"next_page": "https://subdomain.zendesk.com/api/v2/channels/voice/stats/incremental/legs.json?start_time=1547635159"
}