How to GET tasks from the Asana API in Python

While tasks in Asana can be used in a variety of ways, they’re even more valuable when they can be accessed by your other internal applications or your product.

Regardless of your specific integration use case, we'll walk through every step you should take to get tasks from the Asana API using Python.

Prerequisites

To follow along, you’ll need:

  • A valid Asana account 
  • Python version 3.10 or later
  • The python requests library installed in your environment (like your laptop)

Authenticating to the Asana tasks API

There are 3 ways you can authenticate with Asana’s APIs

1. Personal Access Token

A personal access token is similar to a username & password when logging into Asana, but it grants you unique access to using their API endpoints associated with your account. 

You have to generate a token through the Asana developer console. These tokens will be passed through the Authorization header when making requests.

Note: We’ll be using this token for our walkthrough. Learn more about generating a personal access token in Asana.

2. OAuth

OAuth provides an additional layer of security when sending in authorization tokens because your credentials are then “exchanged” for temporary access tokens. This process is also described in Asana’s docs.

3. OpenID Connect

This process uses JSON Web Tokens instead of access tokens for sending in authentication information. This requires an additional scope enabled for openid on your account. You can read about this form of authentication with Asana.

Generating a personal access token

You’ll need to generate a personal access token (“PAT”) through the Asana develop console.

  1. Visit the developer console while logged into your Asana account.
  2. Press “Create new token” and assign it a name that describes how this specific token will be used.

Creating a token in Asana
  1. Note that you must save the token after you generate it, as there will be no way to access it after it has been created and shown to you. DO NOT store this token directly in your application code. Tokens should be treated similar to passwords and have the appropriate security protocols.

We are now ready to take our access token and make some authenticated requests!

When making a request, send your token through the headers as so:


curl https://app.asana.com/api/1.0/users/me \
  	-H "Authorization: Bearer ACCESS_TOKEN"
    

Fetching tasks from the Asana API in Python

We’ll walk through an example of fetching all of your organization’s tasks for a specific project through the Asana API. We will also go through adding some filters to make this API response more suited to our specific needs. The endpoint I’ll be using is documented here.

First we’ll import the necessary requests package and construct the URL that we want to make a request to.

We know based on the documentation that our endpoint URL should be https://app.asana.com/api/1.0/tasks.

For this endpoint, we need to know the Project ID for the tasks we’re fetching. 

If you log into Asana on your browser, click on a project under the “Projects Tab” that you want to retrieve the tasks for. When you do, you should get redirected to a URL that looks like https://app.asana.com/0/{PROJECT_ID}/{viewing_tab}.

Grab the ID location where I defined PROJECT_ID in the URL above. For example, my test project has the following URL: https://app.asana.com/0/1202095602265837/1204819944726585.

the project ID for a specific project in Asana

My Project ID in this case will be: 1202095602265837

We can set up our call with the following information:


import requests


ASANA_BASE_TASK_URL = "https://app.asana.com/api/1.0/tasks"


PROJECT_ID = "1202095602265837" # This is hardcoded for the purpose of this  example, but I would recommend grabbing the ID you want from an additional API call

Now, we’re ready to use our requests library to make a GET request to the URL we constructed to fetch all of the tasks from the project we’re looking at.

We’ll want to set up the headers for our request, which will contain our personal access token in the “Authorization” key.


personal_access_token = "fake-token" # Grab this from env variables or secrets where you saved it!


headers = {
   "Authorization": f"Bearer {personal_access_token}"}

After this, we can pass in the headers to our request and make an authenticated request to the Asana API. We’ll need to add our “Project ID” to our base URL as an additional input in our request since Asana requires you to filter the endpoint by either Project, Tag, Assignee or Workspace.

When sending in an additional parameter through the API request, we can use URL query parameters by adding a “?” with the query name and value added to the end as “?project=1202095602265837”. If you want to join multiple query parameters, just add a “&” in between them.


url = f"{ASANA_BASE_TASK_URL}?project={PROJECT_ID}"
# This constructed URL should look something like this: https://app.asana.com/api/1.0/tasks?project=1202095602265837


# Make the API Request. Note the .get() function, which corresponds to the HTTP GET method of our request
response = requests.get(url, headers=headers)


# If the status code is 200, it means the request was successful
if response.status_code == 200:
   tasks = response.json()
   # After this -- you can do whatever you want with the tasks that is useful to you!


# If status code is not 200, print an error message since something went wrong
else:
   print(f"Failed to retrieve tasks. Status code: {response.status_code}")
   

We’ve now successfully made an authenticated request to the GitHub API and retrieved useful information. 

We can add extra query parameters to filter down the information we’re retrieving even more. There are tons of different possible filters defined in the API endpoint docs. Something that is often useful is using “modified_since” to grab all the tasks changed since you last called this endpoint. 

The “https://app.asana.com/api/1.0/tasks” could return thousands of tasks within a project, however, and all of these tasks might not fit within one API response. For this reason, this endpoint is paginated with a max of 100 tickets returned in one page. We can set the page size smaller if we want using the “limit” parameter.

In the API response, we know there is more info available if we receive a “next_page” key. For example, if I request the API with more than 100 tasks, I receive the following in the response JSON. 

JSON response if there are more than 100 tasks

I can check for a “next page” in my response and continue requesting until it’s empty. We can use the “URI” returned to properly access the next page of results. 


url = f"{ASANA_BASE_TASK_URL}?project={PROJECT_ID}"
has_next = True


while has_next and url is not None:
   response = requests.get(url, headers=headers)


   if response.status_code == 200:
       page = response.json()
       tasks = page.get("data", [])
       # After this -- you can do whatever you want with the tasks that is useful to you!
       # Do this before proceeding to the next page


       next_page = page.get("next_page", None)
       # Proceed to the next page
       if next_page:
           url = next_page.get("uri", None)
       else:
           has_next = False


   else:
       print(f"Failed to retrieve tasks. Status code: {response.status_code}")
       break
       

Now we’ve successfully gone through how to retrieve ALL tasks associated with your Asana project! All of the other Asana APIs should be very similar in how to request and access information if you follow the API docs.

Final thoughts

As you can tell, retrieving tasks from Asana via API requests can be technically complex and time consuming to set up (and maintain!). These issues only get exacerbated when you consider the other project management tools your clients want to integrate with your product, such as Trello or Jira.

To help you integrate with any of your clients' project management solutions, you can simply build to Merge's Ticketing and Project Management Unified API.

You can learn more about Merge and its Unified API by scheduling a demo with one of our integration experts.