Asana supports a few methods of authenticating with the API.

  • 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.
  • API Key (Deprecated) The API key has been deprecated in favor of OAuth 2.0. For personal scripts, testing or prototyping an application we support API Keys as described below.


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.

  1. 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)!

  2. A user will arrive at your application and click a button that says “Connect with Asana.”

  3. 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.

  4. 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.)

  5. 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).

  6. The application can make requests of the API using this Bearer Token for the next hour.

  7. 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.)

This is just one example using the Authorization Code Grant - applications that run entirely in the browser would generally use the Implicit Grant flow instead.

We definitely recommend using a library to take care of the nitty-gritty 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
  • The endpoint for token exchange is
  • Asana supports both the Authorization Code Grant flow, and the Implicit Grant flows.
  • Once an access token has been obtained your application can make calls on behalf of the user in the following form:

    curl -H "Authorization: Bearer ACCESS_TOKEN"

User Authorization Endpoint


Your app redirects the user to, 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 one of either code (if using the Authorization Code Grant flow) or token (if using the Implicit Grant flow). Other flows are currently not supported.
state required 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.


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.

If using the response_type=code, your app will receive the following parameters in the query string on successful authorization. If using the response_type=token, these parameters will appear in the URL fragment (the bit following the #):

Parameter Description
code If response_type=code in the request, this is the code your app can exchange for a token
token If response_type=token in the request, this is the token your app can use to make requests of the API
state The state parameter that was sent with the authorizing request

Token Exchange Endpoint


If your app received a code from the authorization endpoint, it can now be exchanged for a proper token, optionally including a refresh_token, which can be used to request new tokens when the current one expires without needing to redirect or reauthorize the user.

Your app should make a POST request to, passing the parameters as part of a standard form-encoded post body.

Parameter Description
grant_type required One of authorization_code, refresh_token or password. 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 sometimes required If grant_type=authorization_code 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.
username sometimes required If grant_type=password this is the username you are exchanging for an authorization token.

The token exchange endpoint is used to exchange a code, refresh token or a user’s API key for an access token and also a refresh token in the code and API key cases. If exchanging an API key for an access and refresh token pair, read more here.


In the response, you will receive a JSON payload with the following parameters:

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:

  1. Send the user to the authorization endpoint so that they can approve access of your app to their Asana account

    # Send the user to the authorization endpoint. Newlines inserted for readability
  2. Receive a redirect back from the authorization endpoint with a code embedded in the parameters

    # After the user authenticates they will redirected back to your app with a code for your app to exchange.
    # Newlines inserted for readability
  3. Exchange the code for a token via the token exchange endpoint

The token that you have at the end can be used to make calls to the Asana API on the user’s behalf.

Implicit Grant

The Implicit Grant flow is suitable for in-browser web apps written in JavaScript or other applications that cannot securely make the POST request containing the client secret to the authorization server without exposing that secret to the user or others. To implement this flow, there are only two steps:

  1. Redirect a user to the authorization endpoint so that they can approve access of your app to their Asana account

    # Send the user to the authorization endpoint. Newlines inserted for readability
  2. Receive a redirect back from the authorization endpoint with a token embedded in the fragment portion (the bit following the #) of the URL.

    # After the user authenticates they will redirected back to your app with a short-lived access token.

This token can then be used to access the API, in this case typically using CORS.

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. Asana is deprecating this behavior. We’re enforcing the use of https redirect endpoints for new application registrations, and will soon stop calling back to http apps during the authorization process.

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.

Exchanging an API Key for an OAuth Bearer Token

Note: This should only be useful if you have previously built an application that relied on API keys for user’s authentication and would like to migrate to OAuth. If you are building a new application this method should not be used for authorization, please implement the Authorization Code Grant or Implicit Grant flows described above.

Asana is deprecating the use of API keys for accessing the API. This means that in the future, such keys will no longer be an acceptable means of authentication and will cease to provide access to the Asana API.

In preparation for deprecation, Asana is outlining alternatives and providing a migration mechanism from API keys to OAuth authorizations for applications that have previously relied on API keys. If you have a service that operates for multiple different users, it should be using OAuth for authentication of those users instead of individuals API keys. Assuming you already have API keys for a set of users, this article will outline how to migrate to using OAuth without disrupting your user experience and having to re-request authorization from them.

Asana provides a service that will accept a user’s API key and return a new OAuth refresh and access token pair to be used by an application. It implements the standard OAuth 2.0 Resource Owner Password Credentials grant flow.

Here’s how it works.

What You’ll Need

  • A client capable of making secure requests to the Asana oauth controller on
  • User’s API key
  • Client ID
  • Client Secret

How it works

You must make a POST request to the Asana url and pass the following parameters in the request body:

  • grant_type: This should be set to password
  • username: This should be set to the user’s API key
  • client_id: The ID of the client app being authorized
  • client_secret: The secret key of the client app being authorized

Note: The password parameter is not necessary even though it is normal for this type of OAuth flow. It is ok to provide a blank value, but a non-empty value will be assumed to be a mistake and will result in an error.



curl '' \
    -d grant_type=password \
    -d username=FcZ23.M4xsMtXmTKmDA4ssLCkEnYi \
    -d client_id=123456 \
    -d client_secret=d3afa84f920bc329e6b0d047c9a7bc9d'

# Response
HTTP/1.1 200
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI.rT4MgExTSnh4tR0jiw5Kiydr7bTRmpXBvvlFweZxbTg",
    "token_type": "bearer",
    "expires_in": 3600,
    "data": {
        "id": 3142770933465480,
        "name": "Wombat",
        "email": ""
    "refresh_token": "0/1c145b13eb9785e96562ad4a7a8dxc690"

If successful, the app will be authorized on behalf of the user, and the response will be a standard token grant response, providing an access token and a refresh token encoded in JSON as seen in the example above. These credentials should be stored by the application and used in future requests authenticated with the OAuth mechanism. The User API key should be discarded. Future authorizations from users should go through OAuth.

Personal Access Token

Personal Access Tokens 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:

curl -H "Authorization: Bearer ACCESS_TOKEN"

You should regularly review the list of personal access tokens you have created and deauthorize those that you no longer need.

Note: 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.

API Key (Deprecated)

WARNING The API key is being deprecated. If your application is supporting multiple users we require that you implement OAuth 2.0 which is supported in all of our client libraries. If you need command line access or authentication for a personal application you may look into using personal access tokens.

If you have already deployed an application that has collected API keys from many users and you wish to implement OAuth Asana has provided a migration mechanism to exchange a user’s API key for an OAuth app authorization.

Please note that the API keys should be reserved for one-off or personal scripts & applications and not for production applications supporting many users. Please implement OAuth for those applications.

Each user has their own unique API key, which they can provide to applications to talk to Asana on their behalf. The API uses the widely supported HTTP Basic Authentication mechanism to authenticate requests with the API key. (See Using basic authentication below for details.)


Any user can get their own API key by visiting the Account Settings dialog and clicking on the Apps tab. The API key is located at the bottom of this dialog.

You can go directly to the tab now to see your API key.


To authenticate a request, clients should use HTTP Basic Authentication and pass the API key as the username, and an empty password. This will cause the client to send a header like the following:

Field Notes
Username FcZ23.M4xsMtXmTKmDA4ssLCkEnYi Most utilities and libraries that allow you to specify a username and password will handle proper encoding of the header for you. However, if you need to set the Authorization header manually, the header value is constructed by adding a colon (:) to the API key, then base64-encoding that string. You can read more on basic authentication if you need further details.
Password The password should be blank.
# curl request using basic authentication
curl -u FcZ23.M4xsMtXmTKmDA4ssLCkEnYi:

# Convert API key plus colon to base64
echo -n 'FcZ23.M4xsMtXmTKmDA4ssLCkEnYi:' | openssl enc -base64
>>> RmNaMjMuTTR4c010WG1US21EQTRzc0xDa0VuWWk6

# Example header using basic authentication
Authorization: Basic RmNaMjMuTTR4c010WG1US21EQTRzc0xDa0VuWWk6