Legacy Custom Objects Jobs
The Jobs API lets you define and run asynchronous batch operation jobs on legacy object records and legacy relationship records. For example, you can define and run a single job that creates many object records.
For more information, see Jobs in the Legacy custom objects developer guide.
See also Rate limits in the introduction.
JSON format
Jobs are represented as JSON objects with the following properties:
Name | Type | Read-only | Mandatory | Description |
---|---|---|---|---|
completed_at | string | true | false | When the job was completed |
created_at | string | true | false | Creation date-time for this job |
id | string | true | false | The ID of the Job |
job_status | string | true | false | The job status. See Job statuses. Allowed values are "queued", "processing", "failed", "completed", or "aborted". |
results | array | false | false | The results that were affected by this Job |
updated_at | string | true | false | Last update date-time for this job |
Job statuses
A job can have one of the following statuses:
Status | Description |
---|---|
queued | Processing the job hasn't started yet |
processing | The job is being processed |
completed | The job has been processed completely and the record is available. The result indicates if some records have failed. A job can be completed even if some or all the records have failed |
failed | The job failed to process the full request due to an unexpected error, such as the request is compressed with an unsupported format, or an internal server error. Even if the job failed, some records could have been completed successfully |
aborted | The job won't be processed. This status is assigned when a job is aborted while the job is queued |
You might also receive an "404 Not Found" HTTP response. Jobs and their related ids expire after a day.
Example
{
"completed_at": "2017-11-03T16:00:16Z",
"created_at": "2017-11-03T16:00:06Z",
"id": "8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6",
"job_status": "completed",
"results": [
{
"data": {
"id": "73c698be-cb64-4678-ba73-29683d2c32er"
},
"success": true
},
{
"errors": [
{
"code": "UnprocessableEntity",
"detail": "External Id is already in use for the Resource Type key: product",
"status": "422",
"title": "Unprocessable Entity"
}
],
"success": false
}
],
"updated_at": "2017-11-03T16:00:16Z"
}
List Jobs
GET /api/sunshine/jobs
Returns all current jobs or a list filtered by status. See Job statuses.
Jobs expire after one day, after which they can no longer be accessed.
You can use a parameter named status
to filter the results. Example:
GET /api/sunshine/jobs?status=queued
The allowed parameter values are queued, processing, failed, completed, or aborted.
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
status | string | Query | false | The status to filter the jobs. Allowed values are "queued", "processing", "failed", "completed", or "aborted". |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/sunshine/jobs \
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/sunshine/jobs?status="
method := "GET"
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
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/sunshine/jobs")
.newBuilder()
.addQueryParameter("status", "");
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://support.zendesk.com/api/sunshine/jobs',
headers: {
'Content-Type': 'application/json',
},
params: {
'status': '',
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://support.zendesk.com/api/sunshine/jobs?status="
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"GET",
url,
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://support.zendesk.com/api/sunshine/jobs")
uri.query = URI.encode_www_form("status": "")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
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
{
"data": [
{
"completed_at": "2017-11-03T16:04:06Z",
"created_at": "2017-11-03T16:00:06Z",
"id": "559ae838-c9a0-11e7-abc4-cec278b6b50a",
"job_status": "completed",
"updated_at": "2017-11-03T16:04:06Z"
},
{
"completed_at": null,
"created_at": "2017-11-03T16:02:06Z",
"id": "886ae838-c9a0-11e7-abc4-cec278b6b50a",
"job_status": "processing",
"updated_at": "2017-11-03T16:04:06Z"
}
]
}
Show Job
GET /api/sunshine/jobs/{custom_object_job_id}
Returns the status of the specified job. See Job statuses.
Jobs expire after one day, after which they can no longer be accessed.
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
custom_object_job_id | string | Path | true | The ID of the legacy custom object job |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/sunshine/jobs/{id} \
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/sunshine/jobs/8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6"
method := "GET"
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
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/sunshine/jobs/8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6")
.newBuilder();
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("GET", null)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'GET',
url: 'https://support.zendesk.com/api/sunshine/jobs/8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6',
headers: {
'Content-Type': 'application/json',
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://support.zendesk.com/api/sunshine/jobs/8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"GET",
url,
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://support.zendesk.com/api/sunshine/jobs/8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6")
request = Net::HTTP::Get.new(uri, "Content-Type": "application/json")
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
{
"data": {
"completed_at": "2017-11-03T16:00:16Z",
"created_at": "2017-11-03T16:00:06Z",
"id": "8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6",
"job_status": "completed",
"results": [
{
"data": {
"id": "73c698be-cb64-4678-ba73-29683d2c32er"
},
"success": true
},
{
"errors": [
{
"code": "UnprocessableEntity",
"detail": "External Id is already in use for the Resource Type key: product",
"status": "422",
"title": "Unprocessable Entity"
}
],
"success": false
}
],
"updated_at": "2017-11-03T16:00:16Z"
}
}
Create Job
POST /api/sunshine/jobs
Creates a job with supported type and action.
The API doesn't wait for the job to finish before sending a response. The response gives you a job id that you can use to poll the API for the status of the job. See Show Job and Job statuses.
The maximum number of concurrent jobs that can be processed for an account is 1000.
When creating a Job, you may use the following properties:
Name | Type | Required | Comment |
---|---|---|---|
type | string | yes | One of "resources" or "relationships". Resources refer to legacy object records. Relationships refer to relationship records |
action | string | yes | One of the following depending on job type: "post", "delete", "update", "external_id_delete", "external_id_set". See action property |
data | array | yes | An array of legacy object or relationship records or ids to process. See data property |
action property
The action you can specify depends on the job type.
A job of type "resources" (legacy object records) supports the following actions:
- "post"
- "delete"
- "update"
- "external_id_delete"
- "external_id_set"
A job of type "relationships" (legacy relationship records) supports the following action:
- "post"
- "delete"
data property
The data
property in the request body specifies an array of JSON objects to batch process. The format of the JSON objects you can specify depends on the job.
Jobs to post object records or relationship records
When a job's type is "resources" or "relationships" and its action is "post", the data
property supports legacy object records or relationship records. The format of each legacy object is the same as the data
object for the equivalent single-operation endpoints for legacy object records or legacy relationship records.
Example:
{
"type": "resources",
"action": "post",
"data": [
{
"type": "product",
"external_id": "3",
"attributes": {
"id": "3",
"name": "Strawberry Chewing Gum"
}
},
{
"type": "product",
"external_id": "4",
"attributes": {
"id": "4",
"name": "Coffee Chewing Gum"
}
}
]
}
Jobs to update legacy object records
When a job's type is "resources" and its action is "update", the data
property supports JSON objects with the following properties:
Name | Type | Description |
---|---|---|
id | string | The id of the legacy object record to update |
attributes | object | A legacy object containing the properties to update |
For each legacy object, the id
value is used to locate the legacy object record in the database and the attributes
value is used to patch the existing value.
Example:
{
"type": "resources",
"action": "update",
"data": [
{
"id": "576a0d0d-fb3f-11e9-80f8-65590b274410",
"attributes": {
"name": "Strawberry Chewing Gum v2"
}
},
{
"id": "576a5b2e-fb3f-11e9-80f8-f1af99ee4b4c",
"attributes": {
"name": "Coffee Chewing Gum (decaf)"
}
}
]
}
Jobs to set legacy object records using external id
When a job's type is "resources" and its action is "external_id_set", the
data
property supports JSON objects with the following properties:
Name | Type | Description |
---|---|---|
type | string | The legacy object type of the legacy object record |
external_id | string | The external_id of the legacy object record to set |
attributes | object | A legacy object containing the properties to set |
For each legacy object, the external_id
and resource type
values are used to locate
the legacy object record in the database. If the resource exists, the attributes
value is used to patch the existing value. If the resource does not exist, a new
resource of the given resource type is created with the external_id and attributes.
Example:
{
"type": "resources",
"action": "external_id_set",
"data": [
{
"type": "product",
"external_id": "4",
"attributes": {
"name": "Coffee Chewing Gum (decaf)"
}
},
{
"type": "product",
"external_id": "5",
"attributes": {
"name": "Blueberry Chewing Gum"
}
}
]
}
Jobs to delete legacy object records or relationship records
When a job's type is "resources" or "relationships" and its action is "delete", the data
property supports a list of ids of the legacy object or relationship records to be deleted.
Examples:
{
"type": "resources",
"action": "delete",
"data": [
"576a0d0d-fb3f-11e9-80f8-65590b274410",
"576a5b2e-fb3f-11e9-80f8-f1af99ee4b4c",
"69d0b3e2-ec4e-11e9-ad75-4b6f5c0467f5"
]
}
{
"type": "relationships",
"action": "delete",
"data": [
"576a0d0d-fb3f-11e9-80f8-65590b274410",
"576a5b2e-fb3f-11e9-80f8-f1af99ee4b4c",
"69d0b3e2-ec4e-11e9-ad75-4b6f5c0467f5"
]
}
Jobs to delete legacy object records using external id
When a job's type is "resources" and its action is "delete", the data
property
supports a list of object type
and external_id
of the legacy object records to be deleted.
Examples:
{
"type": "resources",
"action": "external_id_delete",
"data": [
{
"type": "product",
"external_id": "4"
},
{
"type": "product",
"external_id": "5"
}
]
}
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/sunshine/jobs \
-d '{"type": "resources", "action": "post", "data": [{...}, {...}, ...]}' \
-H "Content-Type: application/json" -X POST \
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/sunshine/jobs"
method := "POST"
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
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/sunshine/jobs")
.newBuilder();
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
"""
""");
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'POST',
url: 'https://support.zendesk.com/api/sunshine/jobs',
headers: {
'Content-Type': 'application/json',
},
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Python
import requests
url = "https://support.zendesk.com/api/sunshine/jobs"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"POST",
url,
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://support.zendesk.com/api/sunshine/jobs")
request = Net::HTTP::Post.new(uri, "Content-Type": "application/json")
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
{
"data": {
"completed_at": null,
"created_at": "2017-11-03T16:00:06Z",
"id": "8b72559ae838-c9a0-11e7-abc4-cec278b6b50a6e6",
"job_status": "queued",
"results": [],
"updated_at": "2017-11-03T16:00:06Z"
}
}