When working with OAuth access tokens in Zendesk, you can't retrieve the full access token after creation. To protect these sensitive credentials from exposure or misuse, Zendesk shows only the first 10 characters of each token in API responses, allowing you to verify and differentiate tokens without revealing the full secret required for authentication. However, you can view other information about the token, such as its scope and id.

This article explains how to list OAuth access tokens to view their related information.

Listing OAuth access tokens

Listing OAuth tokens lets you see how tokens are being used, such as:

  • Auditing active tokens: See which OAuth tokens are currently active in your Zendesk account.
  • Reviewing token scopes: View the scopes assigned to each token to see the permissions granted, helping to ensure tokens have the appropriate access.
  • Associating tokens with users and applications: Helps you track which users or apps can access these tokens.

You can use this information to detect unused or overly permissive tokens, and then revoke or renew them as necessary.

The List Tokens endpoint returns a list of access tokens for a Zendesk account. Only admins can make the request. This endpoint does not provide full user or client details, token expiration information, or in-depth usage statistics.

curl https://{subdomain}.zendesk.com/api/v2/oauth/tokens.json \  -v -u {email_address}/token:{api_token}

Here is an example response:

{  "tokens": [    {      "url": "https://example.zendesk.com/api/v2/oauth/tokens/15022151901588.json",      "id": 15022151901588,      "user_id": 1905826600027,      "client_id": 223443,      "token": "52d7ef4ee0",      ...      "scopes": [        "tickets:read"      ]    },    ...  ]}
  • id: Unique identifier for the access token, used for revocation or inspection.
  • user_id: The Zendesk user id associated with the token.
  • client_id: The OAuth client application id that requested the token.
  • token: Partial token string (first 10 characters) for identification only.
  • scopes: Permissions granted to the token, such as read or write access to tickets.

Python script to list tokens

Here's a short Python script to list all tokens for your account.

import osimport requests
# Load Zendesk API credentials and subdomain from environment variablesZENDESK_API_TOKEN = os.getenv('ZENDESK_API_TOKEN')ZENDESK_USER_EMAIL = os.getenv('ZENDESK_USER_EMAIL')ZENDESK_SUBDOMAIN = os.getenv('ZENDESK_SUBDOMAIN')
# Exit if any required environment variables are missingif not all([ZENDESK_API_TOKEN, ZENDESK_USER_EMAIL, ZENDESK_SUBDOMAIN]):    print('Error: Missing required environment variables.')    exit(1)
# Set up HTTP Basic Authentication with email/token and API tokenAUTH = f'{ZENDESK_USER_EMAIL}/token', ZENDESK_API_TOKEN
API_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/oauth/tokens.json"
response = requests.get(API_URL, auth=AUTH)response.raise_for_status()tokens = response.json().get("tokens", [])for token in tokens:    print(f"Token id: {token['id']}, User: {token['user_id']}, Scopes: {token['scopes']}")

Here's an example output:

Token id: 33160940517527, User: 1509756491122, Scopes: ['read', 'write']Token id: 33188809869719, User: 1509756491122, Scopes: ['read', 'write']Token id: 1501173602742, User: 1509756491122, Scopes: ['any_channel:write']

Python script to show more token details

The following script expands the above example to show:

  • Who owns each token (user details)
  • Which application issued the token (client details)
  • Token validity period and revocation status
import osimport requests
# Load Zendesk API credentials and subdomain from environment variablesZENDESK_API_TOKEN = os.getenv('ZENDESK_API_TOKEN')ZENDESK_USER_EMAIL = os.getenv('ZENDESK_USER_EMAIL')ZENDESK_SUBDOMAIN = os.getenv('ZENDESK_SUBDOMAIN')
# Exit if any required environment variables are missing to prevent unauthorized callsif not all([ZENDESK_API_TOKEN, ZENDESK_USER_EMAIL, ZENDESK_SUBDOMAIN]):    print("Error: Missing required environment variables.")    exit(1)
# Setup HTTP Basic Authentication using API tokenAUTH = f'{ZENDESK_USER_EMAIL}/token', ZENDESK_API_TOKEN
# Base API URL constructed using the Zendesk subdomainBASE_API_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2"
def get_oauth_tokens():    """Get the list of OAuth access tokens for the Zendesk account."""    url = f"{BASE_API_URL}/oauth/tokens.json"    response = requests.get(url, auth=AUTH)  # Send authenticated GET request    response.raise_for_status()               # Raise exception on HTTP error    return response.json().get('tokens', []) # Return list of tokens or empty list
def get_users(user_ids):    """    Retrieve detailed user info.    Returns a dictionary mapping user id to user data.    """    if not user_ids:    return {}  # Return empty dict if no ids provided
    users = {}    for user_id in user_ids:        url = f'{BASE_API_URL}/api/v2/users/{user_id}'        response = requests.get(url, auth=AUTH)        user_data = response.json()        users[user_data['id']] = user_data
    return users
