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:
Name | Type | Read-only | Mandatory | Description |
---|---|---|---|---|
agent_id | string | true | false | The id of the agent assigned to the ticket during the engagement |
agent_messages_count | integer | true | false | The number of messages sent by an agent during an engagement |
agent_replies_count | integer | true | false | The number of replies sent by an agent to an end user during an engagement |
assignment_to_first_reply_time_seconds | integer | true | false | The 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_seconds | integer | true | false | The average time between an end user response and the agent’s reply during the engagement |
channel | string | true | false | The channel name. Valid value: Messaging |
end_user_messages_count | integer | true | false | Number of messages/emails sent by an end user during an engagement |
engagement_end_reason | string | true | false | The reason an engagement ended. Valid value: UNKNOWN_REMOVE, REMOVED, INACTIVITY_TIMEOUT, AGENT_ENDED, MANUAL_REASSIGNMENT, WORK_ITEM_ON_HOLD, WORK_ITEM_SOLVED |
engagement_end_time | string | true | false | The time an engagement ended, formatted as "YYYY-MM-DD'T'hh:mm:ss" in UTC |
engagement_id | string | true | false | A unique id that is automatically assigned |
engagement_start_reason | string | true | false | The reason an engagement started. Valid values: UNKNOWN_ADD, ASSIGNED, OFFERED, ACCEPTED, MANUAL_ASSIGNED, REOPENED, ASSIGNED_TRANSFER |
engagement_start_time | string | true | false | The time an engagement started, formatted as "YYYY-MM-DD'T'hh:mm:ss" in UTC |
group_id | string | true | false | The id of the group assigned to the ticket during the engagement |
longest_requester_wait_time_seconds | integer | true | false | The longest time between an end user response and the agent’s reply during the Engagement |
offer_time_seconds | integer | true | false | The time, in seconds, between offering the ticket to the agent that eventually accepts the assignment and the agent accepting the assignment |
requester_id | integer | true | false | The user who requested this ticket |
ticket_id | string | true | false | The id of the ticket associated with the engagement |
ticket_status_end | string | true | false | The ticket's status when the engagement ended |
ticket_status_start | string | true | false | The ticket's status when the engagement started |
total_requester_wait_time_seconds | integer | true | false | The 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
Name | Type | In | Required | Description |
---|---|---|---|---|
agent_id | integer | Query | false | The id of the agent assigned to the ticket during the engagement |
channel | string | Query | false | The channel name. Valid value: Messaging |
end_time | integer | Query | true | A Unix epoch time, in milliseconds. Defaults to 0 |
page_size | integer | Query | false | The number of items returned per page. Default is 10. Maximum of 100 |
start_time | integer | Query | true | A Unix epoch time, in milliseconds. Defaults to 0 |
ticket_id | integer | Query | false | The 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 requests
from 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 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/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
Name | Type | In | Required | Description |
---|---|---|---|---|
engagement_id | string | Path | true | The 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 requests
from 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 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/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]."
}