In this post I’m going to talk about how I completed the second #DataDev challenge. The challenge was about connecting to Tableau Server using Tableau’s REST API to get the list of all workbook owners on the server. For more details on these challenges and how to participate see my first post.

What is Tableau REST API?

In general, REST APIs, short for REpresentational State Transfer application programming interface (API), are computing interfaces that allow you to send requests to your Tableau Server using an HTTP verb that describes the action being requested. Some of the most frequent verbs are:

  • GET (read information)
  • POST (create new resources)
  • PUT (update existing resources)
  • DELETE (remove resources or configurations)

Tableau’s REST API allows you to programmatically access your Tableau Server or Tableau Online, and work with data sources, content, projects, site users, sites, and more. You can also use it to create your own custom applications to interact with Tableau Server.

I recommend going through the Get Started Tutorial on Tableau’s website to understand the basics of working with the REST API.

Some use cases for Tableau’s REST API include:

  • Automatically add new users and sites to the server.
  • Generate images from Tableau dashboards.
  • Create subscriptions for users.

You can find REST API code samples on Tableau’s GitHub page.

Challenge 2: Programmatically build a list of workbook owners

This time I decided to do the Level 2 of the challenge as I’m more familiar with Python than with JavaScript, the programming language that was used in the first challenge. To connect to my Tableau Online instance, I used the Tableau Server Client (TSC) Python library.

To complete the challenge I wrote a Python script that users can execute in the Terminal, and which has the following functionality:

1. Sign in to a site on the Tableau Server

Let’s begin with importing the Python libraries we are going to use for this challenge:

import getpass, argparse, logging
import tableauserverclient as TSC
import pandas as pd

Next step is to create arguments that a user will need to pass to the script in the terminal to log in to the server. First, let’s define arguments for the site ID and site URL that you can find from your server’s URL:


parser = argparse.ArgumentParser()
parser.add_argument("--logging-level", "-l", choices=['debug','info','error'],
parser.add_argument("--site_id", "-i", required=True)
parser.add_argument("--site_url", "-s", required=True,
help='url in the format "https://SITE_URL" where SITE_URL is the URL of your Tableau server')

Next, we need to define arguments for the user’s login details. Typically, you can login to a Tableau Server either using your login and password, or a personal access token. The latter is seen as a more secure option when connecting to the server remotely. In my code I gave the user an option to choose the way to log in, and made these options mutually exclusive. When a user runs the script, and inputs either their username or personal access token’s name, the script will request either the user’s password or their personal access token respectively.

login_mutual_exclusion = parser.add_mutually_exclusive_group(required=True)
login_mutual_exclusion.add_argument("--username", "-u")
login_mutual_exclusion.add_argument("--token_name", '-n')

args = parser.parse_args()

The next part of the script sets the logging level based on the user’s input or uses the default ‘error’ level. This means that the user will see additional messages in the command line only when there is an error. Otherwise, all other system notes will not be displayed in the command line.

logging_level = getattr(logging, args.logging_level.upper())
logging.basicConfig(level = logging_level)

Then we create new variables for the site’s ID and URL taken from the arguments that the user entered in the terminal:

site_id = args.site_id
print("Site ID is ", site_id)
site_url = args.site_url
print("Site URL is ", site_url)

And finally, we need to update the Tableau’s REST API’s version to the most recent one, depending on the user’s server version:

server = TSC.Server(site_url, use_server_version=True)

Once the user inputs their username or personal access token name, the script decides how the user should be authenticated, and requests to input either the password or the personal access token:

# Authenticating the user based on their server's username and password

if args.username:
    username = args.username
    password = getpass.getpass("Input your password: ")
    tableau_auth = TSC.TableauAuth(username,password,site_id)
    print("Logged in to the server {} as a user {}.".format(site_url,username))

# Authenticating the user based on their server's Personal Access Token

    token_name = args.token_name
    personal_access_token = input("Input your Personal Access Token: ")
    tableau_auth = TSC.PersonalAccessTokenAuth(token_name=token_name,personal_access_token=personal_access_token, site_id=site_id)
    print("Logged in to the server {} with the token {}.".format(site_url,args.token_name))

2. Request the list of all workbooks and owners

Once the authentication is successful, the script collects information about all workbooks on the server as well as all workbook owners based on the owner id.

all_workbooks, pagination_item = server.workbooks.get()
workbook_data = [{"workbook_name":,
    "size": workbook.size,
    "owner_name": server.users.get_by_id(workbook.owner_id).name}
    for workbook in all_workbooks]

3. Export this list out as a CSV

We now collected information about the workbooks, but we need to export it as a .CSV file so we can create our dashboard. To do so, I created a dataframe using the Pandas library:

df = pd.DataFrame.from_dict(workbook_data)
df.to_csv("list_workbooks.csv", index=False)
print("CSV file was saved to the same folder as this script.")

As there is no specified path in the script above, the new .CSV file will be saved in the same location as the Python script.

4. Log out of the server

Once the file is generated, remember to log out of the server:

print('Logged out of the server {}'.format(site_url))

It’s a good practice to print out comments on how the code is progressing to help with debugging. Here is how the command line output looks when I ran my code:

Click on the image to open the full-sized version.

5. Connect to the .CSV file on the server and create a workbook showing all workbook owners and their content

To complete this last step, manually login to your Tableau Server and click on Create Workbook button in the welcome banner.

When the new workbook opens, click on Files in the Connect to Data dialogue box, and upload the .CSV file you’ve created in the previous step.

After you connect to the file, you will be able to create a dashboard showing all the owners and their workbooks on your server. I started using my Tableau Online account quite recently, so my dashboard for the challenge looks quite empty:

You can see my final code for this project in my GitHub repository.

Previously completed #DataDev challenges:

Challenge 1: Extensions in Tableau

Challenge 5: Setting up webhooks to receive Tableau event notifications