Legacy Custom Objects Permissions
Important: Relationship-based access control is in early access. This API is subject to change and should not be used in a production environment.
You can customize the authorization of requests by implementing policies. Every legacy object type and legacy relationship type has a policy to define role-based access control (RBAC). Every legacy object type has zero or more policies to define relationship-based access control (ReBAC).
The RBAC policy on a legacy object type or relationship type grants create, read, update, and delete permissions to agents and end users for object records or relationship records of that type. If you provision agent and end user RBAC read permission, then they can read the type as well.
A ReBAC policy on a legacy object type ot
grants additional read and update permissions to agents and end users. Each ReBAC
policy specifies a relationship type with a source object type of zen:user
and a target object type of ot
. If an
existing legacy relationship record of that type points from the user making the request to a legacy object record of type ot
, then
the ReBAC policy grants read and update permissions to the object record. In other words, the RBAC policy on the object
type might forbid an agent or end user from reading or updating legacy object records of that type, but a ReBAC policy on the
legacy object type can allow the user to read or update specific object records of the type.
JSON format
Permissions are represented as JSON objects with the following properties:
Name | Type | Read-only | Mandatory | Description |
---|---|---|---|---|
rbac | object | false | false | The RBAC policy for the object type |
rebac | object | false | false |
Relationship type policies are defined by a JSON object with the following properties:
Name | Type | Writable | Required | Comment |
---|---|---|---|---|
rbac | object | yes | yes | The RBAC policy for the relationship type |
An RBAC policy consists of a JSON object with the following properties:
Name | Type | Writable | Required | Comment |
---|---|---|---|---|
admin | object | yes | no | The CRUD permission definition for admins |
agent | object | yes | no | The CRUD permission definition for agents |
end_user | object | yes | no | The CRUD permission definition for end users |
custom | object | yes | no | The CRUD permission definitions for custom agent roles. In this object, each property maps a custom agent role to a CRUD permission definition. |
A ReBAC policy consists of a JSON object with the following properties:
Name | Type | Writable | Required | Comment |
---|---|---|---|---|
admin | object | yes | no | The RU (read/update) permission definition for admins |
agent | object | yes | no | The RU permission definition for agents |
end_user | object | yes | no | The RU permission definition for end users |
custom | object | yes | no | The RU permission definitions for custom agent roles. In this object, each property maps a custom agent role to an RU permission definition. |
A CRUD permission definition consists of a JSON object with the following properties:
Name | Type | Writable | Required | Comment |
---|---|---|---|---|
create | boolean | yes | no | |
read | boolean | yes | no | |
update | boolean | yes | no | |
delete | boolean | yes | no |
An RU (read/update) permission definition consists of a JSON object with the following properties:
Name | Type | Writable | Required | Comment |
---|---|---|---|---|
read | boolean | yes | no | |
update | boolean | yes | no |
Policies for custom agent roles
On the Enterprise plan, admins can define custom agent roles and assign those roles to any agent. See Creating custom roles and assigning agents (Enterprise) in Help Center.
An RBAC or ReBAC policy can have a legacy custom
object that defines the permissions of an agent with a custom agent role.
The object specifies the ID of the custom role and a permissions policy, which can either be a CRUD or a RU policy depending on whether the parent is RBAC or ReBAC, respectively.
You can get the id of the custom role using the List Custom Roles endpoint. Custom role IDs are not validated to see if roles exist for them.
If any permission value is left unspecified (create, read, update or delete for a CRUD permission definition, and read or update for an RU permission definition) within a custom agent role policy, the unspecified values will be populated with the value false.
If a request is made by a user with a custom agent role, but no policy has been created for that custom agent role, the request will be handled with the existing agent permissions for the object or relationship type that is the subject of the request.
If a request is made by a user with a custom agent role and a policy exists for that custom role, that policy will override the normal agent permissions granted to the user.
Example
{
"data": {
"rbac": {
"agent": {
"create": true,
"read": true,
"update": false,
"delete": false
},
"custom": {
"8237": {
"create": false,
"read": true,
"update": true,
"delete": false
}
}
},
"rebac": {
"user_to_many_products": {
"end_user": {
"update": true
},
"custom": {
"8237": {
"read": true,
"update": false
}
}
}
}
}
}
Default role-based access control (RBAC) policy
When a legacy object type or relationship type is created, a default RBAC policy is issued to the type. The default RBAC policy is used to enforce the authorization rules for any incoming requests on legacy object records or relationship records associated with the legacy object type or relationship type. The permissions defined in the default RBAC policy are as follows.
{
"admin": {
"create": true,
"read": true,
"update": true,
"delete": true
},
"agent": {
"create": true,
"read": true,
"update": true,
"delete": true
},
"end_user": {
"create": false,
"read": false,
"update": false,
"delete": false
}
}
Default relationship-based access control (ReBAC) policy
When a ReBAC policy is created on a legacy object type, not all permissions need to be specified. If the definition omits some permissions, then their default values are as follows.
{
"admin": {
"read": true,
"update": true
},
"agent": {
"read": false,
"update": false
},
"end_user": {
"read": false,
"update": false
}
}
A final full example with all properties.
Example
{
"rbac": {
"agent": {
"create": true,
"delete": false,
"read": true,
"update": true
},
"custom": {
"8237": {
"create": false,
"delete": false,
"read": true,
"update": true
}
},
"end_user": {
"read": true
}
},
"rebac": {
"user_to_many_products": {
"custom": {
"8237": {
"read": true,
"update": true
}
},
"end_user": {
"update": true
}
}
}
}
Show Legacy Object Type Policies
GET /api/sunshine/objects/types/{object_type_key}/permissions
Returns the policies for the specified legacy object type.
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
object_type_key | string | Path | true | The key property is a unique identifier for the legacy object type that you define yourself |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/sunshine/objects/types/{object_type_key}/permissions \
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/sunshine/objects/types/product/permissions"
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/objects/types/product/permissions")
.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/objects/types/product/permissions',
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/objects/types/product/permissions"
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/objects/types/product/permissions")
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": {
"rbac": {
"admin": {
"create": true,
"delete": true,
"read": true,
"update": true
},
"agent": {
"create": true,
"delete": true,
"read": true,
"update": true
},
"end_user": {
"create": false,
"delete": false,
"read": false,
"update": false
}
}
}
}
Update Legacy Object Type Policies
PATCH /api/sunshine/objects/types/{object_type_key}/permissions
Updates the policies for the specified legacy object type. If no updates to the RBAC policy have occurred, then the default RBAC policy is used. If a request creates a new ReBAC policy for a legacy object type and a property is omitted from the ReBAC policy, then the corresponding property from the default ReBAC policy is used. If a request updates an existing RBAC policy or ReBAC policy and a property is omitted, then the corresponding property from the previous policy is used.
Allowed for
- Admins
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
object_type_key | string | Path | true | The key property is a unique identifier for the legacy object type that you define yourself |
Code Samples
curl
For clarity, the example places the JSON in a separate file and imports it into the cURL statement.
policies.json
{
"data": {
"rbac": {
"agent": {
"create": true,
"read": true,
"update": true,
"delete": false
},
"end_user": {
"read": true
}
},
"rebac": {
"user_to_many_products": {
"end_user": {
"update": true
}
}
}
}
}
curl snippet
curl https://{subdomain}.zendesk.com/api/sunshine/objects/types/{object_type_key}/permissions \
-d @policies.json \
-H "Content-Type: application/merge-patch+json" -X PATCH \
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/sunshine/objects/types/product/permissions"
method := "PATCH"
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/objects/types/product/permissions")
.newBuilder();
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
"""
""");
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("PATCH", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'PATCH',
url: 'https://support.zendesk.com/api/sunshine/objects/types/product/permissions',
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/objects/types/product/permissions"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"PATCH",
url,
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://support.zendesk.com/api/sunshine/objects/types/product/permissions")
request = Net::HTTP::Patch.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": {
"rbac": {
"admin": {
"create": true,
"delete": true,
"read": true,
"update": true
},
"agent": {
"create": true,
"delete": false,
"read": true,
"update": true
},
"end_user": {
"create": false,
"delete": false,
"read": true,
"update": false
}
},
"rebac": {
"user_to_many_products": {
"admin": {
"read": true,
"update": true
},
"agent": {
"read": false,
"update": false
},
"end_user": {
"read": false,
"update": true
}
}
}
}
}
Show Legacy Relationship Type Policies
GET /api/sunshine/relationships/types/{relationship_type_key}/permissions
Returns the policies for the specified legacy relationship type.
Allowed for
- Agents
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
relationship_type_key | string | Path | true | The key of the legacy relationship type |
Code Samples
curl
curl https://{subdomain}.zendesk.com/api/sunshine/relationships/types/{relationship_type_key}/permissions \
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/sunshine/relationships/types/suppliers/permissions"
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/relationships/types/suppliers/permissions")
.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/relationships/types/suppliers/permissions',
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/relationships/types/suppliers/permissions"
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/relationships/types/suppliers/permissions")
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": {
"rbac": {
"admin": {
"create": true,
"delete": true,
"read": true,
"update": true
},
"agent": {
"create": true,
"delete": true,
"read": true,
"update": true
},
"end_user": {
"create": false,
"delete": false,
"read": false,
"update": false
}
}
}
}
Update Legacy Relationship Type Policies
PATCH /api/sunshine/relationships/types/{relationship_type_key}/permissions
Updates the policies for the specified legacy relationship type. If no updates to the RBAC policy have occurred, then the default RBAC policy is used. ReBAC policies cannot be created for legacy relationship types. If a request updates an existing RBAC policy or ReBAC policy and a property is omitted, then the corresponding property from the previous policy is used.
Allowed for
- Admins
Parameters
Name | Type | In | Required | Description |
---|---|---|---|---|
relationship_type_key | string | Path | true | The key of the legacy relationship type |
Code Samples
curl
For clarity, the example places the JSON in a separate file and imports it into the cURL statement.
policies.json
{
"data": {
"rbac": {
"agent": {
"create": true,
"read": true,
"update": true,
"delete": false
},
"end_user": {
"read": true
}
}
}
}
curl snippet
curl https://{subdomain}.zendesk.com/api/sunshine/relationships/types/{relationship_type_key}/permissions \
-d @policies.json \
-H "Content-Type: application/merge-patch+json" -X PATCH \
-v -u {email_address}/token:{api_token}
Go
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://support.zendesk.com/api/sunshine/relationships/types/suppliers/permissions"
method := "PATCH"
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/relationships/types/suppliers/permissions")
.newBuilder();
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
"""
""");
Request request = new Request.Builder()
.url(urlBuilder.build())
.method("PATCH", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');
var config = {
method: 'PATCH',
url: 'https://support.zendesk.com/api/sunshine/relationships/types/suppliers/permissions',
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/relationships/types/suppliers/permissions"
headers = {
"Content-Type": "application/json",
}
response = requests.request(
"PATCH",
url,
headers=headers
)
print(response.text)
Ruby
require "net/http"
uri = URI("https://support.zendesk.com/api/sunshine/relationships/types/suppliers/permissions")
request = Net::HTTP::Patch.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": {
"rbac": {
"admin": {
"create": true,
"delete": true,
"read": true,
"update": true
},
"agent": {
"create": true,
"delete": false,
"read": true,
"update": true
},
"end_user": {
"create": false,
"delete": false,
"read": true,
"update": false
}
},
"rebac": {}
}
}