Ticket Audits
Audits are a read-only history of all updates to a ticket. When a ticket is updated in Zendesk Support, an audit is stored. Each audit represents a single update to the ticket. An update can consist of one or more events. Examples:
- The value of a ticket field was changed
- A new comment was added
- Tags were added or removed
- A notification was sent
For a complete list, see the Ticket Audit events reference.
Required OAuth scope
The Ticket Audits endpoints require a global "read" scope for OAuth authentication. You can't access the endpoints using the "auditlogs:read" or "tickets:read" scopes.
JSON format
Ticket Audits are represented as JSON objects with the following properties:
Name | Type | Read-only | Mandatory | Description |
---|---|---|---|---|
author_id | integer | true | false | The user who created the audit |
created_at | string | true | false | The time the audit was created |
events | array | false | false | An array of the events that happened in this audit. See the Ticket Audit events reference |
id | integer | true | false | Automatically assigned when creating audits |
metadata | object | true | false | Metadata for the audit, custom and system data |
ticket_id | integer | true | false | The ID of the associated ticket |
via | object | false | false | Describes how the object was created. See the Via object reference |
Example
{
"author_id": 35436,
"created_at": "2009-07-20T22:55:29Z",
"events": [
{
"attachments": [],
"body": "Thanks for your help!",
"id": 1564245,
"public": true,
"type": "Comment"
},
{
"body": "Ticket #47 has been updated",
"id": 1564246,
"subject": "Your ticket has been updated",
"type": "Notification"
}
],
"id": 35436,
"metadata": {
"custom": {
"time_spent": "3m22s"
},
"system": {
"ip_address": "184.106.40.75"
}
},
"ticket_id": 47,
"via": {
"channel": "web"
}
}
List All Ticket Audits
GET /api/v2/ticket_audits
GET /api/v2/ticket_audits.json?cursor=fDE1MDE1OTE1MzQuMHx8MTEzMjQ4NDI1MQ%3D%3D
Returns ticket audits. Archived tickets are not included in the response. Use the List Audits for a Ticket endpoint to retrieve audit records for an archived ticket. To learn more about archived tickets, see About archived tickets.
This endpoint should not be used for capturing change data. When continually chasing the tail of a cursor, some records will be skipped. For this use case, use the Incremental Ticket Event Export API.
Pagination
This API supports two cursor-based pagination methods:
- standard Zendesk cursor-based pagination
- legacy 'cursor' parameter based pagination
Zendesk recommends using the standard cursor-based pagination method. The legacy method has known problems.
Legacy cursor pagination method
By default, this endpoint uses the legacy cursor pagination method. This method differs from the standard cursor pagination used in other Zendesk endpoints.
The records are ordered sequentially by the created_at
timestamp, then by id within duplicate timestamp values. The first page will return the most recent audits.
The cursor
parameter is a non-human-readable argument you can use to move forward or backward in time.
Each JSON response will contain the following attributes to help you get more results:
after_url
requests more recent resultsbefore_url
requests older resultsafter_cursor
is the cursor to build the request yourselfbefore_cursor
is the cursor to build the request yourself.
The after_cursor
and before_cursor
attributes may contain non-URL-safe characters. Make sure to URL-encode them, or simply use the after_url
or before_url
values to paginate.
The properties are null if no more records are available.
You can request a maximum of 1,000 results. The default number of results is 1,000, but you can change it with the limit
parameter.
Allowed For
- Admins
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
limit | integer | Query | false | Maximum number of results returned |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/v2/ticket_audits.json?limit=1000 \
-v -u {email_address}:{password}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://example.zendesk.com/api/v2/ticket_audits?limit="
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 "username:password"
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://example.zendesk.com/api/v2/ticket_audits")
.newBuilder()
.addQueryParameter("limit", "");
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", Credentials.basic("your-email", "your-password"))
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://example.zendesk.com/api/v2/ticket_audits',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"
},
params: {
'limit': '',
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://example.zendesk.com/api/v2/ticket_audits?limit="
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"GET",
url,
auth=('<username>', '<password>'),
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://example.zendesk.com/api/v2/ticket_audits")
uri.query = URI.encode_www_form("limit": "")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
request.basic_auth "username", "password"
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
{
"after_cursor": "MTUwMTYwNzUyMi4wfHwxMzQ3NTMxNjcxfA==",
"after_url": "https://subdomain.zendesk.com/api/v2/ticket_audits.json?cursor=MTUwMTYwNzUyMi4wfHwxMzQ3NTMxNjcxfA%3D%3D&limit=1000",
"audits": [
{
"author_id": 35436,
"created_at": "2011-09-25T22:35:44Z",
"events": [
{
"attachments": [],
"body": "Thanks for your help!",
"id": 1564245,
"public": true,
"type": "Comment"
},
{
"body": "Ticket #47 has been updated",
"id": 1564246,
"subject": "Your ticket has been updated",
"type": "Notification"
},
{
"field_name": "status",
"id": 1564247,
"previous_value": "new",
"type": "Change",
"value": "open"
},
{
"field_name": "custom_status_id",
"id": 1564248,
"previous_value": 1,
"type": "Change",
"value": 123
}
],
"id": 2127301143,
"metadata": {
"custom": {
"time_spent": "3m22s"
},
"system": {
"ip_address": "184.106.40.75"
}
},
"ticket_id": 123,
"via": {
"channel": "web"
}
}
],
"before_cursor": "fDE1MDE1NzUxMjIuMHx8MTM0NzM0MzAxMQ==",
"before_url": "https://subdomain.zendesk.com/api/v2/ticket_audits.json?cursor=fDE1MDE1NzUxMjIuMHx8MTM0NzM0MzAxMQ%3D%3D&limit=1000"
}
List Audits for a Ticket
GET /api/v2/tickets/{ticket_id}/audits
Lists the audits for a specified ticket.
Pagination
- Cursor pagination (recommended)
- Offset pagination
See Pagination.
Returns a maximum of 100 records per page.
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
ticket_id | integer | Path | true | The ID of the ticket |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/v2/tickets/{ticket_id}/audits.json \
-v -u {email_address}:{password}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://example.zendesk.com/api/v2/tickets/123456/audits"
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 "username:password"
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://example.zendesk.com/api/v2/tickets/123456/audits")
.newBuilder();
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", Credentials.basic("your-email", "your-password"))
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://example.zendesk.com/api/v2/tickets/123456/audits',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://example.zendesk.com/api/v2/tickets/123456/audits"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"GET",
url,
auth=('<username>', '<password>'),
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://example.zendesk.com/api/v2/tickets/123456/audits")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
request.basic_auth "username", "password"
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
{
"audits": [
{
"author_id": 5246746,
"created_at": "2011-09-25T22:35:44Z",
"events": [
{
"attachments": [],
"body": "This is a new private comment",
"html_body": "<p>This is a new private comment</p>",
"id": 2127301148,
"public": false,
"type": "Comment"
},
{
"field_name": "status",
"id": 2127301163,
"previous_value": "new",
"type": "Change",
"value": "open",
"via": {
"channel": "rule",
"source": {
"from": {
"id": 35079792,
"title": "Assign to first responder"
},
"rel": "trigger",
"to": {}
}
}
},
{
"field_name": "custom_status_id",
"id": 2127301164,
"previous_value": 1,
"type": "Change",
"value": 123,
"via": {
"channel": "rule",
"source": {
"from": {
"id": 22472716,
"title": "Assign to first responder"
},
"rel": "trigger",
"to": {}
}
}
}
],
"id": 2127301143,
"metadata": {
"custom": {},
"system": {
"client": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1",
"ip_address": "76.218.201.212",
"location": "San Francisco, CA, United States"
}
},
"ticket_id": 666,
"via": {
"channel": "web"
}
}
],
"count": 1,
"next_page": null,
"previous_page": null
}
Count Audits for a Ticket
GET /api/v2/tickets/{ticket_id}/audits/count
Returns an approximate count of audits for a specified ticket. If the count exceeds 100,000, the count will return a cached result. This cached result will update every 24 hours.
The count[refreshed_at]
property is a timestamp that indicates when the count was last updated.
Note: When the count exceeds 100,000, count[refreshed_at]
may occasionally be null.
This indicates that the count is being updated in the background, and count[value]
is limited to 100,000 until the update is complete.
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
ticket_id | integer | Path | true | The ID of the ticket |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/v2/tickets/{ticket_id}/audits/count.json \
-v -u {email_address}:{password}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://example.zendesk.com/api/v2/tickets/123456/audits/count"
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 "username:password"
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://example.zendesk.com/api/v2/tickets/123456/audits/count")
.newBuilder();
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", Credentials.basic("your-email", "your-password"))
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://example.zendesk.com/api/v2/tickets/123456/audits/count',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://example.zendesk.com/api/v2/tickets/123456/audits/count"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"GET",
url,
auth=('<username>', '<password>'),
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://example.zendesk.com/api/v2/tickets/123456/audits/count")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
request.basic_auth "username", "password"
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": {
"refreshed_at": "2020-04-06T02:18:17Z",
"value": 18
}
}
Show Audit
GET /api/v2/tickets/{ticket_id}/audits/{ticket_audit_id}
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
ticket_audit_id | integer | Path | true | The ID of the ticket audit |
ticket_id | integer | Path | true | The ID of the ticket |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/v2/tickets/{ticket_id}/audits.json \
-v -u {email_address}:{password}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143"
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 "username:password"
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://example.zendesk.com/api/v2/tickets/123456/audits/2127301143")
.newBuilder();
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", Credentials.basic("your-email", "your-password"))
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"GET",
url,
auth=('<username>', '<password>'),
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
request.basic_auth "username", "password"
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
{
"audit": {
"author_id": 5246746,
"created_at": "2011-09-25T22:35:44Z",
"events": [
{
"attachments": [],
"body": "This is a new private comment",
"html_body": "<p>This is a new private comment</p>",
"id": 2127301148,
"public": false,
"type": "Comment"
},
{
"field_name": "status",
"id": 2127301163,
"previous_value": "new",
"type": "Change",
"value": "open",
"via": {
"channel": "rule",
"source": {
"from": {
"id": 22472716,
"title": "Assign to first responder"
},
"rel": "trigger",
"to": {}
}
}
},
{
"field_name": "custom_status_id",
"id": 2127301164,
"previous_value": 1,
"type": "Change",
"value": 123,
"via": {
"channel": "rule",
"source": {
"from": {
"id": 22472716,
"title": "Assign to first responder"
},
"rel": "trigger",
"to": {}
}
}
}
],
"id": 2127301143,
"metadata": {
"custom": {},
"system": {
"client": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1",
"ip_address": "76.218.201.212",
"location": "San Francisco, CA, United States"
}
},
"ticket_id": 666,
"via": {
"channel": "web"
}
}
}
Change a comment from public to private
PUT /api/v2/tickets/{ticket_id}/audits/{ticket_audit_id}/make_private
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
ticket_audit_id | integer | Path | true | The ID of the ticket audit |
ticket_id | integer | Path | true | The ID of the ticket |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/v2/tickets/{ticket_id}/audits/{ticket_audit_id}/make_private.json \
-v -u {email_address}:{password} -X PUT -d '{}' -H "Content-Type: application/json"
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143/make_private"
method := "PUT"
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 "username:password"
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://example.zendesk.com/api/v2/tickets/123456/audits/2127301143/make_private")
.newBuilder();
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
"""
""");
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("PUT", body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", Credentials.basic("your-email", "your-password"))
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'PUT',
url: 'https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143/make_private',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143/make_private"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"PUT",
url,
auth=('<username>', '<password>'),
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://example.zendesk.com/api/v2/tickets/123456/audits/2127301143/make_private")
request = Net::HTTP::Put.new(uri, "Content-Type": "application/json")
request.basic_auth "username", "password"
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
null