Omnichannel Engagements

The Engagements API extracts data about agent interactions with tickets over the course of the ticket's lifecycle. An engagement is the interaction between the agent assigned to the ticket and one end user within a single channel. Engagement data is available after the engagement ends.

The Engagements API is currently part of an early access program. For more information, see Using the omnichannel routing Engagements API.

Data Retention

The Omnichannel Engagements API allows you to extract data only from the previous 90 days.

JSON format

Omnichannel Engagements are represented as JSON objects with the following properties:

NameTypeRead-onlyMandatoryDescription
agent_idstringtruefalseThe id of the agent assigned to the ticket during the engagement
agent_messages_countintegertruefalseThe number of messages sent by an agent during an engagement
agent_replies_countintegertruefalseThe number of replies sent by an agent to an end user during an engagement
assignment_to_first_reply_time_secondsintegertruefalseThe time, in seconds, from the ticket being assigned to an agent to the agent’s first response. Excludes offer state and engagements that begin outside of business hours
average_requester_wait_time_secondsintegertruefalseThe average time between an end user response and the agent’s reply during the engagement
channelstringtruefalseThe channel name. Valid value: Messaging
end_user_messages_countintegertruefalseNumber of messages/emails sent by an end user during an engagement
engagement_end_reasonstringtruefalseThe reason an engagement ended. Valid value: UNKNOWN_REMOVE, REMOVED, INACTIVITY_TIMEOUT, AGENT_ENDED, MANUAL_REASSIGNMENT, WORK_ITEM_ON_HOLD, WORK_ITEM_SOLVED
engagement_end_timestringtruefalseThe time an engagement ended, formatted as "YYYY-MM-DD'T'hh:mm:ss" in UTC
engagement_idstringtruefalseA unique id that is automatically assigned
engagement_start_reasonstringtruefalseThe reason an engagement started. Valid values: UNKNOWN_ADD, ASSIGNED, OFFERED, ACCEPTED, MANUAL_ASSIGNED, REOPENED, ASSIGNED_TRANSFER
engagement_start_timestringtruefalseThe time an engagement started, formatted as "YYYY-MM-DD'T'hh:mm:ss" in UTC
group_idstringtruefalseThe id of the group assigned to the ticket during the engagement
longest_requester_wait_time_secondsintegertruefalseThe longest time between an end user response and the agent’s reply during the Engagement
offer_time_secondsintegertruefalseThe time, in seconds, between offering the ticket to the agent that eventually accepts the assignment and the agent accepting the assignment
requester_idintegertruefalseThe user who requested this ticket
ticket_idstringtruefalseThe id of the ticket associated with the engagement
ticket_status_endstringtruefalseThe ticket's status when the engagement ended
ticket_status_startstringtruefalseThe ticket's status when the engagement started
total_requester_wait_time_secondsintegertruefalseThe total time, in seconds, between when the end user sent their latest response to the time the agent replies, across all active conversations

List Engagements

  • GET /api/v2/engagements?end_time={end_time}&start_time={start_time}

Returns a list of engagements.

Allowed For

  • Admins

Pagination and Polling

The list of engagements returned by this request is filtered by engagement_start_time and engagement_end_time. Because of how large this dataset is, we use cursor-based pagination rather than offset-based pagination. This data can be paginated by engagement_start_time and engagement_id as cursors. The next_page URL is provided in the response to enable fetching the next page.

Parameters

NameTypeInRequiredDescription
agent_idintegerQueryfalseThe id of the agent assigned to the ticket during the engagement
channelstringQueryfalseThe channel name. Valid value: Messaging
end_timeintegerQuerytrueA Unix epoch time, in milliseconds. Defaults to 0
page_sizeintegerQueryfalseThe number of items returned per page. Default is 10. Maximum of 100
start_timeintegerQuerytrueA Unix epoch time, in milliseconds. Defaults to 0
ticket_idintegerQueryfalseThe id of the ticket associated with the engagement

Code Samples

