How to create tasks in Asana via the Asana API in Python

Asana, one of the most popular project management tools on the market, makes it easy to manage and collaborate on projects of all scales across platforms. It's not only easy to learn and use; it also offers integrations with a wide range of third-party tools and services.

Despite all these integrations, you still might need to access tasks and other data via APIs. For example, you might be building a custom integration, want to connect Asana with internal apps or tools, or set up custom automations. The Asana API can help you in these cases.

In this tutorial, you'll learn how to use the Asana API to create new tasks and fetch all available tasks programmatically using a Python script. The complete code for this tutorial is available in this GitHub repo.

Prerequisites

To follow along with this tutorial, you'll need a local installation of Python and an Asana account.

Create a New Python Script

The first step is to create a new Python script file by running the following command:

touch script.py

Alternatively, you can use any editor of your choice to create the file.

You also need to create an input.csv file to store the details of the tasks that the script will create in Asana. Use the following data for now:

Purchase ingredients, Purchase the ingredients required to make coffee, 2023-01-10,
Send out invitations, Send out the invitations for the housewarming party, 2023-01-11,
Buy grocery, Buy groceries for the next week, 2023-01-08

Each row on the CSV file above contains the following information:

  • Task name (e.g., Purchase Ingredients)
  • Task notes (e.g., Purchase the ingredients required to make coffee)
  • Due On date (e.g., 2023-01-10)

You can add any other attributes to your Asana tasks using the API, but for the sake of brevity, this tutorial uses only the attributes above.

Related: The 7 steps for creating your access token in Asana

Handle Asana API Authentication

To interact with the Asana API, you must generate a personal access token. Generating one is simple:

Asana developer console
  • Enter a description for the token and click on the Create token button.
Creating a new token
  • Asana will show you the token's value. Copy and store it safely as you will not be able to see this token again. You can always create a new token, but each token will be visible to you only once right after you create it.
Token created

To use the token in your script, create a variable and store the token's value in it.

PAT_TOKEN = ''

You'll now see how to use this token to authenticate a simple request to the Asana API that fetches your user details.

Install pip install requests and import the requests package in your script:

import requests'

Next, define a few constants that you'll use in your requests:

PAT_TOKEN = ''
BASE_URL = 'https://app.asana.com/api/1.0' # The base URL for the Asana API
USERS_ENDPOINT = '/users/me' # The users endpoint to fetch your own details
TASKS_ENDPOINT = '/tasks' # The tasks endpoint to create and fetch tasks from
'

Finally, write the request to fetch your own details:

result = requests.get(
        BASE_URL + USERS_ENDPOINT,
        headers={
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': 'Bearer {}'.format(PAT_TOKEN) # Adding the PAT token for authentication
        }
    )

data = result.json()

print(data)

The result should look like this:

{"data":{"gid":"1203633602789119","email":"kumar@draft.dev","name":"Kumar Harsh","photo":null,"resource_type":"user","workspaces":[{"gid":"12036336567142129","name":"draft.dev","resource_type":"workspace"}]}}

It signifies that you have correctly set up authentication in your code for the Asana API.

Before continuing, you need to take care of one more thing. When creating tasks in Asana, you must associate them with a workspace, project, or a parent task. When fetching tasks from Asana, you need to specify either a project, tag, or a combination of workspace and assignee to filter the tasks before retrieving them.

To keep things simple, you'll use the default workspace and your own user ID as assignee with which to associate your tasks. The request that you created earlier in this tutorial fetched both of these details. All you now need to do is to wrap the request into a method and have it return only the two IDs you need. Here's what the method looks like:

def getIds():
    result = requests.get(
        BASE_URL + USERS_ENDPOINT,
        headers={
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': 'Bearer {}'.format(PAT_TOKEN) # Adding the PAT token for authentication
        }
    )

    data = result.json()

    workspaceId = data["data"]["workspaces"][0]["gid"]
    assigneeId = data["data"]["gid"]

    return workspaceId, assigneeId

At this point, your script.py file should look like this:

import requests

PAT_TOKEN = ""
BASE_URL = 'https://app.asana.com/api/1.0'
USERS_ENDPOINT = '/users/me'
TASKS_ENDPOINT = '/tasks'

HEADERS = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer {}'.format(PAT_TOKEN) # Adding the PAT token for authentication
},


def getIds():
    result = requests.get(
        BASE_URL + USERS_ENDPOINT,
        headers={
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': 'Bearer {}'.format(PAT_TOKEN) # Adding the PAT token for authentication
        }
    )

    data = result.json()

    workspaceId = data["data"]["workspaces"][0]["gid"]
    assigneeId = data["data"]["gid"]

    return workspaceId, assigneeId

Create Tasks in Asana

