asana_preview
This is a preview version of Asana's new python client library. For feedback and feature requests, please leave a comment on this forum thread or through the feedback form on our documentation site
- API version: 1.0
- Package version: 1.2.40
Requirements.
Python 3.4+
Installation & Usage
pip install from PyPI
pip install asana-preview
Then import the package:
import asana_preview
Setuptools
Install via Setuptools.
python setup.py install --user
(or sudo python setup.py install
to install the package for all users)
Then import the package:
import asana_preview
Getting Started
Please follow the installation procedure and then run the following:
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
users_api_instance = asana_preview.UsersApi(api_client)
user_gid = "me"
opts = {}
try:
user = users_api_instance.get_user(user_gid, opts)
pprint(user)
except ApiException as e:
print("Exception when calling UsersApi->get_user: %s\n" % e)
Example: GET, POST, PUT, DELETE on tasks
GET - get multiple tasks
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
opts = {
'limit': 50,
'offset': "eyJ0eXAiOJiKV1iQLCJhbGciOiJIUzI1NiJ9",
'assignee': "14641",
'project': "321654",
'section': "321654",
'workspace': "321654",
'completed_since': '2012-02-22T02:06:58.158Z',
'modified_since': '2012-02-22T02:06:58.158Z',
'opt_fields': "actual_time_minutes,approval_status,assignee,assignee.name,assignee_section,assignee_section.name,assignee_status,completed,completed_at,completed_by,completed_by.name,created_at,created_by,custom_fields,custom_fields.asana_created_field,custom_fields.created_by,custom_fields.created_by.name,custom_fields.currency_code,custom_fields.custom_label,custom_fields.custom_label_position,custom_fields.date_value,custom_fields.date_value.date,custom_fields.date_value.date_time,custom_fields.description,custom_fields.display_value,custom_fields.enabled,custom_fields.enum_options,custom_fields.enum_options.color,custom_fields.enum_options.enabled,custom_fields.enum_options.name,custom_fields.enum_value,custom_fields.enum_value.color,custom_fields.enum_value.enabled,custom_fields.enum_value.name,custom_fields.format,custom_fields.has_notifications_enabled,custom_fields.is_formula_field,custom_fields.is_global_to_workspace,custom_fields.is_value_read_only,custom_fields.multi_enum_values,custom_fields.multi_enum_values.color,custom_fields.multi_enum_values.enabled,custom_fields.multi_enum_values.name,custom_fields.name,custom_fields.number_value,custom_fields.people_value,custom_fields.people_value.name,custom_fields.precision,custom_fields.resource_subtype,custom_fields.text_value,custom_fields.type,dependencies,dependents,due_at,due_on,external,external.data,followers,followers.name,hearted,hearts,hearts.user,hearts.user.name,html_notes,is_rendered_as_separator,liked,likes,likes.user,likes.user.name,memberships,memberships.project,memberships.project.name,memberships.section,memberships.section.name,modified_at,name,notes,num_hearts,num_likes,num_subtasks,offset,parent,parent.created_by,parent.name,parent.resource_subtype,path,permalink_url,projects,projects.name,resource_subtype,start_at,start_on,tags,tags.name,uri,workspace,workspace.name"
}
try:
tasks = tasks_api_instance.get_tasks(opts)
for task in tasks:
pprint(task)
except ApiException as e:
print("Exception when calling TasksApi->get_tasks: %s\n" % e)
POST - create a task
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
body = {
"data": {
"name": "New Task",
"projects": ["<YOUR_PROJECT_GID>"],
}
}
opts = {}
try:
task = tasks_api_instance.create_task(body, opts)
pprint(task)
except ApiException as e:
print("Exception when calling TasksApi->create_task: %s\n" % e)
PUT - update a task
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
body = {
"data": {
"name": "Updated Task",
}
}
task_gid = "<YOUR_TASK_GID>"
opts = {}
try:
task = tasks_api_instance.update_task(body, task_gid, opts)
pprint(task)
except ApiException as e:
print("Exception when calling TasksApi->update_task: %s\n" % e)
DELETE - delete a task
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
task_gid = "<YOUR_TASK_GID>"
try:
task = tasks_api_instance.delete_task(task_gid)
pprint(task)
except ApiException as e:
print("Exception when calling TasksApi->delete_task: %s\n" % e)
Documentation for API Endpoints
All URIs are relative to https://app.asana.com/api/1.0
Accessing repsonse data
Example: Accessing task data
.
.
.
try:
task = tasks_api_instance.get_task(task_gid, opts)
task_name = task['name']
task_notes = task['notes']
except ApiException as e:
.
.
.
Accessing response status code and headers
In the scenario you want to access the response headers or the status code along with the response data you can
provide the _return_http_data_only
parameter argument in the request method and set the value to False
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
users_api_instance = asana_preview.UsersApi(api_client)
user_gid = 'me'
opts = {}
try:
(api_response, status, headers) = users_api_instance.get_user(user_gid, opts, _return_http_data_only=False)
pprint(api_response)
pprint(status)
pprint(headers)
except ApiException as e:
print("Exception when calling UsersApi->get_user: %s\n" % e)
On the client
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
api_client.default_headers['asana-enable'] = 'string_ids'
OR
On the request
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
users_api_instance = asana_preview.UsersApi(api_client)
user_gid = 'me'
opts = {}
try:
api_response = users_api_instance.get_user(user_gid, opts, header_params={'asana-enable': 'string_ids'})
pprint(api_response)
except ApiException as e:
print("Exception when calling UsersApi->get_user: %s\n" % e)
Async requests with multithreading
This client library uses multithreading to make async requests. To make async requests you can pass in async_req=True
in the method call.
NOTE:
- This feature disables our auto-pagination feature
- You will want to add logic to handle the Asana API rate limits
The code belows is an example of how to make 15 async create task calls. It does not handle the Asana API rate limits.
You will have to implement your own solution for API rate limits based on your tier.
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
threads = []
for i in range(1, 15+1):
body = {
"data": {
"name": f"Task: {i}",
"projects": ["<YOUR_PROJECT_GID>"]
}
}
opts = {}
threads.append(tasks_api_instance.create_task(body, opts, async_req=True))
for thread in threads:
try:
pprint(thread.get())
except ApiException as e:
print("Exception when calling TasksApi->create_task: %s\n" % e)
The pagination feature is enabled by default. This means two things:
1: Endpoints that return a single response (EX: get_task (Get a task), get_project (Get a project), etc...)
will return a response with the "data"
key abstracted from the response.
Instead of returning:
{
"data": {
"gid": "123",
"actual_time_minutes": null,
"assignee": null,
...
"workspace": {
"gid": "1234567",
"name": "user@example.com",
"resource_type": "workspace"
}
}
}
It returns:
{
"gid": "123",
"actual_time_minutes": null,
"assignee": null,
...
"workspace": {
"gid": "1234567",
"name": "user@example.com",
"resource_type": "workspace"
}
}
2: Endpoints that return an array of resources (EX: get_tasks (Get multiple tasks), get_projects (Get multiple projects), etc...)
will return a generator object (PageIterator.items) that you can use to iterate through each result.
Example usage 1:
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
opts = {"project": "<YOUR_PROJECT_GID>"}
try:
tasks = tasks_api_instance.get_tasks(opts)
for task in tasks:
pprint(task)
except Exception as e:
print("Exception when calling TasksApi->get_tasks: %s\n" % e)
Example response:
{'gid': '123',
'name': 'Task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'},
.
.
.
Example usage 2:
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
opts = {"project": "<YOUR_PROJECT_GID>"}
try:
tasks = tasks_api_instance.get_tasks(opts)
pprint(list(tasks))
except Exception as e:
print("Exception when calling TasksApi->get_tasks: %s\n" % e)
Example response:
[{'gid': '123',
'name': 'Task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'},
.
.
.]
In the scenario where you want to end the pagination early, you can specify an item_limit
in the method call. This will stop the iterator from going past that limit.
Example Scenario: You have 1000 tasks in a project and are only interested in the first 2 tasks. Instead of letting the pagination code continue to run to get all those 1000 tasks you can specify that you only want the first X results with item_limit
.
Without item_limit
- The for loop will continue to run until it runs out of tasks:
...
tasks = tasks_api_instance.get_tasks(opts)
for task in tasks:
pprint(task)
...
Sample response:
{'gid': '123',
'name': 'Task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'},
.
.
.
<1000th_TASK>
With item_limit
- the for loop will stop at the item_limit
you specified:
...
tasks = tasks_api_instance.get_tasks(opts, item_limit=2)
for task in tasks:
pprint(task)
...
Sample response:
{'gid': '123',
'name': 'Task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'},
{'gid': '456',
'name': 'Task 2',
'resource_subtype': 'default_task',
'resource_type': 'task'}
Alternatively, if you are iterating over the generator object in a for loop, you can also just break out of the loop.
EX:
...
opts = {'project': "<YOUR_PROJECT_GID>"}
try:
count = 0
tasks = tasks_api_instance.get_tasks(opts)
for task in tasks:
if count == 2:
break
pprint(task)
count += 1
...
Sample response:
{'gid': '123',
'name': 'Task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'},
{'gid': '456',
'name': 'Task 2',
'resource_subtype': 'default_task',
'resource_type': 'task'}
If you do not want to use the default pagination behaviour there are two ways to disbale it.
1: Per request - Disable pagination behavior for a single request - pass in full_payload=True
in the method request
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
tasks_api_instance = asana_preview.TasksApi(api_client)
opts = {"project": "<YOUR_PROJECT>", "limit": 2}
try:
tasks = tasks_api_instance.get_tasks(opts, full_payload=True)
pprint(tasks)
except Exception as e:
print("Exception when calling TasksApi->get_tasks: %s\n" % e)
Sample response:
{'data': [{'gid': '123',
'name': 'Task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'},
{'gid': '456',
'name': 'Task 2',
'resource_subtype': 'default_task',
'resource_type': 'task'}],
'next_page': {'offset': 'eyJ0...',
'path': '/tasks?project=789&limit=2&offset=eyJ0...',
'uri': 'https://app.asana.com/api/1.0/tasks?project=789&limit=2&offset=eyJ0...'}}
2: Globally - Disable pagination behavior for all requests - Set return_page_iterator
to False
...
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
configuration.return_page_iterator = False
api_client = asana_preview.ApiClient(configuration)
...
Documentation for Using the call_api
method
Use this to make HTTP calls when the endpoint does not exist in the current library version or has bugs
Example: GET, POST, PUT, DELETE on tasks
GET - get a task
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
try:
api_response = api_client.call_api(
"/tasks/{task_gid}",
"GET",
path_params={"task_gid": "<YOUR_TASK_GID>"},
query_params={},
header_params={"Accept": "application/json; charset=utf-8"},
body=None,
post_params=[],
files={},
response_type=object,
auth_settings=["token"],
async_req=None,
_return_http_data_only=True,
_preload_content=True,
_request_timeout=None,
collection_formats={},
)
pprint(api_response)
except ApiException as e:
print("Exception: %s\n" % e)
GET - get multiple tasks -> with opt_fields
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
try:
api_response = api_client.call_api(
"/tasks",
"GET",
path_params={},
query_params={
"project": "<YOUR_PROJECT_GID>",
"opt_fields": "name,notes,projects",
},
header_params={"Accept": "application/json; charset=utf-8"},
body=None,
post_params=[],
files={},
response_type=object,
auth_settings=["token"],
async_req=None,
_return_http_data_only=True,
_preload_content=True,
_request_timeout=None,
collection_formats={},
)
pprint(api_response)
except ApiException as e:
print("Exception: %s\n" % e)
POST - create a task
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
try:
api_response = api_client.call_api(
"/tasks",
"POST",
path_params={},
query_params={},
header_params={
"Accept": "application/json; charset=utf-8",
"Content-Type": "application/json; charset=utf-8",
},
body={
"data": {
"name": "New Task",
"projects": ["<YOUR_PROJECT_GID>"],
}
},
post_params=[],
files={},
response_type=object,
auth_settings=["token"],
async_req=None,
_return_http_data_only=True,
_preload_content=True,
_request_timeout=None,
collection_formats={},
)
pprint(api_response)
except ApiException as e:
print("Exception: %s\n" % e)
PUT - update a task
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
try:
api_response = api_client.call_api(
"/tasks/{task_gid}",
"PUT",
path_params={"task_gid": "<YOUR_TASK_GID>"},
query_params={},
header_params={
"Accept": "application/json; charset=utf-8",
"Content-Type": "application/json; charset=utf-8",
},
body={
"data": {
"name": "Updated Task",
}
},
post_params=[],
files={},
response_type=object,
auth_settings=["token"],
async_req=None,
_return_http_data_only=True,
_preload_content=True,
_request_timeout=None,
collection_formats={},
)
pprint(api_response)
except ApiException as e:
print("Exception: %s\n" % e)
DELETE - delete a task
import asana_preview
from asana_preview.rest import ApiException
from pprint import pprint
configuration = asana_preview.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana_preview.ApiClient(configuration)
try:
api_response = api_client.call_api(
"/tasks/{task_gid}",
"DELETE",
path_params={"task_gid": "<YOUR_TASK_GID>"},
query_params={},
header_params={"Accept": "application/json; charset=utf-8"},
body=None,
post_params=[],
files={},
response_type=object,
auth_settings=["token"],
async_req=None,
_return_http_data_only=True,
_preload_content=True,
_request_timeout=None,
collection_formats={},
)
pprint(api_response)
except ApiException as e:
print("Exception: %s\n" % e)