cURL
curl 'https://{subdomain}.zendesk.com/api/v2/engagements?start_time={start_time}&end_time={end_time}&ticket_id={ticket_id}&agent_id={agent_id}&channel={channel}&page_size={page_size}' \  -v -u {email_address}/token:{api_token}
Go
import (	"fmt"	"io"	"net/http")
func main() {	url := "https://support.zendesk.com/api/v2/engagements?agent_id=1&channel=Messaging&end_time=1630003600&page_size=10&start_time=1630000000&ticket_id=12345"	method := "GET"	req, err := http.NewRequest(method, url, nil)
	if err != nil {		fmt.Println(err)		return	}	req.Header.Add("X-Zendesk-Doorman", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...")	req.Header.Add("X-Zendesk-Doorman-Auth-Response", "200")	req.Header.Add("X-Zendesk-Original-Uri", "https://example.com/original/uri")	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/engagements")		.newBuilder()		.addQueryParameter("agent_id", "1")		.addQueryParameter("channel", "Messaging")		.addQueryParameter("end_time", "1630003600")		.addQueryParameter("page_size", "10")		.addQueryParameter("start_time", "1630000000")		.addQueryParameter("ticket_id", "12345");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("X-Zendesk-Doorman", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...")		.addHeader("X-Zendesk-Doorman-Auth-Response", "200")		.addHeader("X-Zendesk-Original-Uri", "https://example.com/original/uri")		.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/engagements',  headers: {	'X-Zendesk-Doorman': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...',	'X-Zendesk-Doorman-Auth-Response': '200',	'X-Zendesk-Original-Uri': 'https://example.com/original/uri',	'Content-Type': 'application/json',	'Authorization': 'Basic <auth-value>', // Base64 encoded "{email_address}/token:{api_token}"  },  params: {    'agent_id': '1',    'channel': 'Messaging',    'end_time': '1630003600',    'page_size': '10',    'start_time': '1630000000',    'ticket_id': '12345',  },};
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/engagements?agent_id=1&channel=Messaging&end_time=1630003600&page_size=10&start_time=1630000000&ticket_id=12345"headers = {	"X-Zendesk-Doorman": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...",	"X-Zendesk-Doorman-Auth-Response": "200",	"X-Zendesk-Original-Uri": "https://example.com/original/uri",	"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/engagements")uri.query = URI.encode_www_form("agent_id": "1", "channel": "Messaging", "end_time": "1630003600", "page_size": "10", "start_time": "1630000000", "ticket_id": "12345")request = Net::HTTP::Get.new(uri, "X-Zendesk-Doorman": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...", "X-Zendesk-Doorman-Auth-Response": "200", "X-Zendesk-Original-Uri": "https://example.com/original/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
{  "agent_engagement_data": [    {      "agent_id": "1",      "agent_messages_count": 10,      "agent_replies_count": 5,      "assignment_to_first_reply_time_seconds": 180,      "average_requester_wait_time_seconds": 100,      "channel": "Messaging",      "end_user_messages_count": 25,      "engagement_end_reason": "agent_ended",      "engagement_end_time": "2018-10-19T14:34:09.989524Z",      "engagement_id": "R6vTXhl.agent:980824.y7Q4aI",      "engagement_start_reason": "Assignment",      "engagement_start_time": "2018-10-19T12:33:50.140101Z",      "group_id": "1234",      "longest_requester_wait_time_seconds": 600,      "offer_time_seconds": 120,      "requester_id": 1234,      "ticket_id": "12345",      "ticket_status_end": "Pending",      "ticket_status_start": "New",      "total_requester_wait_time_seconds": 600    }  ],  "has_more": true,  "next_page_url": "http://HOST:8080/api/v2/engagement?start_time=1731326400000&end_time=1731333600000&startTimeCursor=1731328052000&engagementIdCursor=ENG961289&pageSize=10",  "page_size": 10}
400 Bad Request
// Status 400 Bad Request
{  "error": "start_time and end_time must be provided."}
401 Unauthorized
// Status 401 Unauthorized
{  "error": "Could not authenticate the request. Doorman auth response code:<response_code>"}
500 Internal Server Error
// Status 500 Internal Server Error
{  "error": "Unhandled error:[error message]"}

Get Engagement by ID

  • GET /api/v2/engagements/{engagement_id}

Returns information about the specified engagement.

Allowed For

  • Admins

Parameters

NameTypeInRequiredDescription
engagement_idstringPathtrueThe id of the engagement

Code Samples

cURL
curl 'https://{subdomain}.zendesk.com/api/v2/engagements/{engagement_id}' \  -v -u {email_address}/token:{api_token}
Go
import (	"fmt"	"io"	"net/http")
func main() {	url := "https://support.zendesk.com/api/v2/engagements/R6vTXhl.agent:980824.y7Q4aI"	method := "GET"	req, err := http.NewRequest(method, url, nil)
	if err != nil {		fmt.Println(err)		return	}	req.Header.Add("X-Zendesk-Doorman", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...")	req.Header.Add("X-Zendesk-Doorman-Auth-Response", "200")	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/engagements/R6vTXhl.agent:980824.y7Q4aI")		.newBuilder();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("X-Zendesk-Doorman", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...")		.addHeader("X-Zendesk-Doorman-Auth-Response", "200")		.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/engagements/R6vTXhl.agent:980824.y7Q4aI',  headers: {	'X-Zendesk-Doorman': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...',	'X-Zendesk-Doorman-Auth-Response': '200',	'Content-Type': 'application/json',	'Authorization': 'Basic <auth-value>', // Base64 encoded "{email_address}/token:{api_token}"  },};
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/engagements/R6vTXhl.agent:980824.y7Q4aI"headers = {	"X-Zendesk-Doorman": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...",	"X-Zendesk-Doorman-Auth-Response": "200",	"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/engagements/R6vTXhl.agent:980824.y7Q4aI")request = Net::HTTP::Get.new(uri, "X-Zendesk-Doorman": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijp7ImlkIj...", "X-Zendesk-Doorman-Auth-Response": "200", "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
{  "agent_id": "1",  "agent_messages_count": 10,  "agent_replies_count": 5,  "assignment_to_first_reply_time_seconds": 180,  "average_requester_wait_time_seconds": 100,  "channel": "Messaging",  "end_user_messages_count": 25,  "engagement_end_reason": "agent_ended",  "engagement_end_time": "2018-10-19T14:34:09.989524Z",  "engagement_id": "R6vTXhl.agent:980824.y7Q4aI",  "engagement_start_reason": "Assignment",  "engagement_start_time": "2018-10-19T12:33:50.140101Z",  "group_id": "1234",  "longest_requester_wait_time_seconds": 600,  "offer_time_seconds": 120,  "requester_id": 1234,  "ticket_id": "12345",  "ticket_status_end": "Pending",  "ticket_status_start": "New",  "total_requester_wait_time_seconds": 600}
400 Bad Request
// Status 400 Bad Request
{  "error": "engagement_id must be a positive long integer."}
401 Unauthorized
// Status 401 Unauthorized
{  "error": "Could not authenticate the request. Doorman auth response code:<response_code>"}
500 Internal Server Error
// Status 500 Internal Server Error
{  "error": "Unhandled error :[error message]."}