def get_oauth_client(client_id):    """    Retrieve details for a single OAuth client application by client id.    Returns a dictionary of client info or empty dict if not found.    """    url = f"{BASE_API_URL}/oauth/clients/{client_id}.json"    response = requests.get(url, auth=AUTH)    if response.status_code == 404:        # Client not found or no access, log and return empty        print(f"OAuth client {client_id} not found or inaccessible.")        return {}    response.raise_for_status()    return response.json().get('client', {})
def get_token_details(token_id):    """    Retrieve detailed info for a specific OAuth token by token id.    Returns a dictionary with token metadata.    """    url = f"{BASE_API_URL}/oauth/tokens/{token_id}.json"    response = requests.get(url, auth=AUTH)    response.raise_for_status()    return response.json().get('token', {})
def main():    tokens = get_oauth_tokens()  # Get all OAuth tokens    print(f"Found {len(tokens)} OAuth tokens:")
    user_ids = set()   # Colect unique user ids from tokens    client_ids = set() # Collect unique OAuth client ids from tokens
    # Iterate tokens to display summary info and collect related ids    for token in tokens:        print(f"Token id: {token['id']}, Partial token: {token.get('token')}, Scopes: {token.get('scopes')}")        user_ids.add(token.get('user_id'))        client_ids.add(token.get('client_id'))
    # Get detailed user information for collected user ids    users = get_users(user_ids)    print("\nFetched User Details:")    for uid, user in users.items():        print(f"User id: {uid}, Email: {user.get('email')}, Name: {user.get('name')}")
    # Get and display OAuth client details per collected client id    print("\nFetching OAuth Client Details:")    for cid in client_ids:        client = get_oauth_client(cid)        print(f"Client id: {cid}, Name: {client.get('name')}, Redirect URIs: {client.get('redirect_uri')}")
    # Get detailed token metadata for each token id and display    print("\nFetching Token Details:")    for token in tokens:        details = get_token_details(token['id'])        print(f"Token id: {token['id']}, Expires At: {details.get('expires_at')}, Status: {details.get('status')}")
if __name__ == "__main__":    main()

Here's an example output:

Found 3 OAuth tokens:Token id: 33160940517527, Partial token: 5b24bd1adc, Scopes: ['read', 'write']Token id: 33188809869719, Partial token: b916c4b6b5, Scopes: ['read', 'write']Token id: 1501173602742, Partial token: ea604660a1, Scopes: ['any_channel:write']
Fetched User Details:User id: 1509756491122, Email: [email protected], Name: Cris P Bacon
Fetching OAuth Client Details:OAuth client 218 not found or inaccessible.Client id: 218, Name: None, Redirect URIs: NoneClient id: 33160833707415, Name: Talk Make test, Redirect URIs: ['https://www.example.com/oauth/cb/zendesk/']
Fetching Token Details:Token id: 33160940517527, Expires At: None, Status: NoneToken id: 33188809869719, Expires At: None, Status: NoneToken id: 1501173602742, Expires At: None, Status: None

The example output shows:

  • Token ids and partial tokens: Displays each token's unique id and a partial token string to differentiate tokens without exposing the full secrets.
  • Scopes: The permissions assigned to each token. Such as ['read', 'write'] or ['any_channel:write'].
  • User details: Lists the users associated with the token, including email and name. In this example, the same user is associated with all three tokens.
  • OAuth client details: Information about the OAuth client applications that issued the tokens.
  • Token details: Metadata about each token, such as expiration date and status. In this example, these fields are empty, meaning the tokens have no expiration configured or the information is unavailable.