OAuth Tokens for Grant Types
This API includes the Create Token for Grant Type endpoint that allows you to obtain access tokens for both the authorization code and the refresh token grant types.
For more information, see Authorization code grant flow and Refresh token grant flow in Zendesk help.
If you're not working with grant types, use the Create Token endpoint in the OAuth Tokens API. The two APIs don't share the same path, JSON format, or request parameters. However, both APIs return access tokens that can be used to authenticate API requests.
Authorization code grant type
The authorization code grant flow enables an application to obtain an access token on behalf of a user after the user successfully authenticates and grants permission.
To initiate this flow, redirect the user to the authorization server's authorization endpoint, where they log in and authorize the application. After successful authorization, the server redirects the user back to the specified redirect URI with an authorization_code.
The application then exchanges this authorization code for an access token by sending a request to the /oauth/tokens endpoint, including the authorization_code, client_id, and, if using PKCE, the code_verifier.
This access token allows the application to access protected resources on behalf of the user. When using PKCE, the initial authorization request must also include the code_challenge and code_challenge_method parameters.
Refresh token grant type
The refresh token grant type allows for refreshing an access token that has either expired or is about to expire. To generate a new OAuth access token, pass a refresh_token parameter to the /oauth/tokens endpoint using grant_type: refresh_token. This process returns a new access token and refresh token while invalidating the previous access and refresh tokens. Refresh tokens will be issued for all new OAuth token requests, but existing OAuth tokens cannot be refreshed.
The authorization_code and refresh_token grant types accept the expires_in and refresh_token_expires_in parameters in requests to the /oauth/tokens endpoint, allowing clients to set expiration times.
For clients created before April 30, 2026, there is no default expires_in value. For clients created on or after April 30, 2026, there is a default expires_in value of 30 minutes. You can still specify an expires_in value through the API when creating a token to set a custom expiration. The refresh_token_expires_in has a default value of 30 days, but can be adjusted through the API.
Note: The refresh_token flow does not impact Zendesk Integration Services (ZIS) flows. No mandatory token expirations are enforced that could disrupt ZIS functionality. Although you can set expires_in for testing in non-ZIS OAuth use cases, ZIS does not currently support or require this.
Client credentials grant type
The client credentials grant type is intended only for confidential clients. It lets you create an access token using only the client’s secret. This grant flow consists in making a request to the /oauth/tokens endpoint with "grant_type": "client_credentials" and a valid client_secret value.
Unlike other authorization flows, this grant type does not return a refresh token and does not require user authorization. The token’s user will be the one associated with the client. You can optionally include an expires_in value in seconds to set the token’s expiration time.
For security reasons, public clients are not allowed to use this grant type.
JSON format
OAuth Tokens for Grant Types are represented as JSON objects with the following properties:
| Name | Type | Read-only | Mandatory | Description |
|---|---|---|---|---|
| access_token | string | true | false | The access token |
| expires_in | integer | false | false | Number of seconds the access token is valid. Must be greater than or equal to 300 seconds (5 minutes) and less than or equal to 172,800 seconds (2 days), or less than refresh_token_expires_in, whichever is smallest. Defaults to null for clients created before April 30, 2026. Clients created on or after that date have a default value of 1,800 seconds (30 minutes). |
| refresh_token | string | true | false | The refresh token |
| refresh_token_expires_in | integer | false | false | Number of seconds the refresh token is valid. Must be greater than or equal to 604,800 seconds (7 days) or expires_in (if given), and less than or equal to 7,776,000 seconds (90 days). Defaults to 2,592,000 seconds (30 days) |
| scope | string | true | false | The valid scopes for this token. See Scope below |
| token_type | string | true | false | Type of the access token, for example "bearer" |
Example
{"access_token": "gErypPlm4dOVgGRvA1ZzMH5MQ3nLo8bo","expires_in": 86400,"refresh_token": "af3t24tfj34h43s...","refresh_token_expires_in": 604800,"scope": "read","token_type": "bearer"}
Create Token for Grant Type
POST /oauth/tokens
Returns an OAuth access token in exchange for one of the following:
Note: The password grant type flow, which used a Zendesk username and password to get an access token, has been deprecated and is highly discouraged.
To revoke an access token, see Revoke Token.
Request parameters
The POST request takes the following parameters, which must be formatted as JSON:
| Name | Description |
|---|---|
| grant_type | "authorization_code", "refresh_token", or "client_credentials" |
| code | Authorization grant flow only. The authorization code you received from Zendesk after the user granted access. The code is valid for only 120 seconds. See Handle the user's authorization decision in Zendesk help |
| client_id | The Identifier value specified in an OAuth client in the Zendesk Admin Center (Apps and integrations > APIs > OAuth clients). See Registering your application with Zendesk |
| client_secret | The Secret value specified in an OAuth client in the Admin Center (Apps and integrations > APIs > OAuth clients). See Registering your application with Zendesk |
| redirect_uri | Authorization grant flow only. The redirect URL you specified when you sent the user to the Zendesk authorization page. For ID purposes only. See Send the user to the Zendesk authorization page |
| scope | Valid scope for this token. A space-separated string of scope values. Must be within the client's configured allowed scopes, if set. See Scope below |
| expires_in | Number of seconds the access token is valid. Must be greater than or equal to 300 seconds (5 minutes) and less than or equal to 172,800 seconds (2 days), or less than refresh_token_expires_in, whichever is the shorter. Defaults to null |
| refresh_token_expires_in | Number of seconds the refresh token is valid. Must be greater than or equal to 604,800 seconds (7 days) or expires_in (if given), and less than or equal to 7,776,000 seconds (90 days). Defaults to 2,592,000 seconds (30 days) |
| refresh_token | A valid refresh token. See Replacing expired access tokens |
Authorization code example
const tokenResponse = await axios.post("https://{subdomain}.zendesk.com/oauth/tokens",{grant_type: "authorization_code",code: AUTHORIZATION_CODE,client_id: ZENDESK_CLIENT_ID,redirect_uri: REDIRECT_URI_PKCE,scope: "tickets:read users:read",code_verifier: CODE_VERIFIER,expires_in: 86400,refresh_token_expires_in: 604800,},{ headers: { "Content-Type": "application/json" } });
Refresh token example
const tokenResponse = await axios.post("https://{subdomain}.zendesk.com/oauth/tokens",{grant_type: "refresh_token",refresh_token: REFRESH_TOKEN,client_id: ZENDESK_CLIENT_ID,client_secret: ZENDESK_CLIENT_SECRET,scope: "tickets:write",expires_in: 86400,refresh_token_expires_in: 604800,},{ headers: { "Content-Type": "application/json" } });
Client credentials example
const tokenResponse = await axios.post("https://{subdomain}.zendesk.com/oauth/tokens",{grant_type: "client_credentials",client_id: ZENDESK_CLIENT_ID,client_secret: ZENDESK_CLIENT_SECRET,scope: "tickets:write",expires_in: 86400},{ headers: { "Content-Type": "application/json" } });
Scope
You must specify a scope to control the app's access to Zendesk resources. The "read" scope gives access to GET endpoints and includes permission to sideload related resources. The "write" scope gives access to POST, PUT, and DELETE endpoints for creating, updating, and deleting resources.
Note: Don't confuse the scope parameter (singular) with the scopes parameter (plural) for non-grant-type tokens described in OAuth Tokens.
The "impersonate" scope allows a Zendesk admin to make requests on behalf of end users. See Making API requests on behalf of end users.
Broad scopes
The following parameter gives read access to all resources:
"scope": "read"
The following parameter gives read and write access to all resources:
"scope": "read write"
Resource-specific scopes
You can fine-tune access using resource-specific scopes. The syntax is as follows:
"scope": "resource:action"
For example, the following parameter restricts the scope to only reading tickets:
"scope": "tickets:read"
To give read and write access to a resource, specify both scopes:
"scope": "users:read users:write"
To give write access only to one resource, such as organizations, and read access to everything else:
"scope": "organizations:write read"
Scope errors
There are two distinct scope-related error cases to be aware of:
- Unrecognized scope string: If you specify a scope value that doesn't exist (for example, a typo such as
"scope": ["read", "write"]using an array instead of a string), the endpoint still creates an access token. However, any API request made with that token will return a403 Forbiddenerror. - Scope outside client's allowed scopes: If the OAuth client has allowed scopes configured and you request a scope not included in that list, the endpoint returns
400 Bad Requestwith aninvalid_scopeerror and no token is created.
Available scopes
| Scope | Description |
|---|---|
read | Read all data. Gives access to GET endpoints, including permission to sideload related resources. |
write | Write all data. Gives access to POST, PUT, and DELETE endpoints. |
impersonate | Allows Zendesk Support admins to make requests on behalf of end users. See Making API requests on behalf of end users. |
account_settings:read | View account settings. Includes account configuration, ticket and user fields, and workspaces. |
account_settings:write | Create, edit, and delete account settings. Includes account configuration, ticket and user fields, and workspaces. |
ai_agents:chat | Chat with AI agents. Includes sending messages and receiving responses via the Zendesk Developers API. |
apps:read | View installed apps and their settings. Includes which apps are installed and each app's settings. |
apps:write | Install, configure, and remove apps. Includes installing and uninstalling apps, changing settings, and uploading custom app packages. |
auditlogs:read | View audit logs. Includes the account-wide record of changes: who changed what and when. Read only. |
automations:read | View automations and their details. |
automations:write | Create, edit, and delete automations. |
brands:read | View brands and their agent assignments. |
brands:write | Create, edit, and delete brands and their agent assignments. |
custom_objects:read | View custom objects. Includes custom object definitions and record attachments. |
custom_objects:write | Create, edit, and delete custom objects. Includes definitions and record attachments. |
deletion_schedules:read | View deletion schedules. Includes data retention policies that automatically delete tickets, users, and other data. |
deletion_schedules:write | Delete deletion schedules. Includes deleting data retention policies. |
dynamic_content:read | View dynamic content items and language variants. |
dynamic_content:write | Create, edit, and delete dynamic content items and language variants. |
groups:read | View groups and their memberships. |
groups:write | Create, edit, and delete groups and their memberships. |
hc:read | View Help Center content. Includes articles, sections, categories, community posts and comments. |
hc:write | Create, edit, and delete Help Center content. Includes articles, sections, categories, community posts and comments. |
macros:read | View macros, their categories, and attachments. |
macros:write | Create, edit, and delete macros and their attachments. |
organizations:read | View organizations and their details. Includes memberships, subscriptions, and merge history. |
organizations:write | Create, edit, and delete organizations and manage their memberships. Includes adding and removing users, managing subscriptions, and merging organizations. |
requests:read | View support requests and their comments. |
requests:write | Submit and edit support requests. Includes creating new requests and adding to existing ones. |
satisfaction_ratings:read | View satisfaction ratings, scores, and reasons. |
satisfaction_ratings:write | Submit satisfaction ratings. Includes rating a ticket good or bad with an optional reason. |
security:read | View security and sign-in settings. Includes password policy, session timeouts, IP restrictions, and SSO configuration. Read only. |
sla_policies:read | View SLA and group SLA policies. |
sla_policies:write | Create, edit, delete, and reorder SLA and group SLA policies. |
targets:read | View targets and their delivery failures. |
targets:write | Create, edit, and delete targets. |
themes:read | View Guide themes and their files. |
themes:write | Create, edit, and delete Guide themes. Includes importing, updating, publishing, exporting, and deleting themes. |
ticket_attachments:read | View files attached to tickets. |
ticket_attachments:write | Upload, edit, and delete ticket attachments. Includes uploading files, updating and deleting attachments, and redacting them. |
ticket_views:read | View ticket views and the tickets they return. |
ticket_views:write | Create, edit, and delete ticket views. |
tickets:read | View tickets. Includes ticket contents, comments and conversation history, tags, forms and fields, audits, events, and metrics. |
tickets:write | Create, edit, and delete tickets. Includes adding comments, tags, merging tickets, marking spam, attachments, forms, and custom statuses. |
triggers:read | View triggers, trigger categories, and their revision history. |
triggers:write | Create, edit, delete, and reorder triggers and trigger categories. |
users:read | View users. Includes identities, active sessions, group, organization, and brand memberships, roles, and settings. |
users:write | Create, edit, and delete users and manage their access. Includes resetting passwords, ending sessions, adding identities, changing memberships, and managing custom roles. |
webhooks:read | View webhooks and their activity history. |
webhooks:write | Create, edit, test, and delete webhooks. |
any_channel:write | Push messages from an external channel into Zendesk. Includes creating tickets, comments, and users from an integrated channel. Write only. |
web_widget:write | Edit Web Widget settings and configuration. Write only. |
zis:read | View private integrations. Includes configurations, connections, and inbound webhooks. |
zis:write | Create, edit, and delete private integrations. Includes configurations, connections, and inbound webhooks. |
Code Samples
curl
Authorization code grant
curl https://{subdomain}.zendesk.com/oauth/tokens \-H "Content-Type: application/json" \-d '{"grant_type": "authorization_code", "code": "7xqwtlf3rrdj8uyeb1yf","client_id": "acme_rockets", "client_secret": "77f9931747b63f720f9fbc6","redirect_uri": "https://www.example.com/app/grant_decision","scope": "tickets:read users:read" }' \-X POST
Go
import ("fmt""io""net/http")func main() {url := "https://example.zendesk.com/oauth/tokens"method := "POST"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 "{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://example.zendesk.com/oauth/tokens").newBuilder();RequestBody body = RequestBody.create(MediaType.parse("application/json"),"""""");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("POST", body).addHeader("Content-Type", "application/json").addHeader("Authorization", basicAuth).build();Response response = client.newCall(request).execute();
Nodejs
var axios = require('axios');var config = {method: 'POST',url: 'https://example.zendesk.com/oauth/tokens',headers: {'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 requestsfrom requests.auth import HTTPBasicAuthurl = "https://example.zendesk.com/oauth/tokens"headers = {"Content-Type": "application/json",}email_address = 'your_email_address'api_token = 'your_api_token'# Use basic authenticationauth = HTTPBasicAuth(f'{email_address}/token', api_token)response = requests.request("POST",url,auth=auth,headers=headers)print(response.text)
Ruby
require "net/http"require "base64"uri = URI("https://example.zendesk.com/oauth/tokens")request = Net::HTTP::Post.new(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)
201 Created
// Status 201 Created{"access_token": "gErypPlm4dOVgGRvA1ZzMH5MQ3nLo8bo","scope": "organizations:write read","token_type": "bearer"}