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:

NameTypeRead-onlyMandatoryDescription
countintegertruefalseThe number of results returned for the current request
end_timeintegertruefalseThe 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_pagestringtruefalseThe 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.

NameTypeDescription
agent_idintegerThe id of the first agent who picked up the call
call_chargestringTotal 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_idintegerThe id number of the group the call was last placed in before completion.
call_recording_consentstringCall recording consent value configured for the phone number. Allowed values are "always", "opt_in", "opt_out" or "never"
call_recording_consent_actionstringCall recording consent option selected by the caller. Allowed values are "caller_opted_in", "caller_opted_out" or "null"
call_recording_consent_keypressstringKeypress the caller chose to give their call recording consent option. Allowed values are "3" or "null"
callbackbooleanTrue if the call was initiated by a callback request from the customer
callback_sourcestringThe source of the callback request. Allowed values are "null", "queue" or "web_widget"
completion_statusstringStatus of the call. Allowed values are "completed", "abandoned_in_queue", "abandoned_in_ivr", "abandoned_in_voicemail", "abandoned_on_hold", "pending_voicemail", or "failed"
consultation_timeintegerSum of how long in seconds agents consulted with each other while the customer was on hold
created_atdateWhen the call object was created
customer_requested_voicemailbooleanThe customer requested to be directed to voicemail instead of waiting for an agent to answer
default_groupbooleanThe call was answered by an agent who is a member of the call's default group, if group routing is used
directionstringInbound or outbound. The agent or customer who initialized the call
durationintegerCall duration in seconds
exceeded_queue_timebooleanThe customer exceeded the maximum queue wait time and did not speak with an agent
hold_timeintegerSum of how long in seconds the customer was placed on hold by an agent(s)
idintegerCall id
ivr_actionstringMenu 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_namestringName of the group that received the call through IVR routing. null if IVR is disabled
ivr_hopsintegerHow many menu options the customer went through in IVR before talking to an agent. null if IVR is disabled
ivr_routed_tostringPhone number where call was routed to by IVR. Example: "+1311123456789". null if IVR is disabled
ivr_time_spentintegerHow long in seconds the customer spent in IVR. Null if IVR is disabled
minutes_billedintegerMinutes billed
not_recording_timeintegerHow long in seconds spent not recording on the call.
outside_business_hoursbooleanThe call was received outside business hours
overflowedbooleanTrue if the call overflowed
overflowed_tostringThe phone number that the call overflowed to. null if overflowed is false
phone_numberstringTalk phone associated with the call. If this a digital line, the digital line nickname. Example: "+1311123456789"
phone_number_idintegerTalk phone number id
quality_issuesarrayA 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_interactionsintegerThe amount of times agents have paused or resumed a recording on the call.
recording_timeintegerHow long in seconds spent recording on the call
talk_timeintegerSum 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_idintegerThe id of the ticket related to the call
time_to_answerintegerHow long in seconds the customer waited for an agent to answer after hearing the Available agents greeting
updated_atdateWhen the call object was last created
voicemailbooleanIf true, the call was a voicemail
wait_timeintegerHow long in seconds the customer was in the call before an agent answered
wrap_up_timeintegerSum of how long in seconds the agent(s) spent in wrap up
call_channelstringChannel the call came in. Allowed values are "phone", "mobile-sdk", "web-widget", "messaging-widget", or "messaging-mobile-sdk"
line_typestringType of line the call originated from. Allowed values are "phone" or "digital"
post_call_transcription_createdbooleanIf true, the post call transcription has been created
post_call_summary_createdbooleanIf true, the post call summary has been created

Parameters

NameTypeInRequiredDescription
start_timeintegerQuerytrueThe 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 requestsfrom 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 authenticationauth = 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.

NameTypeDescription
agent_idintegerId 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_viastringWays the agent is available for incoming calls. It can be null on customer leg. Allowed values are "browser" or "phone"
call_chargestringCall charge on the leg. String representation of a decimal number with six decimal places. Example: "1.230000"
call_idintegerCall id
completion_statusstringCompletion status of the leg. Allowed values are "agent_declined", "agent_missed", "agent_transfer_declined", "customer_hang_up" or "completed"
conference_fromintegerid of agent who initiated the third-party conference
conference_timeintegerTime that agent spent in third-party conference (if call has multiple conferences we will sum the conference time)
conference_tointegerid of user or agent who joined the third-party conference
consultation_fromintegerid of the agent who requested the consultation
consultation_timeintegerHow long the agent consulted with another agent while the customer was on hold. null if there was no consultation
consultation_tointegerThe id of the agent who received and accepted the consultation request. null if there was no transfer
created_atdateWhen the leg object was created
durationintegerHow long in seconds the leg existed
forwarded_tostringPhone number the call was forwarded to. Example: "+1311123456789". It can be null on customer leg
hold_timeintegerHow long in seconds the leg existed
idintegerLeg id
minutes_billedintegerMinutes billed
quality_issuesarrayA 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_timeintegerHow long in seconds the agent was in conference with the customer for this leg
transferred_fromintegerThe 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_tointegerThe id of the agent who received and accepted the transfer request
typestringThe type of the leg. Allowed values are "customer", "agent", "external" or "supervisor"
updated_atdateWhen the leg object was last updated
user_idintegerId 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_timeintegerHow long in seconds the leg was in wrap up. It can be null on customer leg

Parameters

NameTypeInRequiredDescription
start_timeintegerQuerytrueThe 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 requestsfrom 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 authenticationauth = 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"}