Zendesk has a default set of system ticket statuses that help you manage ticket workflows. If your account has activated custom ticket statuses, you can create additional, more-specific ticket statuses.

For more information about custom ticket statuses, see Activating custom ticket statuses in Zendesk help.

Status categories

Each custom ticket status belongs to a status category. Each category corresponds to one of the built-in system ticket statuses:

  • "new"
  • "open"
  • "pending"
  • "hold"
  • "solved"

Note: Tickets with a "Closed" status belong to the "solved" status category.

You can't create, change, or delete status categories.

Changing the default ticket status of a status category

Each status category has a default ticket status that's always active. When using the API, you can only change a category's default ticket status using a Bulk Update Default Custom Ticket Status request.

Note: The "hold" status category and its corresponding system ticket status are optional. If it's inactive, the "hold" status category doesn't require an active default ticket status.

Limitations

Custom ticket statuses have the following limitations:

  • 300 custom ticket statuses per account
  • 100 custom ticket statuses per status category

JSON format

Custom Ticket Statuses are represented as JSON objects with the following properties:

NameTypeRead-onlyMandatoryDescription
activebooleanfalsefalseIf true, the custom status is set to active, If false, the custom status is set to inactive
agent_labelstringfalsetrueThe label displayed to agents. Maximum length is 48 characters
created_atstringtruefalseThe date and time the custom ticket status was created
defaultbooleanfalsefalseIf true, the custom status is set to default. If false, the custom status is set to non-default
descriptionstringfalsefalseThe description of when the user should select this custom ticket status
end_user_descriptionstringfalsefalseThe description displayed to end users
end_user_labelstringfalsefalseThe label displayed to end users. Maximum length is 48 characters
idintegertruefalseAutomatically assigned when the custom ticket status is created
raw_agent_labelstringtruefalseThe dynamic content placeholder. If the dynamic content placeholder is not available, this is the "agent_label" value. See Dynamic Content Items
raw_descriptionstringtruefalseThe dynamic content placeholder. If the dynamic content placeholder is not available, this is the "description" value. Dynamic Content Items
raw_end_user_descriptionstringtruefalseThe dynamic content placeholder. If the dynamic content placeholder is not available, this is the "end_user_description" value. See Dynamic Content Items
raw_end_user_labelstringtruefalseThe dynamic content placeholder. If the dynamic content placeholder is not available, this is the "end_user_label" value. See Dynamic Content Items
status_categorystringfalsetrueThe status category the custom ticket status belongs to. Allowed values are "new", "open", "pending", "hold", or "solved".
updated_atstringtruefalseThe date and time the custom ticket status was last updated

List Custom Ticket Statuses

  • GET /api/v2/custom_statuses

Lists all undeleted custom ticket statuses for the account. No pagination is provided.

Allowed For

  • End Users

Parameters

NameTypeInRequiredDescription
activebooleanQueryfalseIf true, show only active custom ticket statuses. If false, show only inactive custom ticket statuses. If the filter is not used, show all custom ticket statuses
defaultbooleanQueryfalseIf true, show only default custom ticket statuses. If false, show only non-default custom ticket statuses. If the filter is not used, show all custom ticket statuses
status_categoriesstringQueryfalseFilter the list of custom ticket statuses by a comma-separated list of status categories

Code Samples

curl
curl https://{subdomain}.zendesk.com/api/v2/custom_statuses.json \  -v -u {email_address}:{password}
Go
import (	"fmt"	"io"	"net/http")
func main() {	url := "https://example.zendesk.com/api/v2/custom_statuses?active=&default=&status_categories="	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/custom_statuses")		.newBuilder()		.addQueryParameter("active", "")		.addQueryParameter("default", "")		.addQueryParameter("status_categories", "");
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/custom_statuses',  headers: {	'Content-Type': 'application/json',	'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"  },  params: {    'active': '',    'default': '',    'status_categories': '',  },};
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/custom_statuses?active=&default=&status_categories="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/custom_statuses")uri.query = URI.encode_www_form("active": "", "default": "", "status_categories": "")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
{  "custom_statuses": [    {      "active": true,      "agent_label": "Responding quickly",      "created_at": "2021-07-20T22:55:29Z",      "default": false,      "description": "Customer needs a response quickly",      "end_user_description": "Your ticket is being responded to",      "end_user_label": "Urgent processing",      "id": 35436,      "raw_agent_label": "Responding quickly",      "raw_description": "Customer needs a response quickly",      "raw_end_user_description": "Your ticket is being responded to",      "raw_end_user_label": "Urgent processing",      "status_category": "open",      "updated_at": "2021-07-20T22:55:29Z"    }  ]}

Show Custom Ticket Status

  • GET /api/v2/custom_statuses/{custom_status_id}

Returns the custom ticket status object.

Allowed For

  • End Users

Parameters

