Overview
Helpful code snippets will show up in this column.
curl https://app.asana.com/api/1.0/users/me \
-H "Authorization: Bearer 0/a7f89e98g007e0s07da763a"
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 and returns JSON content in all of its responses, including errors. Only the UTF-8 character encoding is supported for both requests and responses.
Notes on Pagination
Pagination is an important concept when working with queries for multiple objects. Requests with large result sets may timeout or be truncated; therefore, pagination is strongly encouraged to ensure both you and your users have the best experience when using the Asana API.
Happy coding!
Object Hierarchy
Asana is a work tracking and collaboration tool. This guide is designed to give developers a brief overview of how Asana is structured. It’s not meant to be exhaustive and may be too basic for experienced Asana users. The intention is to describe the fundamental elements of Asana to help you scope apps and avoid common points of confusion.
How work is organized
Tasks
Tasks are the basic unit of action in Asana. Tasks have many fields including a single assignee, name, notes, followers (i.e. collaborators), likes, and comments (among others). Tasks inherit custom fields from their parent project(s). Custom fields values are set for each individual task.
In addition to standard Create / Read / Update / Delete operations, there are a few things to watch out for when working with tasks:
- Tasks can be orphaned and belong to no projects, they can belong to one project, or they can be multi-homed across two or more projects. The
membershipsfield is a collection of the projects with which the task is associated. - Tasks can be multi-homed as subtasks. For example, task A can be in project B and the same task A can also be a subtask of task C.
Projects
A project is a collection of tasks that can be viewed as a list, board, timeline, and calendar. Projects can only exist in a single organization or workplace and only belong to a single team. Projects can be public in the team or private to project members. Among the many fields associated with projects, they can have global (shared across the organization) or local (project-specific) custom fields. A project’s custom fields will be displayed on each task within the project.
Portfolios
Portfolios are collections of projects (or other portfolios). Custom fields can be added to portfolios in addition to standard fields that are displayed on every portfolio. These fields provide a high-level overview of the status of each project within the portfolio.
Sections
A section is a group of tasks within a project. Sections let you divide tasks into categories, workflow stages, priorities, and more.
Subtasks
A subtask is exactly the same as tasks in a project except that one (and only one) of its parents is a task (although subtasks can also simultaneously be organized into projects). To check if a task has a subtask, include the num_subtasks field when fetching the parent task.
Things to note when working with subtasks:
- Subtasks do not inherit the projects of their parent tasks.
- There can be up to 5 levels of subtasks below a task. We do not recommend making sub-subtasks.
- There is no way to fetch all subtasks of all tasks in a project in a single request.
How users are organized
Workspaces
A workspace is the highest-level organizational unit in Asana. All projects, tasks, and teams have an associated workspace.
Organizations
An organization is a special kind of workspace that represents a company. Organizations connect all the employees at a company using Asana in a single space based on the company’s shared email domain. In an organization, you can group your projects into teams.
Teams
Teams are a subset of users in an organization who collaborate on projects together. Every project in an organization is associated with one team. Team messages are not currently available in the API.
Users
A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. Asana accounts are free and tied to individuals; Asana accounts grant access to one or more shared Workspaces and Organizations to collaborate with other Asana users.
Guest Users
Users can invite clients, contractors, customers, or anyone else who does not have an email address at an approved Organization email domain. These users join as Organization Guests. Guests have limited access in an Organization -- they can only see what’s explicitly shared with them.
Note: it can be advantageous to use guests to create bot accounts. Due to the access restrictions, bots created from a guest account Personal Access Token can be given fine-grained access to only the data that it needs to use.
Authentication
Asana supports a few methods of authenticating with the API. Simple cases are usually handled with a Personal Access Token, while multi-user apps utilize OAuth.
"Authorization: Bearer ACCESS_TOKEN"
- OAuth 2.0 We require that applications designed to access the Asana API on behalf of multiple users implement OAuth 2.0.
- Personal Access Token Personal Access Tokens are designed for accessing the API from the command line or from personal applications.
OAuth
Most of the time, OAuth is the preferred method of authentication for developers, users, and Asana as a platform. If you're new to OAuth, take a moment to learn about it here. It's not as scary as you might think!
In addition to learning about how to use OAuth on the Asana platform here, feel free to take a look at the official OAuth spec!
At its core, OAuth is a mechanism for applications to access the Asana API on behalf of a user without the application having access to the username and password. Instead, apps get a token which they can use with their own application credentials to make API calls.
What is OAuth?
If you're using a library to handle this or already understand OAuth and have registered an OAuth application, you may want to skip ahead to the quick reference.
If you have not already, you will need to register an application. Take note of the client ID, an application's username, and the client secret, an application's password (protect it like one)!
A user will arrive at your application and click a button that says "Connect with Asana."
This takes the customer to the User Authorization Endpoint, which displays a page asking the user if they would like to grant access to your third-party application.
If the customer clicks "Allow", they are redirected back to the application, bringing along a special code as a query parameter. (We are assuming the Authorization Code Grant flow, which is the most common.)
The application can now use the Token Exchange Endpoint to exchange the code, together with the Client Secret, for a Bearer Token (which lasts an hour) and a Refresh Token (which can be used to fetch new Bearer Tokens when the current one expires).
The application can make requests of the API using this Bearer Token for the next hour.
Once the Bearer Token expires, the application can again use the Token Exchange Endpoint to exchange the Refresh Token for a new Bearer Token. (This can be repeated for as long as the user has authorized the application.)
We definitely recommend using a library to take care of the details of OAuth, but hopefully this helps demystify the process somewhat.
Register an Application
You must first register your application with Asana to receive a client ID and client secret. Fortunately, this process is fast and easy: visit your Account Settings dialog, click the Apps tab, and "Add New Application".
You must supply your new application with:
- App Name - A name for your application. A user will see this name when your application requests permission to access their account as well as when they review the list of apps they have authorized.
- App URL - The URL where users can access your application or, in the case of native applications, this can be a link to setup or support instructions. Note that this URL must start with "http" or "https".
- Redirect URL - As described in the OAuth specification, this is where the user will be redirected upon successful
or failed authentications. Native or command line applications should use the special redirect URL
urn:ietf:wg:oauth:2.0:oob. For security reasons, non-native applications must supply a "https" URL (more on this below). - Icon - Optionally, you can upload an icon to enhance the recognizability of the application when users are authenticating.
Note that all of these attributes can be changed later, so don't worry too much right away.
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.
Note Your Client Secret is a secret, it should never be shared with anyone or checked into source code that others could gain access to.
Quick Reference
- Applications can be created from the "Apps" tab of your account settings, where you will find your Client ID and Client Secret.
- The endpoint for user authorization is
https://app.asana.com/-/oauth_authorize - The endpoint for token exchange is
https://app.asana.com/-/oauth_token - The endpoint for revoking a token is
https://app.asana.com/-/oauth_revoke - Asana supports the Authorization Code Grant flow.
- Once an access token has been obtained your application can make calls on behalf of the user
User Authorization Endpoint
Request
Send a user to oauth_authorize
<a href="https://app.asana.com/-/oauth_authorize
?client_id=753482910
&redirect_uri=https://my.app.com
&response_type=code
&state=thisIsARandomString
&code_challenge_method=S256
&code_challenge=671608a33392cee13585063953a86d396dffd15222d83ef958f43a2804ac7fb2
&scope=default">Authenticate with Asana</a>
Your app redirects the user to https://app.asana.com/-/oauth_authorize, passing parameters along as a standard query string:
| Parameter | Description | |
| client_id | required The Client ID uniquely identifies the application making the request. | |
| redirect_uri | required The URI to redirect to on success or error. This must match the Redirect URL specified in the application settings. | |
| response_type | required Must be either code or id_token, or the space-delimited combination code id_token. | |
| state | optional Encodes state of the app, which will be returned verbatim in the response and can be used to match the response up to a given request. | |
| code_challenge_method | PKCE The hash method used to generate the challenge. Typically S256. | |
| code_challenge | PKCE The code challenge used for PKCE. | |
| scope | optional A space-delimited set of one or more scopes to get the user's permission to access. Defaults to the default OAuth scope if no scopes are specified. |
Response
If either the client_id or redirect_uri do not match, the user will simply see a plain-text error. Otherwise,
all errors will be sent back to the redirect_uri specified.
The user then sees a screen giving them the opportunity to accept or reject the request for authorization. In either
case, the user will be redirected back to the redirect_uri.
User is redirected to the redirect_uri
https://my.app.com?code=325797325&state=thisIsARandomString
When using the response_type=code, your app will receive the following parameters in the query string on successful authorization.
| Parameter | Description | |
| code | If response_type=code in the request, this is the code your app can exchange for a token | |
| state | The state parameter that was sent with the authorizing request |
You should check that the state is the same in this response as it was in the request. You can read more about the state
parameter here.
OAuth Scopes
The Asana API supports a small set of OAuth scopes you can request using the
scope parameter during the user authorization step of your authentication
flow. Multiple scopes can be requested at once as a space-delimited list of
scopes. An exhaustive list of the supported scopes is provided here:
| Scope | Access provided | |
| default | Provides access to all endpoints documented in our API reference. If no scopes are requested, this scope is assumed by default. | |
| openid | Provides access to OpenID Connect ID tokens and the OpenID Connect user info endpoint. | |
| Provides access to the user's email through the OpenID Connect user info endpoint. | ||
| profile | Provides access to the user's name and profile photo through the OpenID Connect user info endpoint. |
Token Exchange Endpoint
Request
When your app receives a code from the authorization endpoint, it can now be exchanged for a proper token.
If you have a client_secret, this request should be sent from your secure server.
The browser should never see your client_secret.
App sends request to oauth_token
{
"grant_type": "authorization_code",
"client_id": "753482910",
"client_secret": "6572195638271537892521",
"redirect_uri": "https://my.app.com",
"code": "325797325",
"code_verifier": "fdsuiafhjbkewbfnmdxzvbuicxlhkvnemwavx"
}
Your app should make a POST request to https://app.asana.com/-/oauth_token,
passing the parameters as part of a standard form-encoded post body.
| Parameter | Description | |
| grant_type | required One of authorization_code or refresh_token. See below for more details. | |
| client_id | required The Client ID uniquely identifies the application making the request. | |
| client_secret | required The Client Secret belonging to the app, found in the details pane of the developer console. | |
| redirect_uri | required Must match the redirect_uri specified in the original request. | |
| code | required This is the code you are exchanging for an authorization token. | |
| refresh_token | sometimes required If grant_type=refresh_token this is the refresh token you are using to be granted a new access token. | |
| code_verifier | PKCE This is the string previously used to generate the code_challenge. |
The token exchange endpoint is used to exchange a code or refresh token for an access token.
Response
In the response, you will receive a JSON payload with the following parameters:
{
"access_token": "f6ds7fdsa69ags7ag9sd5a",
"expires_in": 3600,
"token_type": "bearer",
"refresh_token": "hjkl325hjkl4325hj4kl32fjds",
"data": {
"id": "4673218951",
"name": "Greg Sanchez",
"email": "gsanchez@example.com"
}
}
| Parameter | Description | |
| access_token | The token to use in future requests against the API | |
| expires_in | The number of seconds the token is valid, typically 3600 (one hour) | |
| token_type | The type of token, in our case, bearer | |
| refresh_token | If exchanging a code, a long-lived token that can be used to get new access tokens when old ones expire. | |
| data | A JSON object encoding a few key fields about the logged-in user, currently id, name, and email. |
Authorization Code Grant
To implement the Authorization Code Grant flow (the most typical flow for most applications), there are three steps:
Send the user to the authorization endpoint so that they can approve access of your app to their Asana account
Receive a redirect back from the authorization endpoint with a code embedded in the parameters
Exchange the code via the token exchange endpoint for a
**refresh_token**and, for convenience, an initialaccess_token.When the short-lived
access_tokenexpires, the**refresh_token**can be used with the token exchange endpoint, without user intervention, to get a freshaccess_token.
The token that you have at the end can be used to make calls to the Asana API on the user's behalf.
Proof Key for Code Exchange (PKCE) OAuth Extension
User Authorization Endpoint
{
...
"code_challenge": "671608a33392cee13585063953a86d396dffd15222d83ef958f43a2804ac7fb2",
"code_challenge_method": "S256"
}
Token Exchange Endpoint
{
...
"code_verifier": "fdsuiafhjbkewbfnmdxzvbuicxlhkvnemwavx"
}
PKCE proves the app that started the authorization flow is the same app that finishes the flow. You can read more about it here.
Here's what you need to know:
Whenever a user wants to OAuth with Asana, your app server should generate a random string called the
code_verifier. This string should be saved to the user (as everycode_verifiershould be unique per user). This should stay on the app server and only be sent to the Token Exchange Endpoint.Your app server will hash the
code_verifierwith SHA256 to get a string called thecode_challenge. Your server will give the browser only thecode_challenge&code_challenge_method. Thecode_challenge_methodshould be the string "S256" to tell Asana we hashed with SHA256. More specifically, code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))).The browser includes
code_challenge&code_challenge_methodwhen redirecting to the User Authorization Endpoint.The app server should include the
code_verifierin it's request to the Token Exchange Endpoint.
Asana confirms that hashing the code_verifier with the code_challenge_method results in the code_challenge. This
proves to Asana the app that hit the User Authorization Endpoint is the same app that hit the Token Exchange
Endpoint.
Secure Redirect Endpoint
As the redirect from the authorization endpoint in either grant procedure contains a code that is secret between Asana's
authorization servers and your application, this response should not occur in plaintext over an unencrypted http connection.
Because of this, we enforce the use of https redirect endpoints for application registrations.
For non-production or personal use, you may wish to check out stunnel, which can act as a proxy to receive an encrypted connection, decrypt it, and forward it on to your application. For development work, you may wish to create a self-signed SSL/TLS certificate for use with your web server; for production work we recommend purchasing a certificate from a certificate authority. A short summary of the steps for each of these processes can be read here.
Your application will need to be configured to accept SSL/TLS connections for your redirect endpoint when users become authenticated, but for many apps, this will simply require a configuration update of your application server. Instructions for Apache and Nginx can be found on their respective websites, and most popular application servers will contain documentation on how to proceed.
Token Deauthorization Endpoint
Request
An authorization token can be deauthorized or invalidated by making a request to Asana's API.
Your app should make a POST request to https://app.asana.com/-/oauth_revoke,
passing the parameters as part of a standard form-encoded post body.
| Parameter | Description | |
| client_id | required The Client ID uniquely identifies the application making the request. | |
| client_secret | required The Client Secret belonging to the app, found in the details pane of the developer console. | |
| token | required The Refresh Token that should be deauthorized. Bearer Tokens will be rejected. |
The body should include a valid Refresh Token, which will cause the Refresh Token and any Associated Bearer Tokens to be deauthorized. Bearer Tokens are not accepted in the request body since a new Bearer Token can always be obtained by reusing an authorized Refresh Token.
Response
A successful response with a 200 status code indicates that the token was deauthorized or not found. An unsuccessful response with a 400 status code will be returned if the request was malformed due to missing any required fields or specifying an invalid token (such as a bearer access token).
Personal Access Token
Personal Access Tokens (PATs) are a useful mechanism for accessing the API in scenarios where OAuth would be considered overkill, such as access from the command line and personal scripts or applications. A user can create many, but not unlimited, personal access tokens. When creating a token you must give it a description to help you remember what you created the token for.
Personal Access Tokens should be used similarly to OAuth access tokens when accessing the API, passing them in the Authorization header.
Example cURL request authenticating with a PAT
curl https://app.asana.com/api/1.0/users/me \
-H "Authorization: Bearer ACCESS_TOKEN"
You can generate a Personal Access Token from the Asana developer console. See the Authentication Quick Start for detailed instructions on getting started with PATs.
You should regularly review the list of personal access tokens you have created and deauthorize those that you no longer need.
Remember to keep your tokens secret; treat them just like passwords! They act on your behalf when interacting with the API. Don't hardcode them into your programs. Instead, opt to use them as environment variables.
OpenID Connect
Asana also supports the OpenID Connect protocol for authenticating Asana users with your
applications. This means that, in addition to the normal code and token response types for the OAuth flow, you can
also use the id_token response type.
For this response type, you are not granted an access token for the API, but
rather given a signed Json Web Token containing the user's ID along with some metadata. If you want
to allow users to log into your services using their Asana account, the OpenID Connect protocol is an ideal way to
authenticate an Asana user. To obtain an ID token, you must request the openid scope during the authentication flow.
It is also possible to obtain an ID token alongside an authorization code in the authorization code grant
flow by using the (space-delimited) code id_token response type. If you do, the redirect parameters will include
the ID token in addition to everything you would normally receive.
To access additional information about the user in a standardized format, we also expose a
user info endpoint that can provide the user's name,
email address, and profile photo. This data is available by making a GET request to
https://app.asana.com/api/1.0/openid_connect/userinfo with an OAuth access token that has the openid scope.
Depending on the scopes tied to that token, you will receive different pieces of data. Refer to our
list of OAuth scopes to determine which additional scopes you need to get the data you want.
Metadata about our OpenID Connect implementation is also made available through OpenID Connect's
discovery protocol. Making an unauthenticated GET
request to https://app.asana.com/api/1.0/.well-known/openid-configuration will provide all the details of our
implementation necessary for you to use OpenID Connect with Asana's API.
Errors
Missing authorization header
GET https://app.asana.com/api/1.0/users/me HTTP/1.1
HTTP/1.1 401 Not Authorized
{
"errors": [
{
"message": "Not Authorized"
}
]
}
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.
In the event of a server error the response body will contain an error phrase. These phrases are automatically generated using the node-asana-phrase library and can be used by Asana support to quickly look up the incident that caused the server error.
Bad request parameters
GET https://app.asana.com/api/1.0/tasks HTTP/1.1
Authorization: Bearer <personal_access_token>
HTTP/1.1 400 Bad Request
{
"errors": [
{
"message": "workspace: Missing input"
}
]
}
Asana had a problem
GET https://app.asana.com/api/1.0/users/me HTTP/1.1
Authorization: Bearer <personal_access_token>
HTTP/1.1 500 Server Error
{
"errors": [
{
"message": "Server Error",
"phrase": "6 sad squid snuggle softly"
}
]
}
| Code | Meaning | Description | |
| 200 | Success | If data was requested, it will be available in the data field at the top level of the response body. | |
| 201 | Created (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 | Bad Request | This usually occurs because of a missing or malformed parameter. Check the documentation and the syntax of your request and try again. | |
| 401 | Unauthorized | A valid authentication token was not provided with the request, so the API could not associate a user with the request. | |
| 402 | Payment Required | The request was valid, but the queried object or object mutation specified in the request is only available to premium organizations and workspaces. | |
| 403 | Forbidden | The authentication 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 | Too Many Requests | You have exceeded one of the enforced rate limits in the API. See the documentation on rate limiting for more information. | |
| 451 | Unavailable For Legal Reasons | This request was blocked for legal reasons, commonly caused by embargoed IP addresses. | |
| 500 | Internal 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:
| Example | Description | |
| 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. |
Rate Limits
To protect the stability of the API and keep it available to all users, Asana enforces multiple kinds of rate limiting. Requests that hit any of our rate limits will receive a 429 Too Many Requests response, which contains the standard Retry-After header indicating how many seconds the client should wait before retrying the request.
Limits are allocated per authorization token. Different tokens will have independent limits.
The client libraries respect the rate-limited responses and will wait the appropriate amount of time before automatically retrying the request, up to a configurable maximum number of retries.
Standard Rate Limits
Request
GET https://app.asana.com/api/1.0/users/me HTTP/1.1
Authorization: Bearer <personal_access_token>
Response
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 30
{
"errors": [
{
"message": "You've made too many requests and hit a rate limit. Please retry after the given amount of time."
}
]
}
Our standard rate limiter imposes a quota on how many requests can be made in a given window of time. Our limits are based on minute-long windows, and differ depending on whether the domain is premium or not. We may change these quotas or add new quotas (such as maximum requests per hour) in the future.
| Domain type | Maximum requests per minute | |
| Free | 150 | |
| Premium | 1500 |
In addition, calls to the search API are limited to 60 requests per minute. The duplication endpoints are limited to 5 concurrent jobs.
Although the quota is defined per minute, it is evaluated more frequently than once per minute, so you may not need to wait for a full minute before retrying your request. For requests rejected by this limiter, the Retry-After header has the result of this calculation.
Requests rejected by this limiter still count against the quotas so that ignoring the Retry-After header will result in fewer and fewer requests being accepted during the subsequent tine windows.
Concurrent Request Limits
In addition to limiting the total number of requests in a given time window, we also limit the number of requests being handled at any given instant. We may change these limits or add new limits in the future.
| Request type | Maximum concurrent requests | |
Reads GET | 50 | |
Writes POST, PUT, PATCH, DELETE | 15 |
For example, if you have 50 read requests in-flight and attempt to make another read request, the API will return a 429 Too Many Requests error. The read and write limits are independent of each other, so the number of read requests you make at one time will have no impact on the number of write requests you can make.
Responses for requests rejected by this concurrent request limiter will contain a Retry-After header specifying a duration long enough such that the other in-flight requests are guaranteed to have either completed or timed out.
Cost Limits
Objects in Asana are connected to each other in a graph. Some examples of links in this graph are:
- a task object is linked to a user object as the assignee
- a user is linked to the projects it's following
- a tag is linked to all its tasks
- a task is linked to all its subtasks
- a task is linked to all its custom field values
Depending on the kind of requests you make to our API, our servers have to traverse different parts of the graph. The sizes of these parts directly influence how expensive it is for our servers to build the API responses. For example, fetching just the name and gid of a task requires very few resources and no traversal of the graph, but fetching all tasks in a project and all their attributes (assignee, followers, custom fields, likes) can require following several thousand links in the graph.
Because there can be a wide range in the cost of any given API request in terms of the computational resources and database load, the standard rate limits are not always enough to maintain stability of the API. In the past, when we’ve received bursts of expensive requests, our typical course of action has been to block the offending authorization token and reject all future requests, resulting in confusion for both the user and the app developer. Instead, to protect against the extreme cases where API requests require inordinate traversal of the graph, we impose an additional limit based on the computational cost.
The cost we associate with a request isn't equivalent to the number of links in the subset of the graph involved, but it is roughly proportional. The cost of a request is calculated after the response has been fully built and we know how much data we needed to fetch from our databases to build it. This cost is then deducted from a quota, and the response is returned. Because the cost of a request is not known until we’ve built the response, we allow this deduction to result in a net negative quota. The request that causes the quota to become negative will receive the expected response and not be rejected.
When a request is received, if the remaining quota is not positive, the new request is rejected with a 429 Too Many Requests. As with the standard rate limits, this quota is defined per-minute but is updated on a more frequent interval. The Retry-After header will specify how long you must wait for the quota to become positive again.
The vast majority of developers will be unaffected by the cost limit, and the quota is set sufficiently high that it only affects users making requests that would compromise the stability of the API. Rather than unconditionally blocking their token from the API, this cost limiter will permit them to continue operation at a slower but safe and stable rate.
Common issues & pathological cases to avoid
- Deeply nested subtasks (i.e. working sub-subtasks, sub-sub-subtasks, etc.)
- Projects with too many tasks (i.e projects with over 1,000 tasks)
- Too many unreadable tags in a workspace
- Domains with too many projects for typeahead to work well
- Undeleted webhooks
Rich Text
Note: we are actively adding new rich texts formats to various objects in Asana. This may break existing apps. New apps should be built using parsers and display logic that is forward compatible with the forthcoming rich text formats. More details and ongoing updates can be found in this post in the developer forum.
Example Rich Text
<body>All these new tasks are <em>really</em> getting disorganized, so <a data-asana-gid="4168112"/> just made the new <a data-asana-gid="5732985"/> project to help keep them organized. <strong>Everyone</strong> should start using the <a data-asana-gid="6489418" data-asana-project="5732985"/> when adding new tasks there.</body>
The web product offers a number of rich formatting features when writing task notes, comments, project descriptions, and project status updates. These features include bold, italic, underlined, and monospaced text, as well as bulleted and numbered lists. Additionally, users can "@-mention" other users, tasks, projects, and many other objects within Asana to create links.
The rich text field name for an object is equivalent to it's plain text field name prefixed with html_. The following object types in Asana support rich text:
| Object | Plain text field | Rich text field | |
| Tasks | notes | html_notes | |
| Projects | notes | html_notes | |
| Stories | text | html_text | |
| Project status updates | text | html_text | |
| Teams | description | html_description |
Reading rich text
Python
from lxml import etree
html_text = "<body>...</body>"
root = etree.HTML(html_text)
user_ids = root.xpath('//a[@data-asana-type="user"]/@data-asana-gid')
for user_id in user_ids:
print(user_id)
Java
import com.jcabi.xml.XML;
import com.jcabi.xml.XMLDocument;
import java.util.List;
XML root = new XMLDocument("<body>...</body>");
List<String> userIds = root.xpath("//a[@data-asana-type=\"user\"]/@data-asana-gid");
for (String userId : userIds) {
System.out.println(userId);
}
JavaScript
var htmlText = '<body>...</body>'
var parser = new DOMParser()
var doc = parser.parseFromString(htmlText, "text/html")
var iterator = doc.evaluate(
'//a[@data-asana-type="user"]/@data-asana-gid', doc, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE)
var node = iterator.iterateNext()
while (node) {
console.log(node.nodeValue);
node = iterator.iterateNext();
}
Rich text in the API is formatted as an HTML fragment, which is wrapped in a root <body> tag. Rich text is guaranteed
to be valid XML; there will always be a root element, all tags will be closed, balanced, and case-sensitive, and all
attribute values will be quoted. The following is a list of all the tags that are currently returned by the API:
| Tag | Meaning in Asana | |
<body> | None | |
<strong> | Bold text | |
<em> | Italic text | |
<u> | Underlined text | |
<s> | Strikethrough text | |
<code> | Monospaced text | |
<ol> | Ordered list | |
<ul> | Unordered list | |
<li> | List item | |
<a> | Link |
Note: This list can expand as new features are introduced to the Asana web product. Treat rich text as you would treat arbitrary HTML, and ensure that your code doesn't break when it encounters a tag not on this list.
While links are easy to understand when users view the rendered in the Asana web product, an <a> tag and its href alone are insufficient to programmatically understand what the target of the link is. This is confused further by the fact that the formats of these links are frequently ambiguous. For example, an @-mention to a user generates a link to their "My Tasks", which looks identical to a link to a normal project.
Because of this, the API will return additional attributes in <a> tags to convey meaningful information about the target. The following is a complete list of attributes we may return inside an <a> tag, in addition to the usual href:
| Meaning | ||
data-asana-accessible | Boolean, representing whether or not the linked object is accessible to the current user. If the resource is inaccessible, no other data-asana-* attributes will be included in the tag. | |
data-asana-dynamic | Boolean, represents if contents of the a tag is the canonical name of the object in Asana. If you want to set custom text that links to an Asana object, set data-asana-dynamic="false" when creating the tag. | |
data-asana-type | The type of the referenced object. One of user, task, project, tag, conversation, project_status, team, or search. | |
data-asana-gid | The GID of the referenced object. If the referenced object is a user, this is the user's GID. | |
data-asana-project | If the type of the referenced object is a task, and the link references that task in a particular project, this is the GID of that project. | |
data-asana-tag | If the type of the referenced object is a task, and the link references that task in a particular tag, this is the GID of that tag. |
Here are some examples of how this behavior manifests:
- Suppose a user with a name of "Tim" and a user GID of
"53421"is @-mentioned. This will create a link to their "My Tasks" which is a project with a GID of"56789"- The raw link generated in Asana will be
https://app.asana.com/0/56789/list. - The
<a>tag returned in the API will be<a href="https://app.asana.com/0/56789/list" data-asana-accessible="true" data-asana-dynamic="true" data-asana-type="user" data-asana-gid="54321">Tim</a>.
- The raw link generated in Asana will be
- Suppose a link to a task with name "Buy milk" and GID
"1234"being viewed in a project with GID"5678"is copied from the address bar and pasted into a comment.- The raw link generated in Asana will be
https://app.asana.com/0/5678/1234. - The
<a>tag returned in the API will be<a href="https://app.asana.com/0/5678/1234" data-asana-accessible="true" data-asana-dynamic="true" data-asana-type="task" data-asana-gid="1234" data-asana-project="5678">Buy milk</a>
- The raw link generated in Asana will be
- Suppose another user @-mentions a project with GID
"5678"that is private and not visible to you in the web product.- The raw link generated in Asana will be
https://app.asana.com/0/5678/list. - The
<a>tag returned in the API will be<a href="https://app.asana.com/0/5678/list" data-asana-accessible="false" data-asana-dynamic="true">Private Link</a>
- The raw link generated in Asana will be
Here's an example of what a complete rich comment might look like in the API:
<body>All these new tasks are <em>really</em> getting disorganized, so <a href="https://app.asana.com/0/4168466/list" data-asana-accessible="true" data-asana-dynamic="true" data-asana-type="user" data-asana-gid="4168112">Tim Bizzaro</a> just made the new <a href="https://app.asana.com/0/5732985/list" data-asana-accessible="true" data-asana-dynamic="true" data-asana-type="project" data-asana-gid="5732985">Work Requests</a> project to help keep them organized. <strong>Everyone</strong> should start using the <a href="https://app.asana.com/0/5732985/6489418" data-asana-accessible="true" data-asana-dynamic="true" data-asana-type="task" data-asana-gid="6489418" data-asana-project="5732985">Request template</a> when adding new tasks there.</body>
Reading defensively
Custom handling external media
<object>
const richText = '<body><object style="display:block" type="application/vnd.asana.external_media" data="https://www.youtube.com/embed/VqnMA3K6-e0"><a href="https://www.youtube.com/embed/VqnMA3K6-e0">https://www.youtube.com/embed/VqnMA3K6-e0</a></object></body>'
const parser = new DOMParser();
const richTextDocument = parser.parseFromString(richText, "text/html");
const objects = richTextDocument.querySelectorAll("object");
for (let i = 0; i < objects.length; i++) {
replacement = null;
switch(objects[i].type) {
case "application/vnd.asana.external_media":
replacement = richTextDocument.createElement('iframe');
replacement.width = 420;
replacement.height = 315;
replacement.src = objects[i].data;
break;
default:
replacement = richTextDocument.createElement('div');
replacement.innerHtml = objects[i].innerHTML;
}
if (replacement) {
objects[i].parentElement.replaceChild(replacement, objects[i]);
}
}
richTextDocument.body.childNodes.forEach (child => {
document.body.append(child);
});
We are actively adding new rich text formats to various objects in Asana. An existing app will break if not built defensively. Apps should use parsers and display logic that is forward compatible with unknown future rich text formats.
To do this, Asana provides two mechanisms to parse and display tags that the app doesn't explicitly support:
- Defaults that render in a WebView
- Guidelines for how to handle new tags
You can read more about rich text changes in this forum post.
Render rich text in a WebView
You can expect the rich text HTML to render reasonably in a WebView if you apply the following CSS style to the
wrapping DOM node: overflow-wrap: break-word; white-space: pre-wrap;. This won't look exactly like it does in Asana,
but it will ensure users read it in the same way.
How to handle new tags (no WebView)
An <object> with an unhandled type
Render the <object> tag as a block and render the contained HTML with the same behavior as if it were not inside an
<object>. We will never send an <object> tag nested inside another <object> tag.
An <img>
Fall back to either the alt text or the src
link if the image can’t be displayed. Wrap the text with newlines like \n<alt text>\n since <img> tags are blocks.
Empty elements except <img>
Empty tags are described here. It is ok to omit them. Render as a new line if the tag is a block.
Other semantic non-terminal tags
Ignore the tag and render whatever is inside. Follow the HTML convention for whether it is a block or not.
Writing rich text
When writing rich text to the API, you must provide similarly structured, valid XML. The text must be wrapped in a <body> tag, all tags must be closed, balanced, and match the case of supported tags, and attributes must be quoted. Invalid XML, as well as unsupported tags, will be rejected with a 400 Bad Request error. Only <a> tags support attributes, and any attributes on other tags will be similarly rejected.
For <a> tags specifically, to make it easier to create @-mentions through the API, we only require that you provide the GID of the object you wish to reference. If you have access to that object, the API will automatically generate the appropriate href and other attributes for you. For example, to create a link to a task with GID "123", you can send the tag <a data-asana-gid="123"/> which will then be expanded to <a href="https://app.asana.com/0/0/123/f" data-asana-accessible="true" data-asana-dynamic="true" data-asana-type="task" data-asana-gid="123">Task Name</a>. You can also generate a link to a task in a specific project or tag by including a data-asana-project or data-asana-tag attribute in the <a> tag. All other attributes, as well as the contents of the tag, are ignored.
To keep the contents of your tag and make a custom vanity link, include the property data-asana-dynamic="false" when setting the contents of the tag. You would send <a data-asana-gid="123" data-asana-dynamic="false">This is some custom text!</a> and receive <a data-asana-accessible="true" data-asana-dynamic="false" data-asana-type="task" data-asana-gid="123">This is some custom text!</a>
If you do not have access to the referenced object when you try to create a link, the API will not generate an href for you, but will instead look for an href you provide. This allows you to write back <a> tags unmodified even if you do not have access to the resource. If you do not have access to the referenced object and no href is provided, your request will be rejected with a 400 Bad Request error. Similarly, if you provide neither a GID nor a valid href, the request will be rejected with the same error.
Writing defensively
When processing rich text and sending it back
It’s ok to ignore tags or attributes on tags that are unknown for rendering/processing. It’s very important to send
everything back (attributes and inner content) to avoid data loss. <object> is an exception where it’s ok to not send
any inner content back (all inner content in <object> will be ignored).
If you plan to write an editor
If the tag and attributes are known, but it contains unknown attributes, it must be treated as unknown.
If a tag is unknown, first determine if the tag is block or inline and render it as a block or inline atomic and non-copiable (and non-cut&paste-able) editor node (all inner content is non-editable). This is because we don’t know if the unknown node has constraints on inner content or where it can appear. The node must also keep track of all attributes and inner content to be serialized back.
Pagination
Paginating requests for object sets that may be large is highly recommended. For requests that will return large result sets the API may truncate the result or timeout attempting to gather the data. Pagination ensures a more reliable experience by limiting requests to a smaller number of objects at a time, ultimately getting you the results faster; should there be more results, the API will return an offset that will allow you to access the next page.
Strongly prefer paginated requests
For all new features in the Asana API, we're making pagination required by specifying a value for the limit parameter. Though they may return more results, our current unpaginated requests are still ultimately subject to a timeout limit, which means requests that work successfully one day may fail later due to factors such as server load and network latency.
Pagination limits provide a mechanism to specify a page size that we should always be able to serve regardless of these factors. To prevent current integrations from breaking, pagination is not enabled by default on "grandfathered" endpoints; instead, you can request paginated results by providing the optional limit parameter in your query. We will be working to deprecate requests to these endpoints in the future.
Request
curl "https://app.asana.com/api/1.0/tasks?project=1337&limit=5&offset=eyJ0eXAiOJiKV1iQLCJhbGciOiJIUzI1NiJ9" \
-H "Authorization: Bearer <personal_access_token>"
Response
{
"data": [
{
"id": 1000,
"name": "Task 1",
...
},
...
],
"next_page": {
"offset": "yJ0eXAiOiJKV1QiLCJhbGciOiJIRzI1NiJ9",
"path": "/tasks?project=1337&limit=5&offset=yJ0eXAiOiJKV1QiLCJhbGciOiJIRzI1NiJ9",
"uri": "https://app.asana.com/api/1.0/tasks?project=1337&limit=5&offset=yJ0eXAiOiJKV1QiLCJhbGciOiJIRzI1NiJ9"
}
}
Note that all of Asana's official client libraries support pagination by default.
When making a paginated request, the API will return a number of results as specified by the limit parameter. If more results exist, then the response will contain a next_page attribute, which will include an offset, a relative path attribute, and a full uri attribute. If there are no more pages available, next_page will be null and no offset will be provided. Do note that an offset token will expire after some time, as data may have changed.
When making paginated requests you are able to page through all objects for a particular query up to 100 objects at a time. Alternatively your query will be truncated at about 1000 objects. In addition, when issuing non-paginated requests to organizations with a large number of objects queries may time out before returning. For these reasons, we recommend that you paginate all requests to the API.
| Parameter | Description | |
| Limit | 20 The number of objects to return per page. The value must be between 1 and 100. | |
| Offset | eyJ0eXAiOJiKV1iQLCJhbGciOiJIUzI1NiJ9 An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not passed in, the API will return the first page of results. Note: You can only pass in an offset that was returned to you via a previously paginated request. |
This method returns paginated results for tasks from a project.
Input/Output Options
GET url params
?opt_pretty
?opt_fields=followers,assignee
PUT or POST body options
options: {
pretty: true,
fields: ["followers", "assignee"]
}
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. If the body uses the application/x-www-form-urlencoded
content type, then options are prefixed with opt_ just like for GET requests. If the body uses the application/json
content type, then options are specified inside the top-level options object
(a sibling of the data object).
?opt_fields=name,notes&opt_pretty response
HTTP/1.1 200
{
"data": {
"name": "Make a list",
"notes": "Check it twice!",
"gid": 1224
}
}
These options can be used in combination in a single request, though some of them may conflict in their impact on the response.
| Option | Description | |
| pretty | 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. | |
| fields | Some requests return compact representations of objects, to conserve resources and complete the request more efficiently. 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. The gid of included objects will always be returned, regardless of the field options. |
opt_fields nesting
"data": { < this
"gid": 1001,
"name": "Feed the cat", < this.name
"workspace": { < this.workspace
"gid": 14916,
"name": "Shared Projects", < this.workspace.name
},
"followers": [{ < this.followers
"gid": 1234,
"email": "tbizarro@…", < this.followers.email
}, {
"gid": 5678,
"email": "gsanchez@…", < this.followers.email
}]
}
Some output options allow you to reference fields of objects to include in the response.
The way to specify a field is by path. A path is made up of a sequence of terms separated by the dot (.)
operator. It takes the form this.a.b… where this refers to an object returned at the top level of the response,
a the name of a field on a root object, b a field on a child object referred to by a, and so on.
For example, when retrieving a task or tasks, the path this.followers.email refers to the email field of all users
mentioned in the followers field of the task or tasks returned. See the annotated output below:
There are also some advanced operators you can use for shorter syntax in selecting fields:
( .. | .. )
The group operator can be used in place of any whole term in a path, and will match any of a group of terms.
this.(followers|assignee).email will match the email field of the assignee object or any of the followers.
Custom External Data
Custom external data allows a client application to add app-specific metadata to Tasks
in the API. The custom data includes a string gid that can be used to retrieve objects and a data blob that can store
character strings.
The blob may store unicode-safe serialized data such as JSON or YAML. The external gid is capped at 1,024 characters, while data
blobs are capped at 32,768 characters. Each object supporting external data can have one gid and one data blob stored
with it. You can also use either or both of those fields.
The external gid field is a good choice to create a reference between a resource in Asana and another database, such as
cross-referencing an Asana task with a customer record in a CRM, or a bug in a dedicated bug tracker. Since it is just
a unicode string, this field can store numeric IDs as well as URIs, however, when using URIs extra care must be taken
when forming queries that the parameter is escaped correctly. By assigning an external gid you can use the notation
external:custom_id to reference your object anywhere that you may use the original object gid.
Note: that you will need to authenticate with Oauth, as the gid and data are app-specific, and these fields are not
visible in the UI. This also means that external data set by one Oauth app will be invisible to all other Oauth apps.
However, the data is visible to all users of the same app that can view the resource to which the data is attached,
so this should not be used for private user data.
| Parameter | Description | |
| gid | "contractor_name" The external gid. Max size is 1024 characters. Can be a URI. | |
| data | "{ \"time_estimate\": 3600, \"time_spent\": 1482 }" The external data blob. Max size is 32,786 characters. |
App Server
Sample Server Code (don't use in production)
An app server cannot be handled via curl.
An App Server is required for working with Webhooks and App Components. When we say "App Server", we are referring to the server Asana directly sends requests to. This is different from the service it may be connecting to in the end (like Slack or Jira).
For some features, Asana needs to send requests to an App. In order for an App to use these features, they will need to implement an App Server. App Servers are simply servers that an app controls. The server needs to be accessible via http requests, return successful response codes, and sometimes return valid json bodies to requests from Asana. Some requests will be sent from an Asana user's browser, while other requests will be sent from Asana's servers.
App Servers define their own paths. Apps will need to declare the endpoints for Asana. For Webhooks, this happens when you create a new webhook. For App Components, some are declared on App Creation while others are dynamically declared in responses to requests from Asana.
You should test/debug your App Server with a tool like Postman or Insomnia.
In short:
- App Servers need to accept
httprequests and be accessible viaurl. - Request payloads will be
jsonand App Servers should respond withjson(if a response is needed). - Successful requests should respond with either a
200or204status code. Some App Components have additional error handling for codes like400. - If an app server is down or throws a
500, we will likely retry the request.
Error Handling and Retry
If we attempt to send a request to an App Server and we receive an error status code, or the request times out, we will retry delivery with exponential backoff.
The tolerance threshold for retries vary between Webhooks and App Components. Refer to the documentation for each for a deeper understanding.
News and Changelog
To keep up to date on changes to the API, subscribe to Platform News in our developers forum.
To subscribe to updates:
- Go to Platform News
- Hit
loginin the top right and login with your Asana account. - Go back to Platform News and change the bell icon in the top right to "Watching First Post" or "Tracking".
Here are the most recent updates:
- Introducing the Goals API 2021-08-05 03:44:38.996
- Upcoming improvements to our webhooks system 2021-06-24 18:02:03.220
- Changes are coming to Rich Text (html_notes and html_text) in Asana 2021-03-10 02:19:24.386
- Custom Fields - Display Value 2021-03-08 22:47:10.264
- Webhooks/Events Outage 2021-02-01 2021-02-02 00:50:09.270
SCIM
SCIM endpoints
Asana supports SCIM operations at https://app.asana.com/api/1.0/scim. Okta provides greats docs for
understanding SCIM.
Note that only Service Accounts in Enterprise Domains can access SCIM endpoints.
| API call | Asana Behavior | |
| GET /Users | Return full list of users in the domain. Does not return Asana guest users | |
| GET /Users/:id | Return specific user in the domain. Does not return Asana guest users. | |
| POST /Users | Creates new user if the user does not exist | |
| PUT /Users/:id | Update / remove attributes for a user. Deprovision user (zombify) in Asana upon active=false | |
| PATCH /Users/:id | Deprovision user (zombify) in Asana upon active=false | |
| DELETE /Users/:id | Deprovision user (zombify) in Asana | |
| GET /ServiceProviderConfig | Read-only meta information | |
| GET /ResourceTypes | Read-only meta information | |
| GET /Schemas | Read-only meta information |
The accepted user attributes are:
| Attribute | Type | Info | |
| userName | string | Unique identifier for the User, typically used by the user to directly authenticate to the service provider. Each User MUST include a non - empty userName value, and it must be an email address. REQUIRED. | |
| name | complex | The user's name | |
| name.givenName | string | Unsupported, use formatted | |
| name.familyName | string | Unsupported, use formatted | |
| name.formatted | string | The full name of the user. | |
| emails | complex | Email addresses for the user. | |
| emails.value | string | Email address for the user | |
| email.primary | string | Whether this email address is the preferred email address for this user. true may only appear once for this attribute. | |
| active | boolean | Indicates whether the user's account is active in Asana. | |
| photo | string | URL for the user's profile photo. |
Deprecations
Communicating about breaking changes
Whenever possible, the Asana API aims to preserve backwards compatibility for its users. Apps you write on top of the API now should, in ideal situations, continue to work indefinitely. However, there are a few rare cases where breaking changes are required. For example:
- When we identify a stability threat, we may need to partially limit or entirely deprecate the culprit feature in the API.
- When making a change in a backwards compatible way results in a cluttered, brittle, and confusing interface to Asana.
- When not making a breaking change poses a security vulnerability, such as when we migrated from SSLv3 to TLS 1.0.
If a breaking change is required, the API team will provide a number of resources to help our developers get through the change:
- We will communicate early, and through a variety of channels. We recommend that you join the developers community forum to learn about changes to the API.
- We will provide a clear description of the change, how it affects your requests, and a migration plan to follow to transition through the deprecation.
- We will designate a deprecation period during which you will be able to choose between both old and new behavior from the API, allowing you to test out the change without having to put your entire app at risk.
Response header notifications
While the previously mentioned communication channels are the best place to learn about upcoming changes, the API itself will also alert you of upcoming changes. Shortly after we post communication, the API will begin sending Asana-Change headers in the responses. These headers will have two or three pieces of information:
- The unique name of the change
- A URL to our blog post describing the change
- Optionally, a flag indicating that your specific request would be affected.
This header may be present multiple times in the response if there are multiple ongoing changes. Here's an example of one of these headers:
Asana-Change: name=security_headers;info=https://asa.na/api-sh;affected=true
Asana-Change: name=other_change;info=https://asa.na/api-oc
Note: If your request is not affected, we will not claim affected=false. This is in case, during the deprecation, we detect that the change has a larger scope than initially thought. A request going from "you may be affected" to "you definitely are affected" is an acceptable update, but a request going from "you definitely are not affected" to "you definitely are affected" is not an acceptable update.
Request header options
During the deprecation period, you can test out how the API will behave by sending additional headers in your requests. Sending an Asana-Enable header including comma-separated names of features will turn those features on for that request. Sending an Asana-Disable header will do the opposite and turn those features off for that request.
If no header is specified, the default behavior will be determined by how far into the deprecation period we are:
- Before the start of the deprecation period (the "start date") the feature will be disabled, and it will not be possible to enable it.
- After the start date, the feature will be disabled by default, but you can begin choosing whether to enable or disable it.
- In roughly the middle of the deprecation period (the "activation date") the default behavior will switch and the feature will be enabled by default. You can continue to disable it with the appropriate header.
- At the end of the deprecation period (the "end date") the feature will be enabled and you will no longer be able to manually disable it.
The start, activation, and end dates will clearly be documented in our communications. These days may be pushed into the future if we discover that developers need more time to migrate their apps, but they are guaranteed to never occur sooner than documented.
These dates are arranged such that, if a developer happens to miss our communication and their app breaks when the default behavior changes on the activation date, they can begin sending the Asana-Disable header to restore the old behavior and use the remaining half of the deprecation period to make their app compatible.
Here's an example of how these headers would look:
Asana-Enable: security_headers,another_change
Asana-Disable: a_third_change
Aside from reserving the right to push the date of changes to a future date, the precise time during the activation date isn't specified. However, since the default will only affect your integration if you do not pass either the Asana-Enable or Asana-Disable headers for a particular deprecation you can ensure predictable behavior of our API for your app during the entire period, including throughout the activation date.
The way we recommend you implement these changes in your integration is this:
- Whenever you detect a new Asana-Change header, log these requests and be sure to take note that a change is coming. Recall that the
infokey in the header will contain a link with the details. - Identify the nature of the upcoming deprecation and decide if your integration is sensitive to the change, paying particular attention to the cases where we return
affected=true. - If changes are necessary in your integration, test the new behavior manually by making requests with
Asana-Enableset to the name of the deprecation. This should provide a clear example of the new behavior as it is implemented in our API. - Implement the changes in your integration in such a way that it can handle the new behavior and be sure to pass the
Asana-Enableheader when you make requests. This will ensure that you will always get the new behavior regardless of when the default behavior changes.
At this point, your integration has been migrated to the new behavior. At any point after the end date the Asana-Enable header will be ignored by the Asana API and you can feel free to remove it. (We strongly recommend keeping it all the way through the end date in case of unforseen circumstances that cause us to temporarily reset the default behavior from the new implementation to the deprecated behavior.)
Client library support
The latest version of our official client libraries for Python, Java, PHP, and JavaScript all support sending custom headers and are able to use our deprecations framework. Consult the individual libraries for how to send headers with each request.
Developer Sandbox
An Asana developer sandbox consists of a temporary Asana domain with limited users. It is essentially a standard Asana account where you can test premium features during development.
Developer Sandboxes are intended for:
- Developers building or maintaining a 3rd-party integration with Asana (submit your completed integration to get listed on our apps page)
- Existing premium Asana customers that require a separate environment to perform risk-free testing on the API
To request a developer sandbox, please fill out this form.
API Explorer
The Asana API Explorer is a tool to easily make API requests in your browser and quickly test various routes, fields, and parameters.
The explorer is not meant to be an exhaustive tool with every endpoint in the API (try Postman if you want a tool with complete coverage). Instead, the explorer is designed to be a simple tool to help developers quickly access the API and see examples of requests and responses fetching real Asana data.
Follow these steps to get started:
Go to the API Explorer site: https://developers.asana.com/explorer
Click the large button that says “Click to authorize API Explorer”. This will use your Asana credentials to provide cookie authentication for the requests you make in the explorer. Because the explorer is using your Asana account, it only allows read requests (i.e.
GETonly) to protect against unintentionally changing your Asana data.Choose the resource you wish to query from the drop-down.
In the next drop-down, choose your desired route for that resource.
Under "Include Fields," You have the option to select only the fields you would like to include in the response (more about I/O options).
The default response limit is 10. You can increase it up to 100.
Add the required “Attribute parameters”. Note that task and project gids are in URLs when viewing those resources in the Asana web product (e.g. when viewing a task in a project: https
://app.asana.com/0/'project-gid'/'task-gid'). In subsequent requests, you may have a pagination token (see the pagination docs for more on this) to paste into the “Offset” field.
You have the option to include additional parameters in your request.
Click “Submit” to send your request to the API. You will receive a JSON pretty-formatted response.
Submit your App
Have you built a web application that you want to share with the Asana community? Submit this form to get your app listed in the Asana apps directory.
Recommendations and resources for app developers:
We strongly recommend that you use OAuth 2.0 for your app. Apps that don’t use Auth 2.0 will likely not be approved for listing in our directory.
Be aware of the OWASP Top 10 Web App Security Risks when developing your app.
If you are new to app security, we recommend reading The Web Application Hacker's Handbook.
Use end-to-end encryption. Use a trusted site to test your TLS security (such as: https://www.ssllabs.com/ssltest/).
Join the Asana developer community. This is the best resource to get technical questions answered as well as get notified about new API features, deprecations, and other breaking changes.
Once your app is listed, you can answer Asana user questions in the integrations section of the Asana community.
Updating your existing app listing
If you wish to update your existing listing, send an email to api-support at asana.com with the specific changes.
We expect existing apps to maintain the same level of user experience that they had when accepted to the apps directory.
Custom Apps
What to consider when building a custom app.
Unlike 3rd-party apps and integrations used by many companies, custom apps are designed to only be used within a single domain. For example, an Asana customer may want to use the API to create a bot, integrate Asana with a homegrown tool, or generate custom reports. If you want to get inspired about what’s possible with custom apps, here are some common use cases.
Authentication
Most custom apps use Personal Access Tokens (PATs) for authentication. In general, PATs are best for projects that don’t require multiple users to log in. For example, it’s advisable to use PATs to auth scripts, bots, or anything else that doesn’t require taking action on behalf of multiple Asana users. While less common, if your custom app requires users to sign in to use it, then you should consider using OAuth.
API Explorer
If you're unfamiliar with our API, it may be helpful to start by playing around with our API explorer. It’s a quick and easy way to test endpoints and see how various parameters affect responses. You will also find guides and code examples in our docs and client libraries that are helpful when getting started.
Client Libraries
You should consider using one of our API client libraries for your custom app. They simplify some of the more technically challenging aspects of development such as authentication and pagination. There are code examples for each library to help you get started. The client libraries also help developers navigate API deprecations, which will help you avoid unexpected breaking changes and reduce the overall time required for maintenance.
Note that client library functions are not documented. You need to check the lib/resources/gen folder of each library to see the built-in functions.
API support
If you get stuck or need help developing your custom app (or just want to meet other Asana developers), join our active developer community. On the forum, you can find answers to many technical questions. If your question has not yet been answered, post it and you should get a reply within a day or so. In addition to community support, internal Asana engineers also help troubleshoot issues on the forum. If you have found an API bug, you can either post it to the community or email the issue to api-support at Asana dot com.
Deployment
Once you’ve created a custom app, you will likely want to host it somewhere. While you could run your script from the command line, doing so is tedious and time consuming.
The most basic, automated option is to use launchd to programmatically execute your app on your machine (launchd is like cron but better). Here’s a tutorial to get you started with launchd.
A more robust option would be to deploy your custom app to a hosted server. Here’s a guide exploring some of the popular hosting providers. Hosting your app makes it more resilient and allows you to add more sophisticated features (e.g. use webhooks).
Remember to securely store your PAT and any other sensitive data (never expose a PAT in a public repository).
Maintenance
Make certain that the email address associated with your custom app is being actively monitored. We only email developers for critical issues such as API bans and upcoming deprecations that our logs show will break your app. If you’re using a PAT to authenticate, you should confirm that the email address associated with the Asana account that generated the PAT is being actively monitored by one or more people.
We also recommend all developers join the Asana developer community. This is where we will communicate new API features as well as announce upcoming breaking changes. To ensure you don’t miss these announcements, we encourage you to turn on notifications for the Platform News section of the community.
If your app is having issues, here are some steps to help you troubleshoot the issue:
- Carefully read any error messages (here are the docs for Asana error codes).
- Check the status of the Asana API to confirm it’s up and available.
- Check for any issues with the server that is hosting your app.
- Check the Asana dev community to see if others are having the same issue.
- If you can't find an answer on the community, post your issue and someone will likely help. Please include all of the required information to reproduce the issue (e.g. verbose CURL request with full response). Never post a PAT to the forum (or share it anywhere else).
How to use the API
Request
https://app.asana.com/api/1.0/users/me
If you're familiar with building against APIs, you can jump to our examples.
If you’re new to developing on APIs, this is a great place to start. You’ll learn in this guide how to make the simplest Asana API request -- getting your user information.
To get started
- Be logged into Asana.
- Go to this URL: https://app.asana.com/api/1.0/users/me
me is a User Identifier that refers to the logged in user. A User Identifier can be either me, an email_address, or the gid of the user.
Response
{
"data": {
"gid": "12e345a67b8910c11",
"email": "jonsnow@example.com",
"name": "Jon Snow",
"photo": {
"image_21x21": "https://s3.amazonaws.com/profile_photos/121110987654321.hJGlskahcKA5hdslf4FS_21x21.png",
"image_27x27": "https://s3.amazonaws.com/profile_photos/121110987654321.hJGlskahcKA5hdslf4FS_27x27.png",
"image_36x36": "https://s3.amazonaws.com/profile_photos/121110987654321.hJGlskahcKA5hdslf4FS_36x36.png",
"image_60x60": "https://s3.amazonaws.com/profile_photos/121110987654321.hJGlskahcKA5hdslf4FS_60x60.png",
"image_128x128": "https://s3.amazonaws.com/profile_photos/121110987654321.hJGlskahcKA5hdslf4FS_128x128.png"
},
"resource_type": "user"
}
}
And Congratulations! You’ve just made your first Asana API request.
Let’s unpack what just happened. The base URL for all requests to the Asana API is https://app.asana.com/api/1.0. We want information about users, so we go down a level to the https://app.asana.com/api/1.0/users resource. Within the set of all users in Asana, We’re specifically looking to get information about our own account, so we get more specific by adding /me to get https://app.asana.com/api/1.0/users/me. The /me part would ordinarily be an identifier (a long number) or email address of the user, but we've created this shorthand for getting the current user of Asana's API, whomever that may be. Put it together and you have the above path to get your user information from Asana.
Since every API request you make will start with the same base URL ('https://app.asana.com/api/1.0'), we'll just talk about what comes next in the URL -- which is often referred to as a 'resource' or 'path'. For instance, when we say /users/me it's actually shorthand for the entire URL which would be https://app.asana.com/api/1.0/users/me.
After requesting information from the API, you will receive a response in JSON format, which can be read and understood by both humans and computers. It's structured in a particular way so programs can rely on a consistent format for the data.
Our API is documented for what resources are available and what sort of return data to expect. For example, here are the docs for the /users endpoint which we just called. This is where you can discover what's possible with our API.
Now, let’s make the same call to /users/me more like software would. Before we do so, we’ll need to get access outside of your web browser to the API.
Authentication Quick Start
Similarly to entering your username/password into a website or logging into Asana with Google, when you access your Asana data via the API you need to authenticate. In the above example, you were already logged into Asana in your browser so you were able to authenticate to the API with credentials stored by your browser.
If you want to write a script that interacts with the Asana API, the easiest method is to get a Personal Access Token (PAT), which you can think of as your unique password for accessing the API.
App or PAT?
If your app needs to perform actions on behalf of users, you should use OAuth.
Getting a Personal Access Token (PAT)
Example PAT
0/68a9e79b868c6789e79a124c30b0
- Open the Developer App Management page by using this permalink or following these steps:
From within Asana, click your profile photo from the top bar and select "My Profile Settings"
Click the "Apps" tab
Click "Manage Developer Apps"
Click "+ Create New Personal Access Token"
Type a description of what you’ll use the Personal Access Token for.
Click "Create"
Copy your token. You will only see this one time, but you can always create another PAT later.
Note: treat your PAT like you would a password. Do not share it or display it online.
Using Terminal
curl Request
curl https://app.asana.com/api/1.0/users/me \
-H "Authorization: Bearer 0/123456789abcdef"
We’ll use cURL, a command line[^1] program to make HTTP requests. MacOS and many Linux distributions have cURL pre-installed, and it’s available for download on Windows and many other operating systems. If you’re curious, you can learn more about cURL in its own documentation.
Let’s do this:
Response
{
data: {
gid: "<your gid>",
email: "<your email>"
name: "<your name>",
...
}
}
Copy/paste the cURL request on the right (make sure to enter your personal access token instead of the placeholder after the word "Bearer", or else you'll get a "Not Authorized" message):
Press Enter
Nice work! You just wrote a cURL command.
In our API documentation, we will often write examples as cURL commands since it's a middle-of-the-road approach to accessing our API: more flexible than using a browser, but user-friendly enough to be quick and easy to do.
You’re ready to start coding!
Asana has client libraries in several popular coding languages. Using these libraries has several advantages (like managing authorization and retrying errors) that make them a good place to go from here. Let’s take a look at making the same /users/me request in Python, JavaScript, and Ruby (feel free to skip ahead to your favorite of the three languages).
Using Postman
You can quickly get started on Asana's API with the API Explorer. However, if you want a more robust experience hitting the API, we recommend using Postman. You can get started with the 'Run in Postman' button!
Once you have the collection, you should create an environment.
You'll want to set:
authentication_tokento a Personal Access Token (PAT). If you don't have one yet, visit our Authentication Quick Start.workspaceto your workspace's gid. You can find this value via a logged-in browser by going to https://app.asana.com/api/1.0/users/me/workspaces, or you can hit that endpoint using your PAT.- Any other gids you want to easily access.
- For example, you can set
taskto the gid of a task that you regularly test with,projectto the gid of a private sandbox project, anduserto the string 'me'.
- For example, you can set
No need to edit your environment for requests on different objects, simply navigate to the endpoint you want to use, and change the {{object}} to any gid you want.
Importing this collection gives you a snapshot of the API at this time. To stay up to date with API changes, you'll have to re-import the collection by hitting the 'Run in Postman' button, and choosing to override your existing collection. This means if you want to save custom requests, you should do so in a different collection.
Common Usecases
Collaboration across teams and tools works best when everyone stays in sync and processes flow easily and without friction. This is why we have Asana's API: it's a platform to ensure all of your information is up to date and that your teams stay efficient and in the loop.
Asana’s API provides a means for software and scripts to read information from inside Asana, input information from outside Asana, and automatically react when things change. This can include:
- Consistently doing repetitive or tedious tasks.
- Chaining a process together by responding to changes.
- Creating reports on the state of tasks and projects.
- Staying in sync with other software such as Slack or Salesforce used in your organization.
- Pulling information from other locations like email or Evernote into Asana.
- Adding new features on top of Asana.
- Customizing Asana for your team’s processes and workflows.
The role of Asana's platform is to allow Asana to meet your team where you are and how you work. Asana is built to be flexible and powerful, to be intuitive enough for all teams to adopt and maintain clarity on who is doing what by when. Asana’s platform enables you to specialize this flexibility to maximize efficiency. Here are some ideas for what you can build:
Doing repetitive work
Integrations and bots are great for making sure that repetitive tasks are always taken care of. Running a script with Asana's API can quickly take care of work like moving cards between board columns, setting assignees or due dates based on the state of the task, or asking that all custom fields are set before work can begin on a task. This can save time and overhead when trying to keep your projects clear and correct.
Reacting to changes
Workflows with Asana often have a "when this task changes, do something" feel. An example is moving tasks between projects based on subtasks: if one team completes a subtask, move the parent task to the next team's project. Integrations can be built to respond in near-real time to changes in Asana to move work forward to the next step.
Generating reports
Fetching the state of the tasks in a project or for your teammates can unlock the ability to create simple - or complex - metrics around how you are progressing. How many open tasks are there in the project? Who has the most tasks assigned? How often does the due date of each task get shifted back? Our platform enables pulling of data from Asana to make customized metrics to track your work.
Keeping in sync
Teams frequently use a multitude of software tools to accomplish work, from email to asset management to file storage. These specialized tools are often used with colleagues who don't track their work with Asana; and even if they do, keeping all of your tools in sync makes the transitions between tools straightforward to minimize work about work.
Some of our integration partners, like Tray.io, Unito, and Zapier, offer syncing solutions out of the box with common workplace tools, or you could build your own solution in cases where you need more flexibility, such as when connecting to customized or internally-built software.
Capturing work
Asana is built for teamwork and knowing who is doing what by when. Having an easy way to capture information in Asana makes it less likely that work will slip through the cracks. For example, when communicating with people who work in other companies who aren't members of your Asana organization, an integration like we built for Gmail lets you create follow-up tasks with just a few clicks.
Getting information into Asana in a quick and easy way is important for ensuring that you don’t drop the ball. Asana’s platform is a great way to pull information from many channels into Asana with minimum hassle.
Extending Asana
Asana is built to be a tool that works well for all teams, so we build features into our core product that aren't overly opinionated about how you get work done. At the same time, there is opportunity for teams to use Asana in a specialized way or with specific additional features. When there are features that you'd like Asana to have, our platform is a resource to make them happen. As a matter of fact, some of our more successful integrations like Instagantt exist purely to provide additional features to Asana.
Customizing workflows
Integrations or scripts work great to maintain a custom workflow, saving a team member from having to continually pay attention to the state of tasks in Asana.
Whether it's ensuring that custom fields are filled out, tasks are completed, tasks live in the correct board-view column, or automatically assigning tasks at certain stages in your process, integrations can react to changes in Asana to ensure that everyone is up to date. When processes mature around how you get work done, it's a great time to use Asana's platform to make sure everything stays consistent and clear.
Check out some examples of integrations we've built on Asana in the next section.
Examples
Python Hello World
import asana
# replace with your personal access token.
personal_access_token = '0/123456789....'
# Construct an Asana client
client = asana.Client.access_token(personal_access_token)
# Set things up to send the name of this script to us to show that you succeeded! This is optional.
client.options['client_name'] = "hello_world_python"
# Get your user info
me = client.users.me()
# Print out your information
print("Hello world! " + "My name is " + me['name'] + "!")
To get started, run pip install asana or follow the detailed installation instructions on the GitHub page for the Python client library.
Once it’s installed, open your favorite text editor and we’ll code a GET request to /users/me in Python.
Save this file as something descriptive like "hello_world.py"
To run this script in your console, pass it as an argument to the python interpreter, i.e. python hello_world.py from the same directory as the file. You should see the message we wrote above with your user information.
As an aside, for clarity python-asana will also work with Python 3.x (with small changes to the above example to make it compatible.)
All of the built-in functions can be found in the /gen folder of the client library.
You can see a variant of this script, and other useful Asana API scripts, in our open-source GitHub examples repository
Node Hello World
var asana = require('asana');
// replace with your personal access token.
var personalAccessToken = '0/123456789....';
// Construct an Asana client
var client = asana.Client.create().useAccessToken(personalAccessToken);
// Get your user info
client.users.me()
.then(function(me) {
// Print out your information
console.log('Hello world! ' + 'My name is ' + me.name + '!');
});
To get started, npm install asana or follow the detailed installation instructions on the GitHub page for the Node client library.
Once it’s installed, open your favorite text editor and we’ll code a GET request to /users/me - the same request as above, but in JavaScript.
Save this file as something descriptive like "hello_world.js"
To run this script in your console, pass it as an argument to the node interpreter, i.e. node hello_world.js from the same directory as the file. You should see the message we wrote above with your user information.
All of the built-in functions can be found in the /gen folder of the client library.
You can see a variant of this script, and other useful Asana API scripts, in our open-source GitHub examples repository
Ruby Hello World
require 'asana'
# replace with your personal access token.
personal_access_token = '0/123456789....'
client = Asana::Client.new do |c|
c.authentication :access_token, personal_access_token
end
me = client.users.me
puts "Hello world! " + "My name is " + me.name + "!"
To get started, `gem install asana` or follow the detailed installation instructions on the [GitHub page for the Ruby client library](https://github.com/Asana/ruby-asana/).
Once it’s installed, open your favorite text editor and we’ll code a GET request to /users/me - the same request as above, but in Ruby.
Save this file as something descriptive like "hello_world.rb"
To run this script in your console, pass it as an argument to the ruby interpreter, i.e. ruby hello_world.rb from the same directory as the file. You should see the message we wrote above with your user information.
All of the built-in methods can be found in the /resources folder of the client library.
You can see a variant of this script, and other useful Asana API scripts, in our open-source GitHub examples repository
Workflow automation script
Asana's API enables customization and automation of your organization’s workflow through scripts built to specialize your use of Asana. Using Asana to track your work and leveraging Asana’s API to automate your processes is a powerful combination which can make your team much more efficient. Here's one example of how we do it at Asana.
Tracking timely responses to support questions
Asana’s developer relations team manages technical support for our API through a number of channels: support tickets, questions about our API and integrations forwarded on from our colleagues, the Asana Community's Developer category, Stack Overflow, pull requests and bug reports from open-source GitHub projects like our client libraries, and more. Staying on top of all of these channels can be daunting, but we want our users to reach us however works best for them. At the same time, we want to isolate the noisiness of incoming requests for our colleagues at Asana who are involved with only one channel.
Additionally, the management of the question and answer process, triaging the incoming requests, troubleshooting with our engineers, and measuring our response performance are all internal processes. Even if we have a workflow in place to support our developer relations team, we want the experience for other teams to be easy and lightweight. We want to ensure our coworkers do the right things by default without hindering the consistency of our work and our ability to track progress.
Our solution: automation and reporting through our API to provide consistent management of the whole process.
To do this, we wrote an integration with the following goals in mind:
- Maintain clarity amongst our teams by tracking work in Asana.
- Have only one place we have to look to stay in the loop.
- Ensure that no questions get missed, i.e. a reminder bot.
- Let our API users know that they've been heard in a timely fashion.
- Track our performance in remaining responsive.
- Automate some of the bookkeeping required to maintain a consistent workflow.
- Separate the specifics of how we track our performance from our colleagues’ workflows.
The script we built does the following for us:
- Integrate with external sources to put incoming questions into Asana, one project per channel.
- Add question tasks from each incoming project into a single combined project.
- Acknowledge a question has been received and begin tracking response times.
- Upon first response, complete a task to signal relevant followers that we've reached out.
Maintain focus
We use webhooks to get notified in near-real time when new tasks are created in any of several Asana projects, one per incoming channel. Some of these projects are automatically synced with outside sources, others are available for our coworkers to create tasks in. Keeping tasks in their source channel helps keep us organized for where to go to respond. These projects are what our colleagues follow in order to remain focused on their own channels.
Our script responds to these webhook notifications from each project by adding these tasks into a single "Developer Questions" project. Our developer relations team can then see all outstanding questions about our API in a single place. This is a key part of hitting our service level agreement (SLA) goals: not having to cycle through many projects and channels to see how we're progressing.
Ensure timely responses
Once a question gets added to our Developer Questions project, our integration creates a subtask on it. This signals to our colleagues that we have received the question and will begin to triage and investigate. The subtask is completed when we first respond to our users to inform them that we're investigating. Completion of the question task itself signals that we've achieved a resolution for the person who reached out to us.
Track progress
Our script can generate a simple report to see which questions are still open, how long they’ve been open, and how much time we have left to answer before we miss our service level agreement limits. A simple webpage that the integration creates enables a high level view of what's still in progress and how timely we've been in the past.
Keep the process moving, automatically
Our integration also helps automate some of the routine steps to ensure questions get answered. After a task gets triaged for priority, our integration sets an appropriate due date. It can also set an assignee and followers based on current workload and by matching certain keywords in the task description. If the task approaches its due date and it has not received a response, the script comments on the task to alert us that the question is about to reach our SLA limit. This helps us keep the right people in the loop with minimal overhead and maximum clarity of what needs to be done by when.
By managing this routine and specialized workflow with automation through Asana’s API, our team is more efficient, more effective, and less likely to make a mistake. We know how responsive we've been and can see how we're doing at any time. We're better able to minimize the number of questions which slip through the cracks. The result is better support for outside developers and increased focus on core work, not work about work.
Over time, we've continuously tweaked how our integration behaves to evolve our process, empowering us to adjust and iterate our approach. This is one of the key opportunities that Asana's API provides: ownership and control over how work gets done. Incremental improvements provide the chance to try out new workflows and settle on one that works well for everyone, leading to a more consistent and customized experience of using Asana.
To get started, check out our examples page. For support or to generate ideas of how your team can work more effectively with Asana, head to the Asana Community to chat with Asana team members and users!
Triage bot
Let’s start coding!
Follow along below in the right pane to see the terminal commands and code for this tutorial. We will use a very basic file structure for the purposes of this guide. Start by making a project directory, moving into it, and running
npm init.
$ mkdir triage-bot
$ cd triage-bot
$ npm init
Install the Node Asana client library and create config and app files:
$ npm install asana
$ touch config.js app.js
Add gids (global ids) for the workspace, design request project, and designers that will be assigned requests (note that all gids in Asana should be strings). You can get a project’s gid from its URL in the Asana web product (e.g. the structure of links for a task is www.asana.com/0/{project_gid}/{task_gid}). Similarly, you can get user’s gid from the URL of their task list (i.e. click on their name in Asana). To get your workspace gid(s), go to https://app.asana.com/api/1.0/users/me/workspaces.
let config = {
workspaceId: "15793206719",
designRequestProjectId: "180350018127066",
//gids of designers who are fulfilling design requests
designers: ["180015866142449", "180015866142454", "180015886142844"]
};
module.exports = config;
Next, let’s get started on our app.js file. Include the Asana node client library and the config file:
let asana = require('asana');
let config = require('./config');
Get your access token and use it to create an Asana client. At the time of writing this guide, the Asana API is going through two deprecations (moving to string gids and changing how sections function). You can learn about our deprecations framework in our docs. To prevent my app from breaking when the deprecations are finalized, I'm passing headers to enable the new API behavior for string gids and sections. We will also set a delay to determine how quickly our parallel requests are sent.
// Get personal access token (PAT) from environment variables.
const accessToken = process.env.triage_bot_pat;
const deprecationHeaders = {"defaultHeaders": {"asana-enable": "new_sections,string_ids"}};
// Create Asana client using PAT and deprecation headers.
const client = asana.Client.create(deprecationHeaders).useAccessToken(accessToken);
// Request delay in ms
const delay = 200;
Use the search API to fetch unassigned tasks from the design requests project. Note that the search API doesn’t return paginated results so you need to pass the max limit which is 100. If there are often more than 100 unassigned tasks, you can add a function to keep running the script until there are no more unassigned tasks.
function getUnassignedTasks() {
let workspaceId = config.workspaceId;
let params = {
"projects.any" : config.designRequestProjectId,
"assignee.any" : "null",
"resource_subtype": "default_task",
"fields": "gid",
"limit": 100
};
client.tasks.searchInWorkspace(workspaceId, params).then(tasks => {
randomAssigner(tasks.data);
});
}
We’ll need a few helper functions. One to shuffle an array and another to assign tasks.
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
let temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function assignTask(taskStringId, assigneeStringId) {
client.tasks.update(taskStringId, {assignee: assigneeStringId})
}
Our final function will take the array of unassigned tasks and round-robin assign them to the group of shuffled designers from the config file. We will use an interval to loop so we can control the speed of the requests. You can change the delay with the const you declared earlier. This is a balance between speed and staying within our concurrent request limit. In node, a normal loop would send all requests at once, which doesn’t work in larger projects.
function randomAssigner(unassignedTasks) {
let shuffledDesigners = shuffleArray(config.designers);
let numDesigners = shuffledDesigners.length;
// Let's use an interval to loop, so we control how quickly requests are sent
let index = 0;
let interval = setInterval(function() {
assignTask(unassignedTasks[index].gid, shuffledDesigners[index % numDesigners]);
index++;
// When our index reaches the end, we're done
if (index >= unassignedTasks.length) {
clearInterval(interval);
console.log("You've assigned " + unassignedTasks.length + " new design requests");
}
}, delay);
}
Then we just need to call our getUnassignedTasks function to kick-off the script:
getUnassignedTask();
Now run your script, sit back, and watch the bot do your work.
$ node app.js
Why build a bot?
When processes get complex in Asana there can begin to be work about work. This could be happening to you (or someone you love) if you find yourself spending time doing repetitive work such as triaging tasks, reminding people to do something, or adding/removing followers as you move a task through a workflow.
What we’re going to build
In this guide, we will build a simple triage bot that will assign tasks. This is a common Asana use case with support inboxes or request projects.
If you want to skip ahead and see the code for the triage bot, it’s on GitHub in the JavaScript folder of our devrel-examples repo.
For this guide, let’s suppose a design team has a requests project where people from the marketing team fill out an Asana form to request graphics from the design team. The form creates a task in the design requests project that needs to be assigned to a designer.
Our triage bot will gather all unassigned tasks in the design request project and then randomly distribute the requests across a group of designers.
For the purposes of this guide, we will keep it this simple, however, you could add more complex logic to your bot. For instance, you could check custom field values on the request task to see what type of request it is (e.g. video, graphic, logo, etc.) and then assign it to the designer that has those skills. You could go even further and check the designers workload to see who currently has the least amount of work already assigned to them (this could be determined by a point value for tasks assigned to them in the project). You could then have the bot ping the design request task as it approaches the due date to ensure that the designer will have it completed on deadline.
Helpful links
Before we get started, here are some helpful links for building on the Asana API:
- Asana API reference docs
- Asana longform documentation
- Asana developer community -- if you get blocked or have a question about the API, there are devs in our community that are eager to help. We also post API updates and news to the community forum.
- The code for this bot on GitHub
Create your bot user in Asana
Create a new Asana account for your bot (instructions for inviting users). You want to create a distinct Asana account for your bot because any action it takes in Asana will be attributed to this user. Give your bot a name and photo that will be recognizable to users in Asana that encounter it. Note that if your bot is a guest member in Asana that it will need to be added to every project you need it to work in. Bots based on guest Asana accounts will also not have access to some API features such as defining new custom fields or modifying their settings.
Authenticating your bot
We will authenticate our bot using a Personal Access Token (PAT). Log in to the Asana account that will be used for the bot and navigate to the developer console. You can get to your dev console by either using this URL https://app.asana.com/-/developer_console or from within Asana by clicking your photo icon in the upper right of Asana -> My Profile Settings -> Apps -> Manage Developer Apps.
Next, click “+ New access token” and follow the instructions to get your token. Treat this token like a username and password. Don’t share it with anyone and never publish it to a public repository. I like to save my PAT as an environment variable (here are instructions on how to do this on Mac). For this guide, I’ve saved a PAT as an env variable called triage_bot_pat.
Create an Asana sandbox
Before we start coding, create a project in Asana to use as a sandbox. While not required, I like to set the project to private while developing. To get some users in the project, add your main Asana user as well as your bot account. You could also invite a personal email as a guest user.
Choose an Asana client library
The Asana API has SDKs in several popular languages. For most developers, we recommend using one of our client libraries because they help with some of the complexities of using an API such as authentication, pagination, and deprecations.
For this guide, we will use the Asana Node client library, however, you can follow along in any language of your choice.
Each library has an examples folder in addition to the readme, which can be helpful for getting started. The methods for each resource can be found in the “gen” folder of each client library (e.g. node-asana/lib/resources/gen/).
Now head over to the top of the right pane to start coding your bot ----->
Congratulations! Now go above and beyond
You’ve created an Asana triage bot. Let’s explore a few ideas on how to make it even better.
Deploy your app
While you can run your bot from the command line, that seems like a lot of work to run a bot that’s supposed to eliminate work about work.
One option is to use launchd to automatically execute your script (launchd is like cron but better). Here’s a tutorial to get you started with launchd.
The next step would be to deploy to a hosted server. Here’s a guide exploring some of the popular hosting providers. Hosting your app makes it more resilient and allows you to create more sophisticated apps (e.g. use webhooks).
Use Asana as your config file
To take your bot’s accessibility to the next level, put your configuration in an Asana task(s) and then have your script read that task(s) for instructions. This allows you (or anyone else) to make config changes without touching any code. For example, if a designer is on vacation, you can easily remove them from the group that gets assigned requests. Similarly, if a designer joins or leaves the team, this change could be easily configured in a task instead of having to change the bot’s code.
To see this approach in the wild, checkout Ohmega, an automation framework we created. Here’s the configuration service that reads a tree of tasks for its configuration.
Use webhooks for real-time triaging
If you need your bot to react to changes in real time, then you’ll need to use webhooks. We built a python webhook inspector to help developers get started using Asana webhooks.
Other bot examples
Reminder bot
Even the most conscientious and best-intentioned teammate can get overloaded and occasionally forget a task. For project managers, team leads, or coordinators, it can be draining to check-in on everyone to make sure that everything is going according to schedule. How can you stay on track and minimize the work-about-work?
Instead of continually reminding teammates to stay focused, use Asana’s API to create a bot for automatic reminders (a bot is a script that performs a task automatically). In this case, a "ping bot" takes action when due dates are approaching (or for any other specified trigger). This can act as a more intelligent version of the reminders that Asana already sends when due dates approach. For example, this persistent friend could comment with reminders further in advance, ask assignees or followers to take some action like setting a custom field, re-assign the work, and/or push out due dates. With a bot taking care of the schedule and reminders, people can spend their time on the work that needs human attention, like ideation and feedback.
Recruiting bot
At Asana, we use a bot to help automate the process for evaluating engineering candidates. The bot helps ensure that applicant coding tests are graded in a timely manner by the right engineer.
When candidates have submitted their coding test, the bot uses the Asana API to assign the test to a grader based on specific criteria tracked in Asana, such as their preferred programming languages and number of previous evaluations. Graders are given x days to grade tests (the bot takes into account when graders are out of office). If tests have not been graded by the due date, graders are pinged by the bot with a comment on the task to either grade the test or re-assign it to someone else. After y days, the bot automatically re-assigns the test to the next grader to keep the process moving.
Bugs bot
Our engineering teams handle triaging bug reports by creating a task in a "Bugs" project. A bot then adds the project manager of the relevant team in Asana as a follower, moves the task into a "needs triage" section, and requests assistance. The project manager can then evaluate the bug and triage it.
Since the evaluation of the severity of the bug is important for understanding how urgent the fix is, Bugs Bot will remain persistent, commenting every few days until the task has been moved out of the triage section and into a section of the relevant priority. This process ensures that we're aware of the impact of bugs and helps us avoid severe bugs slipping through the cracks.
Official Client Libraries
Asana is committed to making the developer experience as smooth as possible. Part of this effort is providing high-quality libraries you can use to access the API. The available libraries are listed below, and more are in development. If you don't see what you need, check the open-source community for your platform, and let us know that you'd like to find one here!
JavaScript (Node)
npm install asana
For use in the Node server-side JavaScript runtime.
Installation: Install with npm
JavaScript (Browser)
<script src="asana-min.js"></script>
This is built our Node library, so you get the exact same interface.
Installation: Visit the releases page to download the latest full or minified JS bundle, then include the script in your web page.
Python
pip install asana
Installation: Install with pip
Ruby
gem install asana
Installation: Install with gem
Java
<dependency>
<groupId>com.asana</groupId>
<artifactId>asana</artifactId>
<version>0.10.1</version>
</dependency>
Installation: If you use Maven for dependency management simply include the following in your pom.xml.
PHP
"require": {
"asana/asana": "^0.10.0"
}
Installation: If you use Composer to manage dependencies you can include the "asana/asana" package as a dependency.
App Components Beta
BETA
App Components are currently in a Closed Beta. If you want to participate in the App Components Beta Program, please complete and submit this form. We are limiting the number of apps that can use these features at this time. This will open up more as we move to beta.
The App Components Beta Program is a pre-general-release version of a program developed by Asana that allows developers to develop and test App Components. The App Component Beta Program is for development, evaluation, and testing purposes only, and is not for production use or subject to availability or security obligations from Asana. The App Components Beta Program is made available on an “as is” basis without warranties (express or implied) of any kind, and may be discontinued or modified at any time.
App Components Overview
BETA - For access, please see App Components Beta
To start building, follow our Quick Start guide!
Apps can use App Components to display customized widgets, forms, and rules within Asana's UI.
Requests go from Asana directly to an App's server. The App Server controls
the information within these customized widgets and the App Server controls what
happens when a User takes actions within these components.
A new in-app gallery and install flow, a customizable modal, a widget, and more.

App Widget
BETA - For access, please see App Components Beta
Request to the App Server
https://app-server.com/widget?workspace=12345&task=23456&user=34567&locale=en&attachment=45678&asset=56789&expires_at=2011-10-05T14%3A48%3A00.000Z&resource_url=https%3A%2F%2Fcompany.atlassian.net%2Fissue%2F1254
Response from the App Server
{
"template": "summary_with_details_v0",
"data": {
"title": "MSB-3 As a user, I see a flexible widget",
"subtitle": "Jira Cloud Story · Open in Jira Cloud",
"subicon_url": "https://jira.com/icons/subicon.png",
"footer": "Last updated in Jira Cloud 10 minutes ago",
"comment_count": 12,
"fields": [
{
"name": "Status",
"type": "pill",
"text": "In Progress",
"color": "blue"
},
{
"name": "Priority",
"type": "value_with_icon",
"icon_url": "https://jira.com/icons/priority_highest.png",
"text": "Highest"
},
{
"name": "Assignee",
"type": "value_with_icon",
"icon_url": "https://jira.com/avatars/rhian.png",
"text": "Rhian Sheehan"
}
]
}
}

An App Widget displays external data within Asana. The contents of a
widget may change, but the overall format stays consistent across apps.
Apps can control what layout they prefer by supplying their preferred
template. You can see the available templates in the Enumerated Values
section of response schema.
The App Server controls the content of this widget. When an Asana user's browser navigates to a widget, Asana sends a request to the registered App Server. As long as the response from the server is valid (like the example on the right), the widget will display.
How does Asana determine when a widget should be shown? When a task is opened in
Asana, it checks each attachment on the task. If an attachment has a url
that fits with an App's registered match url (ex: https:\/\/.*.atlassian.net\/.*)
then it shows a widget. A GET request is sent to the App's widget url, including
URL parameters like task, user, and workspace.
Related References:
App Form
BETA - For access, please see App Components Beta
Request to the App Server
https://app-server.com/form?workspace=12345&task=23456&user=34567&locale=en&expires_at=2011-10-05T14%3A48%3A00.000Z
Response from the App Server
{
"title": "Create New Issue",
"on_submit_callback": "https://app-server.com/actions/create",
"submit_button_text": "Create Issue",
"fields": [
{
"type": "single_line_text",
"name": "summary",
"title": "Summary",
"value": "",
"placeholder": "Enter some text",
"width": "full",
"is_required": true
},
{
"type": "rich_text",
"name": "description",
"title": "Description",
"value": "",
"placeholder": "",
"is_required": true
},
{
"type": "typeahead",
"name": "jira-project",
"title": "Jira project",
"value": "",
"placeholder": "Search Jira for a project...",
"is_required": true,
"typeahead_url": "https://app-server.com/jira/project/typeahead",
},
{
"type": "checkboxes",
"name": "attachments",
"is_required": false,
"options": [
{
"id": "shouldIncludeAttachments",
"label": "Attach files from this Asana task"
}
]
}
]
}

An App Form allows users to fill out a dynamic app-controlled list of fields. The # of fields can range from 0-20. Once a form is submitted, the information is sent to the App Server and Asana will perform different functionality depending on what they responded with. If the App wants to cause additional changes within Asana, the App Server will need to make the changes via the API.
An advanced feature of App Forms is live on_change events. While a user is filling out a form,
the App Server can receive on_change requests. These requests include what the user has changed, and
allow the App Server to respond with an updated form. Apps can build complex branching logic depending
on changes a user makes.
To take advantage of on_change events, set some form fields is_watched value to true and an on_change_callback
endpoint to hit with updates.
See the on_change field in the response to the
form metadata request. The request sent to that
endpoint is the On change callback request.
Related References:
Widget Resource Searching
BETA - For access, please see App Components Beta
Request to the App Server
https://app-server.com/resource-search?value=Cool&workspace=12345&task=23456&user=34567&locale=en&expires_at=2011-10-05T14%3A48%3A00.000Z
Response from the App Server
{
"resource_name": "Cool Attachment",
"resource_url": "https://localhost:5000/attachments/123456789"
}

Users can send a search term to the app server. The term is often a url or the title of an external resource. The app server then responds with a resource or an error.
Related References:
App Action
BETA - For access, please see App Components BETA
Request to the App Server
https://app-server.com/rule?workspace=12345&project=23456&action_type=45678&action=56789&user=34567&locale=en&expires_at=2011-10-05T14%3A48%3A00.000Z
Response from the App Server
{
"on_submit_callback": "https://app-server.com/slack/action/onsubmit",
"on_change": {
"on_change_callback": "https://app-server.com/slack/action/onchange",
},
"fields": [
{
"title": "Choose a channel",
"type": "typeahead",
"id": "typeahead_full_width",
"is_watched": true,
"is_required": true,
"typeahead_url": "https://app-server.com/slack/typeahead"
},
{
"title": "Write a message",
"type": "rich_text",
"name": "description",
"is_required": true
}
]
}

An App Action allows users to customize app actions triggered by Asana's rule engine. They use the same functionality as
the App Form, as Asana requests a form definition from the App Server. The app controls the form
fields, handles on_change events, and stores the inputs of the form. When a rule is created, Asana sends a request to
the App Server with the user-specified inputs. When the rule is triggered, Asana sends an event to the App Server.
App actions are a part of Asana Rules.
Related References:
App Components Definition
BETA - For access, please see App Components Beta
Sample of an app with a full App Components definition
{
identifier: "jira",
name: "Jira Cloud",
description: "Short description of the app.",
extendedDescription: "A long description of the functionality of the app and the value it provides for users.",
features: [
{
src: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/create.svg",
alt: "Create issue dialog",
text: "Kick off new work by creating Jira issues from Asana.",
},
{
src: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/sync.svg",
alt: "Syncing Jira Widget",
text: "Add issues to Asana tasks to sync the status from Jira.",
},
{
src: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/visibility.svg",
alt: "Person surrounded by issues",
text: "Add visibility for stakeholders to reduce status meetings.",
},
],
siteUrl: "https://jira-asana-integration.asana.com",
appDirectoryUrl: "https://www.asana.com/apps/jiracloud",
authenticationUrl: "https://jira-asana-integration.asana.com/auth",
icon: {
x32: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/jira_cloud_32.png",
x64: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/jira_cloud_64.png",
x96: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/jira_cloud_96.png",
x192: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/jira_cloud_192.png",
},
logo: "https://abcdefghijklmnop.cloudfront.net/obj/56fd875687fa6875fda7f586dsa/Jira-full.png",
capabilities: [
{
type: "ResourceSearch",
resourceTypeaheadUrl: "https://jira-asana-integration.asana.com/project/typeahead",
resourceAttachUrl: "https://jira-asana-integration.asana.com/actions/attach"
},
{
type: "ResourceWidget",
widgetMetadataUrl: "https://jira-asana-integration.asana.com/issue/widget",
matchUrlPattern: "https:\\/\\/.*.atlassian.net\\/.*"
},
{
type: "CreateResource",
formMetadataUrl: "https://jira-asana-integration.asana.com/actions/form",
formOnChangeUrl: "https://jira-asana-integration.asana.com/actions/form/onchange",
formOnSubmitUrl: "https://jira-asana-integration.asana.com/actions/create",
},
],
authModalMetadata: {
title: "Drive visibility & transparency across teams",
subtitle: "Here's what you can do in Asana with the Jira Cloud app.",
buttonText: "Get started",
},
coachmarkText: "Add or create new Jira issues on any task in this project.",
actionsMenuTitle: "Add Jira Issue",
feedbackLink: "https://form-beta.asana.com?hash=6da775cf552078ee2299eda9309d22f32239aa29900b5b9330cd57891e7d6068&id=1148560723305775",
externalSupportUrl: "https://asana.com/guide/help/api/jira",
}
To create an app with App Components, you will need to create an OAuth App and request the App Components functionality onto it via the Create an App Components App form.
To create an OAuth app, see Authentication Quick Start.
To create an App Components app you'll need to fill out the Create an App Components App form with the data in the table below.
| Field | Type | Description | |
description | String | A short description of the app shown in the app gallery. | |
extendedDescription | String | An extended description of the functionality of the app shown in the app settings. | |
features | Object | A list of feature descriptions used to illustrate the functionality of the app in marketing views. | |
siteUrl | String (url) | A URL which informs Asana which domain will handle auth | |
authenticationUrl | String (url) | A URL which informs Asana where to make requests for authenticating and authorizing users. This is called during installation or when the app returns a response indicating the user must authenticate to continue. | |
icon | Object | A collection of URLs pointing to icon assets of various sizes. Used to display icons of the app in the Asana UI. Note: This field is experimental. We may move to managing uploading and displaying these assets instead of allowing developers to specify them as a url in the app definition. | |
capabilities | Object | A list of capabilities supported by the app and their configuration. | |
logo | String (url) | A link to the image of the App logo. Appears in the app installation modal | |
authModalMetadata | Object | Information about the text displayed in the auth modal | |
coachmarkText | String | Text displayed to new users to inform them about the app’s capabilities. | |
actionsMenuTitle | String | Text displayed in the app field in the task pane | |
feedbackLink | String (url) | Link to a form for collecting feedback about the app. | |
externalSupportUrl | String (url) | Link to page where users can learn more about the app, access detailed setup instructions, or get support. |
Once your app is submitted, an Asana Developer will enable your app and notify you via email when it's ready to use.
App Components Guidelines
BETA - For access, please see App Components Beta
Apps built on App Components are manually reviewed before they are accessible within Asana. To ensure a smooth review process and user experience, here are some guidelines you can follow.
When submitting an app definition, you should:
- Add necessary images (e.g., feature images, icon, logo, etc.)
- Add support links (e.g., feedback link, external support URL)
- Proof-read marketing-related text (e.g., description, extended description, features)
- Make sure button text has 3-4 words or fewer and start with a verb
- Use consistent language for similar concepts (where applicable)
- Use sentence case by default and capitalize proper nouns
When testing your application, you should:
- Try to "break" your forms (e.g., test watched fields, limit invalid submissions, test typeahead fetches, etc.)
- Test and proof-read any custom error messages
- Test the auth flow from both the web browser and desktop app
- Test app actions with a variety of trigger combinations
App Components Security
App Components Security Checklist
BETA - For access, please see App Components Beta
When handling requests from Asana, an App Components app should:
- Reject requests with missing or incorrect signatures.
- Reject requests with an "expires" time in the past.
- Note: Make sure to use the correct units for this. "expires" is in milliseconds. If you compare the expiration time to a timestamp in seconds, it will always look like the request expires thousands of years in the future.
If an app uses OAuth for authentication, the app should:
- Prevent OAuth CSRF attacks. This is often done using a one-time CSRF token in the "state" parameter. This can also be done using PKCE instead, if it's supported.
If an app doesn't use OAuth for authentication, the Asana Security Team should manually review the authentication scheme the app uses. In particular, we will try to verify that:
- An attacker can't authenticate themselves as someone else
- An attacker can't force a victim to authenticate as another user (eg. with a CSRF attack)
App Components Authorization
BETA - For access, please see App Components Beta
Authorization is handled by the app. When an app with App Components is added to a project, the user adding it is sent
to the App's authenticationUrl. The App may perform OAuth with Asana, OAuth with a different app, perform both, or
perform none!
As long as the app confirms the flow was complete, Asana will successfully add the app to the project. This will allow requests to be sent to the App's pre-defined endpoints.
If the App wants additional data from Asana or wants to make changes within Asana, they should have the user complete an OAuth flow against Asana (see https://developers.asana.com/docs/oauth).
Keep in mind, this authorization provides the App Server with a single user's auth token. Multiple users of Asana will hit the UI Hooks and send requests to the App Server, but the server will likely only have the token for 1 user. It might be a good idea to suggest users authenticate with a bot account.
App Components Message Integrity
BETA - For access, please see App Components Beta
Message integrity is provided by a SHA-256 HMAC signature on the contents of the request. This is URL parameters in the case of GET requests and a JSON blob in the case of a POST request. The signature is transmitted via a header. The app calculates the same signature and compares that to the value in the header, rejecting the request if the two do not match. The signature must be on the exact parameter string that will be passed to the app because the signature will change if something as trivial as spacing changes.
The burden of verifying the request is on the app. Without this check, attackers can send requests to the App Server pretending to be Asana.
App Components Timeliness
BETA - For access, please see App Components Beta
Timeliness is provided by the addition of an expiration parameter. If this parameter were not added then a request recorded, such as in logs, could be reused to continue to request information from the app at a later time.
The burden of verifying the request has not expired is on the app. Without this check, the App Server is vulnerable to replay attacks.
App Components Quick Start
BETA - For access, please see App Components Beta
This guide offers a quick way for developers to start building on App Components. By following these steps, you'll gain an understanding of how to install App Component apps to your developer sandbox, as well as how an example app communicates with endpoints exposed on a pre-built local server.
Note that for the App Components apps that you create, you'll be able to define your own icons, images, descriptions, and other content. Many of the values for these fields are marked by {curly braces} in the example app.
Before you begin, you'll need a developer sandbox in order to use App Components in your application. Click here to request a sandbox if you don't already have one.
- Clone this repository containing an example Express server.
- Follow the instructions in the README to run the server. This server needs to remain on as you use the example app.
- Open the developer sandbox in your browser.
- In an existing project, go to Customize > Apps > {Example} to install the App Components example app.
- Once the example app is installed, create a task in your project. In the task's {Example} custom field, go to {Add Example Resource} > {Open form} to see examples of customizable inputs. Click Submit.
- View the newly-generated widget on your task. You can begin editing
index.jsto modify the contents of the widget. Note that you'll need to restart the local server and reload the page to see your changes.
That's it! At this point, feel free to keep exploring how changes in the server affects data in the task's widget. Once you're ready to define an app, click here to create your own app with App Components.
App Component Reference
BETA - For access, please see App Components Beta
Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.
This is the interface for handling requests for App Components. This reference is generated from an OpenAPI spec.
Base URLs:
App Forms
BETA - For access, please see App Components Beta
GET /{form_metadata_url}
POST /{on_change_callback}
POST /{on_submit_callback}
The creation form is displayed when the user starts the flow to create a resource. Asana will make a signed request to the specified form_metadata_url in the capabilities, and expect a response with the metadata needed to create the form. This process is also used for forms within rules.
Get form metadata
BETA - For access, please see App Components Beta
Code samples
curl -X GET {siteUrl}/{form_metadata_url}?workspace=string&task=string&user=string&expires_at=string \
-H 'Accept: application/json'
200 Response
{
"metadata": {
"fields": [
{
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
],
"on_change_callback": "https://www.example.com/on_change",
"on_submit_callback": "https://www.example.com/on_submit",
"submit_button_text": "Create New Issue",
"title": "Create New Issue"
},
"template": "form_metadata_v0"
}
See Input/Output Options to include more fields in your response.
GET /{form_metadata_url}
Get the metadata from the App Server to render a form.
Parameters
| Name | Description | |
| ?workspace string required | The workspace gid this hook is coming from. | |
| ?task string required | The task gid this hook is coming from. | |
| ?user string required | The user gid this hook is coming from. | |
| ?expires_at string required | The time (in ISO-8601 date format) when the request should expire |
Responses
| Status | Description | ||||
| 200 FormMetadata | Successfully retrieved the metadata for a single form. | ||||
| ↓ Show Common Responses ↓ | |||||
On change callback
BETA - For access, please see App Components Beta
Code samples
curl -X POST {siteUrl}/{on_change_callback} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"changed_field": "string",
"expires_at": "string",
"task": "string",
"user": "string",
"workspace": "string"
}
200 Response
{
"metadata": {
"fields": [
{
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
],
"on_change_callback": "https://www.example.com/on_change",
"on_submit_callback": "https://www.example.com/on_submit",
"submit_button_text": "Create New Issue",
"title": "Create New Issue"
},
"template": "form_metadata_v0"
}
See Input/Output Options to include more fields in your response.
POST /{on_change_callback}
The callback request made to an App Server when a watched field's value changes within a form.
Parameters
| Name | Description | |
| body object required | Request to notify of an on change event. |
Responses
| Status | Description | ||||
| 200 FormMetadata | Successfully returned the new state of the form. | ||||
| ↓ Show Common Responses ↓ | |||||
On submit callback
BETA - For access, please see App Components Beta
Code samples
curl -X POST {siteUrl}/{on_submit_callback} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"expires_at": "string",
"task": "string",
"user": "string",
"values": {
"property1": {
"field_name": "string",
"field_object": {
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
},
"property2": {
"field_name": "string",
"field_object": {
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
}
},
"workspace": "string"
}
200 Response
{
"error": "No resource matched that input",
"resource_name": "Build the Thing",
"resource_url": "https://example.atlassian.net/browse/CP-1"
}
See Input/Output Options to include more fields in your response.
POST /{on_submit_callback}
The callback request made to an App Server when a form is submitted.
Parameters
| Name | Description | |
| body object required | Request to notify of a form submission. |
Enumerated Values
| Parameter | Value | |
| type | single_line_text | |
| type | multi_line_text | |
| type | rich_text | |
| type | static_text | |
| type | dropdown | |
| type | checkbox | |
| type | radio_button | |
| type | date | |
| type | datetime | |
| type | typeahead | |
| width | full | |
| width | half |
Responses
| Status | Description | ||||
| 200 AttachedResource | Successfully attached the resource created by the form. | ||||
| ↓ Show Common Responses ↓ | |||||
App Rules
BETA - For access, please see App Components Beta
POST /{run_action_url}
GET /{action.metadata_url}
POST /{action.on_change_callback}
POST /{action.on_submit_callback}
When a rule containing an app action is triggered, the Rules Engine will make a request to the app to inform the app to run the configured app action. The resulting status code will indicate to the Rules Engine whether the action was successfully completed and, if not, specify a cause for the error.
Run action
BETA - For access, please see App Components Beta
Code samples
curl -X POST {siteUrl}/{run_action_url} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"action": "string",
"action_type": "string",
"expires_at": "string",
"idempotency_key": "string",
"target_object": "string",
"user": "string",
"workspace": "string"
}
200 Response
{
"action_result": "ok",
"error": "That resource no longer exists",
"resources_created": [
{
"error": "No resource matched that input",
"resource_name": "Build the Thing",
"resource_url": "https://example.atlassian.net/browse/CP-1"
}
]
}
See Input/Output Options to include more fields in your response.
POST /{run_action_url}
The request made when an action is triggered.
Parameters
| Name | Description | |
| body object required | Request to notify of an action running. |
Responses
| Status | Description | ||||
| 200 RanAction | Successfully attached the resource created by the form. | ||||
| ↓ Show Common Responses ↓ | |||||
Get action metadata
BETA - For access, please see App Components Beta
Code samples
curl -X GET {siteUrl}/{action.metadata_url}?action_type=string&project=string&workspace=string&user=string&expires_at=string \
-H 'Accept: application/json'
200 Response
{
"metadata": {
"fields": [
{
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
],
"on_change_callback": "https://www.example.com/on_change",
"on_submit_callback": "https://www.example.com/on_submit",
"submit_button_text": "Create New Issue",
"title": "Create New Issue"
},
"template": "form_metadata_v0"
}
See Input/Output Options to include more fields in your response.
GET /{action.metadata_url}
When a user has navigated to the Custom Rule Builder UI and selected an App Action (either through the sidebar or via a Rule Preset), Asana will make a request to the app to get the configuration form definition for the chosen app action. This will initiate the flow to configure a new app action or edit the configuration of an existing app action. This is the endpoint and schema for updating app actions; app triggers (V2) will be analogous.
Parameters
| Name | Description | |
| ?action string | The id of an existing app action that is being edited. Should be omitted when configuring a new app action. | |
| ?action_type string required | The id of the configuration used to create the app action | |
| ?project string required | The project gid this hook is coming from. | |
| ?workspace string required | The workspace gid this hook is coming from. | |
| ?user string required | The user gid this hook is coming from. | |
| ?expires_at string required | The time (in ISO-8601 date format) when the request should expire |
Responses
| Status | Description | ||||
| 200 FormMetadata | Successfully retrieved the metadata for a single action. | ||||
| ↓ Show Common Responses ↓ | |||||
On action change callback
BETA - For access, please see App Components Beta
Code samples
curl -X POST {siteUrl}/{action.on_change_callback} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"action": "string",
"action_type": "string",
"changed_field": "string",
"expires_at": "string",
"user": "string",
"workspace": "string"
}
200 Response
{
"metadata": {
"fields": [
{
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
],
"on_change_callback": "https://www.example.com/on_change",
"on_submit_callback": "https://www.example.com/on_submit",
"submit_button_text": "Create New Issue",
"title": "Create New Issue"
},
"template": "form_metadata_v0"
}
See Input/Output Options to include more fields in your response.
POST /{action.on_change_callback}
The callback request made to an App Server when a watched field's value changes within an action form.
Parameters
| Name | Description | |
| body object required | Request to notify of an on change event. |
Responses
| Status | Description | ||||
| 200 FormMetadata | Successfully returned the new state of the form. | ||||
| ↓ Show Common Responses ↓ | |||||
On action submit callback
BETA - For access, please see App Components Beta
Code samples
curl -X POST {siteUrl}/{action.on_submit_callback} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"action": "string",
"action_type": "string",
"expires_at": "string",
"rule_name": "string",
"task": "string",
"user": "string",
"values": {
"property1": {
"field_name": "string",
"field_object": {
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
},
"property2": {
"field_name": "string",
"field_object": {
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
}
},
"workspace": "string"
}
400 Response
{
"metadata": {
"fields": [
{
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
],
"on_change_callback": "https://www.example.com/on_change",
"on_submit_callback": "https://www.example.com/on_submit",
"submit_button_text": "Create New Issue",
"title": "Create New Issue"
},
"template": "form_metadata_v0"
}
See Input/Output Options to include more fields in your response.
POST /{action.on_submit_callback}
The form is submitted when the user chooses to create their Rule. Asana will create the app action data model object and make a signed request to the on_submit_callback specified in the form metadata returned from the fetch/update app rule form endpoints. Information about the created app action should be included in the response if it was successfully created. This is the endpoint and schema for updating app actions; app triggers (V2) will be analogous.
Parameters
| Name | Description | |
| body object required | Request to submit an action form. |
Enumerated Values
| Parameter | Value | |
| type | single_line_text | |
| type | multi_line_text | |
| type | rich_text | |
| type | static_text | |
| type | dropdown | |
| type | checkbox | |
| type | radio_button | |
| type | date | |
| type | datetime | |
| type | typeahead | |
| width | full | |
| width | half |
Responses
| Status | Description | ||||
| 200 None | Successfully handled form submission. | ||||
| ↓ Show Common Responses ↓ | |||||
App Resource Searching
BETA - For access, please see App Components Beta
POST /{resource_search_url}
If the app defined a search url, tasks without a widget offer the search functionality. This appears as a text input to the user. When the user submits the text, the app responds with either an attachment or an error.
Resource Search
BETA - For access, please see App Components Beta
Code samples
curl -X POST {siteUrl}/{resource_search_url} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"attachment": "string",
"expires_at": "string",
"query": "string",
"task": "string",
"user": "string",
"workspace": "string"
}
200 Response
{
"error": "No resource matched that input",
"resource_name": "Build the Thing",
"resource_url": "https://example.atlassian.net/browse/CP-1"
}
See Input/Output Options to include more fields in your response.
POST /{resource_search_url}
The search request made to an App Server when the search field is submitted.
Parameters
| Name | Description | |
| body object required | Request to attach a resource with a user given value. |
Responses
| Status | Description | ||||
| 200 AttachedResource | Successfully attached the resource created by the form. | ||||
| ↓ Show Common Responses ↓ | |||||
App Widgets
BETA - For access, please see App Components Beta
GET /{widget_metadata_url}
POST /{resource_attach_url}
The widget is displayed when the user views a task with an attachment with a resource URL matching your capability’s match_url_pattern. When this happens, Asana will make a signed request to your widget_metadata_url, and expect a response with information to build the widget.
Get widget metadata
BETA - For access, please see App Components Beta
Code samples
curl -X GET {siteUrl}/{widget_metadata_url}?resource_url=string&workspace=string&task=string&user=string&attachment=string&expires_at=string \
-H 'Accept: application/json'
200 Response
{
"metadata": {
"error": "The resource cannot be accessed",
"fields": [
{
"color": "gray",
"icon_url": "https://example-icon.png",
"name": "Status",
"text": "To Do",
"timestamp": "2012-02-22T02:06:58.147Z",
"type": "pill"
}
],
"footer": {
"created_at": "2012-02-22T02:06:58.147Z",
"footer_type": "custom_text",
"icon_url": "https://example-icon.png",
"info": "This is a custom footer message",
"last_updated_at": "2012-02-22T02:06:58.147Z"
},
"num_comments": 2,
"subicon_url": "https://example-icon.png",
"subtitle": "Custom App Story · Open in Custom App",
"title": "Status"
},
"template": "summary_with_details_v0"
}
See Input/Output Options to include more fields in your response.
GET /{widget_metadata_url}
Get the metadata from the App Server to render a widget.
Parameters
| Name | Description | |
| ?resource_url string required | The URL of the URL attachment on the task (i.e. Jira issue, GitHub pull request) | |
| ?workspace string required | The workspace gid this hook is coming from. | |
| ?task string required | The task gid this hook is coming from. | |
| ?user string required | The user gid this hook is coming from. | |
| ?attachment string required | The attachment id of the URL attachment | |
| ?expires_at string required | The time (in ISO-8601 date format) when the request should expire |
Responses
| Status | Description | ||||
| 200 WidgetMetadata | Successfully retrieved the metadata for a single widget. | ||||
| 418 None | Unauthorized | ||||
| ↓ Show Common Responses ↓ | |||||
Attach resource
BETA - For access, please see App Components Beta
Code samples
curl -X POST {siteUrl}/{resource_attach_url} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"attachment": "string",
"expires_at": "string",
"query": "string",
"task": "string",
"user": "string",
"workspace": "string"
}
200 Response
{
"error": "No resource matched that input",
"resource_name": "Build the Thing",
"resource_url": "https://example.atlassian.net/browse/CP-1"
}
See Input/Output Options to include more fields in your response.
POST /{resource_attach_url}
When the user attaches a resource URL to a task, Asana will make a signed request to the specified resource_attach_url in the capabilities. Information about the attached resource should be included in the response.
Parameters
| Name | Description | |
| body object required | Request to attach a resource. |
Responses
| Status | Description | ||||
| 200 AttachedResource | Successfully attached the resource to the given object. | ||||
| ↓ Show Common Responses ↓ | |||||
App Component Schemas
BETA - For access, please see App Components BETA
The schema definitions for each object requested or returned from Asana's API. Some fields are not returned by default and you'll need to use Input/Output Options to include them.
AttachedResource
BETA - For access, please see App Components Beta
{
"error": "No resource matched that input",
"resource_name": "Build the Thing",
"resource_url": "https://example.atlassian.net/browse/CP-1"
}
The response to a successful attach request.
Properties
| Name | Description | |
| error string | The error that should be displayed to the user | |
| resource_name string | The name of the attached resource | |
| resource_url string | The URL of the attached resource |
FormMetadata
BETA - For access, please see App Components Beta
{
"metadata": {
"fields": [
{
"id": "item-description",
"is_required": true,
"is_watched": true,
"name": "Item Description",
"options": [
{
"icon_url": "some-icon.png",
"id": "opt-in",
"label": "Opt in to emails."
}
],
"placeholder": "Type description here...",
"type": "single_line_text",
"value": "It's over 9000",
"width": "full"
}
],
"on_change_callback": "https://www.example.com/on_change",
"on_submit_callback": "https://www.example.com/on_submit",
"submit_button_text": "Create New Issue",
"title": "Create New Issue"
},
"template": "form_metadata_v0"
}
Contains the metadata that describes how to display and manage a form
Properties
| Name | Description | |
| metadata object | none | |
| template string | none |
Enumerated Values
| Property | Value | |
| type | single_line_text | |
| type | multi_line_text | |
| type | rich_text | |
| type | static_text | |
| type | dropdown | |
| type | checkbox | |
| type | radio_button | |
| type | date | |
| type | datetime | |
| type | typeahead | |
| width | full | |
| width | half | |
| template | form_metadata_v0 |
RanAction
BETA - For access, please see App Components Beta
{
"action_result": "ok",
"error": "That resource no longer exists",
"resources_created": [
{
"error": "No resource matched that input",
"resource_name": "Build the Thing",
"resource_url": "https://example.atlassian.net/browse/CP-1"
}
]
}
The response to an action request.
Properties
| Name | Description | |
| action_result string | Specifies any additional information that the app wants to send to Asana on completion of the action. Can only be resources_created or ok. | |
| error string | The error that should be displayed to the user | |
| resources_created [object] | A field with the data corresponding to the action_result value. Each action_result has its own data field shape that Asana expects. resources_created expects the name and url of the resources that the action created. |
Enumerated Values
| Property | Value | |
| action_result | resources_created | |
| action_result | ok |
TypeaheadItem
BETA - For access, please see App Components Beta
{
"icon_url": "https://example-icon.png",
"subtitle": "OTP",
"title": "OTP Team PF",
"value": "OTP"
}
An object describing a typeahead result
Properties
| Name | Description | |
| icon_url string | The URL of the icon to display next to the title | |
| subtitle string | The subtitle of the typeahead item | |
| title string | The title of the typeahead item | |
| value string | The value of the typeahead item |
WidgetMetadata
BETA - For access, please see App Components Beta
{
"metadata": {
"error": "The resource cannot be accessed",
"fields": [
{
"color": "gray",
"icon_url": "https://example-icon.png",
"name": "Status",
"text": "To Do",
"timestamp": "2012-02-22T02:06:58.147Z",
"type": "pill"
}
],
"footer": {
"created_at": "2012-02-22T02:06:58.147Z",
"footer_type": "custom_text",
"icon_url": "https://example-icon.png",
"info": "This is a custom footer message",
"last_updated_at": "2012-02-22T02:06:58.147Z"
},
"num_comments": 2,
"subicon_url": "https://example-icon.png",
"subtitle": "Custom App Story · Open in Custom App",
"title": "Status"
},
"template": "summary_with_details_v0"
}
An object containing information about the widget
Properties
| Name | Description | |
| metadata object | none | |
| template string | none |
Enumerated Values
| Property | Value | |
| color | none | |
| color | red | |
| color | orange | |
| color | yellow-orange | |
| color | yellow | |
| color | yellow-green | |
| color | green | |
| color | blue-green | |
| color | aqua | |
| color | blue | |
| color | indigo | |
| color | purple | |
| color | magenta | |
| color | hot-pink | |
| color | pink | |
| color | cool-gray | |
| type | pill | |
| type | text_with_icon | |
| type | datetime_with_icon | |
| footer_type | custom_text | |
| footer_type | updated | |
| footer_type | created | |
| template | summary_with_details_v0 |
API Reference
Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.
This is the interface for interacting with the Asana Platform. Our API reference is generated from our OpenAPI spec.
Base URLs:
Attachments
GET /attachments/{attachment_gid}
DELETE /attachments/{attachment_gid}
GET /tasks/{task_gid}/attachments
POST /tasks/{task_gid}/attachments
An attachment object represents any file attached to a task in Asana, whether it’s an uploaded file or one associated via a third-party service such as Dropbox or Google Drive.
Get an attachment
Code samples
curl -X GET https://app.asana.com/api/1.0/attachments/{attachment_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "attachment",
"name": "Screenshot.png",
"resource_subtype": null,
"created_at": "2012-02-22T02:06:58.147Z",
"download_url": "https://s3.amazonaws.com/assets/123/Screenshot.png",
"host": "dropbox",
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"view_url": "https://www.dropbox.com/s/123/Screenshot.png"
}
}
See Input/Output Options to include more fields in your response.
GET /attachments/{attachment_gid}
Get the full record for a single attachment.
Parameters
| Name | Description | ||||
| /attachment_gid string required | Globally unique identifier for the attachment. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Attachment | Successfully retrieved the record for a single attachment. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete an attachment
Code samples
curl -X DELETE https://app.asana.com/api/1.0/attachments/{attachment_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /attachments/{attachment_gid}
Deletes a specific, existing attachment.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /attachment_gid string required | Globally unique identifier for the attachment. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified attachment. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get attachments for a task
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid}/attachments \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "attachment",
"name": "Screenshot.png",
"resource_subtype": null
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}/attachments
Returns the compact records for all attachments on the task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 AttachmentCompact | Successfully retrieved the compact records for all attachments on the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Upload an attachment
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/attachments \
-H 'Content-Type: multipart/form-data' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
file: string
name: string
resource_subtype: text
url: string
200 Response
{
"data": {
"gid": "12345",
"resource_type": "attachment",
"name": "Screenshot.png",
"resource_subtype": null,
"created_at": "2012-02-22T02:06:58.147Z",
"download_url": "https://s3.amazonaws.com/assets/123/Screenshot.png",
"host": "dropbox",
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"view_url": "https://www.dropbox.com/s/123/Screenshot.png"
}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/attachments
Upload an attachment.
This method uploads an attachment to a task and returns the compact record for the created attachment object. It is not possible to attach files from third party services such as Dropbox, Box & Google Drive via the API. You must download the file content first and then upload it as any other attachment.
The 100MB size limit on attachments in Asana is enforced on this endpoint.
This endpoint expects a multipart/form-data encoded request containing the full contents of the file to be uploaded.
Requests made should follow the HTTP/1.1 specification that line
terminators are of the form CRLF or \r\n outlined
here
in order for the server to reliably and properly handle the request.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The file you want to upload. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
body: The file you want to upload.
Note when using curl:
Be sure to add an ‘@’ before the file path, and use the --form
option instead of the -d option.
When uploading PDFs with curl, force the content-type to be pdf by
appending the content type to the file path: --form
"file=@file.pdf;type=application/pdf".
Enumerated Values
| Parameter | Value | |
| resource_subtype | asana_file_attachments | |
| resource_subtype | external |
Responses
| Status | Description | ||||
| 200 Attachment | Successfully uploaded the attachment to the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Batch API
POST /batch
There are many cases where you want to accomplish a variety of work in the Asana API but want to minimize the number of HTTP requests you make. For example:
- Modern browsers limit the number of requests that a single web page can make at once.
- Mobile apps will use more battery life to keep the cellular radio on when making a series of requests.
- There is an overhead cost to developing software that can make multiple requests in parallel.
- Some cloud platforms handle parallelism poorly, or disallow it entirely.
To make development easier in these use cases, Asana provides a batch API that enables developers to perform multiple “actions” by making only a single HTTP request.
Making a Batch Request
To make a batch request, send a POST request to /batch. Like other POST endpoints, the body should contain a data envelope. Inside this envelope should be a single actions field, containing a list of “action” objects. Each action represents a standard request to an existing endpoint in the Asana API.
The maximum number of actions allowed in a single batch request is 10. Making a batch request with no actions in it will result in a 400 Bad Request.
When the batch API receives the list of actions to execute, it will dispatch those actions to the already-implemented endpoints specified by the relative_path and method for each action. This happens in parallel, so all actions in the request will be processed simultaneously. There is no guarantee of the execution order for these actions, nor is there a way to use the output of one action as the input of another action (such as creating a task and then commenting on it).
The response to the batch request will contain (within the data envelope) a list of result objects, one for each action. The results are guaranteed to be in the same order as the actions in the request, e.g., the first result in the response corresponds to the first action in the request.
The batch API will always attempt to return a 200 Success response with individual result objects for each individual action in the request. Only in certain cases (such as missing authorization or malformed JSON in the body) will the entire request fail with another status code. Even if every individual action in the request fails, the batch API will still return a 200 Success response, and each result object in the response will contain the errors encountered with each action.
Rate Limiting
The batch API fully respects all of our rate limiting. This means that a batch request counts against both the standard rate limiter and the concurrent request limiter as though you had made a separate HTTP request for every individual action. For example, a batch request with five actions counts as five separate requests in the standard rate limiter, and counts as five concurrent requests in the concurrent request limiter. The batch request itself incurs no cost.
If any of the actions in a batch request would exceed any of the enforced limits, the entire request will fail with a 429 Too Many Requests error. This is to prevent the unpredictability of which actions might succeed if not all of them could succeed.
Restrictions
Not every endpoint can be accessed through the batch API. Specifically, the following actions cannot be taken and will result in a 400 Bad Request for that action:
- Uploading attachments
- Creating, getting, or deleting organization exports
- Any SCIM operations
- Nested calls to the batch API
Submit parallel requests
Code samples
curl -X POST https://app.asana.com/api/1.0/batch \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"actions": [
{
"data": {
"assignee": "me",
"workspace": "1337"
},
"method": "get",
"options": {
"fields": [
"name",
"notes",
"completed"
],
"limit": 3
},
"relative_path": "/tasks/123"
}
]
}
}
200 Response
{
"data": [
{
"body": {
"data": {
"completed": false,
"gid": "1967",
"name": "Hello, world!",
"notes": "How are you today?"
}
},
"headers": {
"location": "/tasks/1234"
},
"status_code": 200
}
]
}
See Input/Output Options to include more fields in your response.
POST /batch
Make multiple requests in parallel to Asana's API.
Parameters
| Name | Description | ||||
| body object required | The requests to batch together via the Batch API. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| method | get | |
| method | post | |
| method | put | |
| method | delete | |
| method | patch | |
| method | head |
Responses
| Status | Description | ||||
| 200 Batch | Successfully completed the requested batch API operations. | ||||
| ↓ Show Common Responses ↓ | |||||
Custom Fields
POST /custom_fields
GET /custom_fields/{custom_field_gid}
PUT /custom_fields/{custom_field_gid}
DELETE /custom_fields/{custom_field_gid}
GET /workspaces/{workspace_gid}/custom_fields
POST /custom_fields/{custom_field_gid}/enum_options
POST /custom_fields/{custom_field_gid}/enum_options/insert
PUT /enum_options/{enum_option_gid}
In the Asana application, Tasks, Projects, and Portfolios can hold user-specified Custom Fields which provide extra information; for example, a priority value or a number representing the time required to complete a Task. This lets a user define the type of information that each Item within a Project or Portfolio can contain in addition to the built-in fields that Asana provides.
Note: Custom Fields are a premium feature. Integrations which work with Custom Fields need to handle an assortment of use cases for free and premium users in context of free and premium organizations. For a detailed examination of to what data users will have access in different circumstances, read the section below on access control.
display_value is a read-only field that will always be a string. For apps that use custom fields, this is a great way to safely display/export the value of a custom field, regardless of its type. We suggest apps use this field in order to future-proof for changes to Custom Fields.
The characteristics of Custom Fields are:
- There is metadata that defines the Custom Field. This metadata can be shared across an entire workspace, or be specific to a Project or Portfolio.
- Creating a Custom Field Setting on a Project or Portfolio means each direct child will have the custom field. This is conceptually akin to adding columns in a database or a spreadsheet: every Task (row) in the Project (table) can contain information for that field, including "blank" values, i.e.
nulldata. For Portfolio custom fields, every Project (row) in the Portfolio (table) will contain information for the custom field. - Custom Field Settings only go one child deep. Meaning a custom field setting on a portfolio will give each project the custom field, but not each task within those projects.
- Tasks have Custom Field values assigned to them.
A brief example: let's imagine that an organization has defined a Custom Field for "Priority". This field is of enum type and can have user-defined values of Low, Medium, or High. This is the field metadata, and it is visible within, and shared across, the entire organization.
A Project is then created in the organization, called "Bugs", and the "Priority" Custom Field is associated with that Project. This will allow all Tasks within the "Bugs" Project to have an associated "Priority".
A new Task is created within "Bugs". This Task, then, has a field named "Priority" which can take on the Custom Field value of one of [null], Low, Medium, and High.
These Custom Fields are accessible via the API through a number of endpoints at the top level (e.g. /custom_fields and /custom_field_settings) and through calls on Workspaces, Portfolios, Projects, and Tasks resources. The API also provides a way to fetch both the metadata and data which define each particular Custom Field, so that a client application may render proper UI to display or edit the values.
Custom Field aware integrations need to be aware of the basic types that Custom Fields can adopt. These types are:
text- an arbitrary, relatively short string of textnumber- a number with a defined level of precisionenum- a selection from a defined list of options
Text fields are currently limited to 1024 characters. On Tasks, their Custom Field value will have a text_value property to represent this field.
Number fields can have an arbitrary precision associated with them; for example, a precision of 2 would round its value to the second (hundredths) place, i.e. 1.2345 would round to 1.23. On Tasks, the Custom Field value will have a number_value property to represent this field.
Enum fields represent a selection from a list of options. On the metadata, they will contain all of the options in an array. Each option has 4 properties:
gid- the gid of this enum option. Note that this is the gid of the option - the Custom Field itself has a separategid.name- the name of the option, e.g. "Choice #1"enabled- whether this field is enabled. Disabled fields are not available to choose from when disabled, and are visually hidden in the Asana application, but they remain in the metadata for Custom Field values which were set to the option before the option was disabled.color- a color associated with this choice.
On the Task's Custom Field value, the enum will have an enum_value property which will be the same as one of the choices from the list defined in the Custom Field metadata.
Querying an organization for its Custom Fields
For Custom Fields shared across the workspace or organization, the Workspace can be queried for its list of defined Custom Fields. Like other collection queries, the fields will be returned as a compact record; slightly different from most other compact records is the fact that the compact record for Custom Fields includes type as well as gid and name.
Accessing Custom Field definitions
The Custom Fields reference describes how the metadata which defines a Custom Field is accessed. A GET request with a gid can be issued on the /custom_fields endpoint to fetch the full definition of a single Custom Field given its gid from (for instance) listing all Custom Fields on a Workspace, or getting the gid from a Custom Field Settings object or a Task.
Associating Custom Fields with a Project or Portfolio
A mapping between a Custom Field and a Project or Portfolio is handled with a Custom Field Settings object. This object contains a reference for each of the Custom Field and the Project or Porfolio, as well as additional information about the status of that particular Custom Field. For instance, is_important, which defines whether or not the custom field will appear in the list/grid on the Asana application.
Accessing Custom Field values on Tasks or Projects
The Tasks reference has information on how Custom Fields look on Tasks. Custom Fields will return as an array on the property custom_fields, and each entry will contain, side-by-side, the compact representation of the Custom Field metadata and a {typename}_value property that stores the value set for the Custom Field.
Of particular note is that the top-level gid of each entry in the custom_fields array is the gid of the Custom Field metadata, as it is the compact representation of this metadata. This can be used to refer to the full metadata by making a request to the /custom_fields/{custom_fields_id} endpoint as described above.
Custom Fields can be set just as in the Asana-defined fields on a task via POST or PUT requests. You can see an example on the update a task endpoint.
Custom Fields on projects follow this same pattern.
Warning: Program defensively with regards to Custom Field definitions
Asana application users have the ability to change the definitions of Custom Field metadata. This means that as you write scripts or applications to work with them, it's possible for the definitions to change at any time, which may cause an application using them to break or malfunction if it makes assumptions about the metadata for a particular Custom Field. When using Custom Fields, it is a good idea to program defensively, meaning you your application should double-check that the Custom Field metadata is what it expects.
Storing the state of the Custom Field metadata for too long if you dynamically create a model for it can cause your model to become unsynchronized with the model stored in Asana. If you encounter (for example) an enum value on a Task that does not match any option in your metadata model, your metadata model has become out of date with the Custom Field metadata.
Note: We are currently studying proposals for future implementations to more elegantly handle the modification of Custom Field metadata for application integrations.
Enabled and Disabled Values
When information that is contained in a Custom Field value loses a logical association with its metadata definition, the value becomes disabled. This can happen in a couple of simple ways, for example, if you remove the Custom Field metadata from a Project, or move a Task with a Custom Field to a different Project which does not have the Custom Field metadata associated with it. The value remains on the Task, and the Custom Field metadata can still be found and examined, but as the context in which the Custom Field makes sense is gone, the Custom Field cannot change its value; it can only be cleared.
Note: Tasks that are associated with multiple Projects do not become disabled, so long as at least one of the Projects is still associated with the Custom Field metadata. In other words, Tasks with multiple Projects will retain logically associated to the set of Custom Field metadata represented by all of their Projects.
Moving the Task back under a Project with that Custom Field applied to it or applying the Custom Field metadata to the current Project will return the Custom Field value to an enabled state. In this scenario, the Custom Field will be re-enabled and editable again.
In the Asana application, disabled fields are grayed out and not allowed to change, other than to be discarded. In the API, we return a property enabled: false to inform the external application that the value has been disabled.
Note that the API enforces the same operations on disabled Custom Field values as hold in the Asana application: they may not have their values changed, since the lack of context for the values of a custom field in general doesn't provide enough information to know what new values should be. Setting the Custom Field value to null will clear and remove the Custom Field value from the Task.
Custom Field access control
Custom Fields are a complex feature of the Asana platform, and their access in the Asana application and in the API vary based on the status of the user and project. When building your application, it's best to be defensive and not assume the given user will have read or write access to a custom field, and fail gracefully when this occurs.
Create a custom field
Code samples
curl -X POST https://app.asana.com/api/1.0/custom_fields \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"enabled": true,
"enum_options": [
{
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"format": "custom",
"has_notifications_enabled": true,
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"workspace": "1331"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
}
See Input/Output Options to include more fields in your response.
POST /custom_fields
Creates a new custom field in a workspace. Every custom field is required to be created in a specific workspace, and this workspace cannot be changed once set.
A custom field’s name must be unique within a workspace and not conflict with names of existing task properties such as ‘Due Date’ or ‘Assignee’. A custom field’s type must be one of ‘text’, ‘enum’, or ‘number’.
Returns the full record of the newly created custom field.
Parameters
| Name | Description | ||||
| body object | The custom field object to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
precision: Only relevant for custom fields of type ‘Number’. This field dictates the number of places after the decimal to round to, i.e. 0 is integer values, 1 rounds to the nearest tenth, and so on. Must be between 0 and 6, inclusive. For percentage format, this may be unintuitive, as a value of 0.25 has a precision of 0, while a value of 0.251 has a precision of 1. This is due to 0.25 being displayed as 25%. The identifier format will always have a precision of 0.
Enumerated Values
| Parameter | Value | |
| custom_label_position | prefix | |
| custom_label_position | suffix | |
| format | currency | |
| format | identifier | |
| format | percentage | |
| format | custom | |
| format | none | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number |
Responses
| Status | Description | ||||
| 201 CustomField | Custom field successfully created. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a custom field
Code samples
curl -X GET https://app.asana.com/api/1.0/custom_fields/{custom_field_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
}
See Input/Output Options to include more fields in your response.
GET /custom_fields/{custom_field_gid}
Get the complete definition of a custom field’s metadata.
Since custom fields can be defined for one of a number of types, and these types have different data and behaviors, there are fields that are relevant to a particular type. For instance, as noted above, enum_options is only relevant for the enum type and defines the set of choices that the enum could represent. The examples below show some of these type-specific custom field definitions.
Parameters
| Name | Description | ||||
| /custom_field_gid string required | Globally unique identifier for the custom field. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 CustomField | Successfully retrieved the complete definition of a custom field’s metadata. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a custom field
Code samples
curl -X PUT https://app.asana.com/api/1.0/custom_fields/{custom_field_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"enabled": true,
"enum_options": [
{
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"format": "custom",
"has_notifications_enabled": true,
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"workspace": "1331"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
}
See Input/Output Options to include more fields in your response.
PUT /custom_fields/{custom_field_gid}
A specific, existing custom field can be updated by making a PUT request on the URL for that custom field. 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 custom field.
A custom field’s type cannot be updated.
An enum custom field’s enum_options cannot be updated with this endpoint. Instead see “Work With Enum Options” for information on how to update enum_options.
Locked custom fields can only be updated by the user who locked the field.
Returns the complete updated custom field record.
Parameters
| Name | Description | ||||
| /custom_field_gid string required | Globally unique identifier for the custom field. | ||||
| body object | The custom field object with all updated properties. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
precision: Only relevant for custom fields of type ‘Number’. This field dictates the number of places after the decimal to round to, i.e. 0 is integer values, 1 rounds to the nearest tenth, and so on. Must be between 0 and 6, inclusive. For percentage format, this may be unintuitive, as a value of 0.25 has a precision of 0, while a value of 0.251 has a precision of 1. This is due to 0.25 being displayed as 25%. The identifier format will always have a precision of 0.
Enumerated Values
| Parameter | Value | |
| custom_label_position | prefix | |
| custom_label_position | suffix | |
| format | currency | |
| format | identifier | |
| format | percentage | |
| format | custom | |
| format | none | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number |
Responses
| Status | Description | ||||
| 200 CustomField | The custom field was successfully updated. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a custom field
Code samples
curl -X DELETE https://app.asana.com/api/1.0/custom_fields/{custom_field_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /custom_fields/{custom_field_gid}
A specific, existing custom field can be deleted by making a DELETE request on the URL for that custom field. Locked custom fields can only be deleted by the user who locked the field. Returns an empty data record.
Parameters
| Name | Description | ||||
| /custom_field_gid string required | Globally unique identifier for the custom field. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | The custom field was successfully deleted. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get a workspace's custom fields
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/custom_fields \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}/custom_fields
Returns a list of the compact representation of all of the custom fields in a workspace.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 CustomField | Successfully retrieved all custom fields for the given workspace. | ||||
| ↓ Show Common Responses ↓ | |||||
Create an enum option
Code samples
curl -X POST https://app.asana.com/api/1.0/custom_fields/{custom_field_gid}/enum_options \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"color": "blue",
"enabled": true,
"insert_after": "12345",
"insert_before": "12345",
"name": "Low"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
}
See Input/Output Options to include more fields in your response.
POST /custom_fields/{custom_field_gid}/enum_options
Creates an enum option and adds it to this custom field’s list of enum options. A custom field can have at most 50 enum options (including disabled options). By default new enum options are inserted at the end of a custom field’s list. Locked custom fields can only have enum options added by the user who locked the field. Returns the full record of the newly created enum option.
Parameters
| Name | Description | ||||
| /custom_field_gid string required | Globally unique identifier for the custom field. | ||||
| body object | The enum option object to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 201 EnumOption | Custom field enum option successfully created. | ||||
| ↓ Show Common Responses ↓ | |||||
Reorder a custom field's enum
Code samples
curl -X POST https://app.asana.com/api/1.0/custom_fields/{custom_field_gid}/enum_options/insert \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"after_enum_option": "12345",
"before_enum_option": "12345",
"enum_option": "97285"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
}
See Input/Output Options to include more fields in your response.
POST /custom_fields/{custom_field_gid}/enum_options/insert
Moves a particular enum option to be either before or after another specified enum option in the custom field. Locked custom fields can only be reordered by the user who locked the field.
Parameters
| Name | Description | ||||
| /custom_field_gid string required | Globally unique identifier for the custom field. | ||||
| body object | The enum option object to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 EnumOption | Custom field enum option successfully reordered. | ||||
| ↓ Show Common Responses ↓ | |||||
Update an enum option
Code samples
curl -X PUT https://app.asana.com/api/1.0/enum_options/{enum_option_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"color": "blue",
"enabled": true,
"insert_after": "12345",
"insert_before": "12345",
"name": "Low"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
}
See Input/Output Options to include more fields in your response.
PUT /enum_options/{enum_option_gid}
Updates an existing enum option. Enum custom fields require at least one enabled enum option. Locked custom fields can only be updated by the user who locked the field. Returns the full record of the updated enum option.
Parameters
| Name | Description | ||||
| /enum_option_gid string required | Globally unique identifier for the enum option. | ||||
| body object | The enum option object to update | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 EnumOption | Successfully updated the specified custom field enum. | ||||
| ↓ Show Common Responses ↓ | |||||
Custom Field Settings
GET /projects/{project_gid}/custom_field_settings
GET /portfolios/{portfolio_gid}/custom_field_settings
Custom fields are attached to a particular project with the Custom Field Settings resource. This resource both represents the many-to-many join of the Custom Field and Project as well as stores information that is relevant to that particular pairing; for instance, the is_important property determines some possible application-specific handling of that custom field.
Get a project's custom fields
Code samples
curl -X GET https://app.asana.com/api/1.0/projects/{project_gid}/custom_field_settings \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /projects/{project_gid}/custom_field_settings
Returns a list of all of the custom fields settings on a project, in compact form. Note that, as in all queries to collections which return compact representation, opt_fields can be used to include more data than is returned in the compact representation. See the getting started guide on input/output options for more information.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 CustomFieldSetting | Successfully retrieved custom field settings objects for a project. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a portfolio's custom fields
Code samples
curl -X GET https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/custom_field_settings \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /portfolios/{portfolio_gid}/custom_field_settings
Returns a list of all of the custom fields settings on a portfolio, in compact form.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 CustomFieldSetting | Successfully retrieved custom field settings objects for a portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Events
GET /events
An event is an object representing a change to a resource that was observed by an event subscription.
In general, requesting events on a resource is faster and subject to higher rate limits than requesting the resource itself. Additionally, change events bubble up - listening to events on a project would include when stories are added to tasks in the project, even on subtasks.
Establish an initial sync token by making a request with no sync token. The response will be a 412 error - the same as if the sync token had expired.
Subsequent requests should always provide the sync token from the immediately preceding call.
Sync tokens may not be valid if you attempt to go ‘backward’ in the history by requesting previous tokens, though re-requesting the current sync token is generally safe, and will always return the same results.
When you receive a 412 Precondition Failed error, it means that the sync token is either invalid or expired. If you are attempting to keep a set of data in sync, this signals you may need to re-crawl the data.
Sync tokens always expire after 24 hours, but may expire sooner, depending on load on the service.
Get events on a resource
Code samples
curl -X GET https://app.asana.com/api/1.0/events?resource=12345 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"action": "changed",
"change": {
"action": "changed",
"added_value": {
"gid": "12345",
"resource_type": "user"
},
"field": "assignee",
"new_value": {
"gid": "12345",
"resource_type": "user"
},
"removed_value": {
"gid": "12345",
"resource_type": "user"
}
},
"created_at": "2012-02-22T02:06:58.147Z",
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"resource": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"type": "task",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"sync": "de4774f6915eae04714ca93bb2f5ee81"
}
See Input/Output Options to include more fields in your response.
GET /events
Returns the full record for all events that have occurred since the sync token was created.
A GET request to the endpoint /[path_to_resource]/events can be made in lieu of including the resource ID in the data for the request.
Note: The resource returned will be the resource that triggered the event. This may be different from the one that the events were requested for. For example, a subscription to a project will contain events for tasks contained within the project.
Parameters
| Name | Description | ||||
| ?resource string required | A resource ID to subscribe to. The resource can be a task or project. | ||||
| ?sync string | A sync token received from the last request, or none on first sync. Events will be returned from the point in time that the sync token was generated. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
sync: A sync token received from the last request, or none on first sync. Events will be returned from the point in time that the sync token was generated.
Note: On your first request, omit the sync token. The response will be the same as for an expired sync token, and will include a new valid sync token.If the sync token is too old (which may happen from time to time) the API will return a 412 Precondition Failed error, and include a fresh sync token in the response.
Responses
| Status | Description | ||||
| 200 Event | Successfully retrieved events. | ||||
| ↓ Show Common Responses ↓ | |||||
Goals
GET /goals/{goal_gid}
PUT /goals/{goal_gid}
DELETE /goals/{goal_gid}
GET /goals
POST /goals/{goal_gid}/setMetric
POST /goals/{goal_gid}/setMetricCurrentValue
POST /goals/{goal_gid}/addSubgoal
POST /goals/{goal_gid}/removeSubgoal
POST /goals/{goal_gid}/addFollowers
POST /goals/{goal_gid}/removeFollowers
POST /goals/{goal_gid}/addSupportingWork
POST /goals/{goal_gid}/removeSupportingWork
GET /goals/{goal_gid}/subgoals
GET /goals/{goal_gid}/supportingWork
GET /goals/{goal_gid}/parentGoals
A goal is an object in the goal-tracking system that helps your organization drive measurable results.
Get a goal
Code samples
curl -X GET https://app.asana.com/api/1.0/goals/{goal_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"due_on": "2019-09-15",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"gid": "12345",
"resource_type": "task",
"currency_code": "EUR",
"current_display_value": "8.12",
"current_number_value": 8.12,
"initial_number_value": 5.2,
"precision": 2,
"resource_subtype": "number",
"target_number_value": 10.2,
"unit": "none"
},
"notes": "Start building brand awareness.",
"start_on": "2019-09-14",
"status": "string",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"num_likes": 5
}
}
See Input/Output Options to include more fields in your response.
GET /goals/{goal_gid}
Returns the complete goal record for a single goal.
Parameters
| Name | Description | ||||
| /goal_gid string required | Globally unique identifier for the goal. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Goal | Successfully retrieved the record for a single goal. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a goal
Code samples
curl -X PUT https://app.asana.com/api/1.0/goals/{goal_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"due_on": "2019-09-15",
"followers": [
{
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"current_display_value": "8.12",
"current_number_value": 8.12
},
"name": "Grow web traffic by 30%",
"notes": "Start building brand awareness.",
"owner": {
"name": "Greg Sanchez"
},
"start_on": "2019-09-14",
"status": "string",
"team": {
"name": "Marketing"
},
"workspace": {
"name": "My Company Workspace"
}
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"due_on": "2019-09-15",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"gid": "12345",
"resource_type": "task",
"currency_code": "EUR",
"current_display_value": "8.12",
"current_number_value": 8.12,
"initial_number_value": 5.2,
"precision": 2,
"resource_subtype": "number",
"target_number_value": 10.2,
"unit": "none"
},
"notes": "Start building brand awareness.",
"start_on": "2019-09-14",
"status": "string",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"num_likes": 5
}
}
See Input/Output Options to include more fields in your response.
PUT /goals/{goal_gid}
An existing goal can be updated by making a PUT request on the URL for
that goal. Only the fields provided in the data block will be updated;
any unspecified fields will remain unchanged.
Returns the complete updated goal record.
Parameters
| Name | Description | ||||
| /goal_gid string required | Globally unique identifier for the goal. | ||||
| body object required | The updated fields for the goal. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Goal | Successfully updated the goal. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a goal
Code samples
curl -X DELETE https://app.asana.com/api/1.0/goals/{goal_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /goals/{goal_gid}
A specific, existing goal can be deleted by making a DELETE request on the URL for that goal.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /goal_gid string required | Globally unique identifier for the goal. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified goal. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get goals
Code samples
curl -X GET https://app.asana.com/api/1.0/goals \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /goals
Returns compact goal records.
Parameters
| Name | Description | ||||
| ?portfolio string | Globally unique identifier for supporting portfolio. | ||||
| ?project string | Globally unique identifier for supporting project. | ||||
| ?is_workspace_level boolean | Filter to goals with is_workspace_level set to query value. Must be used with the workspace parameter. | ||||
| ?team string | Globally unique identifier for the team. | ||||
| ?workspace string | Globally unique identifier for the workspace. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 GoalCompact | Successfully retrieved the requested goals. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a goal metric
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/setMetric \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"current_display_value": "8.12",
"current_number_value": 8.12
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"due_on": "2019-09-15",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"gid": "12345",
"resource_type": "task",
"currency_code": "EUR",
"current_display_value": "8.12",
"current_number_value": 8.12,
"initial_number_value": 5.2,
"precision": 2,
"resource_subtype": "number",
"target_number_value": 10.2,
"unit": "none"
},
"notes": "Start building brand awareness.",
"start_on": "2019-09-14",
"status": "string",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"num_likes": 5
}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/setMetric
Creates and adds a goal metric to a specified goal. Note that this replaces an existing goal metric if one already exists.
Parameters
| Name | Description | ||||
| body object required | The goal metric to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Goal | Successfully created a new goal metric. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a goal metric
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/setMetricCurrentValue \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"current_number_value": 8.12
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"due_on": "2019-09-15",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"gid": "12345",
"resource_type": "task",
"currency_code": "EUR",
"current_display_value": "8.12",
"current_number_value": 8.12,
"initial_number_value": 5.2,
"precision": 2,
"resource_subtype": "number",
"target_number_value": 10.2,
"unit": "none"
},
"notes": "Start building brand awareness.",
"start_on": "2019-09-14",
"status": "string",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"num_likes": 5
}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/setMetricCurrentValue
Updates a goal's existing metric's current_number_value if one exists,
otherwise responds with a 400 status code.
Returns the complete updated goal metric record.
Parameters
| Name | Description | ||||
| body object required | The updated fields for the goal metric. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Goal | Successfully updated the goal metric. | ||||
| ↓ Show Common Responses ↓ | |||||
Add a subgoal to a parent goal
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/addSubgoal \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"insert_after": "1331",
"insert_before": "1331",
"subgoal": "1331"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/addSubgoal
Adds a subgoal to a parent goal. *A goal can have at most 100 subgoals, and a subgoal can have at most 4 parent goals.
Returns an empty data block.
Parameters
| Name | Description | ||||
| body object required | The goal to add as a subgoal | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added goal as subgoal. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove a subgoal from a goal
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/removeSubgoal \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"subgoal": "1331"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/removeSubgoal
Removes a goal as a subgoal of a specified parent goal.
Parameters
| Name | Description | ||||
| body object required | The goal to be removed as a subgoal | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed subgoal. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Add a collaborator to a goal
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/addFollowers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"followers": [
"13579",
"321654"
]
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"due_on": "2019-09-15",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"gid": "12345",
"resource_type": "task",
"currency_code": "EUR",
"current_display_value": "8.12",
"current_number_value": 8.12,
"initial_number_value": 5.2,
"precision": 2,
"resource_subtype": "number",
"target_number_value": 10.2,
"unit": "none"
},
"notes": "Start building brand awareness.",
"start_on": "2019-09-14",
"status": "string",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"num_likes": 5
}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/addFollowers
Adds followers to a goal. Returns the goal the followers were added to. Each goal can be associated with zero or more followers in the system. Requests to add/remove followers, if successful, will return the complete updated goal record, described above.
Parameters
| Name | Description | ||||
| body object required | The followers to be added as collaborators | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 201 Goal | Successfully added users as collaborators. | ||||
| ↓ Show Common Responses ↓ | |||||
Remove a collaborator from a goal
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/removeFollowers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"followers": [
"13579",
"321654"
]
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"due_on": "2019-09-15",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"gid": "12345",
"resource_type": "task",
"currency_code": "EUR",
"current_display_value": "8.12",
"current_number_value": 8.12,
"initial_number_value": 5.2,
"precision": 2,
"resource_subtype": "number",
"target_number_value": 10.2,
"unit": "none"
},
"notes": "Start building brand awareness.",
"start_on": "2019-09-14",
"status": "string",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"num_likes": 5
}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/removeFollowers
Removes followers from a goal. Returns the goal the followers were removed from. Each goal can be associated with zero or more followers in the system. Requests to add/remove followers, if successful, will return the complete updated goal record, described above.
Parameters
| Name | Description | ||||
| body object required | The followers to be removed as collaborators | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 201 Goal | Successfully removed users as collaborators. | ||||
| ↓ Show Common Responses ↓ | |||||
Add a project/portfolio as supporting work for a goal.
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/addSupportingWork \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"supporting_work": "1331"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/addSupportingWork
Adds a project or portfolio as supporting work for a goal. A goal can have at most 10 supporting projects/portfolios, and a project/portfolio can support at most 10 goals.
Parameters
| Name | Description | ||||
| body object required | The project/portfolio to set as supporting work | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully set specified project/portfolio as supporting work on the given goal. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove a project/portfolio as supporting work for a goal.
Code samples
curl -X POST https://app.asana.com/api/1.0/goals/{goal_gid}/removeSupportingWork \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"supporting_work": "1331"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /goals/{goal_gid}/removeSupportingWork
Removes a project or portfolio as supporting work for a goal.
Parameters
| Name | Description | ||||
| body object required | The project/portfolio to remove as supporting work | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed specified project/portfolio as supporting work on the given goal. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get subgoals from a goal
Code samples
curl -X GET https://app.asana.com/api/1.0/goals/{goal_gid}/subgoals \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /goals/{goal_gid}/subgoals
Returns a compact representation of all of the subgoals of a goal.
Parameters
| Name | Description | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 GoalCompact | Successfully retrieved the specified goal's subgoals. | ||||
| ↓ Show Common Responses ↓ | |||||
Get supporting work from a goal
Code samples
curl -X GET https://app.asana.com/api/1.0/goals/{goal_gid}/supportingWork \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /goals/{goal_gid}/supportingWork
Returns any portfolios or projects associated with specified goal.
Parameters
| Name | Description | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectCompact | Successfully returned supporting work. | ||||
| ↓ Show Common Responses ↓ | |||||
Get parent goals from a goal
Code samples
curl -X GET https://app.asana.com/api/1.0/goals/{goal_gid}/parentGoals \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /goals/{goal_gid}/parentGoals
Returns a compact representation of all of the parent goals of a goal.
Parameters
| Name | Description | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 GoalCompact | Successfully retrieved the specified goal's parent goals. | ||||
| ↓ Show Common Responses ↓ | |||||
Jobs
GET /jobs/{job_gid}
Jobs represent processes that handle asynchronous work. Jobs are created when an endpoint requests an action that will be handled asynchronously. Such as project or task duplication. Only the creator of the duplication process can access the duplication status of the new object.
Get a job by id
Code samples
curl -X GET https://app.asana.com/api/1.0/jobs/{job_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "job",
"new_project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"new_task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"resource_subtype": "duplicate_task",
"status": "in_progress"
}
}
See Input/Output Options to include more fields in your response.
GET /jobs/{job_gid}
Returns the full record for a job.
Parameters
| Name | Description | ||||
| /job_gid string required | Globally unique identifier for the job. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Job | Successfully retrieved Job. | ||||
| ↓ Show Common Responses ↓ | |||||
Organization Exports
POST /organization_exports
GET /organization_exports/{organization_export_gid}
An organization_export object represents a request to export the complete data of an Organization in JSON format.
To export an Organization using this API:
- Create an
organization_exportrequest and store the id that is returned. - Request the
organization_exportevery few minutes, until thestatefield contains ‘finished’. - Download the file located at the URL in the
download_urlfield. * Exports can take a long time, from several minutes to a few hours for large Organizations.
Note: These endpoints are only available to Service Accounts of an Enterprise Organization.
Create an organization export request
Code samples
curl -X POST https://app.asana.com/api/1.0/organization_exports \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"organization": "1331"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "organization_export",
"created_at": "2012-02-22T02:06:58.147Z",
"download_url": "https://asana-export.s3.amazonaws.com/export-4632784536274-20170127-43246.json.gz?AWSAccessKeyId=xxxxxxxx",
"organization": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"state": "started"
}
}
See Input/Output Options to include more fields in your response.
POST /organization_exports
This method creates a request to export an Organization. Asana will complete the export at some point after you create the request.
Parameters
| Name | Description | ||||
| body object required | The organization to export. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 201 Inline | Successfully created organization export request. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 201
| Name | Description | |
| data OrganizationExportResponse | An organization_export object represents a request to export the complete data of an Organization in JSON format. | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| created_at string(date-time) | The time at which this resource was created. | |
| download_url string(uri)¦null | Download this URL to retreive the full export of the organization in JSON format. It will be compressed in a gzip (.gz) container. Note: May be null if the export is still in progress or failed. If present, this URL may only be valid for 1 hour from the time of retrieval. You should avoid persisting this URL somewhere and rather refresh on demand to ensure you do not keep stale URLs. | |
| organization object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the workspace. | |
| state string | The current state of the export. |
Enumerated Values
| Property | Value | |
| state | pending | |
| state | started | |
| state | finished | |
| state | error |
Get details on an org export request
Code samples
curl -X GET https://app.asana.com/api/1.0/organization_exports/{organization_export_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "organization_export",
"created_at": "2012-02-22T02:06:58.147Z",
"download_url": "https://asana-export.s3.amazonaws.com/export-4632784536274-20170127-43246.json.gz?AWSAccessKeyId=xxxxxxxx",
"organization": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"state": "started"
}
}
See Input/Output Options to include more fields in your response.
GET /organization_exports/{organization_export_gid}
Returns details of a previously-requested Organization export.
Parameters
| Name | Description | ||||
| /organization_export_gid string required | Globally unique identifier for the organization export. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully retrieved organization export object. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
| Name | Description | |
| data OrganizationExportResponse | An organization_export object represents a request to export the complete data of an Organization in JSON format. | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| created_at string(date-time) | The time at which this resource was created. | |
| download_url string(uri)¦null | Download this URL to retreive the full export of the organization in JSON format. It will be compressed in a gzip (.gz) container. Note: May be null if the export is still in progress or failed. If present, this URL may only be valid for 1 hour from the time of retrieval. You should avoid persisting this URL somewhere and rather refresh on demand to ensure you do not keep stale URLs. | |
| organization object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the workspace. | |
| state string | The current state of the export. |
Enumerated Values
| Property | Value | |
| state | pending | |
| state | started | |
| state | finished | |
| state | error |
Portfolios
GET /portfolios
POST /portfolios
GET /portfolios/{portfolio_gid}
PUT /portfolios/{portfolio_gid}
DELETE /portfolios/{portfolio_gid}
GET /portfolios/{portfolio_gid}/items
POST /portfolios/{portfolio_gid}/addItem
POST /portfolios/{portfolio_gid}/removeItem
POST /portfolios/{portfolio_gid}/addCustomFieldSetting
POST /portfolios/{portfolio_gid}/removeCustomFieldSetting
POST /portfolios/{portfolio_gid}/addMembers
POST /portfolios/{portfolio_gid}/removeMembers
A portfolio gives a high-level overview of the status of multiple initiatives in Asana. Portfolios provide a dashboard overview of the state of multiple projects, including a progress report and the most recent project status update.
Portfolios have some restrictions on size. Each portfolio has a max of 250 items and, like projects, a max of 20 custom fields.
Get multiple portfolios
Code samples
curl -X GET https://app.asana.com/api/1.0/portfolios?workspace=1331&owner=14916 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio"
}
]
}
See Input/Output Options to include more fields in your response.
GET /portfolios
Returns a list of the portfolios in compact representation that are owned by the current API user.
Parameters
| Name | Description | ||||
| ?workspace string required | The workspace or organization to filter portfolios on. | ||||
| ?owner string required | The user who owns the portfolio. Currently, API users can only get a list of portfolios that they themselves own. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 PortfolioCompact | Successfully retrieved portfolios. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a portfolio
Code samples
curl -X POST https://app.asana.com/api/1.0/portfolios \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"color": "light-green",
"members": [
"52164",
"15363"
],
"name": "Bug Portfolio",
"workspace": "167589"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio",
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
],
"due_on": "2019-09-15",
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
POST /portfolios
Creates a new portfolio in the given workspace with the supplied name.
Note that portfolios created in the Asana UI may have some state (like the “Priority” custom field) which is automatically added to the portfolio when it is created. Portfolios created via our API will not be created with the same initial state to allow integrations to create their own starting state on a portfolio.
Parameters
| Name | Description | ||||
| body object required | The portfolio to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray |
Responses
| Status | Description | ||||
| 201 Portfolio | Successfully created portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a portfolio
Code samples
curl -X GET https://app.asana.com/api/1.0/portfolios/{portfolio_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio",
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
],
"due_on": "2019-09-15",
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
GET /portfolios/{portfolio_gid}
Returns the complete portfolio record for a single portfolio.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Portfolio | Successfully retrieved the requested portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a portfolio
Code samples
curl -X PUT https://app.asana.com/api/1.0/portfolios/{portfolio_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"color": "light-green",
"members": [
"52164",
"15363"
],
"name": "Bug Portfolio",
"workspace": "167589"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio",
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
],
"due_on": "2019-09-15",
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
PUT /portfolios/{portfolio_gid}
An existing portfolio can be updated by making a PUT request on the URL for
that portfolio. Only the fields provided in the data block will be updated;
any unspecified fields will remain unchanged.
Returns the complete updated portfolio record.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| body object required | The updated fields for the portfolio. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray |
Responses
| Status | Description | ||||
| 200 Portfolio | Successfully updated the portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a portfolio
Code samples
curl -X DELETE https://app.asana.com/api/1.0/portfolios/{portfolio_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /portfolios/{portfolio_gid}
An existing portfolio can be deleted by making a DELETE request on the URL for that portfolio.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get portfolio items
Code samples
curl -X GET https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/items \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /portfolios/{portfolio_gid}/items
Get a list of the items in compact form in a portfolio.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectCompact | Successfully retrieved the requested portfolio's items. | ||||
| ↓ Show Common Responses ↓ | |||||
Add a portfolio item
Code samples
curl -X POST https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/addItem \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"insert_after": "1331",
"insert_before": "1331",
"item": "1331"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /portfolios/{portfolio_gid}/addItem
Add an item to a portfolio. Returns an empty data block.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| body object required | Information about the item being inserted. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added the item to the portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove a portfolio item
Code samples
curl -X POST https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/removeItem \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"item": "1331"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /portfolios/{portfolio_gid}/removeItem
Remove an item from a portfolio. Returns an empty data block.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| body object required | Information about the item being removed. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the item from the portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Add a custom field to a portfolio
Code samples
curl -X POST https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/addCustomFieldSetting \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"custom_field": "14916",
"insert_after": "1331",
"insert_before": "1331",
"is_important": true
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /portfolios/{portfolio_gid}/addCustomFieldSetting
Custom fields are associated with portfolios by way of custom field settings. This method creates a setting for the portfolio.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| body object required | Information about the custom field setting. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added the custom field to the portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove a custom field from a portfolio
Code samples
curl -X POST https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/removeCustomFieldSetting \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"custom_field": "14916"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /portfolios/{portfolio_gid}/removeCustomFieldSetting
Removes a custom field setting from a portfolio.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| body object required | Information about the custom field setting being removed. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the custom field from the portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Add users to a portfolio
Code samples
curl -X POST https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/addMembers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"members": "521621,621373"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /portfolios/{portfolio_gid}/addMembers
Adds the specified list of users as members of the portfolio. Returns the updated portfolio record.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| body object required | Information about the members being added. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added members to the portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove users from a portfolio
Code samples
curl -X POST https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/removeMembers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"members": "521621,621373"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /portfolios/{portfolio_gid}/removeMembers
Removes the specified list of users from members of the portfolio. Returns the updated portfolio record.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| body object required | Information about the members being removed. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the members from the portfolio. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Portfolio Memberships
GET /portfolio_memberships
GET /portfolio_memberships/{portfolio_membership_gid}
GET /portfolios/{portfolio_gid}/portfolio_memberships
This object determines if a user is a member of a portfolio.
Get multiple portfolio memberships
Code samples
curl -X GET https://app.asana.com/api/1.0/portfolio_memberships \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "portfolio_membership",
"portfolio": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /portfolio_memberships
Returns a list of portfolio memberships in compact representation. You must specify portfolio, portfolio and user, or workspace and user.
Parameters
| Name | Description | ||||
| ?portfolio string | The portfolio to filter results on. | ||||
| ?workspace string | The workspace to filter results on. | ||||
| ?user string | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 PortfolioMembershipCompact | Successfully retrieved portfolio memberships. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a portfolio membership
Code samples
curl -X GET https://app.asana.com/api/1.0/portfolio_memberships/{portfolio_membership_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "portfolio_membership",
"portfolio": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
}
See Input/Output Options to include more fields in your response.
GET /portfolio_memberships/{portfolio_membership_gid}
Returns the complete portfolio record for a single portfolio membership.
Parameters
| Name | Description | ||||
| /portfolio_membership_gid string required | none | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 PortfolioMembership | Successfully retrieved the requested portfolio membership. | ||||
| ↓ Show Common Responses ↓ | |||||
Get memberships from a portfolio
Code samples
curl -X GET https://app.asana.com/api/1.0/portfolios/{portfolio_gid}/portfolio_memberships \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "portfolio_membership",
"portfolio": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /portfolios/{portfolio_gid}/portfolio_memberships
Returns the compact portfolio membership records for the portfolio.
Parameters
| Name | Description | ||||
| /portfolio_gid string required | Globally unique identifier for the portfolio. | ||||
| ?user string | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 PortfolioMembershipCompact | Successfully retrieved the requested portfolio's memberships. | ||||
| ↓ Show Common Responses ↓ | |||||
Projects
GET /projects
POST /projects
GET /projects/{project_gid}
PUT /projects/{project_gid}
DELETE /projects/{project_gid}
POST /projects/{project_gid}/duplicate
GET /tasks/{task_gid}/projects
GET /teams/{team_gid}/projects
POST /teams/{team_gid}/projects
GET /workspaces/{workspace_gid}/projects
POST /workspaces/{workspace_gid}/projects
POST /projects/{project_gid}/addCustomFieldSetting
POST /projects/{project_gid}/removeCustomFieldSetting
GET /projects/{project_gid}/task_counts
POST /projects/{project_gid}/addMembers
POST /projects/{project_gid}/removeMembers
POST /projects/{project_gid}/addFollowers
POST /projects/{project_gid}/removeFollowers
A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. 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.
Followers of a project are a subset of the members of that project. Followers of a project will receive all updates including tasks created, added and removed from that project. Members of the project have access to and will receive status updates of the project. Adding followers to a project will add them as members if they are not already, removing followers from a project will not affect membership.
Get multiple projects
Code samples
curl -X GET https://app.asana.com/api/1.0/projects \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /projects
Returns the compact project records for some filtered set of projects. Use one or more of the parameters provided to filter the projects returned. Note: This endpoint may timeout for large domains. Try filtering by team!
Parameters
| Name | Description | ||||
| ?workspace string | The workspace or organization to filter projects on. | ||||
| ?team string | The team to filter projects on. | ||||
| ?archived boolean | Only return projects whose archived field takes on the value of this parameter. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectCompact | Successfully retrieved projects. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"archived": false,
"color": "light-green",
"current_status": {
"author": {
"name": "Greg Sanchez"
},
"color": "green",
"created_by": {
"name": "Greg Sanchez"
},
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"title": "Status Update - Jun 15"
},
"custom_fields": {
"4578152156": "Not Started",
"5678904321": "On Hold"
},
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"followers": "12345,23456",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"name": "Stuff to buy",
"notes": "These are things we need to purchase.",
"owner": "12345",
"public": false,
"start_on": "2019-09-14",
"team": "12345"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy",
"archived": false,
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"current_status": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting"
}
],
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "These are things we need to purchase.",
"public": false,
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"icon": "chat_bubbles",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
}
}
See Input/Output Options to include more fields in your response.
POST /projects
Create a new project in a workspace or team.
Every project is required to be created in a specific workspace or
organization, and this 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.
Returns the full record of the newly created project.
Parameters
| Name | Description | ||||
| body object required | The project to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray | |
| color | green | |
| color | yellow | |
| color | red | |
| color | blue | |
| default_view | list | |
| default_view | board | |
| default_view | calendar | |
| default_view | timeline |
Responses
| Status | Description | ||||
| 201 Project | Successfully retrieved projects. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a project
Code samples
curl -X GET https://app.asana.com/api/1.0/projects/{project_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy",
"archived": false,
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"current_status": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting"
}
],
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "These are things we need to purchase.",
"public": false,
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"icon": "chat_bubbles",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
}
}
See Input/Output Options to include more fields in your response.
GET /projects/{project_gid}
Returns the complete project record for a single project.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Project | Successfully retrieved the requested project. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a project
Code samples
curl -X PUT https://app.asana.com/api/1.0/projects/{project_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"archived": false,
"color": "light-green",
"current_status": {
"author": {
"name": "Greg Sanchez"
},
"color": "green",
"created_by": {
"name": "Greg Sanchez"
},
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"title": "Status Update - Jun 15"
},
"custom_fields": {
"4578152156": "Not Started",
"5678904321": "On Hold"
},
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"followers": "12345,23456",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"name": "Stuff to buy",
"notes": "These are things we need to purchase.",
"owner": "12345",
"public": false,
"start_on": "2019-09-14",
"team": "12345"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy",
"archived": false,
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"current_status": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting"
}
],
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "These are things we need to purchase.",
"public": false,
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"icon": "chat_bubbles",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
}
}
See Input/Output Options to include more fields in your response.
PUT /projects/{project_gid}
A specific, existing project can be updated by making a PUT request on
the URL for that project. 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.
Returns the complete updated project record.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | The updated fields for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray | |
| color | green | |
| color | yellow | |
| color | red | |
| color | blue | |
| default_view | list | |
| default_view | board | |
| default_view | calendar | |
| default_view | timeline |
Responses
| Status | Description | ||||
| 200 Project | Successfully updated the project. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a project
Code samples
curl -X DELETE https://app.asana.com/api/1.0/projects/{project_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /projects/{project_gid}
A specific, existing project can be deleted by making a DELETE request on the URL for that project.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified project. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Duplicate a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/duplicate \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"include": [
"members",
"task_notes"
],
"name": "New Project Name",
"schedule_dates": {
"due_on": "2019-05-21",
"should_skip_weekends": true,
"start_on": "2019-05-21"
},
"team": "12345"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "job",
"new_project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"new_task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"resource_subtype": "duplicate_task",
"status": "in_progress"
}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/duplicate
Creates and returns a job that will asynchronously handle the duplication.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object | Describes the duplicate's name and the elements that will be duplicated. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| include | members | |
| include | notes | |
| include | forms | |
| include | task_notes | |
| include | task_assignee | |
| include | task_subtasks | |
| include | task_attachments | |
| include | task_dates | |
| include | task_dependencies | |
| include | task_followers | |
| include | task_tags | |
| include | task_projects |
Responses
| Status | Description | ||||
| 201 Job | Successfully created the job to handle duplication. | ||||
| ↓ Show Common Responses ↓ | |||||
Get projects a task is in
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid}/projects \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}/projects
Returns a compact representation of all of the projects the task is in.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectCompact | Successfully retrieved the projects for the given task. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a team's projects
Code samples
curl -X GET https://app.asana.com/api/1.0/teams/{team_gid}/projects \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /teams/{team_gid}/projects
Returns the compact project records for all projects in the team.
Parameters
| Name | Description | ||||
| /team_gid string required | Globally unique identifier for the team. | ||||
| ?archived boolean | Only return projects whose archived field takes on the value of this parameter. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectCompact | Successfully retrieved the requested team's projects. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a project in a team
Code samples
curl -X POST https://app.asana.com/api/1.0/teams/{team_gid}/projects \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"archived": false,
"color": "light-green",
"current_status": {
"author": {
"name": "Greg Sanchez"
},
"color": "green",
"created_by": {
"name": "Greg Sanchez"
},
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"title": "Status Update - Jun 15"
},
"custom_fields": {
"4578152156": "Not Started",
"5678904321": "On Hold"
},
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"followers": "12345,23456",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"name": "Stuff to buy",
"notes": "These are things we need to purchase.",
"owner": "12345",
"public": false,
"start_on": "2019-09-14",
"team": "12345"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy",
"archived": false,
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"current_status": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting"
}
],
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "These are things we need to purchase.",
"public": false,
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"icon": "chat_bubbles",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
}
}
See Input/Output Options to include more fields in your response.
POST /teams/{team_gid}/projects
Creates a project shared with the given team.
Returns the full record of the newly created project.
Parameters
| Name | Description | ||||
| /team_gid string required | Globally unique identifier for the team. | ||||
| body object required | The new project to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray | |
| color | green | |
| color | yellow | |
| color | red | |
| color | blue | |
| default_view | list | |
| default_view | board | |
| default_view | calendar | |
| default_view | timeline |
Responses
| Status | Description | ||||
| 201 Project | Successfully created the specified project. | ||||
| ↓ Show Common Responses ↓ | |||||
Get all projects in a workspace
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/projects \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}/projects
Returns the compact project records for all projects in the workspace.
Note: This endpoint may timeout for large domains. Prefer the /teams/{team_gid}/projects endpoint.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ?archived boolean | Only return projects whose archived field takes on the value of this parameter. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectCompact | Successfully retrieved the requested workspace's projects. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a project in a workspace
Code samples
curl -X POST https://app.asana.com/api/1.0/workspaces/{workspace_gid}/projects \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"archived": false,
"color": "light-green",
"current_status": {
"author": {
"name": "Greg Sanchez"
},
"color": "green",
"created_by": {
"name": "Greg Sanchez"
},
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"title": "Status Update - Jun 15"
},
"custom_fields": {
"4578152156": "Not Started",
"5678904321": "On Hold"
},
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"followers": "12345,23456",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"name": "Stuff to buy",
"notes": "These are things we need to purchase.",
"owner": "12345",
"public": false,
"start_on": "2019-09-14",
"team": "12345"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy",
"archived": false,
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"current_status": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting"
}
],
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "These are things we need to purchase.",
"public": false,
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"icon": "chat_bubbles",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
}
}
See Input/Output Options to include more fields in your response.
POST /workspaces/{workspace_gid}/projects
Returns the compact project records for all projects in the workspace.
If the workspace for your project is an organization, you must also supply a team to share the project with.
Returns the full record of the newly created project.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| body object required | The new project to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray | |
| color | green | |
| color | yellow | |
| color | red | |
| color | blue | |
| default_view | list | |
| default_view | board | |
| default_view | calendar | |
| default_view | timeline |
Responses
| Status | Description | ||||
| 201 Project | Successfully created a new project in the specified workspace. | ||||
| ↓ Show Common Responses ↓ | |||||
Add a custom field to a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/addCustomFieldSetting \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"custom_field": "14916",
"insert_after": "1331",
"insert_before": "1331",
"is_important": true
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/addCustomFieldSetting
Custom fields are associated with projects by way of custom field settings. This method creates a setting for the project.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | Information about the custom field setting. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 CustomFieldSetting | Successfully added the custom field to the project. | ||||
| ↓ Show Common Responses ↓ | |||||
Remove a custom field from a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/removeCustomFieldSetting \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"custom_field": "14916"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/removeCustomFieldSetting
Removes a custom field setting from a project.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | Information about the custom field setting being removed. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the custom field from the project. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get task count of a project
Code samples
curl -X GET https://app.asana.com/api/1.0/projects/{project_gid}/task_counts \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"num_completed_milestones": 3,
"num_completed_tasks": 150,
"num_incomplete_milestones": 7,
"num_incomplete_tasks": 50,
"num_milestones": 10,
"num_tasks": 200
}
}
See Input/Output Options to include more fields in your response.
GET /projects/{project_gid}/task_counts
Get an object that holds task count fields. All fields are excluded by default. You must opt in using opt_fields to get any information from this endpoint.
This endpoint has an additional rate limit and each field counts especially high against our cost limits.
Milestones are just tasks, so they are included in the num_tasks, num_incomplete_tasks, and num_completed_tasks counts.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully retrieved the requested project's task counts. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
| Name | Description | |
| data TaskCountResponse | A response object returned from the task count endpoint. | |
| num_completed_milestones integer | The number of completed milestones in a project. | |
| num_completed_tasks integer | The number of completed tasks in a project. | |
| num_incomplete_milestones integer | The number of incomplete milestones in a project. | |
| num_incomplete_tasks integer | The number of incomplete tasks in a project. | |
| num_milestones integer | The number of milestones in a project. | |
| num_tasks integer | The number of tasks in a project. |
Add users to a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/addMembers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"members": "521621,621373"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/addMembers
Adds the specified list of users as members of the project. Returns the updated project record.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | Information about the members being added. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added members to the project. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove users from a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/removeMembers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"members": "521621,621373"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/removeMembers
Removes the specified list of users from members of the project. Returns the updated project record.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | Information about the members being removed. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the members from the project. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Add followers to a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/addFollowers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"followers": "521621,621373"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/addFollowers
Adds the specified list of users as followers to the project. Followers are a subset of members, therefore if the users are not already members of the project they will also become members as a result of this operation. Returns the updated project record.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | Information about the followers being added. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added followers to the project. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove followers from a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/removeFollowers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"followers": "521621,621373"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/removeFollowers
Removes the specified list of users from following the project, this will not affect project membership status. Returns the updated project record.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | Information about the followers being removed. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed followers from the project. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Project Memberships
GET /project_memberships/{project_membership_gid}
GET /projects/{project_gid}/project_memberships
With the introduction of “comment-only” projects in Asana, a user’s membership in a project comes with associated permissions. These permissions (whether a user has full access to the project or comment-only access) are accessible through the project memberships endpoints described here.
Get a project membership
Code samples
curl -X GET https://app.asana.com/api/1.0/project_memberships/{project_membership_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "project_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"write_access": "full_write"
}
}
See Input/Output Options to include more fields in your response.
GET /project_memberships/{project_membership_gid}
Returns the complete project record for a single project membership.
Parameters
| Name | Description | ||||
| /project_membership_gid string required | none | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectMembership | Successfully retrieved the requested project membership. | ||||
| ↓ Show Common Responses ↓ | |||||
Get memberships from a project
Code samples
curl -X GET https://app.asana.com/api/1.0/projects/{project_gid}/project_memberships \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /projects/{project_gid}/project_memberships
Returns the compact project membership records for the project.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ?user string | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectMembershipCompact | Successfully retrieved the requested project's memberships. | ||||
| ↓ Show Common Responses ↓ | |||||
Project Statuses
GET /project_statuses/{project_status_gid}
DELETE /project_statuses/{project_status_gid}
GET /projects/{project_gid}/project_statuses
POST /projects/{project_gid}/project_statuses
A project status is an update on the progress of a particular project, and is sent out to all project followers when created. These updates include both text describing the update and a color code intended to represent the overall state of the project: "green" for projects that are on track, "yellow" for projects at risk, "red" for projects that are behind, and "blue" for projects on hold.
Project statuses can be created and deleted, but not modified.
Get a project status
Code samples
curl -X GET https://app.asana.com/api/1.0/project_statuses/{project_status_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
}
}
See Input/Output Options to include more fields in your response.
GET /project_statuses/{project_status_gid}
Returns the complete record for a single status update.
Parameters
| Name | Description | ||||
| /project_status_gid string required | The project status update to get. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectStatus | Successfully retrieved the specified project's status updates. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a project status
Code samples
curl -X DELETE https://app.asana.com/api/1.0/project_statuses/{project_status_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /project_statuses/{project_status_gid}
Deletes a specific, existing project status update.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /project_status_gid string required | The project status update to get. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified project status. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get statuses from a project
Code samples
curl -X GET https://app.asana.com/api/1.0/projects/{project_gid}/project_statuses \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15"
}
]
}
See Input/Output Options to include more fields in your response.
GET /projects/{project_gid}/project_statuses
Returns the compact project status update records for all updates on the project.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 ProjectStatusCompact | Successfully retrieved the specified project's status updates. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a project status
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/project_statuses \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"title": "Status Update - Jun 15"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/project_statuses
Creates a new status update on the project. Returns the full record of the newly created project status update.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | The project status to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | green | |
| color | yellow | |
| color | red | |
| color | blue |
Responses
| Status | Description | ||||
| 201 ProjectStatus | Successfully created a new story. | ||||
| ↓ Show Common Responses ↓ | |||||
Sections
GET /sections/{section_gid}
PUT /sections/{section_gid}
DELETE /sections/{section_gid}
GET /projects/{project_gid}/sections
POST /projects/{project_gid}/sections
POST /sections/{section_gid}/addTask
POST /projects/{project_gid}/sections/insert
A section is a subdivision of a project that groups tasks together. It can either be a header above a list of tasks in a list view or a column in a board view of a project.
Sections are largely a shared idiom in Asana’s API for both list and board views of a project regardless of the project’s layout.
The ‘memberships’ property when getting a task will return the information for the section or the column under ‘section’ in the response.
Get a section
Code samples
curl -X GET https://app.asana.com/api/1.0/sections/{section_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions",
"created_at": "2012-02-22T02:06:58.147Z",
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
}
See Input/Output Options to include more fields in your response.
GET /sections/{section_gid}
Returns the complete record for a single section.
Parameters
| Name | Description | ||||
| /section_gid string required | The globally unique identifier for the section. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Section | Successfully retrieved section. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a section
Code samples
curl -X PUT https://app.asana.com/api/1.0/sections/{section_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"insert_after": "987654",
"insert_before": "86420",
"name": "Next Actions",
"project": "13579"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions",
"created_at": "2012-02-22T02:06:58.147Z",
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
}
See Input/Output Options to include more fields in your response.
PUT /sections/{section_gid}
A specific, existing section can be updated by making a PUT request on
the URL for that project. Only the fields provided in the data block
will be updated; any unspecified fields will remain unchanged. (note that
at this time, the only field that can be updated is the name field.)
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.
Returns the complete updated section record.
Parameters
| Name | Description | ||||
| /section_gid string required | The globally unique identifier for the section. | ||||
| body object required | The section to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Section | Successfully updated the specified section. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a section
Code samples
curl -X DELETE https://app.asana.com/api/1.0/sections/{section_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /sections/{section_gid}
A specific, existing section can be deleted by making a DELETE request on the URL for that section.
Note that sections must be empty to be deleted.
The last remaining section cannot be deleted.
Returns an empty data block.
Parameters
| Name | Description | ||||
| /section_gid string required | The globally unique identifier for the section. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified section. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get sections in a project
Code samples
curl -X GET https://app.asana.com/api/1.0/projects/{project_gid}/sections \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
]
}
See Input/Output Options to include more fields in your response.
GET /projects/{project_gid}/sections
Returns the compact records for all sections in the specified project.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 SectionCompact | Successfully retrieved sections in project. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a section in a project
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/sections \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"insert_after": "987654",
"insert_before": "86420",
"name": "Next Actions",
"project": "13579"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions",
"created_at": "2012-02-22T02:06:58.147Z",
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/sections
Creates a new section in a project. Returns the full record of the newly created section.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | The section to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 201 Section | Successfully created the specified section. | ||||
| ↓ Show Common Responses ↓ | |||||
Add task to section
Code samples
curl -X POST https://app.asana.com/api/1.0/sections/{section_gid}/addTask \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"insert_after": "987654",
"insert_before": "86420",
"task": "123456"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /sections/{section_gid}/addTask
Add a task to a specific, existing section. This will remove the task from other sections of the project.
The task will be inserted at the top of a section unless an insert_before or insert_after parameter is declared.
This does not work for separators (tasks with the resource_subtype of section).
Parameters
| Name | Description | ||||
| /section_gid string required | The globally unique identifier for the section. | ||||
| body object required | The task and optionally the insert location. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Move or Insert sections
Code samples
curl -X POST https://app.asana.com/api/1.0/projects/{project_gid}/sections/insert \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"after_section": "987654",
"before_section": "86420",
"project": "123456",
"section": "321654"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /projects/{project_gid}/sections/insert
Move sections relative to each other. One of
before_section or after_section is required.
Sections cannot be moved between projects.
Returns an empty data block.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| body object required | The section's move action. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully moved the specified section. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Stories
GET /stories/{story_gid}
PUT /stories/{story_gid}
DELETE /stories/{story_gid}
GET /tasks/{task_gid}/stories
POST /tasks/{task_gid}/stories
See our forum post for more info on when conditional fields are returned.
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.
Get a story
Code samples
curl -X GET https://app.asana.com/api/1.0/stories/{story_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"html_text": "<body>This is a comment.<body>",
"is_pinned": false,
"resource_subtype": "comment_added",
"sticker_name": "dancing_unicorn",
"text": "This is a comment.",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"dependency": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicate_of": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicated_from": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"follower": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"hearted": false,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"is_edited": false,
"liked": false,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"new_approval_status": "approved",
"new_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"new_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"new_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"new_name": "This is the New Name",
"new_number_value": 2,
"new_resource_subtype": "milestone",
"new_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"new_text_value": "This is the New Text",
"num_hearts": 5,
"num_likes": 5,
"old_approval_status": "pending",
"old_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"old_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"old_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"old_name": "This was the Old Name",
"old_number_value": 1,
"old_resource_subtype": "default_task",
"old_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"old_text_value": "This was the Old Text",
"previews": [
{
"fallback": "Greg: Great! I like this idea.\\n\\nhttps//a_company.slack.com/archives/ABCDEFG/12345678",
"footer": "Mar 17, 2019 1:25 PM",
"header": "Asana for Slack",
"header_link": "https://asana.comn/apps/slack",
"html_text": "<body>Great! I like this idea.</body>",
"text": "Great! I like this idea.",
"title": "Greg",
"title_link": "https://asana.slack.com/archives/ABCDEFG/12345678"
}
],
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"source": "web",
"story": {
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"resource_subtype": "comment_added",
"text": "marked today"
},
"tag": {
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
},
"target": {
"gid": "1234",
"name": "Bug Task"
},
"task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
}
}
See Input/Output Options to include more fields in your response.
GET /stories/{story_gid}
Returns the full record for a single story.
Parameters
| Name | Description | ||||
| /story_gid string required | Globally unique identifier for the story. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Story | Successfully retrieved the specified story. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a story
Code samples
curl -X PUT https://app.asana.com/api/1.0/stories/{story_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"html_text": "<body>This is a comment.<body>",
"is_pinned": false,
"sticker_name": "dancing_unicorn",
"text": "This is a comment."
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"html_text": "<body>This is a comment.<body>",
"is_pinned": false,
"resource_subtype": "comment_added",
"sticker_name": "dancing_unicorn",
"text": "This is a comment.",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"dependency": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicate_of": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicated_from": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"follower": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"hearted": false,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"is_edited": false,
"liked": false,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"new_approval_status": "approved",
"new_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"new_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"new_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"new_name": "This is the New Name",
"new_number_value": 2,
"new_resource_subtype": "milestone",
"new_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"new_text_value": "This is the New Text",
"num_hearts": 5,
"num_likes": 5,
"old_approval_status": "pending",
"old_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"old_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"old_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"old_name": "This was the Old Name",
"old_number_value": 1,
"old_resource_subtype": "default_task",
"old_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"old_text_value": "This was the Old Text",
"previews": [
{
"fallback": "Greg: Great! I like this idea.\\n\\nhttps//a_company.slack.com/archives/ABCDEFG/12345678",
"footer": "Mar 17, 2019 1:25 PM",
"header": "Asana for Slack",
"header_link": "https://asana.comn/apps/slack",
"html_text": "<body>Great! I like this idea.</body>",
"text": "Great! I like this idea.",
"title": "Greg",
"title_link": "https://asana.slack.com/archives/ABCDEFG/12345678"
}
],
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"source": "web",
"story": {
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"resource_subtype": "comment_added",
"text": "marked today"
},
"tag": {
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
},
"target": {
"gid": "1234",
"name": "Bug Task"
},
"task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
}
}
See Input/Output Options to include more fields in your response.
PUT /stories/{story_gid}
Updates the story and returns the full record for the updated story. Only comment stories can have their text updated, and only comment stories and attachment stories can be pinned. Only one of text and html_text can be specified.
Parameters
| Name | Description | ||||
| /story_gid string required | Globally unique identifier for the story. | ||||
| body object required | The comment story to update. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| sticker_name | green_checkmark | |
| sticker_name | people_dancing | |
| sticker_name | dancing_unicorn | |
| sticker_name | heart | |
| sticker_name | party_popper | |
| sticker_name | people_waving_flags | |
| sticker_name | splashing_narwhal | |
| sticker_name | trophy | |
| sticker_name | yeti_riding_unicorn | |
| sticker_name | celebrating_people | |
| sticker_name | determined_climbers | |
| sticker_name | phoenix_spreading_love |
Responses
| Status | Description | ||||
| 200 Story | Successfully retrieved the specified story. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a story
Code samples
curl -X DELETE https://app.asana.com/api/1.0/stories/{story_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /stories/{story_gid}
Deletes a story. A user can only delete stories they have created.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /story_gid string required | Globally unique identifier for the story. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified story. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get stories from a task
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid}/stories \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"resource_subtype": "comment_added",
"text": "marked today"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}/stories
Returns the compact records for all stories on the task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 StoryCompact | Successfully retrieved the specified task's stories. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a story on a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/stories \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"html_text": "<body>This is a comment.<body>",
"is_pinned": false,
"sticker_name": "dancing_unicorn",
"text": "This is a comment."
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"html_text": "<body>This is a comment.<body>",
"is_pinned": false,
"resource_subtype": "comment_added",
"sticker_name": "dancing_unicorn",
"text": "This is a comment.",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"dependency": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicate_of": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicated_from": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"follower": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"hearted": false,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"is_edited": false,
"liked": false,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"new_approval_status": "approved",
"new_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"new_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"new_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"new_name": "This is the New Name",
"new_number_value": 2,
"new_resource_subtype": "milestone",
"new_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"new_text_value": "This is the New Text",
"num_hearts": 5,
"num_likes": 5,
"old_approval_status": "pending",
"old_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"old_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"old_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"old_name": "This was the Old Name",
"old_number_value": 1,
"old_resource_subtype": "default_task",
"old_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"old_text_value": "This was the Old Text",
"previews": [
{
"fallback": "Greg: Great! I like this idea.\\n\\nhttps//a_company.slack.com/archives/ABCDEFG/12345678",
"footer": "Mar 17, 2019 1:25 PM",
"header": "Asana for Slack",
"header_link": "https://asana.comn/apps/slack",
"html_text": "<body>Great! I like this idea.</body>",
"text": "Great! I like this idea.",
"title": "Greg",
"title_link": "https://asana.slack.com/archives/ABCDEFG/12345678"
}
],
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"source": "web",
"story": {
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"resource_subtype": "comment_added",
"text": "marked today"
},
"tag": {
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
},
"target": {
"gid": "1234",
"name": "Bug Task"
},
"task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/stories
Adds a story to a task. This endpoint currently only allows for comment stories to be created. The comment will be authored by the currently authenticated user, and timestamped when the server receives the request.
Returns the full record for the new story added to the task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The story to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| sticker_name | green_checkmark | |
| sticker_name | people_dancing | |
| sticker_name | dancing_unicorn | |
| sticker_name | heart | |
| sticker_name | party_popper | |
| sticker_name | people_waving_flags | |
| sticker_name | splashing_narwhal | |
| sticker_name | trophy | |
| sticker_name | yeti_riding_unicorn | |
| sticker_name | celebrating_people | |
| sticker_name | determined_climbers | |
| sticker_name | phoenix_spreading_love |
Responses
| Status | Description | ||||
| 201 Story | Successfully created a new story. | ||||
| ↓ Show Common Responses ↓ | |||||
Tags
GET /tags
POST /tags
GET /tags/{tag_gid}
PUT /tags/{tag_gid}
DELETE /tags/{tag_gid}
GET /tasks/{task_gid}/tags
GET /workspaces/{workspace_gid}/tags
POST /workspaces/{workspace_gid}/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.
Get multiple tags
Code samples
curl -X GET https://app.asana.com/api/1.0/tags \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tags
Returns the compact tag records for some filtered set of tags. Use one or more of the parameters provided to filter the tags returned.
Parameters
| Name | Description | ||||
| ?workspace string | The workspace to filter tags on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TagCompact | Successfully retrieved the specified set of tags. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a tag
Code samples
curl -X POST https://app.asana.com/api/1.0/tags \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"color": "light-green",
"followers": [
"12345",
"42563"
],
"name": "Stuff to buy",
"workspace": "12345"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "tag",
"color": "light-green",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"name": "Stuff to buy",
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
POST /tags
Creates a new tag in a workspace or organization.
Every tag is required to be created in a specific workspace or organization, and this cannot be changed once set. Note that you can use the workspace parameter regardless of whether or not it is an organization.
Returns the full record of the newly created tag.
Parameters
| Name | Description | ||||
| body object required | The tag to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray |
Responses
| Status | Description | ||||
| 201 Tag | Successfully created the newly specified tag. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a tag
Code samples
curl -X GET https://app.asana.com/api/1.0/tags/{tag_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "tag",
"color": "light-green",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"name": "Stuff to buy",
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
GET /tags/{tag_gid}
Returns the complete tag record for a single tag.
Parameters
| Name | Description | ||||
| /tag_gid string required | Globally unique identifier for the tag. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Tag | Successfully retrieved the specified tag. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a tag
Code samples
curl -X PUT https://app.asana.com/api/1.0/tags/{tag_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "tag",
"color": "light-green",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"name": "Stuff to buy",
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
PUT /tags/{tag_gid}
Updates the properties of a tag. 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 tag.
Returns the complete updated tag record.
Parameters
| Name | Description | ||||
| /tag_gid string required | Globally unique identifier for the tag. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Tag | Successfully updated the specified tag. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a tag
Code samples
curl -X DELETE https://app.asana.com/api/1.0/tags/{tag_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /tags/{tag_gid}
A specific, existing tag can be deleted by making a DELETE request on the URL for that tag.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /tag_gid string required | Globally unique identifier for the tag. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified tag. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get a task's tags
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid}/tags \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}/tags
Get a compact representation of all of the tags the task has.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TagCompact | Successfully retrieved the tags for the given task. | ||||
| ↓ Show Common Responses ↓ | |||||
Get tags in a workspace
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/tags \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}/tags
Returns the compact tag records for some filtered set of tags. Use one or more of the parameters provided to filter the tags returned.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TagCompact | Successfully retrieved the specified set of tags. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a tag in a workspace
Code samples
curl -X POST https://app.asana.com/api/1.0/workspaces/{workspace_gid}/tags \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"color": "light-green",
"name": "Stuff to buy",
"workspace": {
"name": "My Company Workspace"
}
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "tag",
"color": "light-green",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"name": "Stuff to buy",
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
POST /workspaces/{workspace_gid}/tags
Creates a new tag in a workspace or organization.
Every tag is required to be created in a specific workspace or organization, and this cannot be changed once set. Note that you can use the workspace parameter regardless of whether or not it is an organization.
Returns the full record of the newly created tag.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| body object required | The tag to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray |
Responses
| Status | Description | ||||
| 201 Tag | Successfully created the newly specified tag. | ||||
| ↓ Show Common Responses ↓ | |||||
Tasks
GET /tasks
POST /tasks
GET /tasks/{task_gid}
PUT /tasks/{task_gid}
DELETE /tasks/{task_gid}
POST /tasks/{task_gid}/duplicate
GET /projects/{project_gid}/tasks
GET /sections/{section_gid}/tasks
GET /tags/{tag_gid}/tasks
GET /user_task_lists/{user_task_list_gid}/tasks
GET /tasks/{task_gid}/subtasks
POST /tasks/{task_gid}/subtasks
POST /tasks/{task_gid}/setParent
GET /tasks/{task_gid}/dependencies
POST /tasks/{task_gid}/addDependencies
POST /tasks/{task_gid}/removeDependencies
GET /tasks/{task_gid}/dependents
POST /tasks/{task_gid}/addDependents
POST /tasks/{task_gid}/removeDependents
POST /tasks/{task_gid}/addProject
POST /tasks/{task_gid}/removeProject
POST /tasks/{task_gid}/addTag
POST /tasks/{task_gid}/removeTag
POST /tasks/{task_gid}/addFollowers
POST /tasks/{task_gid}/removeFollowers
GET /workspaces/{workspace_gid}/tasks/search
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 determines the more detailed information presented in the details pane.
Sections are unique in that they will be included in the memberships field of task objects returned in the API when the task is within a section. They can also be used to manipulate the ordering of a task within a project.
Queries return a compact representation of each object which is typically the id and name fields. Interested in a specific set of fields or all of the fields? Use field selectors to manipulate what data is included in a response.
Get multiple tasks
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks
Returns the compact task records for some filtered set of tasks. Use one or more of the parameters provided to filter the tasks returned. You must specify a project or tag if you do not specify assignee and workspace.
For more complex task retrieval, use workspaces/{workspace_gid}/tasks/search.
Parameters
| Name | Description | ||||
| ?assignee string | The assignee to filter tasks on. | ||||
| ?project string | The project to filter tasks on. | ||||
| ?section string | The section to filter tasks on. | ||||
| ?workspace string | The workspace to filter tasks on. | ||||
| ?completed_since string(date-time) | Only return tasks that are either incomplete or that have been completed since this time. | ||||
| ?modified_since string(date-time) | Only return tasks that have been modified since the given time. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
assignee: The assignee to filter tasks on.
Note: If you specify assignee, you must also specify the workspace to filter on.
section: The section to filter tasks on. Note: Currently, this is only supported in board views.
workspace: The workspace to filter tasks on.
Note: If you specify workspace, you must also specify the assignee to filter on.
modified_since: Only return tasks that have been modified since the given time.
Note: A task is considered “modified” if any of its properties change, or associations between it and other objects are modified (e.g. a task being added to a project). A task is not considered modified just because another object it is associated with (e.g. a subtask) is modified. Actions that count as modifying the task include assigning, renaming, completing, and adding stories.
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved requested tasks. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"approval_status": "pending",
"assignee": "12345",
"assignee_section": "12345",
"assignee_status": "upcoming",
"completed": false,
"completed_by": {
"name": "Greg Sanchez"
},
"custom_fields": {
"4578152156": "Not Started",
"5678904321": "On Hold"
},
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"followers": [
"12345"
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"liked": true,
"name": "Buy catnip",
"notes": "Mittens really likes the stuff from Humboldt.",
"parent": "12345",
"projects": [
"12345"
],
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"tags": [
"12345"
],
"workspace": "12345"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "task",
"name": "Buy catnip",
"approval_status": "pending",
"assignee_status": "upcoming",
"completed": false,
"completed_at": "2012-02-22T02:06:58.147Z",
"completed_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"dependencies": [
{
"gid": "12345",
"resource_type": "task"
}
],
"dependents": [
{
"gid": "12345",
"resource_type": "task"
}
],
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"hearted": true,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"is_rendered_as_separator": false,
"liked": true,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"memberships": [
{
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "Mittens really likes the stuff from Humboldt.",
"num_hearts": 5,
"num_likes": 5,
"num_subtasks": 3,
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"assignee_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
],
"tags": [
{
"gid": "59746",
"name": "Grade A"
}
],
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
POST /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 projects or a parent task instead.
Parameters
| Name | Description | ||||
| body object required | The task to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
assignee_section: The assignee section is a subdivision of a project that groups tasks together in the assignee's "My Tasks" list. It can either be a header above a list of tasks in a list view or a column in a board view of "My Tasks."
The assignee_section property will be returned in the response only if the request was sent by the user who is the assignee of the task. Note that you can only write to assignee_section with the gid of an existing section visible in the user's "My Tasks" list.
external: OAuth Required. Conditional. This field is returned only if external values are set or included by using Opt In.
The external field allows you to store app-specific metadata on tasks, including a gid that can be used to retrieve tasks and a data blob that can store app-specific character strings. Note that you will need to authenticate with Oauth to access or modify this data. Once an external gid is set, you can use the notation external:custom_gid to reference your object anywhere in the API where you may use the original object gid. See the page on Custom External Data for more details.
resource_subtype: The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning.
The resource_subtype milestone represent a single moment in time. This means tasks with this subtype cannot have a start_date.
start_on: The day on which work begins for the task , or null if the task has no start date. This takes a date with YYYY-MM-DD format.
Note: due_on or due_at must be present in the request when setting or unsetting the start_on parameter.
Enumerated Values
| Parameter | Value | |
| approval_status | pending | |
| approval_status | approved | |
| approval_status | rejected | |
| approval_status | changes_requested | |
| assignee_status | today | |
| assignee_status | upcoming | |
| assignee_status | later | |
| assignee_status | new | |
| assignee_status | inbox | |
| resource_subtype | default_task | |
| resource_subtype | milestone | |
| resource_subtype | section | |
| resource_subtype | approval |
Responses
| Status | Description | ||||
| 201 Task | Successfully created a new task. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a task
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "task",
"name": "Buy catnip",
"approval_status": "pending",
"assignee_status": "upcoming",
"completed": false,
"completed_at": "2012-02-22T02:06:58.147Z",
"completed_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"dependencies": [
{
"gid": "12345",
"resource_type": "task"
}
],
"dependents": [
{
"gid": "12345",
"resource_type": "task"
}
],
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"hearted": true,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"is_rendered_as_separator": false,
"liked": true,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"memberships": [
{
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "Mittens really likes the stuff from Humboldt.",
"num_hearts": 5,
"num_likes": 5,
"num_subtasks": 3,
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"assignee_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
],
"tags": [
{
"gid": "59746",
"name": "Grade A"
}
],
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}
Returns the complete task record for a single task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Task | Successfully retrieved the specified task. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a task
Code samples
curl -X PUT https://app.asana.com/api/1.0/tasks/{task_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"approval_status": "pending",
"assignee": "12345",
"assignee_section": "12345",
"assignee_status": "upcoming",
"completed": false,
"completed_by": {
"name": "Greg Sanchez"
},
"custom_fields": {
"4578152156": "Not Started",
"5678904321": "On Hold"
},
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"followers": [
"12345"
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"liked": true,
"name": "Buy catnip",
"notes": "Mittens really likes the stuff from Humboldt.",
"parent": "12345",
"projects": [
"12345"
],
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"tags": [
"12345"
],
"workspace": "12345"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "task",
"name": "Buy catnip",
"approval_status": "pending",
"assignee_status": "upcoming",
"completed": false,
"completed_at": "2012-02-22T02:06:58.147Z",
"completed_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"dependencies": [
{
"gid": "12345",
"resource_type": "task"
}
],
"dependents": [
{
"gid": "12345",
"resource_type": "task"
}
],
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"hearted": true,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"is_rendered_as_separator": false,
"liked": true,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"memberships": [
{
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "Mittens really likes the stuff from Humboldt.",
"num_hearts": 5,
"num_likes": 5,
"num_subtasks": 3,
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"assignee_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
],
"tags": [
{
"gid": "59746",
"name": "Grade A"
}
],
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
PUT /tasks/{task_gid}
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.
Returns the complete updated task record.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The task to update. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
assignee_section: The assignee section is a subdivision of a project that groups tasks together in the assignee's "My Tasks" list. It can either be a header above a list of tasks in a list view or a column in a board view of "My Tasks."
The assignee_section property will be returned in the response only if the request was sent by the user who is the assignee of the task. Note that you can only write to assignee_section with the gid of an existing section visible in the user's "My Tasks" list.
external: OAuth Required. Conditional. This field is returned only if external values are set or included by using Opt In.
The external field allows you to store app-specific metadata on tasks, including a gid that can be used to retrieve tasks and a data blob that can store app-specific character strings. Note that you will need to authenticate with Oauth to access or modify this data. Once an external gid is set, you can use the notation external:custom_gid to reference your object anywhere in the API where you may use the original object gid. See the page on Custom External Data for more details.
resource_subtype: The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning.
The resource_subtype milestone represent a single moment in time. This means tasks with this subtype cannot have a start_date.
start_on: The day on which work begins for the task , or null if the task has no start date. This takes a date with YYYY-MM-DD format.
Note: due_on or due_at must be present in the request when setting or unsetting the start_on parameter.
Enumerated Values
| Parameter | Value | |
| approval_status | pending | |
| approval_status | approved | |
| approval_status | rejected | |
| approval_status | changes_requested | |
| assignee_status | today | |
| assignee_status | upcoming | |
| assignee_status | later | |
| assignee_status | new | |
| assignee_status | inbox | |
| resource_subtype | default_task | |
| resource_subtype | milestone | |
| resource_subtype | section | |
| resource_subtype | approval |
Responses
| Status | Description | ||||
| 200 Task | Successfully updated the specified task. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a task
Code samples
curl -X DELETE https://app.asana.com/api/1.0/tasks/{task_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /tasks/{task_gid}
A specific, existing task can be deleted by making a DELETE request on the URL for that task. Deleted tasks go into the “trash” of the user making the delete request. Tasks can be recovered from the trash within a period of 30 days; afterward they are completely removed from the system.
Returns an empty data record.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully deleted the specified task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Duplicate a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/duplicate \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"include": [
"notes",
"assignee"
],
"name": "New Task Name"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "job",
"new_project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"new_task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"resource_subtype": "duplicate_task",
"status": "in_progress"
}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/duplicate
Creates and returns a job that will asynchronously handle the duplication.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | Describes the duplicate's name and the fields that will be duplicated. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| include | notes | |
| include | assignee | |
| include | subtasks | |
| include | attachments | |
| include | tags | |
| include | followers | |
| include | projects | |
| include | dates | |
| include | dependencies | |
| include | parent |
Responses
| Status | Description | ||||
| 201 Job | Successfully created the job to handle duplication. | ||||
| ↓ Show Common Responses ↓ | |||||
Get tasks from a project
Code samples
curl -X GET https://app.asana.com/api/1.0/projects/{project_gid}/tasks \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /projects/{project_gid}/tasks
Returns the compact task records for all tasks within the given project, ordered by their priority within the project. Tasks can exist in more than one project at a time.
Parameters
| Name | Description | ||||
| /project_gid string required | Globally unique identifier for the project. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the requested project's tasks. | ||||
| ↓ Show Common Responses ↓ | |||||
Get tasks from a section
Code samples
curl -X GET https://app.asana.com/api/1.0/sections/{section_gid}/tasks \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /sections/{section_gid}/tasks
Board view only: Returns the compact section records for all tasks within the given section.
Parameters
| Name | Description | ||||
| /section_gid string required | The globally unique identifier for the section. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the section's tasks. | ||||
| ↓ Show Common Responses ↓ | |||||
Get tasks from a tag
Code samples
curl -X GET https://app.asana.com/api/1.0/tags/{tag_gid}/tasks \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tags/{tag_gid}/tasks
Returns the compact task records for all tasks with the given tag. Tasks can have more than one tag at a time.
Parameters
| Name | Description | ||||
| /tag_gid string required | Globally unique identifier for the tag. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the tasks associated with the specified tag. | ||||
| ↓ Show Common Responses ↓ | |||||
Get tasks from a user task list
Code samples
curl -X GET https://app.asana.com/api/1.0/user_task_lists/{user_task_list_gid}/tasks \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /user_task_lists/{user_task_list_gid}/tasks
Returns the compact list of tasks in a user’s My Tasks list.
Note: Access control is enforced for this endpoint as with all Asana API endpoints, meaning a user’s private tasks will be filtered out if the API-authenticated user does not have access to them.
Note: Both complete and incomplete tasks are returned by default unless they are filtered out (for example, setting completed_since=now will return only incomplete tasks, which is the default view for “My Tasks” in Asana.)
Parameters
| Name | Description | ||||
| /user_task_list_gid string required | Globally unique identifier for the user task list. | ||||
| ?completed_since string | Only return tasks that are either incomplete or that have been completed since this time. Accepts a date-time string or the keyword now. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
completed_since: Only return tasks that are either incomplete or that have been completed since this time. Accepts a date-time string or the keyword now.
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the user task list's tasks. | ||||
| ↓ Show Common Responses ↓ | |||||
Get subtasks from a task
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid}/subtasks \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}/subtasks
Returns a compact representation of all of the subtasks of a task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the specified task's subtasks. | ||||
| ↓ Show Common Responses ↓ | |||||
Create a subtask
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/subtasks \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"approval_status": "pending",
"assignee": "12345",
"assignee_section": "12345",
"assignee_status": "upcoming",
"completed": false,
"completed_by": {
"name": "Greg Sanchez"
},
"custom_fields": {
"4578152156": "Not Started",
"5678904321": "On Hold"
},
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"followers": [
"12345"
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"liked": true,
"name": "Buy catnip",
"notes": "Mittens really likes the stuff from Humboldt.",
"parent": "12345",
"projects": [
"12345"
],
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"tags": [
"12345"
],
"workspace": "12345"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "task",
"name": "Buy catnip",
"approval_status": "pending",
"assignee_status": "upcoming",
"completed": false,
"completed_at": "2012-02-22T02:06:58.147Z",
"completed_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"dependencies": [
{
"gid": "12345",
"resource_type": "task"
}
],
"dependents": [
{
"gid": "12345",
"resource_type": "task"
}
],
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"hearted": true,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"is_rendered_as_separator": false,
"liked": true,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"memberships": [
{
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "Mittens really likes the stuff from Humboldt.",
"num_hearts": 5,
"num_likes": 5,
"num_subtasks": 3,
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"assignee_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
],
"tags": [
{
"gid": "59746",
"name": "Grade A"
}
],
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/subtasks
Creates a new subtask and adds it to the parent task. Returns the full record for the newly created subtask.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The new subtask to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Detailed descriptions
assignee_section: The assignee section is a subdivision of a project that groups tasks together in the assignee's "My Tasks" list. It can either be a header above a list of tasks in a list view or a column in a board view of "My Tasks."
The assignee_section property will be returned in the response only if the request was sent by the user who is the assignee of the task. Note that you can only write to assignee_section with the gid of an existing section visible in the user's "My Tasks" list.
external: OAuth Required. Conditional. This field is returned only if external values are set or included by using Opt In.
The external field allows you to store app-specific metadata on tasks, including a gid that can be used to retrieve tasks and a data blob that can store app-specific character strings. Note that you will need to authenticate with Oauth to access or modify this data. Once an external gid is set, you can use the notation external:custom_gid to reference your object anywhere in the API where you may use the original object gid. See the page on Custom External Data for more details.
resource_subtype: The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning.
The resource_subtype milestone represent a single moment in time. This means tasks with this subtype cannot have a start_date.
start_on: The day on which work begins for the task , or null if the task has no start date. This takes a date with YYYY-MM-DD format.
Note: due_on or due_at must be present in the request when setting or unsetting the start_on parameter.
Enumerated Values
| Parameter | Value | |
| approval_status | pending | |
| approval_status | approved | |
| approval_status | rejected | |
| approval_status | changes_requested | |
| assignee_status | today | |
| assignee_status | upcoming | |
| assignee_status | later | |
| assignee_status | new | |
| assignee_status | inbox | |
| resource_subtype | default_task | |
| resource_subtype | milestone | |
| resource_subtype | section | |
| resource_subtype | approval |
Responses
| Status | Description | ||||
| 201 Task | Successfully created the specified subtask. | ||||
| ↓ Show Common Responses ↓ | |||||
Set the parent of a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/setParent \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"insert_after": "null",
"insert_before": "124816",
"parent": "987654"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "task",
"name": "Buy catnip",
"approval_status": "pending",
"assignee_status": "upcoming",
"completed": false,
"completed_at": "2012-02-22T02:06:58.147Z",
"completed_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"dependencies": [
{
"gid": "12345",
"resource_type": "task"
}
],
"dependents": [
{
"gid": "12345",
"resource_type": "task"
}
],
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"hearted": true,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"is_rendered_as_separator": false,
"liked": true,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"memberships": [
{
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "Mittens really likes the stuff from Humboldt.",
"num_hearts": 5,
"num_likes": 5,
"num_subtasks": 3,
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"assignee_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
],
"tags": [
{
"gid": "59746",
"name": "Grade A"
}
],
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/setParent
parent, or no parent task at all. Returns an empty data block. When using insert_before and insert_after, at most one of those two options can be specified, and they must already be subtasks of the parent.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The new parent of the subtask. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Task | Successfully changed the parent of the specified subtask. | ||||
| ↓ Show Common Responses ↓ | |||||
Get dependencies from a task
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid}/dependencies \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}/dependencies
Returns the compact representations of all of the dependencies of a task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the specified task's dependencies. | ||||
| ↓ Show Common Responses ↓ | |||||
Set dependencies for a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/addDependencies \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"dependencies": [
"133713",
"184253"
]
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/addDependencies
Marks a set of tasks as dependencies of this task, if they are not already dependencies. A task can have at most 15 dependencies.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The list of tasks to set as dependencies. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully set the specified dependencies on the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Unlink dependencies from a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/removeDependencies \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"dependencies": [
"133713",
"184253"
]
}
}
200 Response
{
"data": [
{}
]
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/removeDependencies
Unlinks a set of dependencies from this task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The list of tasks to unlink as dependencies. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully unlinked the dependencies from the specified task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Get dependents from a task
Code samples
curl -X GET https://app.asana.com/api/1.0/tasks/{task_gid}/dependents \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /tasks/{task_gid}/dependents
Returns the compact representations of all of the dependents of a task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the specified dependents of the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Set dependents for a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/addDependents \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"dependents": [
"133713",
"184253"
]
}
}
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/addDependents
Marks a set of tasks as dependents of this task, if they are not already dependents. A task can have at most 30 dependents.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The list of tasks to add as dependents. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully set the specified dependents on the given task. | ||||
| ↓ Show Common Responses ↓ | |||||
Unlink dependents from a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/removeDependents \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"dependents": [
"133713",
"184253"
]
}
}
200 Response
{
"data": [
{}
]
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/removeDependents
Unlinks a set of dependents from this task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The list of tasks to remove as dependents. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully unlinked the specified tasks as dependents. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Add a project to a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/addProject \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"insert_after": "124816",
"insert_before": "432134",
"project": "13579",
"section": "987654"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/addProject
Adds the task to the specified project, in the optional location specified. If no location arguments are given, the task will be added to the end of the project.
addProject can also be used to reorder a task within a project or
section that already contains it.
At most one of insert_before, insert_after, or section should be
specified. Inserting into a section in an non-order-dependent way can be
done by specifying section, otherwise, to insert within a section in a
particular place, specify insert_before or insert_after and a task
within the section to anchor the position of this task.
Returns an empty data block.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The project to add the task to. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added the specified project to the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove a project from a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/removeProject \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"project": "13579"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/removeProject
Removes the task from the specified project. The task will still exist in the system, but it will not be in the project anymore.
Returns an empty data block.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The project to remove the task from. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the specified project from the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Add a tag to a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/addTag \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"tag": "13579"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/addTag
Adds a tag to a task. Returns an empty data block.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The tag to add to the task. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added the specified tag to the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove a tag from a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/removeTag \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"tag": "13579"
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/removeTag
Removes a tag from a task. Returns an empty data block.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The tag to remove from the task. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the specified tag from the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Add followers to a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/addFollowers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"followers": [
"13579",
"321654"
]
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/addFollowers
Adds followers to a task. Returns an empty data block. Each task can be associated with zero or more followers in the system. Requests to add/remove followers, if successful, will return the complete updated task record, described above.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The followers to add to the task. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully added the specified followers to the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Remove followers from a task
Code samples
curl -X POST https://app.asana.com/api/1.0/tasks/{task_gid}/removeFollowers \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"followers": [
"13579",
"321654"
]
}
}
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /tasks/{task_gid}/removeFollowers
Removes each of the specified followers from the task if they are following. Returns the complete, updated record for the affected task.
Parameters
| Name | Description | ||||
| /task_gid string required | The task to operate on. | ||||
| body object required | The followers to remove from the task. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully removed the specified followers from the task. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Search tasks in a workspace
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/tasks/search \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}/tasks/search
To mirror the functionality of the Asana web app's advanced search feature, the Asana API has a task search endpoint that allows you to build complex filters to find and retrieve the exact data you need.
Premium access
Like the Asana web product's advance search feature, this search endpoint will only be available to premium Asana users. A user is premium if any of the following is true:
- The workspace in which the search is being performed is a premium workspace - The user is a member of a premium team inside the workspace
Even if a user is only a member of a premium team inside a non-premium workspace, search will allow them to find data anywhere in the workspace, not just inside the premium team. Making a search request using credentials of a non-premium user will result in a 402 Payment Required error.
Pagination
Search results are not stable; repeating the same query multiple times may return the data in a different order, even if the data do not change. Because of this, the traditional pagination available elsewhere in the Asana API is not available here. However, you can paginate manually by sorting the search results by their creation time and then modifying each subsequent query to exclude data you have already seen. Page sizes are limited to a maximum of 100 items, and can be specified by the limit query parameter.
Eventual consistency
Changes in Asana (regardless of whether they’re made though the web product or the API) are forwarded to our search infrastructure to be indexed. This process can take between 10 and 60 seconds to complete under normal operation, and longer during some production incidents. Making a change to a task that would alter its presence in a particular search query will not be reflected immediately. This is also true of the advanced search feature in the web product.
Rate limits
You may receive a 429 Too Many Requests response if you hit any of our rate limits.
Custom field parameters
| Parameter name | Custom field type | Accepted type | |
| custom_fields.{gid}.is_set | All | Boolean | |
| custom_fields.{gid}.value | Text | String | |
| custom_fields.{gid}.value | Number | Number | |
| custom_fields.{gid}.value | Enum | Enum option ID | |
| custom_fields.{gid}.starts_with | Text only | String | |
| custom_fields.{gid}.ends_with | Text only | String | |
| custom_fields.{gid}.contains | Text only | String | |
| custom_fields.{gid}.less_than | Number only | Number | |
| custom_fields.{gid}.greater_than | Number only | Number |
For example, if the gid of the custom field is 12345, these query parameter to find tasks where it is set would be custom_fields.12345.is_set=true. To match an exact value for an enum custom field, use the gid of the desired enum option and not the name of the enum option: custom_fields.12345.value=67890.
Searching for multiple exact matches of a custom field is not supported.
Note: If you specify projects.any and sections.any, you will receive tasks for the project **and* tasks for the section. If you're looking for only tasks in a section, omit the projects.any from the request.*
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ?text string | Performs full-text search on both task name and description | ||||
| ?resource_subtype string | Filters results by the task's resource_subtype | ||||
| ?assignee.any string | Comma-separated list of user identifiers | ||||
| ?assignee.not string | Comma-separated list of user identifiers | ||||
| ?portfolios.any string | Comma-separated list of portfolio IDs | ||||
| ?projects.any string | Comma-separated list of project IDs | ||||
| ?projects.not string | Comma-separated list of project IDs | ||||
| ?projects.all string | Comma-separated list of project IDs | ||||
| ?sections.any string | Comma-separated list of section or column IDs | ||||
| ?sections.not string | Comma-separated list of section or column IDs | ||||
| ?sections.all string | Comma-separated list of section or column IDs | ||||
| ?tags.any string | Comma-separated list of tag IDs | ||||
| ?tags.not string | Comma-separated list of tag IDs | ||||
| ?tags.all string | Comma-separated list of tag IDs | ||||
| ?teams.any string | Comma-separated list of team IDs | ||||
| ?followers.any string | Comma-separated list of user identifiers | ||||
| ?followers.not string | Comma-separated list of user identifiers | ||||
| ?created_by.any string | Comma-separated list of user identifiers | ||||
| ?created_by.not string | Comma-separated list of user identifiers | ||||
| ?assigned_by.any string | Comma-separated list of user identifiers | ||||
| ?assigned_by.not string | Comma-separated list of user identifiers | ||||
| ?liked_by.any string | Comma-separated list of user identifiers | ||||
| ?liked_by.not string | Comma-separated list of user identifiers | ||||
| ?commented_on_by.any string | Comma-separated list of user identifiers | ||||
| ?commented_on_by.not string | Comma-separated list of user identifiers | ||||
| ?due_on.before string(date) | ISO 8601 date string | ||||
| ?due_on.after string(date) | ISO 8601 date string | ||||
| ?due_on string(date) | ISO 8601 date string or null | ||||
| ?due_at.before string(date-time) | ISO 8601 datetime string | ||||
| ?due_at.after string(date-time) | ISO 8601 datetime string | ||||
| ?start_on.before string(date) | ISO 8601 date string | ||||
| ?start_on.after string(date) | ISO 8601 date string | ||||
| ?start_on string(date) | ISO 8601 date string or null | ||||
| ?created_on.before string(date) | ISO 8601 date string | ||||
| ?created_on.after string(date) | ISO 8601 date string | ||||
| ?created_on string(date) | ISO 8601 date string or null | ||||
| ?created_at.before string(date-time) | ISO 8601 datetime string | ||||
| ?created_at.after string(date-time) | ISO 8601 datetime string | ||||
| ?completed_on.before string(date) | ISO 8601 date string | ||||
| ?completed_on.after string(date) | ISO 8601 date string | ||||
| ?completed_on string(date) | ISO 8601 date string or null | ||||
| ?completed_at.before string(date-time) | ISO 8601 datetime string | ||||
| ?completed_at.after string(date-time) | ISO 8601 datetime string | ||||
| ?modified_on.before string(date) | ISO 8601 date string | ||||
| ?modified_on.after string(date) | ISO 8601 date string | ||||
| ?modified_on string(date) | ISO 8601 date string or null | ||||
| ?modified_at.before string(date-time) | ISO 8601 datetime string | ||||
| ?modified_at.after string(date-time) | ISO 8601 datetime string | ||||
| ?is_blocking boolean | Filter to incomplete tasks with dependents | ||||
| ?is_blocked boolean | Filter to tasks with incomplete dependencies | ||||
| ?has_attachment boolean | Filter to tasks with attachments | ||||
| ?completed boolean | Filter to completed tasks | ||||
| ?is_subtask boolean | Filter to subtasks | ||||
| ?sort_by string | One of due_date, created_at, completed_at, likes, or modified_at, defaults to modified_at | ||||
| ?sort_ascending boolean | Default false | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| resource_subtype | default_task | |
| resource_subtype | milestone | |
| sort_by | due_date | |
| sort_by | created_at | |
| sort_by | completed_at | |
| sort_by | likes | |
| sort_by | modified_at |
Responses
| Status | Description | ||||
| 200 TaskCompact | Successfully retrieved the section's tasks. | ||||
| ↓ Show Common Responses ↓ | |||||
Teams
POST /teams
GET /teams/{team_gid}
GET /organizations/{workspace_gid}/teams
GET /users/{user_gid}/teams
POST /teams/{team_gid}/addUser
POST /teams/{team_gid}/removeUser
A team is used to group related projects and people together within an organization. Each project in an organization is associated with a team.
Create a team
Code samples
curl -X POST https://app.asana.com/api/1.0/teams \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"description": "All developers should be members of this team.",
"html_description": "<body><em>All</em> developers should be members of this team.</body>",
"name": "Marketing",
"organization": "123456789"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing",
"description": "All developers should be members of this team.",
"html_description": "<body><em>All</em> developers should be members of this team.</body>",
"organization": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list"
}
}
See Input/Output Options to include more fields in your response.
POST /teams
Creates a team within the current workspace.
Parameters
| Name | Description | ||||
| body object required | The team to create. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 201 Team | Successfully created a new team. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a team
Code samples
curl -X GET https://app.asana.com/api/1.0/teams/{team_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing",
"description": "All developers should be members of this team.",
"html_description": "<body><em>All</em> developers should be members of this team.</body>",
"organization": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list"
}
}
See Input/Output Options to include more fields in your response.
GET /teams/{team_gid}
Returns the full record for a single team.
Parameters
| Name | Description | ||||
| /team_gid string required | Globally unique identifier for the team. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Team | Successsfully retrieved the record for a single team. | ||||
| ↓ Show Common Responses ↓ | |||||
Get teams in an organization
Code samples
curl -X GET https://app.asana.com/api/1.0/organizations/{workspace_gid}/teams \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
]
}
See Input/Output Options to include more fields in your response.
GET /organizations/{workspace_gid}/teams
Returns the compact records for all teams in the organization visible to the authorized user.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TeamCompact | Returns the team records for all teams in the organization or workspace accessible to the authenticated user. | ||||
| ↓ Show Common Responses ↓ | |||||
Get teams for a user
Code samples
curl -X GET https://app.asana.com/api/1.0/users/{user_gid}/teams?organization=1331 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
]
}
See Input/Output Options to include more fields in your response.
GET /users/{user_gid}/teams
Returns the compact records for all teams to which the given user is assigned.
Parameters
| Name | Description | ||||
| /user_gid string required | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ?organization string required | The workspace or organization to filter teams on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TeamCompact | Returns the team records for all teams in the organization or workspace to which the given user is assigned. | ||||
| ↓ Show Common Responses ↓ | |||||
Add a user to a team
Code samples
curl -X POST https://app.asana.com/api/1.0/teams/{team_gid}/addUser \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"user": "12345"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez",
"email": "gsanchez@example.com",
"photo": {
"image_128x128": "https://...",
"image_21x21": "https://...",
"image_27x27": "https://...",
"image_36x36": "https://...",
"image_60x60": "https://..."
},
"workspaces": [
{
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
]
}
}
See Input/Output Options to include more fields in your response.
POST /teams/{team_gid}/addUser
The user making this call must be a member of the team in order to add others. The user being added must exist in the same organization as the team.
Parameters
| Name | Description | ||||
| /team_gid string required | Globally unique identifier for the team. | ||||
| body object required | The user to add to the team. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 User | Returns the full user record for the added user. | ||||
| ↓ Show Common Responses ↓ | |||||
Remove a user from a team
Code samples
curl -X POST https://app.asana.com/api/1.0/teams/{team_gid}/removeUser \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"user": "12345"
}
}
204 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /teams/{team_gid}/removeUser
The user making this call must be a member of the team in order to remove themselves or others.
Parameters
| Name | Description | ||||
| /team_gid string required | Globally unique identifier for the team. | ||||
| body object required | The user to remove from the team. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 204 Inline | Returns an empty data record | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 204
Team Memberships
GET /team_memberships/{team_membership_gid}
GET /team_memberships
GET /teams/{team_gid}/team_memberships
GET /users/{user_gid}/team_memberships
This object determines if a user is a member of a team.
Get a team membership
Code samples
curl -X GET https://app.asana.com/api/1.0/team_memberships/{team_membership_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "team_membership",
"is_guest": false,
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
}
See Input/Output Options to include more fields in your response.
GET /team_memberships/{team_membership_gid}
Returns the complete team membership record for a single team membership.
Parameters
| Name | Description | ||||
| /team_membership_gid string required | none | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TeamMembership | Successfully retrieved the requested team membership. | ||||
| ↓ Show Common Responses ↓ | |||||
Get team memberships
Code samples
curl -X GET https://app.asana.com/api/1.0/team_memberships \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "team_membership",
"is_guest": false,
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /team_memberships
Returns compact team membership records.
Parameters
| Name | Description | ||||
| ?team string | Globally unique identifier for the team. | ||||
| ?user string | A string identifying a user. This can either be the string "me", an email, or the gid of a user. This parameter must be used with the workspace parameter. | ||||
| ?workspace string | Globally unique identifier for the workspace. This parameter must be used with the user parameter. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TeamMembershipCompact | Successfully retrieved the requested team memberships. | ||||
| ↓ Show Common Responses ↓ | |||||
Get memberships from a team
Code samples
curl -X GET https://app.asana.com/api/1.0/teams/{team_gid}/team_memberships \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "team_membership",
"is_guest": false,
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /teams/{team_gid}/team_memberships
Returns the compact team memberships for the team.
Parameters
| Name | Description | ||||
| /team_gid string required | Globally unique identifier for the team. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TeamMembershipCompact | Successfully retrieved the requested team's memberships. | ||||
| ↓ Show Common Responses ↓ | |||||
Get memberships from a user
Code samples
curl -X GET https://app.asana.com/api/1.0/users/{user_gid}/team_memberships?workspace=31326 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "team_membership",
"is_guest": false,
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /users/{user_gid}/team_memberships
Returns the compact team membership records for the user.
Parameters
| Name | Description | ||||
| /user_gid string required | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ?workspace string required | Globally unique identifier for the workspace. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 TeamMembershipCompact | Successfully retrieved the requested users's memberships. | ||||
| ↓ Show Common Responses ↓ | |||||
Typeahead
GET /workspaces/{workspace_gid}/typeahead
The typeahead search API provides search for objects from a single workspace.
Get objects via typeahead
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/typeahead?resource_type=user \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}/typeahead
Retrieves objects in the workspace based via an auto-completion/typeahead search algorithm. This feature is meant to provide results quickly, so do not rely on this API to provide extremely accurate search results. The result set is limited to a single page of results with a maximum size, so you won’t be able to fetch large numbers of results.
The typeahead search API provides search for objects from a single workspace. This endpoint should be used to query for objects when creating an auto-completion/typeahead search feature. This API is meant to provide results quickly and should not be relied upon for accurate or exhaustive search results. The results sets are limited in size and cannot be paginated.
Queries return a compact representation of each object which is typically the gid and name fields. Interested in a specific set of fields or all of the fields?! Of course you are. Use field selectors to manipulate what data is included in a response.
Resources with type user are returned in order of most contacted to
least contacted. This is determined by task assignments, adding the user
to projects, and adding the user as a follower to tasks, messages,
etc.
Resources with type project are returned in order of recency. This is
determined when the user visits the project, is added to the project, and
completes tasks in the project.
Resources with type task are returned with priority placed on tasks
the user is following, but no guarantee on the order of those tasks.
Leaving the query string empty or omitted will give you results, still
following the resource ordering above. This could be used to list users or
projects that are relevant for the requesting user's api token.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ?resource_type string required | The type of values the typeahead should return. You can choose from one of the following: custom_field, project, portfolio, tag, task, and user. Note that unlike in the names of endpoints, the types listed here are in singular form (e.g. task). Using multiple types is not yet supported. | ||||
| ?type string | Deprecated: new integrations should prefer the resource_type field. | ||||
| ?query string | The string that will be used to search for relevant objects. If an empty string is passed in, the API will currently return an empty result set. | ||||
| ?count integer | The number of results to return. The default is 20 if this parameter is omitted, with a minimum of 1 and a maximum of 100. If there are fewer results found than requested, all will be returned. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| resource_type | custom_field | |
| resource_type | portfolio | |
| resource_type | project | |
| resource_type | tag | |
| resource_type | task | |
| resource_type | user | |
| type | custom_field | |
| type | portfolio | |
| type | project | |
| type | tag | |
| type | task | |
| type | user |
Responses
| Status | Description | ||||
| 200 AsanaNamedResource | Successfully retrieved objects via a typeahead search algorithm. | ||||
| ↓ Show Common Responses ↓ | |||||
Users
GET /users
GET /users/{user_gid}
GET /users/{user_gid}/favorites
GET /teams/{team_gid}/users
GET /workspaces/{workspace_gid}/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.
Get multiple users
Code samples
curl -X GET https://app.asana.com/api/1.0/users \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
]
}
See Input/Output Options to include more fields in your response.
GET /users
Returns the user records for all users in all workspaces and organizations accessible to the authenticated user. Accepts an optional workspace ID parameter. Results are sorted by user ID.
Parameters
| Name | Description | ||||
| ?workspace string | The workspace or organization ID to filter users on. | ||||
| ?team string | The team ID to filter users on. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 UserCompact | Successfully retrieved the requested user records. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a user
Code samples
curl -X GET https://app.asana.com/api/1.0/users/{user_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez",
"email": "gsanchez@example.com",
"photo": {
"image_128x128": "https://...",
"image_21x21": "https://...",
"image_27x27": "https://...",
"image_36x36": "https://...",
"image_60x60": "https://..."
},
"workspaces": [
{
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
]
}
}
See Input/Output Options to include more fields in your response.
GET /users/{user_gid}
Returns the full user record for the single user with the provided ID.
Parameters
| Name | Description | ||||
| /user_gid string required | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 User | Returns the user specified. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a user's favorites
Code samples
curl -X GET https://app.asana.com/api/1.0/users/{user_gid}/favorites?resource_type=project&workspace=1234 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
]
}
See Input/Output Options to include more fields in your response.
GET /users/{user_gid}/favorites
Returns all of a user's favorites in the given workspace, of the given type. Results are given in order (The same order as Asana's sidebar).
Parameters
| Name | Description | ||||
| /user_gid string required | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ?resource_type string required | The resource type of favorites to be returned. | ||||
| ?workspace string required | The workspace in which to get favorites. | ||||
| ↓ Show Common Parameters ↓ | |||||
Enumerated Values
| Parameter | Value | |
| resource_type | portfolio | |
| resource_type | project | |
| resource_type | tag | |
| resource_type | task | |
| resource_type | user |
Responses
| Status | Description | ||||
| 200 AsanaNamedResource | Returns the specified user's favorites. | ||||
| ↓ Show Common Responses ↓ | |||||
Get users in a team
Code samples
curl -X GET https://app.asana.com/api/1.0/teams/{team_gid}/users \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
]
}
See Input/Output Options to include more fields in your response.
GET /teams/{team_gid}/users
Returns the compact records for all users that are members of the team.
Results are sorted alphabetically and limited to 2000. For more results use the /users endpoint.
Parameters
| Name | Description | ||||
| /team_gid string required | Globally unique identifier for the team. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 UserCompact | Returns the user records for all the members of the team, including guests and limited access users | ||||
| ↓ Show Common Responses ↓ | |||||
Get users in a workspace or organization
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/users \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}/users
Returns the compact records for all users in the specified workspace or organization.
Results are sorted alphabetically and limited to 2000. For more results use the /users endpoint.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 UserCompact | Return the users in the specified workspace or org. | ||||
| ↓ Show Common Responses ↓ | |||||
User Task Lists
GET /user_task_lists/{user_task_list_gid}
GET /users/{user_gid}/user_task_list
A user task list represents the tasks assigned to a particular user.
Get a user task list
Code samples
curl -X GET https://app.asana.com/api/1.0/user_task_lists/{user_task_list_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "user_task_list",
"name": "My Tasks in My Workspace",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
GET /user_task_lists/{user_task_list_gid}
Returns the full record for a user task list.
Parameters
| Name | Description | ||||
| /user_task_list_gid string required | Globally unique identifier for the user task list. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 UserTaskList | Successfully retrieved the user task list. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a user's task list
Code samples
curl -X GET https://app.asana.com/api/1.0/users/{user_gid}/user_task_list?workspace=1234 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "user_task_list",
"name": "My Tasks in My Workspace",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
See Input/Output Options to include more fields in your response.
GET /users/{user_gid}/user_task_list
Returns the full record for a user's task list.
Parameters
| Name | Description | ||||
| /user_gid string required | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ?workspace string required | The workspace in which to get the user task list. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 UserTaskList | Successfully retrieved the user's task list. | ||||
| ↓ Show Common Responses ↓ | |||||
Webhooks
GET /webhooks
POST /webhooks
GET /webhooks/{webhook_gid}
DELETE /webhooks/{webhook_gid}
Note: Recently, some users have seen intermittent delays with webhook event distributions. We are in the process of transferring the webhooks system to a more reliable infrastructure while also iteratively improving the current system. As such, for the time being we advise against using webhooks for functionality beyond logging (e.g., syncing state with real-time notification data). If you experience latency issues, we recommend using webhooks in conjunction with fetching the resource periodically (e.g. GET a task). More details and ongoing updates can be found in this post in the developer forum. Webhooks allow an application to be notified of changes in Asana.
This is similar to our Events resource, but webhooks "push" events via HTTP POST rather than expecting integrations to repeatedly "poll" for them. For services that are already accessible on the Internet this is often more convenient and efficient.
However, webhooks require a server to be accessible over the internet at all times to receive the event. For most simple integrations, Events provide much of the same benefits while using a significantly simpler implementation which does not require maintaining an internet-accessible server.
The webhook "handshake"
In order to ensure that the receiving server is available to receive incoming events from a webhook Asana will POST to the requested target endpoint during the webhook creation request. In other words, the outgoing webhook creation request will wait to return until another full POST request from Asana's servers to the target has been completed, then the webhook creation request can return with a successful response.
Note: this means that your server must be able to handle being blocked on the outgoing create request while still being able to receive and handle an incoming request. A common reason that webhook handshakes fail is that servers are not able to asynchronously handle the handshake request.
Included in the webhook handshake is a HTTP header called X-Hook-Secret. To successfully complete the handshake the receiving server should echo back the same header with the same value and a 200 OK or 204 No Content response code.
The purpose of this header is to provide a shared secret that both Asana and the receiving server both store--this is the only time it will be transmitted. In future webhook events Asana will use this key to compute a signature over the webhook callback request's body which can be used to verify that the incoming request was genuine (details below). We strongly recommend that you take advantage of this security feature and reject webhooks that have an invalid signature.
Receiving Events
Because multiple events often happen in short succession, a webhook payload is designed to be able to transmit multiple events at once. The schema of these events is described in Event.
The HTTP POST that the target receives contains:
- An
X-Hook-Signatureheader, which allows verifying that the payload is genuine. The signature is a SHA256 HMAC signature computed on the request body using the shared secret transmitted during the handshake. Verification is strongly recommended, as it would otherwise be possible for an attacker to POST a malicious payload to the same endpoint. - A JSON body with a single key,
events, containing an array of the events that have occurred since the last webhook delivery. (Note that this list may be empty, as periodically we send a "heartbeat" webhook to verify that the endpoint is still available.)
Note that events are "skinny" and contain only some basic details of the change, not the whole resource. We expect integrations to make additional calls to the API to retrieve the latest state from Asana.
Filtering
Webhook events will "propagate up" from contained objects through to parent objects--for instance, changes to comments will be sent to webhooks on the parent task and to ones on the task's projects. In this way a webhook on a project will be notified of all changes that occur in all of its tasks, subtasks of those tasks, and comments on those tasks and subtasks.
This can be a lot of data, some of which might not be relevant to a particular integration, so Asana's webhooks have a filtering feature which allows integrations to specify only the types of changes that they care about. By specifying the list of WebhookFilters on webhook creation an integration can select just the subset of events it wants to receive. When filters are specified on the webhook events will only be delivered if they pass any of the filters specified when creating the webhook.
To reduce the volume of data to transfer, webhooks created on teams, portfolios, and workspaces must specify filters. In addition, the set of event filters that can be placed on a team-level or workspace-level webhook is more limited than filters for webhooks that are created on lower-level resources:
- Webhook events from tasks, subtasks, and stories won't be propagated to these higher-level webhooks, so all changes on these resources are automatically filtered out.
- Webhook events from
projectresources can be filtered for theseactions:added,removed,deleted,undeleted, andchanged. - Webhook events from
team_membershipresources can be filtered toactionsaddedandremoved. - Webhook events from
workspace_membershipresources can be filtered toaddedandremoved.
Error Handling and Retry
If we attempt to send a webhook payload and we receive an error status code, or the request times out, we will retry delivery with exponential backoff. In general, if your servers are not available for an hour, you can expect it to take no longer than approximately an hour after they come back before the paused delivery resumes. However, if we are unable to deliver a message for 24 hours the webhook will be deactivated.
Webhook Heartbeat Events
Webhooks keep track of the last time that delivery succeeded, and this time is updated with each success. To help facilitate this, webhooks have a “heartbeat” that will deliver an empty payload at the initial handshake, and then every eight hours. This way, even if there is no activity on the resource, the last success time (i.e last_success_at) will still be updated continuously.
Resources and Actions
This is not an exhaustive list, but should cover the most common use cases.
- Attachment - deleted, undeleted
- Portfolio - added, deleted, removed
- Project - added, changed, deleted, removed, undeleted
- Project Membership - added, removed
- Section - added, changed, deleted, undeleted
- Story - added, removed, undeleted
- Tag - added, changed, deleted, undeleted
- Task - added, changed, deleted, removed, undeleted
- Team - added, changed, deleted
- Team Membership - added, removed
- Workspace - added, removed, changed
- Workspace Memberships - added, removed
Webhook Limits
Webhooks have two different limits
- 1k limit per resource in Asana. (If 10 apps each have 100 webhooks
watching the same resource, no more webhooks can be placed on the
webhook.
/eventsstreams count towards this limit) - 10k per user-app (An app can have 10k webhooks for EACH user)
Example Integration: Webhook Inspector
The Webhook Inspector is a Python script that demonstrates the features of Asana webhooks, including how to both properly set them up and receive them. By using this script, you can create a webhook and log the contents of incoming notifications to your console. To use this demo, be sure to generate a new personal access token, then follow the instructions in README.
Get multiple webhooks
Code samples
curl -X GET https://app.asana.com/api/1.0/webhooks?workspace=1331 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "webhook",
"active": false,
"resource": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"target": "https://example.com/receive-webhook/7654",
"created_at": "2012-02-22T02:06:58.147Z",
"filters": [
{
"action": "changed",
"fields": [
"due_at",
"due_on",
"dependencies"
],
"resource_subtype": "milestone",
"resource_type": "task"
}
],
"last_failure_at": "2012-02-22T02:06:58.147Z",
"last_failure_content": "500 Server Error\\n\\nCould not complete the request",
"last_success_at": "2012-02-22T02:06:58.147Z"
}
]
}
See Input/Output Options to include more fields in your response.
GET /webhooks
Get the compact representation of all webhooks your app has registered for the authenticated user in the given workspace.
Parameters
| Name | Description | ||||
| ?workspace string required | The workspace to query for webhooks in. | ||||
| ?resource string | Only return webhooks for the given resource. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Webhook | Successfully retrieved the requested webhooks. | ||||
| ↓ Show Common Responses ↓ | |||||
Establish a webhook
Code samples
curl -X POST https://app.asana.com/api/1.0/webhooks \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"filters": [
{
"action": "changed",
"fields": [
"due_at",
"due_on",
"dependencies"
],
"resource_subtype": "milestone",
"resource_type": "task"
}
],
"resource": "12345",
"target": "https://example.com/receive-webhook/7654?app_specific_param=app_specific_value"
}
}
201 Response
{
"data": {
"gid": "12345",
"resource_type": "webhook",
"active": false,
"resource": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"target": "https://example.com/receive-webhook/7654",
"created_at": "2012-02-22T02:06:58.147Z",
"filters": [
{
"action": "changed",
"fields": [
"due_at",
"due_on",
"dependencies"
],
"resource_subtype": "milestone",
"resource_type": "task"
}
],
"last_failure_at": "2012-02-22T02:06:58.147Z",
"last_failure_content": "500 Server Error\\n\\nCould not complete the request",
"last_success_at": "2012-02-22T02:06:58.147Z"
}
}
See Input/Output Options to include more fields in your response.
POST /webhooks
Establishing a webhook is a two-part process. First, a simple HTTP POST request initiates the creation similar to creating any other resource.
Next, in the middle of this request comes the confirmation handshake.
When a webhook is created, we will send a test POST to the target with an
X-Hook-Secret header. The target must respond with a 200 OK or 204
No Content and a matching X-Hook-Secret header to confirm that this
webhook subscription is indeed expected. We strongly recommend storing
this secret to be used to verify future webhook event signatures.
The POST request to create the webhook will then return with the status of the request. If you do not acknowledge the webhook’s confirmation handshake it will fail to setup, and you will receive an error in response to your attempt to create it. This means you need to be able to receive and complete the webhook while the POST request is in-flight (in other words, have a server that can handle requests asynchronously).
Invalid hostnames like localhost will recieve a 403 Forbidden status code.
# Request
curl -H "Authorization: Bearer <personal_access_token>" \
-X POST https://app.asana.com/api/1.0/webhooks \
-d "resource=8675309" \
-d "target=https://example.com/receive-webhook/7654"
# Handshake sent to https://example.com/
POST /receive-webhook/7654
X-Hook-Secret: b537207f20cbfa02357cf448134da559e8bd39d61597dcd5631b8012eae53e81
# Handshake response sent by example.com
HTTP/1.1 200
X-Hook-Secret: b537207f20cbfa02357cf448134da559e8bd39d61597dcd5631b8012eae53e81
# Response
HTTP/1.1 201
{
"data": {
"gid": "43214",
"resource": {
"gid": "8675309",
"name": "Bugs"
},
"target": "https://example.com/receive-webhook/7654",
"active": false,
"last_success_at": null,
"last_failure_at": null,
"last_failure_content": null
}
}
Parameters
| Name | Description | ||||
| body object required | The webhook workspace and target. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 201 Webhook | Successfully created the requested webhook. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a webhook
Code samples
curl -X GET https://app.asana.com/api/1.0/webhooks/{webhook_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "webhook",
"active": false,
"resource": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"target": "https://example.com/receive-webhook/7654",
"created_at": "2012-02-22T02:06:58.147Z",
"filters": [
{
"action": "changed",
"fields": [
"due_at",
"due_on",
"dependencies"
],
"resource_subtype": "milestone",
"resource_type": "task"
}
],
"last_failure_at": "2012-02-22T02:06:58.147Z",
"last_failure_content": "500 Server Error\\n\\nCould not complete the request",
"last_success_at": "2012-02-22T02:06:58.147Z"
}
}
See Input/Output Options to include more fields in your response.
GET /webhooks/{webhook_gid}
Returns the full record for the given webhook.
Parameters
| Name | Description | ||||
| /webhook_gid string required | Globally unique identifier for the webhook. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Webhook | Successfully retrieved the requested webhook. | ||||
| ↓ Show Common Responses ↓ | |||||
Delete a webhook
Code samples
curl -X DELETE https://app.asana.com/api/1.0/webhooks/{webhook_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
DELETE /webhooks/{webhook_gid}
This method permanently removes a webhook. Note that it may be possible to receive a request that was already in flight after deleting the webhook, but no further requests will be issued.
Parameters
| Name | Description | ||||
| /webhook_gid string required | Globally unique identifier for the webhook. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Inline | Successfully retrieved the requested webhook. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 200
Workspaces
GET /workspaces
GET /workspaces/{workspace_gid}
PUT /workspaces/{workspace_gid}
POST /workspaces/{workspace_gid}/addUser
POST /workspaces/{workspace_gid}/removeUser
A workspace is the highest-level 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.
Get multiple workspaces
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces
Returns the compact records for all workspaces visible to the authorized user.
Parameters
| Name | Description | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 WorkspaceCompact | Return all workspaces visible to the authorized user. | ||||
| ↓ Show Common Responses ↓ | |||||
Get a workspace
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace",
"email_domains": [
"asana.com"
],
"is_organization": false
}
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}
Returns the full workspace record for a single workspace.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Workspace | Return the full workspace record. | ||||
| ↓ Show Common Responses ↓ | |||||
Update a workspace
Code samples
curl -X PUT https://app.asana.com/api/1.0/workspaces/{workspace_gid} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"name": "My Company Workspace"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace",
"email_domains": [
"asana.com"
],
"is_organization": false
}
}
See Input/Output Options to include more fields in your response.
PUT /workspaces/{workspace_gid}
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. Returns the complete, updated workspace record.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| body object required | The workspace object with all updated properties. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 Workspace | Update for the workspace was successful. | ||||
| ↓ Show Common Responses ↓ | |||||
Add a user to a workspace or organization
Code samples
curl -X POST https://app.asana.com/api/1.0/workspaces/{workspace_gid}/addUser \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"user": "12345"
}
}
200 Response
{
"data": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez",
"email": "gsanchez@example.com",
"photo": {
"image_128x128": "https://...",
"image_21x21": "https://...",
"image_27x27": "https://...",
"image_36x36": "https://...",
"image_60x60": "https://..."
},
"workspaces": [
{
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
]
}
}
See Input/Output Options to include more fields in your response.
POST /workspaces/{workspace_gid}/addUser
Add a user to a workspace or organization. The user can be referenced by their globally unique user ID or their email address. Returns the full user record for the invited user.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| body object required | The user to add to the workspace. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 User | The user was added successfully to the workspace or organization. | ||||
| ↓ Show Common Responses ↓ | |||||
Remove a user from a workspace or organization
Code samples
curl -X POST https://app.asana.com/api/1.0/workspaces/{workspace_gid}/removeUser \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"data": {"field":"value","field":"value"} }'
Body parameter
{
"data": {
"user": "12345"
}
}
204 Response
{
"data": {}
}
See Input/Output Options to include more fields in your response.
POST /workspaces/{workspace_gid}/removeUser
Remove a user from a workspace or organization. The user making this call must be an admin in the workspace. The user can be referenced by their globally unique user ID or their email address. Returns an empty data record.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| body object required | The user to remove from the workspace. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 204 Inline | The user was removed successfully to the workspace or organization. | ||||
| ↓ Show Common Responses ↓ | |||||
Response Schema
Status Code 204
Workspace Memberships
GET /workspace_memberships/{workspace_membership_gid}
GET /users/{user_gid}/workspace_memberships
GET /workspaces/{workspace_gid}/workspace_memberships
This object determines if a user is a member of a workspace.
Get a workspace membership
Code samples
curl -X GET https://app.asana.com/api/1.0/workspace_memberships/{workspace_membership_gid} \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": {
"gid": "12345",
"resource_type": "workspace_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"is_active": true,
"is_admin": true,
"is_guest": true,
"user_task_list": {
"gid": "12345",
"resource_type": "user_task_list",
"name": "My Tasks in My Workspace",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
}
See Input/Output Options to include more fields in your response.
GET /workspace_memberships/{workspace_membership_gid}
Returns the complete workspace record for a single workspace membership.
Parameters
| Name | Description | ||||
| /workspace_membership_gid string required | none | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 WorkspaceMembership | Successfully retrieved the requested workspace membership. | ||||
| ↓ Show Common Responses ↓ | |||||
Get workspace memberships for a user
Code samples
curl -X GET https://app.asana.com/api/1.0/users/{user_gid}/workspace_memberships \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "workspace_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /users/{user_gid}/workspace_memberships
Returns the compact workspace membership records for the user.
Parameters
| Name | Description | ||||
| /user_gid string required | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | ||||
| 200 WorkspaceMembershipCompact | Successfully retrieved the requested user's workspace memberships. | ||||
| ↓ Show Common Responses ↓ | |||||
Get the workspace memberships for a workspace
Code samples
curl -X GET https://app.asana.com/api/1.0/workspaces/{workspace_gid}/workspace_memberships \
-H 'Accept: application/json' \
-H 'Authorization: Bearer {access-token}'
200 Response
{
"data": [
{
"gid": "12345",
"resource_type": "workspace_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
]
}
See Input/Output Options to include more fields in your response.
GET /workspaces/{workspace_gid}/workspace_memberships
Returns the compact workspace membership records for the workspace.
Parameters
| Name | Description | ||||
| /workspace_gid string required | Globally unique identifier for the workspace or organization. | ||||
| ?user string | A string identifying a user. This can either be the string "me", an email, or the gid of a user. | ||||
| ↓ Show Common Parameters ↓ | |||||
Responses
| Status | Description | |
| 200 WorkspaceMembershipCompact | Successfully retrieved the requested workspace's memberships. |
Schemas
The schema definitions for each object requested or returned from Asana's API. Some fields are not returned by default and you'll need to use Input/Output Options to include them.
AsanaNamedResource
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
A generic Asana Resource, containing a globally unique identifier.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the object. |
AsanaResource
{
"gid": "12345",
"resource_type": "task"
}
A generic Asana Resource, containing a globally unique identifier.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. |
AttachmentCompact
{
"gid": "12345",
"resource_type": "attachment",
"name": "Screenshot.png",
"resource_subtype": null
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the file. | |
| resource_subtype any | The service hosting the attachment. Valid values are asana, dropbox, gdrive, onedrive, box, and external.external attachments are a beta feature currently limited to specific integrations. |
Attachment
{
"gid": "12345",
"resource_type": "attachment",
"name": "Screenshot.png",
"resource_subtype": null,
"created_at": "2012-02-22T02:06:58.147Z",
"download_url": "https://s3.amazonaws.com/assets/123/Screenshot.png",
"host": "dropbox",
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"view_url": "https://www.dropbox.com/s/123/Screenshot.png"
}
An attachment object represents any file attached to a task in Asana, whether it’s an uploaded file or one associated via a third-party service such as Dropbox or Google Drive.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the file. | |
| resource_subtype any | The service hosting the attachment. Valid values are asana, dropbox, gdrive, onedrive, box, and external.external attachments are a beta feature currently limited to specific integrations. | |
| created_at string(date-time) | The time at which this resource was created. | |
| download_url string(uri)¦null | The URL containing the content of the attachment. Note: May be null if the attachment is hosted by Box. If present, this URL may only be valid for two minutes from the time of retrieval. You should avoid persisting this URL somewhere and just refresh it on demand to ensure you do not keep stale URLs. | |
| host string | The service hosting the attachment. Valid values are asana, dropbox, gdrive and box. | |
| parent object | The task this attachment is attached to. | |
| view_url string(uri)¦null | The URL where the attachment can be viewed, which may be friendlier to users in a browser than just directing them to a raw file. May be null if no view URL exists for the service. |
Batch
{
"body": {
"data": {
"completed": false,
"gid": "1967",
"name": "Hello, world!",
"notes": "How are you today?"
}
},
"headers": {
"location": "/tasks/1234"
},
"status_code": 200
}
A response object returned from a batch request.
Properties
| Name | Description | |
| body object | The JSON body that the invoked endpoint returned. | |
| headers object | A map of HTTP headers specific to this result. This is primarily used for returning a Location header to accompany a 201 Created result. The parent HTTP response will contain all common headers. | |
| status_code integer | The HTTP status code that the invoked endpoint returned. |
CustomFieldCompact
{
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| display_value string | A string representation for the value of the custom field. Integrations that don't require the underlying type should use this field to read values. Using this field will future-proof an app against new custom field types. | |
| enabled boolean | Conditional. Determines if the custom field is enabled or not. | |
| enum_options [object] | Conditional. Only relevant for custom fields of type enum. This array specifies the possible values which an enum custom field can adopt. To modify the enum options, refer to working with enum options. | |
| name string | The name of the custom field. | |
| number_value number | Conditional. This number is the value of a number custom field. | |
| resource_subtype string | The type of the custom field. Must be one of the given values. | |
| text_value string | Conditional. This string is the value of a text custom field. | |
| type string | Deprecated: new integrations should prefer the resource_subtype field. The type of the custom field. Must be one of the given values. |
Enumerated Values
| Property | Value | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number | |
| type | text | |
| type | enum | |
| type | multi_enum | |
| type | number |
CustomField
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
Custom Fields store the metadata that is used in order to add user-specified information to tasks in Asana. Be sure to reference the Custom Fields developer documentation for more information about how custom fields relate to various resources in Asana.
Users in Asana can lock custom fields, which will make them read-only when accessed by other users. Attempting to edit a locked custom field will return HTTP error code 403 Forbidden.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| created_by object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| currency_code string¦null | ISO 4217 currency code to format this custom field. This will be null if the format is not currency. | |
| custom_label string¦null | This is the string that appears next to the custom field value. This will be null if the format is not custom. | |
| custom_label_position string | Only relevant for custom fields with custom format. This depicts where to place the custom label. This will be null if the format is not custom. | |
| description string | Opt In. The description of the custom field. | |
| display_value string | A string representation for the value of the custom field. Integrations that don't require the underlying type should use this field to read values. Using this field will future-proof an app against new custom field types. | |
| enabled boolean | Conditional. Determines if the custom field is enabled or not. | |
| enum_options [object] | Conditional. Only relevant for custom fields of type enum. This array specifies the possible values which an enum custom field can adopt. To modify the enum options, refer to working with enum options. | |
| enum_value object | Conditional. Only relevant for custom fields of type enum. This object is the chosen value of an enum custom field. | |
| format string | The format of this custom field. | |
| has_notifications_enabled boolean | Conditional. This flag describes whether a follower of a task with this field should receive inbox notifications from changes to this field. | |
| is_global_to_workspace boolean | This flag describes whether this custom field is available to every container in the workspace. Before project-specific custom fields, this field was always true. | |
| multi_enum_values [object] | Conditional. Only relevant for custom fields of type multi_enum. This object is the chosen values of a multi_enum custom field. | |
| name string | The name of the custom field. | |
| number_value number | Conditional. This number is the value of a number custom field. | |
| precision integer | Only relevant for custom fields of type ‘Number’. This field dictates the number of places after the decimal to round to, i.e. 0 is integer values, 1 rounds to the nearest tenth, and so on. Must be between 0 and 6, inclusive. For percentage format, this may be unintuitive, as a value of 0.25 has a precision of 0, while a value of 0.251 has a precision of 1. This is due to 0.25 being displayed as 25%. The identifier format will always have a precision of 0. | |
| resource_subtype string | The type of the custom field. Must be one of the given values. | |
| text_value string | Conditional. This string is the value of a text custom field. | |
| type string | Deprecated: new integrations should prefer the resource_subtype field. The type of the custom field. Must be one of the given values. |
Enumerated Values
| Property | Value | |
| custom_label_position | prefix | |
| custom_label_position | suffix | |
| format | currency | |
| format | identifier | |
| format | percentage | |
| format | custom | |
| format | none | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number | |
| type | text | |
| type | enum | |
| type | multi_enum | |
| type | number |
CustomFieldSettingCompact
{
"gid": "12345",
"resource_type": "custom_field_setting"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. |
CustomFieldSetting
{
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
Custom Fields Settings objects represent the many-to-many join of the Custom Field and Project as well as stores information that is relevant to that particular pairing.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| custom_field object | The custom field that is applied to the parent. | |
| is_important boolean | is_important is used in the Asana web application to determine if this custom field is displayed in the list/grid view of a project or portfolio. | |
| parent object | The parent to which the custom field is applied. This can be a project or portfolio and indicates that the tasks or projects that the parent contains may be given custom field values for this custom field. | |
| project object | Deprecated: new integrations should prefer the parent field. The id of the project that this custom field settings refers to. |
Enumerated Values
| Property | Value | |
| custom_label_position | prefix | |
| custom_label_position | suffix | |
| format | currency | |
| format | identifier | |
| format | percentage | |
| format | custom | |
| format | none | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number | |
| type | text | |
| type | enum | |
| type | multi_enum | |
| type | number |
EnumOption
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
Enum options are the possible values which an enum custom field can adopt. An enum custom field must contain at least 1 enum option but no more than 50.
You can add enum options to a custom field by using the POST /custom_fields/custom_field_gid/enum_options endpoint.
It is not possible to remove or delete an enum option. Instead, enum options can be disabled by updating the enabled field to false with the PUT /enum_options/enum_option_gid endpoint. Other attributes can be updated similarly.
On creation of an enum option, enabled is always set to true, meaning the enum option is a selectable value for the custom field. Setting enabled=false is equivalent to “trashing” the enum option in the Asana web app within the “Edit Fields” dialog. The enum option will no longer be selectable but, if the enum option value was previously set within a task, the task will retain the value.
Enum options are an ordered list and by default new enum options are inserted at the end. Ordering in relation to existing enum options can be specified on creation by using insert_before or insert_after to reference an existing enum option. Only one of insert_before and insert_after can be provided when creating a new enum option.
An enum options list can be reordered with the POST /custom_fields/custom_field_gid/enum_options/insert endpoint.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| color string | The color of the enum option. Defaults to ‘none’. | |
| enabled boolean | Whether or not the enum option is a selectable value for the custom field. | |
| name string | The name of the enum option. |
Error
{
"errors": [
{
"help": "For more information on API status codes and how to handle them, read the docs on errors: https://asana.github.io/developer-docs/#errors'",
"message": "project: Missing input",
"phrase": "6 sad squid snuggle softly"
}
]
}
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, with a response body in JSON format containing additional information.
In the event of a server error the response body will contain an error phrase. These phrases are automatically generated using the node-asana-phrase library and can be used by Asana support to quickly look up the incident that caused the server error.
Properties
| Name | Description | |
| errors [object] | none |
Event
{
"action": "changed",
"change": {
"action": "changed",
"added_value": {
"gid": "12345",
"resource_type": "user"
},
"field": "assignee",
"new_value": {
"gid": "12345",
"resource_type": "user"
},
"removed_value": {
"gid": "12345",
"resource_type": "user"
}
},
"created_at": "2012-02-22T02:06:58.147Z",
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"resource": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"type": "task",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
An event is an object representing a change to a resource that was observed by an event subscription or delivered asynchronously to the target location of an active webhook.
The event may be triggered by a different user than the
subscriber. For example, if user A subscribes to a task and user B
modified it, the event’s user will be user B. Note: Some events
are generated by the system, and will have null as the user. API
consumers should make sure to handle this case.
The resource that triggered the event may be different from the one
that the events were requested for or the webhook is subscribed to. For
example, a subscription to a project will contain events for tasks
contained within the project.
Note: pay close attention to the relationship between the fields
Event.action and Event.change.action.
Event.action represents the action taken on the resource
itself, and Event.change.action represents how the information
within the resource's fields have been modified.
For instance, consider these scenarios:
When at task is added to a project,
Event.actionwill beadded,Event.parentwill be on object with theidandtypeof the project, and there will be nochangefield.When an assignee is set on the task,
Event.parentwill benull,Event.actionwill bechanged,Event.change.actionwill bechanged, andchanged_valuewill be an object with the user'sidandtype.When a collaborator is added to the task,
Event.parentwill benull,Event.actionwill bechanged,Event.change.actionwill beadded, andadded_valuewill be an object with the user'sidandtype.
Properties
| Name | Description | |
| action string | The type of action taken on the resource that triggered the event. This can be one of changed, added, removed, deleted, or undeleted depending on the nature of the event. | |
| change object | Information about the type of change that has occurred. This field is only present when the value of the property action, describing the action taken on the resource, is changed. | |
| created_at string(date-time) | The timestamp when the event occurred. | |
| parent object | For added/removed events, the parent object that resource was added to or removed from. The parent will be null for other event types. | |
| resource object | The resource which has triggered the event by being modified in some way. | |
| type string | Deprecated: Refer to the resource_type of the resource. The type of the resource that generated the event. | |
| user object | The user who triggered the event. |
GoalCompact
{
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the goal. | |
| owner object¦null | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. |
Goal
{
"gid": "12345",
"resource_type": "goal",
"name": "Grow web traffic by 30%",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"due_on": "2019-09-15",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"html_notes": "<body>Start building brand awareness.</body>",
"is_workspace_level": true,
"liked": false,
"metric": {
"gid": "12345",
"resource_type": "task",
"currency_code": "EUR",
"current_display_value": "8.12",
"current_number_value": 8.12,
"initial_number_value": 5.2,
"precision": 2,
"resource_subtype": "number",
"target_number_value": 10.2,
"unit": "none"
},
"notes": "Start building brand awareness.",
"start_on": "2019-09-14",
"status": "string",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"num_likes": 5
}
A generic Asana Resource, containing a globally unique identifier.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the goal. | |
| owner object¦null | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| due_on string¦null | The localized day on which this goal is due. This takes a date with format YYYY-MM-DD. | |
| followers [object] | Array of users following this goal. | |
| html_notes string | The notes of the goal with formatting as HTML. | |
| is_workspace_level boolean | Whether the goal belongs to the workspace (and is listed as part of the workspace’s goals) or not. If it isn’t a workspace-level goal, it is a team-level goal, and is associated with the goal’s team. | |
| liked boolean | True if the goal is liked by the authorized user, false if not. | |
| metric object¦null | A generic Asana Resource, containing a globally unique identifier. | |
| notes string | Free-form textual information associated with the goal (i.e. its description). | |
| start_on string¦null | The day on which work for this goal begins, or null if the goal has no start date. This takes a date with YYYY-MM-DD format, and cannot be set unless there is an accompanying due date. | |
| status string¦null | The current status of this goal. When the goal is open, its status can be green, yellow, and red to reflect "On Track", "At Risk", and "Off Track", respectively. When the goal is closed, the value can be missed, achieved, partial, or dropped. | |
| team object¦null | A team is used to group related projects and people together within an organization. Each project in an organization is associated with a team. | |
| workspace object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. | |
| likes [object] | Array of likes for users who have liked this goal. | |
| num_likes integer | The number of users who have liked this goal. |
Enumerated Values
| Property | Value | |
| resource_subtype | number | |
| unit | none | |
| unit | currency | |
| unit | percentage |
JobCompact
{
"gid": "12345",
"resource_type": "job",
"new_project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"new_task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"resource_subtype": "duplicate_task",
"status": "in_progress"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| new_project object | A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. 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. | |
| new_task object | The task is the basic object around which many operations in Asana are centered. | |
| resource_subtype string | The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning. | |
| status string | none |
Enumerated Values
| Property | Value | |
| status | not_started | |
| status | in_progress | |
| status | completed | |
| status | failed |
Job
{
"gid": "12345",
"resource_type": "job",
"new_project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"new_task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"resource_subtype": "duplicate_task",
"status": "in_progress"
}
A job is an object representing a process that handles asynchronous work.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| new_project object | A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. 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. | |
| new_task object | The task is the basic object around which many operations in Asana are centered. | |
| resource_subtype string | The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning. | |
| status string | none |
Enumerated Values
| Property | Value | |
| status | not_started | |
| status | in_progress | |
| status | completed | |
| status | failed |
PortfolioCompact
{
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the portfolio. |
PortfolioMembershipCompact
{
"gid": "12345",
"resource_type": "portfolio_membership",
"portfolio": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| portfolio object | A portfolio gives a high-level overview of the status of multiple initiatives in Asana. Portfolios provide a dashboard overview of the state of multiple projects, including a progress report and the most recent project status update. Portfolios have some restrictions on size. Each portfolio has a max of 250 items and, like projects, a max of 20 custom fields. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. |
PortfolioMembership
{
"gid": "12345",
"resource_type": "portfolio_membership",
"portfolio": {
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
This object determines if a user is a member of a portfolio.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| portfolio object | A portfolio gives a high-level overview of the status of multiple initiatives in Asana. Portfolios provide a dashboard overview of the state of multiple projects, including a progress report and the most recent project status update. Portfolios have some restrictions on size. Each portfolio has a max of 250 items and, like projects, a max of 20 custom fields. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. |
Portfolio
{
"gid": "12345",
"resource_type": "portfolio",
"name": "Bug Portfolio",
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting",
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"is_important": false,
"parent": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
}
],
"due_on": "2019-09-15",
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
A portfolio gives a high-level overview of the status of multiple initiatives in Asana. Portfolios provide a dashboard overview of the state of multiple projects, including a progress report and the most recent project status update. Portfolios have some restrictions on size. Each portfolio has a max of 250 items and, like projects, a max of 20 custom fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the portfolio. | |
| color string | Color of the portfolio. | |
| created_at string(date-time) | The time at which this resource was created. | |
| created_by object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| custom_field_settings [object] | Array of custom field settings applied to the portfolio. | |
| due_on string(date-time)¦null | The localized day on which this portfolio is due. This takes a date with format YYYY-MM-DD. | |
| members [object] | none | |
| owner object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| permalink_url string | A url that points directly to the object within Asana. | |
| start_on string(date)¦null | The day on which work for this portfolio begins, or null if the portfolio has no start date. This takes a date with YYYY-MM-DD format. Note: due_on must be present in the request when setting or unsetting the start_on parameter. Additionally, start_on and due_on cannot be the same date. | |
| workspace object | Create-only. The workspace or organization that the portfolio belongs to. |
Enumerated Values
| Property | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray | |
| custom_label_position | prefix | |
| custom_label_position | suffix | |
| format | currency | |
| format | identifier | |
| format | percentage | |
| format | custom | |
| format | none | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number | |
| type | text | |
| type | enum | |
| type | multi_enum | |
| type | number |
ProjectCompact
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | 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. |
ProjectMembershipCompact
{
"gid": "12345",
"resource_type": "project_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. |
ProjectMembership
{
"gid": "12345",
"resource_type": "project_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"write_access": "full_write"
}
With the introduction of “comment-only” projects in Asana, a user’s membership in a project comes with associated permissions. These permissions (whether a user has full access to the project or comment-only access) are accessible through the project memberships endpoints described here.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| project object | A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. 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. | |
| write_access string | Whether the user has full access to the project or has comment-only access. |
Enumerated Values
| Property | Value | |
| write_access | full_write | |
| write_access | comment_only |
Project
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy",
"archived": false,
"color": "light-green",
"created_at": "2012-02-22T02:06:58.147Z",
"current_status": {
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
},
"custom_field_settings": [
{
"gid": "12345",
"resource_type": "custom_field_setting"
}
],
"default_view": "calendar",
"due_date": "2019-09-15",
"due_on": "2019-09-15",
"html_notes": "<body>These are things we need to purchase.</body>",
"is_template": false,
"members": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "These are things we need to purchase.",
"public": false,
"start_on": "2019-09-14",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"icon": "chat_bubbles",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
}
A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. 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.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | 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. | |
| archived boolean | 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. | |
| color string¦null | Color of the project. | |
| created_at string(date-time) | The time at which this resource was created. | |
| current_status object | A project status is an update on the progress of a particular project, and is sent out to all project followers when created. These updates include both text describing the update and a color code intended to represent the overall state of the project: "green" for projects that are on track, "yellow" for projects at risk, and "red" for projects that are behind. | |
| custom_field_settings [object] | Array of Custom Field Settings (in compact form). | |
| default_view string | The default view (list, board, calendar, or timeline) of a project. | |
| due_date string(date-time)¦null | Deprecated: new integrations should prefer the due_on field. | |
| due_on string(date-time)¦null | The day on which this project is due. This takes a date with format YYYY-MM-DD. | |
| html_notes string | Opt In. The notes of the project with formatting as HTML. | |
| is_template boolean | Opt In. Determines if the project is a template. | |
| members [object] | Array of users who are members of this project. | |
| modified_at string(date-time) | 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. | |
| notes string | Free-form textual information associated with the project (ie., its description). | |
| public boolean | True if the project is public to the organization. If false, do not share this project with other users in this organization without explicitly checking to see if they have access. | |
| start_on string(date)¦null | The day on which work for this project begins, or null if the project has no start date. This takes a date with YYYY-MM-DD format. Note: due_on or due_at must be present in the request when setting or unsetting the start_on parameter. Additionally, start_on and due_on cannot be the same date. | |
| workspace object | 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. | |
| custom_fields [object] | Array of Custom Fields. | |
| followers [object] | Array of users following this project. Followers are a subset of members who receive all notifications for a project, the default notification setting when adding members to a project in-product. | |
| icon string¦null | The icon for a project. | |
| owner object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| permalink_url string | A url that points directly to the object within Asana. | |
| team object | Create-only. The team that this project is shared with. This field only exists for projects in organizations. |
Enumerated Values
| Property | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray | |
| color | green | |
| color | yellow | |
| color | red | |
| color | blue | |
| default_view | list | |
| default_view | board | |
| default_view | calendar | |
| default_view | timeline | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number | |
| type | text | |
| type | enum | |
| type | multi_enum | |
| type | number | |
| icon | list | |
| icon | board | |
| icon | timeline | |
| icon | calendar | |
| icon | rocket | |
| icon | people | |
| icon | graph | |
| icon | star | |
| icon | bug | |
| icon | light_bulb | |
| icon | globe | |
| icon | gear | |
| icon | notebook | |
| icon | computer | |
| icon | check | |
| icon | target | |
| icon | html | |
| icon | megaphone | |
| icon | chat_bubbles | |
| icon | briefcase | |
| icon | page_layout | |
| icon | mountain_flag | |
| icon | puzzle | |
| icon | presentation | |
| icon | line_and_symbols | |
| icon | speed_dial | |
| icon | ribbon | |
| icon | shoe | |
| icon | shopping_basket | |
| icon | map | |
| icon | ticket | |
| icon | coins |
ProjectStatusCompact
{
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| title string | The title of the project status update. |
ProjectStatus
{
"gid": "12345",
"resource_type": "project_status",
"title": "Status Update - Jun 15",
"color": "green",
"html_text": "<body>The project <strong>is</strong> moving forward according to plan...</body>",
"text": "The project is moving forward according to plan...",
"author": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"modified_at": "2012-02-22T02:06:58.147Z"
}
A project status is an update on the progress of a particular project, and is sent out to all project followers when created. These updates include both text describing the update and a color code intended to represent the overall state of the project: "green" for projects that are on track, "yellow" for projects at risk, and "red" for projects that are behind.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| title string | The title of the project status update. | |
| color string | The color associated with the status update. | |
| html_text string | Opt In. The text content of the status update with formatting as HTML. | |
| text string | The text content of the status update. | |
| author object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| created_at string(date-time) | The time at which this resource was created. | |
| created_by object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| modified_at string(date-time) | The time at which this project status was last modified. Note: This does not currently reflect any changes in associations such as comments that may have been added or removed from the project status. |
Enumerated Values
| Property | Value | |
| color | green | |
| color | yellow | |
| color | red | |
| color | blue |
SectionCompact
{
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the section (i.e. the text displayed as the section header). |
Section
{
"gid": "12345",
"resource_type": "section",
"name": "Next Actions",
"created_at": "2012-02-22T02:06:58.147Z",
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
]
}
A section is a subdivision of a project that groups tasks together. It can either be a header above a list of tasks in a list view or a column in a board view of a project.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the section (i.e. the text displayed as the section header). | |
| created_at string(date-time) | The time at which this resource was created. | |
| project object | A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. 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 [object] | Deprecated - please use project instead |
StoryCompact
{
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"resource_subtype": "comment_added",
"text": "marked today"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| created_at string(date-time) | The time at which this resource was created. | |
| created_by object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| resource_subtype string | The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning. | |
| text string | 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 …” as the text for a story can both be edited and change based on the language settings of the user making the request. Use the resource_subtype property to discover the action that created the story. |
Story
{
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"html_text": "<body>This is a comment.<body>",
"is_pinned": false,
"resource_subtype": "comment_added",
"sticker_name": "dancing_unicorn",
"text": "This is a comment.",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"custom_field": {
"gid": "12345",
"resource_type": "custom_field",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
},
"dependency": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicate_of": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"duplicated_from": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"follower": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"hearted": false,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"is_edited": false,
"liked": false,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"new_approval_status": "approved",
"new_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"new_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"new_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"new_name": "This is the New Name",
"new_number_value": 2,
"new_resource_subtype": "milestone",
"new_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"new_text_value": "This is the New Text",
"num_hearts": 5,
"num_likes": 5,
"old_approval_status": "pending",
"old_dates": {
"due_at": "2019-09-15T02:06:58.158Z",
"due_on": "2019-09-15",
"start_on": "2019-09-14"
},
"old_enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"old_multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"old_name": "This was the Old Name",
"old_number_value": 1,
"old_resource_subtype": "default_task",
"old_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"old_text_value": "This was the Old Text",
"previews": [
{
"fallback": "Greg: Great! I like this idea.\\n\\nhttps//a_company.slack.com/archives/ABCDEFG/12345678",
"footer": "Mar 17, 2019 1:25 PM",
"header": "Asana for Slack",
"header_link": "https://asana.comn/apps/slack",
"html_text": "<body>Great! I like this idea.</body>",
"text": "Great! I like this idea.",
"title": "Greg",
"title_link": "https://asana.slack.com/archives/ABCDEFG/12345678"
}
],
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"source": "web",
"story": {
"gid": "12345",
"resource_type": "story",
"created_at": "2012-02-22T02:06:58.147Z",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"resource_subtype": "comment_added",
"text": "marked today"
},
"tag": {
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
},
"target": {
"gid": "1234",
"name": "Bug Task"
},
"task": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
}
A story represents an activity associated with an object in the Asana system.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| created_at string(date-time) | The time at which this resource was created. | |
| html_text string | Opt In. HTML formatted text for a comment. This will not include the name of the creator. | |
| is_pinned boolean | Conditional. Whether the story should be pinned on the resource. | |
| resource_subtype string | The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning. | |
| sticker_name string | The name of the sticker in this story. null if there is no sticker. | |
| text string | The plain text of the comment to add. Cannot be used with html_text. | |
| assignee object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| created_by object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| custom_field object | Custom Fields store the metadata that is used in order to add user-specified information to tasks in Asana. Be sure to reference the Custom Fields developer documentation for more information about how custom fields relate to various resources in Asana. Users in Asana can lock custom fields, which will make them read-only when accessed by other users. Attempting to edit a locked custom field will return HTTP error code 403 Forbidden. | |
| dependency object | The task is the basic object around which many operations in Asana are centered. | |
| duplicate_of object | The task is the basic object around which many operations in Asana are centered. | |
| duplicated_from object | The task is the basic object around which many operations in Asana are centered. | |
| follower object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| hearted boolean | Deprecated - please use likes instead Conditional. True if the story is hearted by the authorized user, false if not. | |
| hearts [object] | Deprecated - please use likes instead Conditional. Array of likes for users who have hearted this story. | |
| is_edited boolean | Conditional. Whether the text of the story has been edited after creation. | |
| liked boolean | Conditional. True if the story is liked by the authorized user, false if not. | |
| likes [object] | Conditional. Array of likes for users who have liked this story. | |
| new_approval_status string | Conditional | |
| new_dates object | Conditional | |
| new_enum_value object | Enum options are the possible values which an enum custom field can adopt. An enum custom field must contain at least 1 enum option but no more than 50. You can add enum options to a custom field by using the POST /custom_fields/custom_field_gid/enum_options endpoint.It is not possible to remove or delete an enum option. Instead, enum options can be disabled by updating the enabled field to false with the PUT /enum_options/enum_option_gid endpoint. Other attributes can be updated similarly.On creation of an enum option, enabled is always set to true, meaning the enum option is a selectable value for the custom field. Setting enabled=false is equivalent to “trashing” the enum option in the Asana web app within the “Edit Fields” dialog. The enum option will no longer be selectable but, if the enum option value was previously set within a task, the task will retain the value.Enum options are an ordered list and by default new enum options are inserted at the end. Ordering in relation to existing enum options can be specified on creation by using insert_before or insert_after to reference an existing enum option. Only one of insert_before and insert_after can be provided when creating a new enum option.An enum options list can be reordered with the POST /custom_fields/custom_field_gid/enum_options/insert endpoint. | |
| new_multi_enum_values [object] | Conditional | |
| new_name string | Conditional | |
| new_number_value integer | Conditional | |
| new_resource_subtype string | Conditional | |
| new_section object | A section is a subdivision of a project that groups tasks together. It can either be a header above a list of tasks in a list view or a column in a board view of a project. | |
| new_text_value string | Conditional | |
| num_hearts integer | Deprecated - please use likes instead Conditional. The number of users who have hearted this story. | |
| num_likes integer | Conditional. The number of users who have liked this story. | |
| old_approval_status string | Conditional | |
| old_dates object | Conditional | |
| old_enum_value object | Enum options are the possible values which an enum custom field can adopt. An enum custom field must contain at least 1 enum option but no more than 50. You can add enum options to a custom field by using the POST /custom_fields/custom_field_gid/enum_options endpoint.It is not possible to remove or delete an enum option. Instead, enum options can be disabled by updating the enabled field to false with the PUT /enum_options/enum_option_gid endpoint. Other attributes can be updated similarly.On creation of an enum option, enabled is always set to true, meaning the enum option is a selectable value for the custom field. Setting enabled=false is equivalent to “trashing” the enum option in the Asana web app within the “Edit Fields” dialog. The enum option will no longer be selectable but, if the enum option value was previously set within a task, the task will retain the value.Enum options are an ordered list and by default new enum options are inserted at the end. Ordering in relation to existing enum options can be specified on creation by using insert_before or insert_after to reference an existing enum option. Only one of insert_before and insert_after can be provided when creating a new enum option.An enum options list can be reordered with the POST /custom_fields/custom_field_gid/enum_options/insert endpoint. | |
| old_multi_enum_values [object] | Conditional | |
| old_name string | Conditional' | |
| old_number_value integer | Conditional | |
| old_resource_subtype string | Conditional | |
| old_section object | A section is a subdivision of a project that groups tasks together. It can either be a header above a list of tasks in a list view or a column in a board view of a project. | |
| old_text_value string | Conditional | |
| previews [object] | Conditional. A collection of previews to be displayed in the story. Note: This property only exists for comment stories. | |
| project object | A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. 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. | |
| source string | The component of the Asana product the user used to trigger the story. | |
| story object | A story represents an activity associated with an object in the Asana system. | |
| tag object | A tag is a label that can be attached to any task in Asana. It exists in a single workspace or organization. | |
| target object | The object this story is associated with. Currently may only be a task. | |
| task object | The task is the basic object around which many operations in Asana are centered. |
Enumerated Values
| Property | Value | |
| sticker_name | green_checkmark | |
| sticker_name | people_dancing | |
| sticker_name | dancing_unicorn | |
| sticker_name | heart | |
| sticker_name | party_popper | |
| sticker_name | people_waving_flags | |
| sticker_name | splashing_narwhal | |
| sticker_name | trophy | |
| sticker_name | yeti_riding_unicorn | |
| sticker_name | celebrating_people | |
| sticker_name | determined_climbers | |
| sticker_name | phoenix_spreading_love | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number | |
| type | text | |
| type | enum | |
| type | multi_enum | |
| type | number | |
| source | web | |
| source | ||
| source | mobile | |
| source | api | |
| source | unknown |
TagCompact
{
"gid": "12345",
"resource_type": "tag",
"name": "Stuff to buy"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | 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. |
Tag
{
"gid": "12345",
"resource_type": "tag",
"color": "light-green",
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"name": "Stuff to buy",
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
A tag is a label that can be attached to any task in Asana. It exists in a single workspace or organization.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| color string | Color of the tag. | |
| followers [object] | Array of users following this tag. | |
| name string | 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. | |
| permalink_url string | A url that points directly to the object within Asana. | |
| workspace object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. |
Enumerated Values
| Property | Value | |
| color | dark-pink | |
| color | dark-green | |
| color | dark-blue | |
| color | dark-red | |
| color | dark-teal | |
| color | dark-brown | |
| color | dark-orange | |
| color | dark-purple | |
| color | dark-warm-gray | |
| color | light-pink | |
| color | light-green | |
| color | light-blue | |
| color | light-red | |
| color | light-teal | |
| color | light-brown | |
| color | light-orange | |
| color | light-purple | |
| color | light-warm-gray |
TaskCompact
{
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the task. |
Task
{
"gid": "12345",
"resource_type": "task",
"name": "Buy catnip",
"approval_status": "pending",
"assignee_status": "upcoming",
"completed": false,
"completed_at": "2012-02-22T02:06:58.147Z",
"completed_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"created_at": "2012-02-22T02:06:58.147Z",
"dependencies": [
{
"gid": "12345",
"resource_type": "task"
}
],
"dependents": [
{
"gid": "12345",
"resource_type": "task"
}
],
"due_at": "2019-09-15T02:06:58.147Z",
"due_on": "2019-09-15",
"external": {
"data": "A blob of information",
"gid": "my_gid"
},
"hearted": true,
"hearts": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"html_notes": "<body>Mittens <em>really</em> likes the stuff from Humboldt.</body>",
"is_rendered_as_separator": false,
"liked": true,
"likes": [
{
"gid": "12345",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
],
"memberships": [
{
"project": {
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
},
"section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
}
}
],
"modified_at": "2012-02-22T02:06:58.147Z",
"notes": "Mittens really likes the stuff from Humboldt.",
"num_hearts": 5,
"num_likes": 5,
"num_subtasks": 3,
"resource_subtype": "default_task",
"start_on": "2019-09-14",
"assignee": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"assignee_section": {
"gid": "12345",
"resource_type": "section",
"name": "Next Actions"
},
"custom_fields": [
{
"gid": "12345",
"resource_type": "custom_field",
"created_by": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"currency_code": "EUR",
"custom_label": "gold pieces",
"custom_label_position": "suffix",
"description": "Development team priority",
"display_value": "blue",
"enabled": true,
"enum_options": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"enum_value": {
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
},
"format": "custom",
"has_notifications_enabled": true,
"is_global_to_workspace": true,
"multi_enum_values": [
{
"gid": "12345",
"resource_type": "enum_option",
"color": "blue",
"enabled": true,
"name": "Low"
}
],
"name": "Status",
"number_value": 5.2,
"precision": 2,
"resource_subtype": "text",
"text_value": "Some Value",
"type": "text"
}
],
"followers": [
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
],
"parent": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list",
"projects": [
{
"gid": "12345",
"resource_type": "project",
"name": "Stuff to buy"
}
],
"tags": [
{
"gid": "59746",
"name": "Grade A"
}
],
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
The task is the basic object around which many operations in Asana are centered.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | 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. | |
| approval_status string | Conditional Reflects the approval status of this task. This field is kept in sync with completed, meaning pending translates to false while approved, rejected, and changes_requested translate to true. If you set completed to true, this field will be set to approved. | |
| assignee_status string | Deprecated Scheduling status of this task for the user it is assigned to. This field can only be set if the assignee is non-null. Setting this field to "inbox" or "upcoming" inserts it at the top of the section, while the other options will insert at the bottom. | |
| completed boolean | True if the task is currently marked complete, false if not. | |
| completed_at string(date-time)¦null | The time at which this task was completed, or null if the task is incomplete. | |
| completed_by object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| created_at string(date-time) | The time at which this resource was created. | |
| dependencies [object] | Opt In. Array of resources referencing tasks that this task depends on. The objects contain only the gid of the dependency. | |
| dependents [object] | Opt In. Array of resources referencing tasks that depend on this task. The objects contain only the ID of the dependent. | |
| due_at string(date)¦null | The UTC date and time on which this task is due, or null if the task has no due time. This takes an ISO 8601 date string in UTC and should not be used together with due_on. | |
| due_on string(date)¦null | The localized date on which this task is due, or null if the task has no due date. This takes a date with YYYY-MM-DD format and should not be used together with due_at. | |
| external object | OAuth Required. Conditional. This field is returned only if external values are set or included by using Opt In. The external field allows you to store app-specific metadata on tasks, including a gid that can be used to retrieve tasks and a data blob that can store app-specific character strings. Note that you will need to authenticate with Oauth to access or modify this data. Once an external gid is set, you can use the notation external:custom_gid to reference your object anywhere in the API where you may use the original object gid. See the page on Custom External Data for more details. | |
| hearted boolean | Deprecated - please use liked instead True if the task is hearted by the authorized user, false if not. | |
| hearts [object] | Deprecated - please use likes instead Array of likes for users who have hearted this task. | |
| html_notes string | Opt In. The notes of the text with formatting as HTML. | |
| is_rendered_as_separator boolean | Opt In. In some contexts tasks can be rendered as a visual separator; for instance, subtasks can appear similar to sections without being true section objects. If a task object is rendered this way in any context it will have the property is_rendered_as_separator set to true. | |
| liked boolean | True if the task is liked by the authorized user, false if not. | |
| likes [object] | Array of likes for users who have liked this task. | |
| memberships [object] | Create-only. Array of projects this task is associated with and the section it is in. At task creation time, this array can be used to add the task to specific sections. After task creation, these associations can be modified using the addProject and removeProject endpoints. Note that over time, more types of memberships may be added to this property. | |
| modified_at string(date-time) | 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. | |
| notes string | Free-form textual information associated with the task (i.e. its description). | |
| num_hearts integer | Deprecated - please use likes instead The number of users who have hearted this task. | |
| num_likes integer | The number of users who have liked this task. | |
| num_subtasks integer | Opt In. The number of subtasks on this task. | |
| resource_subtype string | The subtype of this resource. Different subtypes retain many of the same fields and behavior, but may render differently in Asana or represent resources with different semantic meaning. The resource_subtype milestone represent a single moment in time. This means tasks with this subtype cannot have a start_date. | |
| start_on string(date)¦null | The day on which work begins for the task , or null if the task has no start date. This takes a date with YYYY-MM-DD format.Note: due_on or due_at must be present in the request when setting or unsetting the start_on parameter. | |
| assignee object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| assignee_section object | The assignee section is a subdivision of a project that groups tasks together in the assignee's "My Tasks" list. It can either be a header above a list of tasks in a list view or a column in a board view of "My Tasks." The assignee_section property will be returned in the response only if the request was sent by the user who is the assignee of the task. Note that you can only write to assignee_section with the gid of an existing section visible in the user's "My Tasks" list. | |
| custom_fields [object] | Array of custom field values applied to the task. These represent the custom field values recorded on this project for a particular custom field. For example, these custom field values will contain an enum_value property for custom fields of type enum, a text_value property for custom fields of type text, and so on. Please note that the gid returned on each custom field value is identical to the gid of the custom field, which allows referencing the custom field metadata through the /custom_fields/custom_field-gid endpoint. | |
| followers [object] | Array of users following this task. | |
| parent object¦null | 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. | |
| permalink_url string | A url that points directly to the object within Asana. | |
| projects [object] | 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. | |
| tags [object] | Array of tags associated with this task. In order to change tags on an existing task use addTag and removeTag. | |
| workspace object | 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. |
Enumerated Values
| Property | Value | |
| approval_status | pending | |
| approval_status | approved | |
| approval_status | rejected | |
| approval_status | changes_requested | |
| assignee_status | today | |
| assignee_status | upcoming | |
| assignee_status | later | |
| assignee_status | new | |
| assignee_status | inbox | |
| resource_subtype | default_task | |
| resource_subtype | milestone | |
| resource_subtype | section | |
| resource_subtype | approval | |
| custom_label_position | prefix | |
| custom_label_position | suffix | |
| format | currency | |
| format | identifier | |
| format | percentage | |
| format | custom | |
| format | none | |
| resource_subtype | text | |
| resource_subtype | enum | |
| resource_subtype | multi_enum | |
| resource_subtype | number | |
| type | text | |
| type | enum | |
| type | multi_enum | |
| type | number |
TeamCompact
{
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the team. |
TeamMembershipCompact
{
"gid": "12345",
"resource_type": "team_membership",
"is_guest": false,
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| is_guest boolean | Describes if the user is a guest in the team. | |
| team object | A team is used to group related projects and people together within an organization. Each project in an organization is associated with a team. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. |
TeamMembership
{
"gid": "12345",
"resource_type": "team_membership",
"is_guest": false,
"team": {
"gid": "12345",
"resource_type": "team",
"name": "Marketing"
},
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
}
This object represents a user's connection to a team.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| is_guest boolean | Describes if the user is a guest in the team. | |
| team object | A team is used to group related projects and people together within an organization. Each project in an organization is associated with a team. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. |
Team
{
"gid": "12345",
"resource_type": "team",
"name": "Marketing",
"description": "All developers should be members of this team.",
"html_description": "<body><em>All</em> developers should be members of this team.</body>",
"organization": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"permalink_url": "https://app.asana.com/0/resource/123456789/list"
}
A team is used to group related projects and people together within an organization. Each project in an organization is associated with a team.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the team. | |
| description string | Opt In. The description of the team. | |
| html_description string | Opt In. The description of the team with formatting as HTML. | |
| organization object | The organization/workspace the team belongs to. | |
| permalink_url string | A url that points directly to the object within Asana. |
UserCompact
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | Read-only except when same user as requester. The user’s name. |
User
{
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez",
"email": "gsanchez@example.com",
"photo": {
"image_128x128": "https://...",
"image_21x21": "https://...",
"image_27x27": "https://...",
"image_36x36": "https://...",
"image_60x60": "https://..."
},
"workspaces": [
{
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
]
}
A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | Read-only except when same user as requester. The user’s name. | |
| email string(email) | The user's email address. | |
| photo object¦null | A map of the user’s profile photo in various sizes, or null if no photo is set. Sizes provided are 21, 27, 36, 60, and 128. Images are in PNG format. | |
| workspaces [object] | Workspaces and organizations this user may access. Note: The API will only return workspaces and organizations that also contain the authenticated user. |
UserTaskListCompact
{
"gid": "12345",
"resource_type": "user_task_list",
"name": "My Tasks in My Workspace",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the user task list. | |
| owner object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| workspace object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. |
UserTaskList
{
"gid": "12345",
"resource_type": "user_task_list",
"name": "My Tasks in My Workspace",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
A user task list represents the tasks assigned to a particular user. It provides API access to a user’s “My Tasks” view in Asana.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the user task list. | |
| owner object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| workspace object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. |
WebhookCompact
{
"gid": "12345",
"resource_type": "webhook",
"active": false,
"resource": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"target": "https://example.com/receive-webhook/7654"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| active boolean | If true, the webhook will send events - if false it is considered inactive and will not generate events. | |
| resource object | A generic Asana Resource, containing a globally unique identifier. | |
| target string(uri) | The URL to receive the HTTP POST. |
WebhookFilter
{
"action": "changed",
"fields": [
"due_at",
"due_on",
"dependencies"
],
"resource_subtype": "milestone",
"resource_type": "task"
}
A WebhookFilter can be passed on creation of a webhook in order to filter the types of actions that trigger delivery of an Event
Properties
| Name | Description | |
| action string | The type of change on the resource to pass through the filter. For more information refer to Event.action in the Event schema. This can be one of changed, added, removed, deleted, and undeleted depending on the nature of what has occurred on the resource. | |
| fields [string] | Conditional. A whitelist of fields for events which will pass the filter when the resource is changed. These can be any combination of the fields on the resources themselves. This field is only valid for action of type changed | |
| resource_subtype string | The resource subtype of the resource that the filter applies to. This should be set to the same value as is returned on the resource_subtype field on the resources themselves. | |
| resource_type string | The type of the resource which created the event when modified; for example, to filter to changes on regular tasks this field should be set to task. |
Webhook
{
"gid": "12345",
"resource_type": "webhook",
"active": false,
"resource": {
"gid": "12345",
"resource_type": "task",
"name": "Bug Task"
},
"target": "https://example.com/receive-webhook/7654",
"created_at": "2012-02-22T02:06:58.147Z",
"filters": [
{
"action": "changed",
"fields": [
"due_at",
"due_on",
"dependencies"
],
"resource_subtype": "milestone",
"resource_type": "task"
}
],
"last_failure_at": "2012-02-22T02:06:58.147Z",
"last_failure_content": "500 Server Error\\n\\nCould not complete the request",
"last_success_at": "2012-02-22T02:06:58.147Z"
}
Webhook objects represent the state of an active subscription for a server to be updated with information from Asana. This schema represents the subscription itself, not the objects that are sent to the server. For information on those please refer to the Event schema.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| active boolean | If true, the webhook will send events - if false it is considered inactive and will not generate events. | |
| resource object | A generic Asana Resource, containing a globally unique identifier. | |
| target string(uri) | The URL to receive the HTTP POST. | |
| created_at string(date-time) | The time at which this resource was created. | |
| filters [object] | Whitelist of filters to apply to events from this webhook. If a webhook event passes any of the filters the event will be delivered; otherwise no event will be sent to the receiving server. | |
| last_failure_at string(date-time) | The timestamp when the webhook last received an error when sending an event to the target. | |
| last_failure_content string | The contents of the last error response sent to the webhook when attempting to deliver events to the target. | |
| last_success_at string(date-time) | The timestamp when the webhook last successfully sent an event to the target. |
WorkspaceCompact
{
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the workspace. |
WorkspaceMembershipCompact
{
"gid": "12345",
"resource_type": "workspace_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
A Compact object is the same as the full response object, but with less fields included by default. See
Input/Output Options to include more fields.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| workspace object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. |
WorkspaceMembership
{
"gid": "12345",
"resource_type": "workspace_membership",
"user": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
},
"is_active": true,
"is_admin": true,
"is_guest": true,
"user_task_list": {
"gid": "12345",
"resource_type": "user_task_list",
"name": "My Tasks in My Workspace",
"owner": {
"gid": "12345",
"resource_type": "user",
"name": "Greg Sanchez"
},
"workspace": {
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace"
}
}
}
This object determines if a user is a member of a workspace.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| user object | A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks. | |
| workspace object | A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace. | |
| is_active boolean | Reflects if this user still a member of the workspace. | |
| is_admin boolean | Reflects if this user is an admin of the workspace. | |
| is_guest boolean | Reflects if this user is a guest of the workspace. | |
| user_task_list object | A user task list represents the tasks assigned to a particular user. It provides API access to a user’s “My Tasks” view in Asana. |
Workspace
{
"gid": "12345",
"resource_type": "workspace",
"name": "My Company Workspace",
"email_domains": [
"asana.com"
],
"is_organization": false
}
A workspace is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace.
Properties
| Name | Description | |
| gid string | Globally unique identifier of the resource, as a string. | |
| resource_type string | The base type of this resource. | |
| name string | The name of the workspace. | |
| email_domains [string] | The email domains that are associated with this workspace. | |
| is_organization boolean | Whether the workspace is an organization. |
