Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Asana Build Status Maven Version

Java client library for the Asana API.


If you use Maven to manage dependencies you can include the "asana" artifact by adding it as a dependency in your pom.xml file.


Or, you can build the artifact and install it to your local Maven repository:

mvn install


mvn compile


mvn test


Be sure to run mvn compile first.

Set the ASANA_ACCESS_TOKEN, ASANA_CLIENT_ID, and ASANA_CLIENT_SECRET environment variables. The app's redirect URL should be set to "urn:ietf:wg:oauth:2.0:oob" for command line scripts examples, and "http://localhost:5000/auth/asana/callback" for the server example.


Web application example:

mvn exec:java -Dexec.mainClass="com.asana.examples.ExampleServer"

OAuth command line script example:

mvn exec:java -Dexec.mainClass="com.asana.examples.ExampleOAuth"

Personal access token command line script example:

mvn exec:java -Dexec.mainClass="com.asana.examples.ExamplePersonalAccessToken"

Demo create a task and upload an attachment:

mvn exec:java -Dexec.mainClass="com.asana.examples.ExampleCreateTaskAndUpload"

Demo create project and stream change events:

mvn exec:java -Dexec.mainClass="com.asana.examples.ExampleCreateProjectAndStreamEvents"


Personal Access Token

Create a client using a personal access token:

Client client = Client.accessToken("ASANA_ACCESS_TOKEN");

OAuth 2

Asana supports OAuth 2. java-asana handles some of the details of the OAuth flow for you.

Create a client using your OAuth Client ID and secret:

OAuthApp app = new OAuthApp(
Client client = Client.oauth(app);

Redirect the user to the authorization URL obtained from the client's session object:

String url = app.getAuthorizationUrl()

getAuthorizationUrl() takes an optional state parameter to be used for preventing CSRF attacks:

String state = UUID.randomUUID().toString();
String url = app.getAuthorizationUrl(state);

When the user is redirected back to your callback, check the state URL parameter matches, then pass the code parameter to obtain a bearer token:

if (request.param("state").equals(state)) {
  String token = app.fetchToken(request.params("code"));
  // ... 
} else {
  // error! possible CSRF attack

Note: if you're writing a non-browser-based application (e.x. a command line tool) you can use the special redirect URI urn:ietf:wg:oauth:2.0:oob to prompt the user to copy and paste the code into the application.


The client's methods are divided into several resources: attachments, customFields, customFieldSettings, events, jobs, organizationExports, portfolios, portfolioMemberships, projects, projectMemberships, projectStatuses, stories, tags, tasks, teams, users, userTaskLists, webhooks, and workspaces.

Request methods use the "builder" pattern to set query string or JSON body parameters, and various request options, so a request must be initated using the execute or executeRaw methods:

Methods that return a single object return that object directly:

User me =;
System.out.println("Hello " +;

String workspaceId = me.workspaces.get(0).gid;
Project project = client.projects.createInWorkspace(workspaceId)
    .data("name", "new project")
System.out.println("Created project with id: " + project.gid);

Methods that return multiple items (e.x. findAll) return an Iterable object. See the "Collections" section


Various options can be set globally on the Client.DEFAULTS object, per-client on client.options, or per-request using the option method. For example:

// global:
Client.DEFAULTS.put("page_size", 1000);

// per-client:
client.options.put("page_size", 1000);

// per-request:
client.tasks.findAll().query("project", 1234).option("page_size", 1000).execute();

Available options

  • base_url (default: ""): API endpoint base URL to connect to
  • max_retries (default: 5): number to times to retry if API rate limit is reached or a server error occures. Rate limit retries delay until the rate limit expires, server errors exponentially backoff starting with a 1 second delay.
  • fields and expand: array of field names to include in the response, or sub-objects to expand in the response. For example .option("fields", Arrays.asList("followers", "assignee")). See API documentation

Collections (methods returning an array as it's 'data' property):

  • item_limit (default: -1): limits the total number of items of a collection to return (spanning multiple requests in the case of an iterator).
  • page_size (default: 50): limits the number of items per page to fetch at a time when using an iterator.
  • offset: offset token returned by previous calls to the same method, when using executeRaw() (in response.nextPage.offset)


  • poll_interval (default: 5): polling interval for getting new events via an EventsRequest iterator (e.x. for (Event event : { ... })
  • sync: sync token returned by previous calls to events.get (e.x., syncToken).executeRaw().sync)


To add global headers (like for our deprecation framework), you simply add them to the client.

client.headers.put("asana-enable", "string_ids");

Asana Change Warnings

You will receive warning logs if performing requests that may be affected by a deprecation. The warning contains a link that explains the deprecation.

If you receive one of these warnings, you should:

  • Read about the deprecation.
  • Resolve sections of your code that would be affected by the deprecation.
  • Add the deprecation flag to your "asana-enable" header.

You can place it on the client for all requests.

client.headers.put("asana-enable", "string_ids,new_sections");
client.headers.put("asana-disable", "string_ids");

If you would rather suppress these warnings, you can set

client.logAsanaChangeWarnings = false;


Items Iterator

APIs that return a collection return a CollectionsRequest, which is an iterable:

Iterable<Workspace> workspaces = client.workspaces.findAll();
for (Workspace workspace: workspaces) {
    System.out.println("Workspace: " +;

Internally the iterator may make multiple HTTP requests, with the number of requested results per page being controlled by the page_size option.


You can also use the raw API to fetch a page at a time:

String offset = null;
while (true) {
    ResultBodyCollection<Workspace> page = client.workspaces.findAll()
            .option("offset", offset)
            .option("limit", 2)
    System.out.println("received " + + " results");
    if (page.nextPage != null) {
        offset = page.nextPage.offset;
    } else {


To deploy a new version to the Maven Central Repository, you can run:

mvn deploy -P release --settings settings.xml

Before you do this, you must set a few environment variables to authenticate:

  • Maven credentials: MAVEN_USERNAME and MAVEN_PASSWORD
  • GPG keyname and password: MAVEN_GPG_KEYNAME and MAVEN_GPG_PASSWORD

You can log in to verify the new version landed, and after some time it will be deployed to maven.


Official Java client library for the Asana API v1



Code of conduct





No packages published