NameTypeInRequiredDescription
custom_status_idintegerPathtrueThe id of the custom status

Code Samples

curl
curl https://{subdomain}.zendesk.com/api/v2/custom_status/{custom_status_id}.json \  -v -u {email_address}:{password}
Go
import (	"fmt"	"io"	"net/http")
func main() {	url := "https://example.zendesk.com/api/v2/custom_statuses/1234567"	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/custom_statuses/1234567")		.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/custom_statuses/1234567',  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/custom_statuses/1234567"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/custom_statuses/1234567")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
{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "created_at": "2021-07-20T22:55:29Z",    "default": false,    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "id": 35436,    "raw_agent_label": "Responding quickly",    "raw_description": "Customer needs a response quickly",    "raw_end_user_description": "Your ticket is being responded to",    "raw_end_user_label": "Urgent processing",    "status_category": "open",    "updated_at": "2021-07-20T22:55:29Z"  }}

Create Custom Ticket Status

  • POST /api/v2/custom_statuses

Takes a custom_status object that specifies the custom ticket status properties to create.

Allowed For

  • Admins

Request body format

NameTypeMandatoryDescription
activebooleanfalseIf true, the custom status is set to active. If false, the custom status is set to inactive
agent_labelstringtrueThe dynamic content placeholder or the label displayed to agents. Maximum length for displayed label is 48 characters
descriptionstringfalseThe description of when the user should select this custom ticket status
end_user_descriptionfalsefalseThe description displayed to end users
end_user_labelstringfalseThe dynamic content placeholder or the label displayed to end users. Maximum length for displayed label is 48 characters
status_categorystringtrueThe status category the custom status belongs to. Allowed values are "new", "open", "pending", "hold", or "solved"

Example body

{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "status_category": "open"  }}

Code Samples

curl
curl https://{subdomain}.zendesk.com/api/v2/custom_statuses.json \  -d '{"custom_status": {"status_category": "open", "agent_label": "Responding quickly", "end_user_label": "Urgent processing", "description": "Responding quickly", "end_user_description": "Responding quickly"}}' \  -H "Content-Type: application/json" -v -u {email_address}:{password} -X POST
Go
import (	"fmt"	"io"	"net/http"	"strings")
func main() {	url := "https://example.zendesk.com/api/v2/custom_statuses"	method := "POST"	payload := strings.NewReader(`{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "status_category": "open"  }}`)	req, err := http.NewRequest(method, url, payload)
	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/custom_statuses")		.newBuilder();RequestBody body = RequestBody.create(MediaType.parse("application/json"),		"""{  \"custom_status\": {    \"active\": true,    \"agent_label\": \"Responding quickly\",    \"description\": \"Customer needs a response quickly\",    \"end_user_description\": \"Your ticket is being responded to\",    \"end_user_label\": \"Urgent processing\",    \"status_category\": \"open\"  }}""");
Request request = new Request.Builder()		.url(urlBuilder.build())		.method("POST", 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 data = JSON.stringify({  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "status_category": "open"  }});
var config = {  method: 'POST',  url: 'https://example.zendesk.com/api/v2/custom_statuses',  headers: {	'Content-Type': 'application/json',	'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"  },  data : data,};
axios(config).then(function (response) {  console.log(JSON.stringify(response.data));}).catch(function (error) {  console.log(error);});
Python
import requestsimport json
url = "https://example.zendesk.com/api/v2/custom_statuses"
payload = json.loads("""{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "status_category": "open"  }}""")headers = {	"Content-Type": "application/json",}
response = requests.request(	"POST",	url,	auth=('<username>', '<password>'),	headers=headers,	json=payload)
print(response.text)
Ruby
require "net/http"uri = URI("https://example.zendesk.com/api/v2/custom_statuses")request = Net::HTTP::Post.new(uri, "Content-Type": "application/json")request.body = %q({  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "status_category": "open"  }})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)

201 Created
// Status 201 Created
{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "created_at": "2021-07-20T22:55:29Z",    "default": false,    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "id": 35436,    "raw_agent_label": "Responding quickly",    "raw_description": "Customer needs a response quickly",    "raw_end_user_description": "Your ticket is being responded to",    "raw_end_user_label": "Urgent processing",    "status_category": "open",    "updated_at": "2021-07-20T22:55:29Z"  }}

Update Custom Ticket Status

  • PUT /api/v2/custom_statuses/{custom_status_id}

Takes a custom_status object that specifies the properties to update.

Allowed For

  • Admins

Request body format

NameTypeDescription
activebooleanIf true, the custom status is set to active. If false, the custom status is set to inactive
agent_labelstringThe dynamic content placeholder or the label displayed to agents. Maximum length for displayed label is 48 characters
descriptionstringThe description of when the user should select this custom ticket status
end_user_descriptionstringThe description displayed to end users
end_user_labelstringThe dynamic content placeholder or the label displayed to end users. Maximum length for displayed label is 48 characters

