Table of Contents
Overview
The Asana API is a RESTful interface, providing programmatic access to much of the data in the system. It provides predictable URLs for accessing resources, and uses built-in HTTP features to receive commands and return responses. This makes it easy to communicate with from a wide variety of environments, from command-line utilities to gadgets to the browser URL bar itself.
The API accepts JSON or form-encoded content in requests. It returns JSON content in all of its responses, including errors. Only the UTF-8 character encoding is supported for both requests and responses.
Use Cases
The Asana API lets you build a variety of applications and scripts to integrate Asana with your business systems, show Asana data in other contexts, and create tasks from various locations.
Here are some examples of the things you can build with the Asana API:
- A browser extension to quickly create tasks from any web page
- Source Control Integration to mark a task as complete and add a link to the code submission as a comment when submitting code.
- A desktop app that shows the tasks assigned to you
- A dashboard page that shows a visual representation of complete and incomplete tasks in a project
Hello World
Here is a sample application that creates a new task named "Hello World!" and assigns it to a user.
First, we set up some constants to deal with values that will depend on who is using this script. These include the user-specific API key, the ID of the workspace in which the new task will be created, and the email address of the user to whom it will be assigned.
Next, we set up our HTTP connection. Note that the API only accepts secure connections via HTTPS.
Then we can start building the request. The most important part is
setting the Authorization header to provide the
API key (more details in the
Authentication section below).
All API POST and PUT requests expect a top-level object with a single
element in it named data. Successful responses will mirror this
format. The data element should itself be an object,
containing the parameters for the request. In the case of creating
a new task, these are the fields we want to set on the task itself.
If the request was
successful, we will get a response code of 201 indicating the object
was created. That response will have a data field at its
top level, which will contain complete information on the new task,
including its ID.
If something went wrong during the request, we'll get a different
status code and the JSON returned will contain an errors
field at the top level containing a list of problems. We look at the
first one and print out its message.
#!/usr/bin/env ruby
require "rubygems"
require "JSON"
require "net/https"
api_key = API-KEY
workspace_id = WORKSPACE-ID
assignee = ASSIGNEE-EMAIL
# set up HTTPS connection
uri = URI.parse("https://app.asana.com/api/1.0/tasks")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
# set up the request
header = {
"Content-Type" => "application/json"
}
req = Net::HTTP::Post.new(uri.path, header)
req.basic_auth(api_key, '')
req.body = {
"data" => {
"workspace" => workspace_id,
"name" => "Hello World!",
"assignee" => assignee
}
}.to_json()
# issue the request
res = http.start { |http| http.request(req) }
# output
body = JSON.parse(res.body)
if body['errors'] then
puts "Server returned an error: #{body['errors'][0]['message']}"
else
puts "Created task with id: #{body['data']['id']}"
end
Example Applications
In addition to the Hello World application, we have written a Chrome extension which demonstrates using the API in a browser extension:
Authentication
All API requests must contain some mechanism for identifying the user and ensuring they are authorized to make the request. The Asana API supports two separate authentication schemes: OAuth 2.0 and HTTP Basic Authentication using API keys. A client with a user's authorization (be that the API key or an OAuth bearer token) may access information and make changes in the Asana system as if it were that user.
Asana Connect (OAuth)
The Asana API supports authentication via Asana Connect, which uses the OAuth 2.0 framework. While we do not support all the authentication strategies detailed in the specification, those we do support conform to Draft 31 of the OAuth 2.0 Authorization Framework, and should be compatible with popular implementations of OAuth 2.0 such as the omniauth gem for ruby (in fact, you can use the omniauth-asana gem to get started right out of the box).
Supported Strategies
We support the Authorization Code Grant flow (most common for traditional web apps, as well as native desktop and mobile applications), as well as the Implicit Grant (suitable for in-browser web apps, such as single-site apps written in JavaScript that cannot make arbitrary POST requests to the Asana API).
Registering an Application
Developers seeking to implement an Asana Connect application must first register their app to receive a Client ID and Client Secret. Fortunately, this process is fast and easy: visit your Account Settings dialog and click the Apps tab. There will be a link to "Register New Application". As with all OAuth apps, you must supply an Application URL as well as a Redirect URL that successful (or failed) authentications will redirect to. Additionally, you can set a name and an icon to enhance the recognizability of the application. When users are prompted to authorize your app, they will be more likely to click "Allow" if it is clear who they are passing their authorization on to.
Once you have created an app, the details view will include a Client ID, needed to uniquely identify your app to the Asana API, as well as a Client Secret. Applications implementing the Authorization Code Grant flow use the secret to securely identify themselves when retrieving the user's bearer token.
Requesting Authorization from the User
While a thorough discussion of the OAuth specification exceeds the scope of this documentation, (and use of existing OAuth libraries for those unfamiliar with the standard is generally recommended), a high-level overview can be useful. In the typical Authorization Code Grant flow, you will redirect the user (or Resource Owner, in the parlance of OAuth) to the authorization endpoint, passing along the parameters for the request as standard HTTP query parameters. The user will either authorize (or not) your application, and will be redirected back to the Redirect URL, along with parameters containing a code. This code can be exchanged via POST to the token exchange endpoint for a token, which can then be used to make authenticated requests against the API.
When prompting users to authenticate with Asana Connect, developers should use a button with the text "Sign in with Asana". We recommend the images shown on the right, but developers may adapt the designs to their app as appropriate.
For a more in-depth look at how Asana Connect is implemented, take a look at our OAuth Examples, which contain both example implementations and a detailed look at the mechanics of using OAuth directly, for the adventurous.
Using the Bearer Token
Once you have a bearer token, you can make authenticated requests against the API on the user's behalf. In order to do this, simply add an HTTP header of the form "Authorization: Bearer $TOKEN" to your requests.
# example header using bearer authentication
Authorization: Bearer 0/d3afa84f920bc329e6b0d047c9a7bc9d
# curl request using bearer token authentication
curl -H "Authorization: Bearer 0/d3afa84f920bc329e6b0d047c9a7bc9d" https://app.asana.com/api/1.0/users/me
API Keys
Each user has their own unique API key, which they can provide to applications to talk to Asana on their behalf. The API uses the widely supported HTTP Basic Authentication mechanism to authenticate requests with the API key. (See Using basic authentication below for details.)
Getting an API key
Any user can get their own API key by visiting the Account Settings dialog and clicking on the Apps tab. The API key is located at the bottom of this dialog.
You can go directly to the tab now to see your API key.
Using basic authentication
To authenticate a request, clients should use HTTP Basic Authentication and pass the API key as the username, and an empty password. This will cause the client to send a header like the following:
| Username | FcZ23.M4xsMtXmTKmDA4ssLCkEnYi |
|
The API key for the requesting user.
Note: Most utilities and libraries that allow you to specify a username and password will handle proper encoding of the header for you. However, if you need to set the Authorization header manually,
the header value is constructed by adding a colon (:)
to the API key, then base64-encoding that string. You can read more on
basic authentication
if you need further details.
|
|
| Password | empty |
| The password should be blank. |
# curl request using basic authentication
curl -u FcZ23.M4xsMtXmTKmDA4ssLCkEnYi: https://app.asana.com/api/1.0/users/me
# Convert API key plus colon to base64
echo -n 'FcZ23.M4xsMtXmTKmDA4ssLCkEnYi:' | openssl enc -base64
>>> RmNaMjMuTTR4c010WG1US21EQTRzc0xDa0VuWWk6
# Example header using basic authentication
Authorization: Basic RmNaMjMuTTR4c010WG1US21EQTRzc0xDa0VuWWk6
Errors
Sadly, sometimes requests to the API are not successful. Failures can occur for a wide range of reasons. In all cases, the API should return an HTTP Status Code that indicates the nature of the failure (below), with a response body in JSON format containing additional information.
| 200 |
Success. If data was requested, it will be available
in the data field at the top level of the response body.
|
| 201 |
Success (for object creation). Its information is
available in the data field at the top level of the response body.
The API URL where the object can be retrieved is also returned
in the Location header of the response.
|
| 400 | Invalid request. This usually occurs because of a missing or malformed parameter. Check the documentation and the syntax of your request and try again. |
| 401 | No authorization. A valid API key was not provided with the request, so the API could not associate a user with the request. |
| 403 | Forbidden. The API key and request syntax was valid but the server is refusing to complete the request. This can happen if you try to read or write to objects or properties that the user does not have access to. |
| 404 | Not found. Either the request method and path supplied do not specify a known action in the API, or the object specified by the request does not exist. |
| 429 |
Rate Limit Enforced. Asana imposes a limit on
the rate at which users can make requests. The limit is currently
around 100 requests per minute, but this is not guaranteed:
it may vary with server load, and we may change it
in the future. The Retry-After response header
will specify the number of seconds until the user can make another request.
Clients sending large bursts of requests should handle this error code
to retry after the delay.
Rate limits are important to prevent abuse and keep the service available to everyone. If you definitely need a higher rate limit for your application, please contact developer support and we will look into granting an exception. |
| 500 | Server error. There was a problem on Asana's end. |
In the event of an error, the response body will contain an errors
field at the top level. This contains an array of at least one error object,
described below:
| message | project: Missing input |
| Message providing more detail about the error that occurred, if available. | |
| phrase | 6 sad squid snuggle softly |
| 500 errors only. A unique error phrase which can be used when contacting developer support to help identify the exact occurrence of the problem in Asana's logs. |
# Request
curl https://app.asana.com/api/1.0/users/me
# Response
HTTP/1.1 401
{
"errors": [
{
"message": "Not Authorized"
}
]
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks
# Response
HTTP/1.1 400
{
"errors": [
{
"message": "workspace: Missing input"
}
]
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/users/me
# Response
HTTP/1.1 500
{
"errors": [
{
"message": "Server Error",
"phrase": "6 sad squid snuggle softly"
}
]
}
Input/Output Options
In addition to providing fields and their values in a request, you may
also specify options to control how your request is interpreted
and how the response is generated. For GET requests, options are
specified as URL parameters prefixed with opt_. For
POST or PUT requests, options are specified in the body, inside the
top-level options object (a sibling of the data object).
These options can be used in combination in a single request, though some of them may conflict in their impact on the response.
| pretty |
?opt_pretty
options: { pretty: true } |
| Provides the response in "pretty" output. In the case of JSON this means doing proper line breaking and indentation to make it readable. This will take extra time and increase the response size so it is advisable only to use this during debugging. | |
| method | options: { method: "put" } |
|
In environments that do not support the full range of HTTP verbs,
this can be helpful to override the request method sent by the
browser, allowing access to the full range of actions in the API.
This should only be used when absolutely necessary, as circumventing
the browser's normal interpretation of the HTTP verbs can cause
issues.
Note: For security reasons, you cannot use this parameter from a GET request, you can only use it to transform a POST request into something else (like a PUT or DELETE). |
|
| fields |
?opt_fields=followers,assignee
options: { fields: ["followers", "assignee"] } |
|
Some requests return compact representations of objects,
to conserve resources and complete the request more quickly.
Other times requests return more information than you may need.
This option allows you to list the exact set of fields that the API
should be sure to return for the objects. The field names should
be provided as paths, described below.
Note: the id of included objects will always be
returned, regardless of the field options.
|
|
| expand |
?opt_expand=followers
options: { expand: ["followers"] } |
|
Query results and sub-objects are returned in compact form
by default. This option can be used to expand query results or
sub-objects to return more detailed information. Be sure you really
need the information in the expanded form, as executing a query
with many results in expanded form can be costly and
return you a lot of data to consume.
Note: If the fields option is also used, it will
take precedence over the expand option and prevent
expansion.
|
|
| jsonp | ?opt_jsonp=myCallback |
Returns the output in JSON-P
format instead of plain JSON, to allow requests to come from
within browsers and work around the "same origin policy." The
function named as the value of the opt_jsonp parameter
will be called with a single argument, a JavaScript object
representing the response.
Note: This option is only allowed when using Asana Connect, for security reasons. |
Paths for fields/expand options
Some output options allow you to reference fields of objects that
specify paths of fields to either include or expand. These paths
take the form a.b.c… where a is the name of a
field on an object returned at the top level that refers to one or
more child objects, b the name of a field on those child objects
that refers to one or more grandchild objects, and so on. The leaf
or final entry in the path refers to any field on that object and is the
field affected by the option.
For example, when retrieving a task or tasks, consider the path
followers.email. It refers to the email
field all users mentioned in the followers field of the
task or tasks returned, as illustrated in the annotated output
below.
A period (.) on its own is the special designator for
the root path, and refers to the object or objects returned at the
root level.
| Data | Path |
"data": { |
. |
"id": 1001, |
|
"name": "Feed the cat", |
name |
"workspace": { |
workspace |
"id": 14916, |
|
"name": "Shared Projects", |
workspace.name |
}, |
|
"followers": [{ |
followers |
"id": 1234, |
|
"email": "tbizarro@…", |
followers.email |
}, { |
|
"id": 5678, |
|
"email": "gsanchez@…", |
followers.email |
}] |
|
} |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/users/me
# Response
HTTP/1.1 200
{"data":{"email":"sanchez@...","id":999,"name":"Greg Sanchez"}}
# Request
curl -u <api_key>: "https://app.asana.com/api/1.0/users/me?opt_pretty"
# Response
HTTP/1.1 200
{
"data": {
"email": "sanchez@...",
"id": 999,
"name": "Greg Sanchez"
}
}
# Request
curl -u <api_key>: "https://app.asana.com/api/1.0/tasks/1224?opt_fields=name,notes"
# Response
HTTP/1.1 200
{
"data": {
"name": "Make a list",
"notes": "Check it twice!",
"id": 1224
}
}
# Request
curl --request PUT -u <api_key>: https://app.asana.com/api/1.0/tasks/1001 \
-d "assignee=1234" \
-d "options.expand=%2Aprojects%2A"
# Response
HTTP/1.1 200
{
"data": {
"id": 1001,
"projects": [
{
"archived": false,
"created_at": "",
"followers": [],
"modified_at": "",
"notes": "",
"id": 1331,
"name": "Things to buy"
}
],
...
}
}
Users
A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks.
Like other objects in the system, users are referred to by numerical IDs. However, the special string identifier me can be used anywhere a user ID is accepted, to refer to the current authenticated user.
Users only have a small set of fields:
| gsanchez@example.com | |
| Read-only. The user's email address. | |
| name | Greg Sanchez |
| Read-only. The user's name. | |
| workspaces | [ { id: 14916, name: "My Workspace"} ... ] |
|
Read-only.
Workspaces and organizations this user may access.
Note: You may only see workspaces and organizations that you are in. |
Showing a single user
GET /users/user-id
GET /users/me
This method returns the full user record for a single user.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/users/5678
# Response
HTTP/1.1 200
{
"data": {
"email": "gsanchez@example.com",
"id": 5678,
"name": "Greg Sanchez",
"workspaces": [
{
"id": 1337,
"name": "My Favorite Workspace"
},
...
]
}
}
Showing all users in all workspaces
GET /users
This method returns the user records, described above, for all users in all workspaces and organizations you may access.
# Request
curl -u <api_key>: "https://app.asana.com/api/1.0/users?opt_fields=name,email"
# Response
HTTP/1.1 200
{
"data": [
{
"email": "tbizarro@example.com",
"id": 1234,
"name": "Tim Bizarro"
},
{
"email": "gsanchez@example.com",
"id": 5678,
"name": "Greg Sanchez"
},
...
]
}
Showing all users in a single workspace or organization
GET /workspaces/workspace-id/users
This method returns the user records, described above, for all users in the specified workspace or organization.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/workspaces/1337/users
# Response
HTTP/1.1 200
{
"data": [
{
"id": 5678,
"name": "Greg Sanchez"
}
]
}
Tasks
The task is the basic object around which many operations in Asana are centered. In the Asana application, multiple tasks populate the middle pane according to some view parameters, and the set of selected tasks determine the more detailed information presented in the details pane.
Tasks have a rich set of metadata associated with them, some of which is exposed via the API. Here are the accessible fields on a task:
| assignee | { id: 1234, name: "Tim Bizarro" } | ||||||||
User to which this task is assigned, or null if the task is unassigned.
|
|||||||||
| assignee_status | upcoming | ||||||||
Scheduling status of this task for the user it is assigned to. One of the following values:
|
|||||||||
| created_at | 2012-02-22T02:06:58.147Z | ||||||||
| Read-only. The time at which this task was created. | |||||||||
| completed | false | ||||||||
| True if the task is currently marked complete, false if not. | |||||||||
| completed_at | 2012-02-22T02:06:58.147Z | ||||||||
Read-only.
The time at which this task was completed, or null if the task is incomplete.
|
|||||||||
| due_on | 2012-03-26 | ||||||||
Date on which this task is due, or null if the task has no due date.
|
|||||||||
| followers | [ { id: 1123, name: "Mittens" }, ... ] | ||||||||
| Read-only. Array of users following this task. | |||||||||
| modified_at | 2012-02-22T02:06:58.147Z | ||||||||
|
Read-only.
The time at which this task was last modified.
Note: This does not currently reflect any changes in associations such as projects or comments that may have been added or removed from the task. |
|||||||||
| name | Buy catnip | ||||||||
| Name of the task. This is generally a short sentence fragment that fits on a line in the UI for maximum readability. However, it can be longer. | |||||||||
| notes | Mittens really likes the stuff from Humboldt. | ||||||||
| More detailed, free-form textual information associated with the task. | |||||||||
| projects | [ { id: 1331, name: "Stuff to Buy" }, ... ] | ||||||||
Create-only.
Array of projects this task is associated with. At task creation time, this array can be used to add the task to many projects at once. After task creation, these associations can be modified using the addProject and removeProject endpoints.
|
|||||||||
| parent | { id: 52992, name: "My Parent task" } | ||||||||
Read-only.
The parent of this task, or null if this is not a subtask. This property cannot be modified using a PUT request but you can change it with the setParent endpoint. You can create subtasks by using the subtasks endpoint.
|
|||||||||
| workspace | { id: 14916, name: "My Workspace" } | ||||||||
| Create-only. The workspace this task is associated with. Once created, task cannot be moved to a different workspace. This attribute can only be specified at creation time. |
Creating a new task
POST /tasks
POST /workspaces/workspace-id/tasks
Creating a new task is as easy as POSTing to the /tasks endpoint with a data block containing the fields you'd like to set on the task. Any unspecified fields will take on default values.
Every task is required to be created in a specific workspace, and this workspace cannot be changed once set. The workspace need not be set explicitly if you specify a parent task instead.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks \
-d "assignee=1235" \
-d "followers[0]=5678" \
-d "name=Hello, world%21" \
-d "notes=How are you today%3F" \
-d "workspace=14916"
# Response
HTTP/1.1 201
{
"data": {
"assignee": {
"id": 1235,
"name": "Tim Bizarro"
},
"assignee_status": "inbox",
"completed": false,
"completed_at": null,
"created_at": "2012-02-22T02:06:58.158Z",
"due_on": null,
"followers": [
{
"id": 5678,
"name": "Greg Sanchez"
}
],
"id": 1001,
"modified_at": "2012-02-22T02:06:58.158Z",
"name": "Hello, world!",
"notes": "How are you today?",
"parent": null,
"projects": [
{
"id": 14641,
"name": "Cat Stuff"
}
],
"workspace": {
"id": 14916,
"name": "My Favorite Workspace"
}
}
}
Showing a specific task
GET /tasks/task-id
You can retrieve an existing task given its ID with a simple GET request.
This method returns the complete task record, described above.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001
# Response
HTTP/1.1 200
{
"data": {
"assignee": {
"id": 1234,
"name": "Tim Bizarro"
},
"created_at": "2012-02-22T02:06:58.158Z",
...
}
}
Updating an existing task
PUT /tasks/task-id
A specific, existing task can be updated by making a PUT request on the URL for that task. Only the fields provided in the data block will be updated; any unspecified fields will remain unchanged.
When using this method, it is best to specify only those fields you wish to change, or else you may overwrite changes made by another user since you last retrieved the task.
This method returns the complete updated task record, described above.
# Request
curl --request PUT -u <api_key>: https://app.asana.com/api/1.0/tasks/1001 \
-d "assignee=me"
# Response
HTTP/1.1 200
{
"data": {
"assignee": {
"id": 1234,
"name": "Tim Bizarro"
},
"id": 1001,
...
}
}
Deleting an existing task
DELETE /tasks/task-id
A specific, existing task can be deleted by making a DELETE request on the URL for that task.
This method returns an empty data response on success.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001
# Response
HTTP/1.1 200
{
"data": {
}
}
Querying for tasks
GET /tasks
GET /projects/project-id/tasks
GET /workspaces/workspace-id/tasks
In the future we plan to expand the power of queries to enable filtering by arbitrary fields so you can more easily select the set of tasks you want. For now, you may limit your query either to a specific project or to an assignee and workspace with the following parameters:
| assignee | 1234 |
|
The ID of the assignee to filter tasks on. Only unarchived tasks in the assignee's list will be returned.
Note: If you specify an assignee, you must also specify a workspace to filter on. |
|
| project | 1331 |
| The ID of a project to get tasks from. Only unarchived tasks in the project will be returned. | |
| workspace | 14619 |
|
The ID of the workspace or organization to filter tasks on.
Note: If you specify a workspace you must also specify an assignee to filter on. |
# Request
curl -u <api_key>: "https://app.asana.com/api/1.0/tasks?workspace=14916&assignee=me"
# Response
HTTP/1.1 200
{
"data": [
{
"id": 1248,
"name": "Buy catnip"
},
{
"id": 24816,
"name": "Reflect on role of kittens in society"
},
{
...
}
]
}
Working with subtasks
GET /tasks/task-id/subtasks
POST /tasks
POST /tasks/parent-id/subtasks
POST /tasks/task-id/setParent
Creating a subtask is the same as a creating an normal task, but instead of specifying a workspace you must specify a parent task. Each task can only have a single parent and you can use the setParent endpoint to add or remove a parent from an existing task.
Created subtasks are added to the end of their parent's list of subtasks.
You can find all of the subtasks of a task via the tasks/:ID/subtasks endpoint.
| parent | 1331 |
| The ID of the parent to add to the task, or null to remove an existing parent. |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/2272/subtasks \
-d "assignee=1235" \
-d "followers[0]=5678" \
-d "name=Tell Luke" \
-d "notes=He%27s going to be upset."
# Response
HTTP/1.1 201
{
"data": {
"assignee": {
"id": 1235,
"name": "Darth Vader"
},
"assignee_status": "inbox",
"completed": false,
"completed_at": null,
"created_at": "2012-02-22T02:06:58.158Z",
"due_on": null,
"followers": [
{
"id": 5678,
"name": "Emperor Palpatine"
}
],
"id": 1001,
"modified_at": "2012-02-22T02:06:58.158Z",
"name": "Tell Luke",
"notes": "He's going to be upset.",
"parent": {
"id": 2272,
"name": "Tell kids I am their father."
},
"projects": [],
"workspace": {
"id": 14916,
"name": "Star Wars"
}
}
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/7331/subtasks
# Response
{
"data": [
{
"id": 5005,
"name": "Steal Underwear"
},
{
"id": 6709,
"name": "???"
},
{
"id": 9812,
"name": "Profit"
}
]
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/2272/setParent \
-d "parent=1331"
# Response
HTTP/1.1 200
{
"data": {
"id": 2272,
"name": "Tell Luke",
"parent": [
{
"id": 1331,
"name": "Tell kids I am their father"
}
],
...
}
}
Reading task activity and comments
GET /tasks/task-id/stories
Tasks, like some other objects in the system, have a series of stories associated with them. A story can be an indicator of some action taken on a task (such as completing it), or it could be a comment left by a user.
See the section on querying for all stories on an object for more information.
Commenting on a task
POST /tasks/task-id/stories
See the section on commenting on an object for more information.
Working with projects associated with a task and reordering within a project
GET /tasks/task-id/projects
POST /tasks/task-id/addProject
POST /tasks/task-id/removeProject
Each task can be associated with zero or more projects in the system. The API allows you to query and change those associations.
You can query the list of projects associated with a task by using the projects endpoint on a task, which will return a compact representation of each of the projects on the task specified.
You can add or remove a project using the addProject or removeProject endpoints, respectively, providing the parameters below. You can also use addProject to reorder tasks that are already part of that project.
Requests to add/remove projects, if successful, will return success and an empty data block.
| project | 1331 |
| The ID of the project to add or remove from the task. | |
| insert_after | 2272 |
| The ID of the task in the same project to insert after, or "null" to insert at the beginning of the list. | |
| insert_before | 2272 |
| The ID of the task in the same project to insert before, or "null" to insert at the end of the list. |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/projects
# Response
{
"data": [
{
"id": 1331,
"name": "Things To Buy"
},
{
"id": 14641,
"name": "Cat Stuff"
}
]
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/addProject \
-d "project=14641"
# Response
{
"data": {
}
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/removeProject \
-d "project=14641"
# Response
{
"data": {
}
}
Working with tags on a task
GET /tasks/task-id/tags
POST /tasks/task-id/addTag
POST /tasks/task-id/removeTag
Each task can be associated with zero or more tags in the system. The API allows you to query and change those associations.
You can query the list of tags associated with a task by using the tags endpoint on a task, which will return a compact representation of each of the tags on the task specified.
You can add or remove a tag using the addTag or removeTag endpoints, respectively, providing the parameters below.
Requests to add/remove tags, if successful, will return success and an empty data block.
| tag | 1331 |
| The ID of the tag to add or remove from the task. |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/tags
# Response
{
"data": [
{
"id": 1331,
"name": "orange"
},
{
"id": 1771,
"name": "fluffy"
}
]
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/addTag \
-d "tag=1771"
# Response
{
"data": {
}
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/removeTag \
-d "tag=1771"
# Response
{
"data": {
}
}
Working with followers on a task
POST /tasks/task-id/addFollowers
POST /tasks/task-id/removeFollowers
Each task can be associated with zero or more followers in the system.
You can add or remove followers using the addFollowers or removeFollowers endpoints, respectively, providing the parameters below.
Requests to add/remove followers, if successful, will return the complete updated task record, described above.
| followers | [1235] |
| The IDs of the users to add or remove as followers to/from the task. |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/addFollowers \
-d "followers[0]=1235"
# Response
HTTP/1.1 200
{
"data": {
"followers": [
{
"id": 1235,
"name": "Darth Vader"
}
],
"id": 1001,
...
}
}
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/removeFollowers \
-d "followers[0]=1235"
# Response
HTTP/1.1 200
{
"data": {
"followers": [],
"id": 1001,
...
}
}
Projects
A project represents a prioritized list of tasks in Asana. It exists in a single workspace or organization and is accessible to a subset of users in that workspace or organization depending on its permissions.
Projects in organizations are shared with a single team. You cannot currently change the team of a project via the API. Non-organization workspaces do not have teams and so you should not specify the team of project in a regular workspace.
Projects, like tasks, can have rich metadata associated with them, including the following fields:
| archived | false |
| True if the project is archived, false if not. Archived projects do not show in the UI by default and may be treated differently for queries. | |
| created_at | 2012-02-22T02:06:58.147Z |
| Read-only. The time at which this project was created. | |
| followers | [ { id: 1123, name: "Mittens" }, ... ] |
| Read-only. Array of users following this project. | |
| modified_at | 2012-02-22T02:06:58.147Z |
|
Read-only.
The time at which this project was last modified.
Note: This does not currently reflect any changes in associations such as tasks or comments that may have been added or removed from the project. |
|
| name | Stuff to buy |
| Name of the project. This is generally a short sentence fragment that fits on a line in the UI for maximum readability. However, it can be longer. | |
| notes | These are things we need to purchase. |
| More detailed, free-form textual information associated with the project. | |
| workspace | { id: 14916, name: "My Workspace" } |
| Create-only. The workspace or organization this project is associated with. Once created, projects cannot be moved to a different workspace. This attribute can only be specified at creation time. | |
| team | { id: 692353, name: "organization.com Marketing" } |
| Create-only. The team that this project is shared with. This field only exists for projects in organizations. |
Creating a new project
POST /projects
POST /workspaces/workspace-id/projects
This method creates a new project and returns its full record.
Every project is required to be created in a specific workspace or organization, and this workspace cannot be changed once set. Note that you can use the workspace parameter regardless of whether or not it is an organization.
If the workspace for your project is an organization, you must also supply a team to share the project with.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/projects \
-d "name=Things to Buy" \
-d "notes=These are things we want to purchase." \
-d "workspace=14916"
# Response
HTTP/1.1 201
{
"data": {
"id": 1331,
"name": "Things to Buy",
"notes": "These are things we want to purchase.",
...
}
}
Showing a single project
GET /projects/project-id
This method returns the full record for a single project.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/projects/1331
# Response
HTTP/1.1 200
{
"data": {
"id": 1331,
"name": "Things to Buy",
"notes": "These are things we want to purchase.",
...
}
}
Updating a project
PUT /projects/project-id
This method modifies the fields of a project provided in the request, then returns the full updated record.
# Request
curl --request PUT -u <api_key>: https://app.asana.com/api/1.0/projects/1331 \
-d "notes=These are things we NEED to purchase."
# Response
HTTP/1.1 200
{
"data": {
"id": 1331,
"name": "Things to Buy",
"notes": "These are things we NEED to purchase.",
...
}
}
Deleting a project
DELETE /projects/project-id
A specific, existing project can be deleted by making a DELETE request on the URL for that project.
This method returns an empty data response on success.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/projects/1331
# Response
HTTP/1.1 200
{
"data": {
}
}
Querying for tasks in a project
GET /projects/project-id/tasks
Returns the list of non-archived tasks in this project. Tasks can exist in more than one project at a time.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/projects/1331/tasks
# Response
HTTP/1.1 200
{
"data": [
{
"id": 2001,
"name": "Catnip"
},
{
"id": 2002,
"name": "Kitty litter"
},
...
]
}
Querying for projects
GET /projects
GET /workspaces/workspace-id/projects
This method returns the projects, described above, according to the filter criteria provided.
| archived | false |
| If provided, this parameter will filter on projects whose archived field takes on the specified value. | |
| workspace | 14916 |
| If provided, this parameter will filter on projects which belong in the specified workspace |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/workspaces/14916/projects
# Response
HTTP/1.1 200
{
"data": [
{
"id": 1331,
"name": "Things to buy"
},
{
"id": 14641,
"name": "Cat Stuff"
},
...
]
}
Tags
A tag is a label that can be attached to any task in Asana. It exists in a single workspace or organization.
Tags have some metadata associated with them, but it is possible that we will simplify them in the future so it is not encouraged to rely too heavily on it. Unlike projects, tags do not provide any ordering on the tasks they are associated with.
Tags have the following fields:
| created_at | 2012-02-22T02:06:58.147Z |
| Read-only. The time at which this tag was created. | |
| followers | [ { id: 1123, name: "Mittens" }, ... ] |
| Read-only. Array of users following this tag. | |
| name | Stuff to buy |
| Name of the tag. This is generally a short sentence fragment that fits on a line in the UI for maximum readability. However, it can be longer. | |
| notes | These are things we need to purchase. |
| More detailed, free-form textual information associated with the project. | |
| workspace | { id: 14916, name: "My Workspace" } |
| Create-only. The workspace this tag is associated with. Once created, tag cannot be moved to a different workspace. This attribute can only be specified at creation time. |
Creating a new tag
POST /tags
POST /workspaces/workspace-id/tags
This method creates a new tag and returns its full record.
Every tag is required to be created in a specific workspace or organization, and this workspace cannot be changed once set.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tags \
-d "name=fluffy" \
-d "workspace=14916"
# Response
HTTP/1.1 201
{
"data": {
"id": 1771,
"name": "fluffy",
...
}
}
Showing a single tag
GET /tags/tag-id
This method returns the full record for a single tag.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tags/1331
# Response
HTTP/1.1 200
{
"data": {
"id": 1331,
"name": "Things to Buy",
"notes": "These are things we want to purchase.",
...
}
}
Updating a tag
PUT /tags/tag-id
This method modifies the fields of a tag provided in the request, then returns the full updated record.
# Request
curl --request PUT -u <api_key>: https://app.asana.com/api/1.0/tags/1331 \
-d "name=Things to Sell"
# Response
HTTP/1.1 200
{
"data": {
"id": 1331,
"name": "Things to Sell",
...
}
}
Querying for tasks with a tag
GET /tags/tag-id/tasks
Returns the list of all tasks with this tag. Tasks can have more than one tag at a time.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tags/1331/tasks
# Response
HTTP/1.1 200
{
"data": [
{
"id": 2001,
"name": "Catnip"
},
{
"id": 2002,
"name": "Kitty litter"
},
...
]
}
Querying for tags
GET /tags
GET /workspaces/workspace-id/tags
This method returns the tags, described above, according to the filter criteria provided.
| workspace | 14916 |
| If provided, this parameter will filter on tags which belong in the specified workspace |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/workspaces/14916/tags
# Response
HTTP/1.1 200
{
"data": [
{
"id": 1331,
"name": "Things to buy"
},
{
"id": 14641,
"name": "Cat Stuff"
},
...
]
}
Stories
A story represents an activity associated with an object in the Asana system. Stories are generated by the system whenever users take actions such as creating or assigning tasks, or moving tasks between projects. Comments are also a form of user-generated story.
Stories are a form of history in the system, and such they are read-only. Once generated, it is not possible to modify a story.
| created_at | 2012-02-22T02:06:58.147Z | ||||||||||
| Read-only. The time at which this story was created. | |||||||||||
| created_by | { id: 1123, name: "Mittens" } | ||||||||||
| Read-only. The user who created the story. | |||||||||||
| text | marked today | ||||||||||
|
Create-only.
Human-readable text for the story or comment. This will not include the name of the creator.
Note: This is not guaranteed to be stable for a given type of story. For example, text for a reassignment may not always say "assigned to ...". The API currently does not provide a structured way of inspecting the meaning of a story. |
|||||||||||
| target | { id: 1234, name: "Buy catnip" } | ||||||||||
| Read-only. The object this story is associated with. May be a task or a project. | |||||||||||
| source | web | ||||||||||
Read-only.
The component of the Asana product the user used to trigger the story. Valid values are:
|
|||||||||||
| type | comment | ||||||||||
Read-only.
The type of story this is. Valid values are:
|
Querying for all stories on an object
GET /tasks/task-id/stories
GET /projects/project-id/stories
Returns the list of stories associated with the object. As usual with queries, stories are returned in compact form. However, the compact form for stories contains more information by default than just the ID. There is presently no way to get a filtered set of stories.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/stories
# Response
{
"data": [
{
"created_at": "2011-12-21T23:23:01.259Z",
"created_by": {
"id": 5678,
"name": "Greg Sanchez"
},
"id": 2001,
"text": "added to Things To Buy",
"type": "system"
},
{
"created_at": "2012-01-02T21:32:40.112Z",
"created_by": {
"id": 1234,
"name": "Tim Bizarro"
},
"id": 2002,
"text": "Again? Wow, we really go through this stuff fast.",
"type": "comment"
}
]
}
Showing a single story
GET /stories/story-id
This method returns the full record for a single story.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/stories/2001
# Response
HTTP/1.1 200
{
"data": {
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"id": 1123,
"name": "Mittens"
},
"id": 2001,
"source": "web",
"target": {
"id": 1234,
"name": "Buy catnip"
},
"text": "Yes, please!",
"type": "comment"
}
}
Commenting on an object
POST /tasks/task-id/stories
POST /projects/project-id/stories
Adds a comment to an object. The comment will be authored by the authorized user, and timestamped when the server receives the request. You can provide the following parameters when posting the comment:
| text | Hello! |
| The body of the comment to add. |
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/tasks/1001/stories \
-d "text=This is a very nice comment."
# Response
{
"data": {
"created_at": "2011-12-21T23:23:01.259Z",
"created_by": {
"id": 5678,
"name": "Greg Sanchez"
},
"id": 2001,
"source": "api",
"target": {
"id": 1001,
"name": "Buy catnip"
},
"text": "This is a very nice comment.",
"type": "comment"
}
}
Workspaces and Organizations
A workspace is the most basic organizational unit in Asana. All projects and tasks have an associated workspace.
An organization is a special kind of workspace that represents a company. In an organization, you can group your projects into teams. You can read more about how organizations work on the Asana Guide. To tell if your workspace is an organization or not, check its is_organization property.
Over time, we intend to migrate most workspaces into organizations and to release more organization-specific functionality. We may eventually deprecate using workspace-based APIs for organizations. Currently, and until after some reasonable grace period following any further announcements, you can still reference organizations in any workspace parameter.
Workspaces expose the following fields:
| name | My Favorite Workspace |
| Name of the workspace. | |
| is_organization | false |
| Whether this workspace is an organization |
Showing available workspaces
GET /workspaces
This method returns the workspace records, described above.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/workspaces
# Response
{
"data": [
{
"id": 1337,
"name": "My Favorite Workspace"
},
...
]
}
Updating an existing workspace
PUT /workspaces/workspace-id
A specific, existing workspace can be updated by making a PUT request on the URL for that workspace. Only the fields provided in the data block will be updated; any unspecified fields will remain unchanged.
Currently the only field that can be modified for a workspace is its name.
This method returns the complete updated workspace record, described above.
# Request
curl --request PUT -u <api_key>: https://app.asana.com/api/1.0/workspaces/1337 \
-d "name=Everyone%27s Favorite Workspace"
# Response
{
"data": {
"id": 1337,
"name": "Everyone's Favorite Workspace"
}
}
Teams
A team is used to group related projects and people together within an organization. Each project in an organization is associated with a team.
| name | Engineering |
| Name of the team |
Show all teams you're a member of in an organization
GET /organizations/organization-id/teams
This method returns team records that match the given organization.
# Request
curl -u <api_key>: https://app.asana.com/api/1.0/organizations/13523
# Response
{
"data": [
{
"id": 5832,
"name": "Atlanta Braves"
},
{
"id": 15923,
"name": "New York Yankees"
},
...
]
}
