Reassigning orphaned tickets with the Tickets API

Keeping your Zendesk environment organized and efficient often requires routine housekeeping, especially as your support team grows or changes. One common support operation is reassigning open tickets from a departing agent to a new owner.

In Zendesk, when an agent leaves the company and their user account is deactivated or deleted, any open tickets assigned to that agent remain assigned to them by default. Zendesk does not automatically reassign or unassign the tickets.

This article shows you how to use the Zendesk Tickets API to automatically reassign or unassign open tickets from a departing agent.

What you need

You'll need an API token from a Zendesk account. The API token must be created by an admin in the Zendesk account to ensure the token has sufficient API permissions.

You also need to install Python and the following packages if you don't already have them:

Setting your environment variables

Gather your Zendesk user email, API token, and Zendesk subdomain such as the string "mondocam" in "https://mondocam.zendesk.com".

To set the environment variables

  1. In your project folder, create a text file named .env (with a leading period).

  2. Use a text editor to paste the environment variables into the file:

    ZENDESK_SUBDOMAIN=your_subdomainZENDESK_USER_EMAIL=your_email@example.comZENDESK_API_TOKEN=your_api_token

    Note that the values don't use quotes.

  3. Save the updated .env file in your project folder.

  4. If you're using GitHub for this project, add .env to your .gitignore file so it doesn't get pushed to the remote branch where others could access it.

Reassigning orphaned tickets

When an agent leaves your organization or changes roles, it's best practice to transfer any open tickets they're assigned to, either by reassigning them to another agent or unassigning them for triage.

In your project folder, create a file named reassign_orphaned_tickets.py and paste the following Python script into it.

import osimport requestsfrom dotenv import load_dotenv
# load Zendesk credentialsload_dotenv()   # reads variables from the .env file and sets them in os.environ
# set global variablesBASE_URL = f"https://{os.environ['ZENDESK_SUBDOMAIN']}.zendesk.com"AUTH = f"{os.environ['ZENDESK_USER_EMAIL']}/token", os.environ['ZENDESK_API_TOKEN']

def fetch_open_tickets_for_agent(agent_id) -> list:    """    Finds all open tickets (not solved/closed) assigned to the departed agent.    Returns a list of ticket ids.    """    ticket_ids = []
    url = f"{BASE_URL}/api/v2/search.json"    query = f"type:ticket assignee:{agent_id} status<solved"    params = {'query': query, 'per_page': 100}    response = requests.get(url, auth=AUTH, params=params)    while url:        if response.status_code != 200:            raise requests.HTTPError(f"{response.status_code}: {response.reason}")        data = response.json()        for ticket in data['results']:            ticket_ids.append(ticket['id'])        url = data['next_page']        if url:            response = requests.get(url, auth=AUTH)
    return ticket_ids

def reassign_ticket(ticket_id, new_agent_id):    """    Updates the assignee of a ticket, or unassigns if new_agent_id is None.    Adds a public comment for transparency.    """    url = f"{BASE_URL}/api/v2/tickets/{ticket_id}.json"
    # build ticket update payload    data = {        'ticket': {            'assignee_id': new_agent_id,    # None = unassigned            'comment': {                'public': True,                'body': ''            }        }    }    if new_agent_id:        data['ticket']['comment']['body'] = 'Ticket reassigned due to agent departure.'    else:        data['ticket']['comment']['body'] = 'Ticket unassigned due to agent departure. Awaiting assignment.'
    response = requests.put(url, auth=AUTH, json=data)    if response.status_code == 200:        if new_agent_id:            msg = f"Reassigned ticket {ticket_id} to agent {new_agent_id}"        else:            msg = f"Unassigned ticket {ticket_id}"        print(msg)    else:        print(f"Failed to update ticket {ticket_id}: {response.status_code} {response.text}")

def main():
    # prompt the user for the agent user ids    agents = prompt_for_agent_ids()    print(f"Reassigning tickets from {agents['departed_agent_id']} to {agents['new_agent_id']}.")
    # find open tickets assigned to the departed agent    ticket_ids = fetch_open_tickets_for_agent(agents['departed_agent_id'])    print(f"Found {len(ticket_ids)} open tickets to reassign.")
    # reassign or unassign each ticket    for ticket_id in ticket_ids:        reassign_ticket(ticket_id, agents['new_agent_id'])

if __name__ == "__main__":    main()

How it works

The script automatically detects and closes tickets that have not been updated within a configured number of days, and adds a public comment to each affected ticket.

The script starts by prompting the user to enter the departed agent's user id as well as the new agent's user id, if applicable. The user can also unassign the tickets by pressing Enter instead of specifying the user id of a new agent.

The script searches for all tickets in your Zendesk account that are currently assigned to the departed agent and are not solved or closed.

Next, the script reassigns the tickets to the new agent or unassigns them.

A public comment is added to each updated ticket, explaining the reason for the change.

The script prints the outcome of every update to the console, so you’ll know which tickets were reassigned or unassigned.

Example output:

Enter the departed agent's user id and press Enter: 153101458061 <Enter>Enter the new agent's user id or leave blank to unassign the ticket, then press Enter: <Enter>Reassigning tickets from 1531014568061 to None.Found 3 open tickets to reassign.Unassigned ticket 129Unassigned ticket 128Unassigned ticket 13

In this example, a new agent id was not provided. Accordingly, the tickets were unassigned and the following public comment was added to the tickets:

Ticket unassigned due to agent departure. Awaiting assignment.

To run the script, navigate to your project folder with your command line interface, then run python3 reassign_orphaned_tickets.py.