Parameters

NameTypeInRequiredDescription
custom_status_idintegerPathtrueThe id of the custom status

Example body

{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing"  }}

Code Samples

curl
curl https://{subdomain}.zendesk.com/api/v2/custom_statuses/{custom_status_id}.json \  -d '{"custom_status": {"agent_label": "{{dc.quick}}", "end_user_label": "{{dc.urgent}}"}}' \  -H "Content-Type: application/json" -v -u {email_address}:{password} -X PUT
Go
import (	"fmt"	"io"	"net/http"	"strings")
func main() {	url := "https://example.zendesk.com/api/v2/custom_statuses/1234567"	method := "PUT"	payload := strings.NewReader(`{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing"  }}`)	req, err := http.NewRequest(method, url, payload)
	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/custom_statuses/1234567")		.newBuilder();RequestBody body = RequestBody.create(MediaType.parse("application/json"),		"""{  \"custom_status\": {    \"active\": true,    \"agent_label\": \"Responding quickly\",    \"description\": \"Customer needs a response quickly\",    \"end_user_description\": \"Your ticket is being responded to\",    \"end_user_label\": \"Urgent processing\"  }}""");
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 data = JSON.stringify({  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing"  }});
var config = {  method: 'PUT',  url: 'https://example.zendesk.com/api/v2/custom_statuses/1234567',  headers: {	'Content-Type': 'application/json',	'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"  },  data : data,};
axios(config).then(function (response) {  console.log(JSON.stringify(response.data));}).catch(function (error) {  console.log(error);});
Python
import requestsimport json
url = "https://example.zendesk.com/api/v2/custom_statuses/1234567"
payload = json.loads("""{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing"  }}""")headers = {	"Content-Type": "application/json",}
response = requests.request(	"PUT",	url,	auth=('<username>', '<password>'),	headers=headers,	json=payload)
print(response.text)
Ruby
require "net/http"uri = URI("https://example.zendesk.com/api/v2/custom_statuses/1234567")request = Net::HTTP::Put.new(uri, "Content-Type": "application/json")request.body = %q({  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing"  }})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
{  "custom_status": {    "active": true,    "agent_label": "Responding quickly",    "created_at": "2021-07-20T22:55:29Z",    "default": false,    "description": "Customer needs a response quickly",    "end_user_description": "Your ticket is being responded to",    "end_user_label": "Urgent processing",    "id": 35436,    "raw_agent_label": "Responding quickly",    "raw_description": "Customer needs a response quickly",    "raw_end_user_description": "Your ticket is being responded to",    "raw_end_user_label": "Urgent processing",    "status_category": "open",    "updated_at": "2021-07-20T22:55:29Z"  }}

Bulk Update Default Custom Ticket Status

  • PUT /api/v2/custom_status/default

Updates the default values for many custom ticket statuses at once.

Allowed For

  • Admins

Request body format

NameTypeDescription
idsstringThe comma-separated list of custom status ids to be set as default for their category

Example body

{  "ids": "1234567,1234577"}

Code Samples

curl
curl https://{subdomain}.zendesk.com/api/v2/custom_status/default.json \  -d '{"ids": "1234567,1234577"}' \  -H "Content-Type: application/json" -v -u {email_address}:{password} -X PUT
Go
import (	"fmt"	"io"	"net/http"	"strings")
func main() {	url := "https://example.zendesk.com/api/v2/custom_status/default"	method := "PUT"	payload := strings.NewReader(`{  "ids": "1234567,1234577"}`)	req, err := http.NewRequest(method, url, payload)
	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/custom_status/default")		.newBuilder();RequestBody body = RequestBody.create(MediaType.parse("application/json"),		"""{  \"ids\": \"1234567,1234577\"}""");
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 data = JSON.stringify({  "ids": "1234567,1234577"});
var config = {  method: 'PUT',  url: 'https://example.zendesk.com/api/v2/custom_status/default',  headers: {	'Content-Type': 'application/json',	'Authorization': 'Basic <auth-value>', // Base64 encoded "username:password"  },  data : data,};
axios(config).then(function (response) {  console.log(JSON.stringify(response.data));}).catch(function (error) {  console.log(error);});
Python
import requestsimport json
url = "https://example.zendesk.com/api/v2/custom_status/default"
payload = json.loads("""{  "ids": "1234567,1234577"}""")headers = {	"Content-Type": "application/json",}
response = requests.request(	"PUT",	url,	auth=('<username>', '<password>'),	headers=headers,	json=payload)
print(response.text)
Ruby
require "net/http"uri = URI("https://example.zendesk.com/api/v2/custom_status/default")request = Net::HTTP::Put.new(uri, "Content-Type": "application/json")request.body = %q({  "ids": "1234567,1234577"})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
{}