Now you're ready to write the function that will create new tasks in Asana. To allow bulk task creation, you'll take input from the CSV file as described earlier and create a task for each row of the file:

import csv

def createTasks():

    workspaceId, assigneeId = getIds()

    with open('./input.csv', 'r') as file:
        reader = csv.reader(file)
        for row in reader:
            data = {
                "data": {
                    "name": row[0].strip(), # Fetch from input file and strip any extra whitespaces from the text
                    "notes": row[1].strip(),
                    "due_on": row[2].strip(),
                    "workspace": workspaceId, # Add the default workspace ID
                    "assignee": assigneeId # Assign the task to the current user
                }
            }

            result = requests.post(
                BASE_URL + TASKS_ENDPOINT,
                headers={
                    'Content-Type': 'application/json',
                    'Accept': 'application/json',
                    'Authorization': 'Bearer {}'.format(PAT_TOKEN) # Adding the PAT token for authentication
                },
                json=data
            )

            print(result.json())

The code is fairly simple to understand. You start by fetching the workspace and assignee IDs using the function you created earlier. Next, you open the input file and process each of its rows individually. For each row, you create a data object and send a request to the Asana API with the data object attached. Lastly, you print the result of the request.

You'll receive the details of the newly created tasks in response to your request. Here's what it will look like:

{'data': {'gid': '1203633772927990', 'projects': [], 'memberships': [], 'resource_type': 'task', 'created_at': '2023-01-01T23:03:02.484Z', 'modified_at': '2023-01-01T23:03:03.100Z', 'name': 'Purchase ingredients', 'notes': 'Purchase the ingredients required to make coffee', 'assignee': {'gid': '1203633602142119', 'resource_type': 'user', 'name': 'Kumar Harsh'}, 'completed': False, 'assignee_status': 'inbox', 'completed_at': None, 'due_on': '2023-01-10', 'due_at': None, 'resource_subtype': 'default_task', 'start_on': None, 'start_at': None, 'tags': [], 'workspace': {'gid': '1203633602142129', 'resource_type': 'workspace', 'name': 'draft.dev'}, 'num_hearts': 0, 'num_likes': 0, 'permalink_url': 'https://app.asana.com/0/1203633602142143/1203633772927990', 'parent': None, 'hearted': False, 'hearts': [], 'liked': False, 'likes': [], 'followers': [{'gid': '1203633602142119', 'resource_type': 'user', 'name': 'Kumar Harsh'}], 'assignee_section': {'gid': '1203633602142159', 'resource_type': 'section', 'name': 'šŸ“¬ New tasks'}, 'custom_fields': []}}
...

Fetch Tasks from Asana

Next, you'll fetch the tasks you created by creating another function:

def getAllTasks():

    workspaceId, assigneeId = getIds()

    result = requests.get(
        BASE_URL + TASKS_ENDPOINT +
        '?workspace={}&assignee={}'.format(workspaceId, assigneeId),
        headers={
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': 'Bearer {}'.format(PAT_TOKEN) # Adding the PAT token for authentication
        }
    )
    data = result.json()["data"]

    print("Total number of tasks", len(data))
    print("Tasks ->")
    print(data)

This code is also straightforward. You're fetching the workspace and assignee IDs first. Then, you're making a request to the Asana API to fetch all tasks associated with the given workspace and assignee. Finally, you're counting the number of tasks and printing their details.

Here's how the output should look:

Total number of tasks 9
Tasks ->
[{'gid': '1203633604772198', 'name': 'Schedule brainstorm', 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633604772200', 'name': 'Draft project proposal', 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633604772202', 'name': 'Incorporate feedback', 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633669717610', 'name': 'Buy grocery', 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633604772184', 'name': '1ļøāƒ£ First: Get started using My Tasks', 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633604772183', 'name': "2ļøāƒ£ Second: Find the layout that's right for you", 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633604772182', 'name': '3ļøāƒ£ Third: Get organized with sections', 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633772927990', 'name': 'Purchase ingredients', 'resource_type': 'task', 'resource_subtype': 'default_task'}, {'gid': '1203633703510178', 'name': 'Send out invitations', 'resource_type': 'task', 'resource_subtype': 'default_task'}]

You can find the complete code for this tutorial here.

Final Thoughts

While the Asana platform offers a robust UI to manage your tasks, there might be situations where you'd want programmatic access to your tasks to set up automations. The Asana API can come in handy in such cases.

As this tutorial showed, the Asana API is straightforward to use for simple use cases. However, figuring out configurations and maintaining them over time can be challenging. This is where Merge can help.

Merge offers a single API to integrate numerous products and services with your app easily. It lets you connect with numerous HRIS, ATS, accounting, CRM, and ticketing APIs, including Asana. If you're a B2B company, you'll love the power and simplicity that Merge will bring to your third-party tool integrations.