Everything an AI agent can do with the Asana API.

A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.

Endpoints25
API version1.0
Last updated22 June 2026
Orientation

How the Asana API works.

The Asana API is how an app or AI agent works with an Asana workspace: creating and searching tasks, organizing them into projects and sections, posting comments as stories, and reading the people and teams in a workspace. Access is granted through a Bearer token, either an OAuth access token carrying granular scopes in a resource:action shape, like tasks:write, or a personal access token that holds a user's full permissions. The API runs at a single continuously updated version, and a change in the workspace can be pushed to a registered webhook as an event.

25Endpoints
7Capability groups
16Read
9Write
13Permissions
Authentication
Asana authenticates every call with a Bearer token. An app acting for a user uses OAuth 2.0, where the token carries the granular scopes the user consented to; a single user can instead generate a personal access token that carries their full account permissions and is unscoped. Enterprise and Enterprise+ organizations add service accounts for server-to-server and admin-only automation. An older app registered with Full permissions can still use the all-or-nothing default scope.
Permissions
Granular OAuth scopes follow a resource:action shape, like tasks:read, tasks:write, projects:write, stories:write, users:read, workspaces:read, and webhooks:read. Delete is its own scope separate from write, so tasks:delete and webhooks:delete are needed to remove those resources. Sections have no scope of their own and use the projects scopes. A token reaches only the scopes it was granted, and a missing scope returns a 403.
Versioning
The API runs at a single version, 1.0, with no dated version to pin and no version header to send. Changes ship continuously and are announced in the developer changelog, where a deprecation is flagged with an Asana-Deprecation-Warning header on affected responses during a transition window. An integration tracks the changelog rather than upgrading between numbered versions.
Data model
Asana models a workspace as a Work Graph of objects identified by a string gid. The core objects are tasks, which live in projects and are grouped by sections, with comments and activity captured as stories. Requests and responses are JSON wrapped in a data envelope, lists are cursor-paginated, and opt_fields selects which fields come back. A change in the graph can be pushed to a registered webhook as an event.
Connect & authenticate

Connection & authentication methods.

How an app or AI agent connects to Asana determines what it can reach. There is a REST API for making calls, a webhook channel for receiving events, and a hosted server that exposes Asana tools to agents, and each is governed by the token behind it and the permissions that token carries.

Ways to connect

REST API

The REST API answers at https://app.asana.com/api/1.0. It takes and returns JSON, wraps every payload in a data envelope, and pages through lists with an opaque cursor. A call authenticates with a Bearer token, either an OAuth access token or a personal access token. There is no dated version to pin; the API at 1.0 is continuously updated.

Best forConnecting an app or AI agent to Asana.
Governed byThe token and the OAuth scopes it carries.
Docs ↗

MCP server

A hosted Model Context Protocol server at https://mcp.asana.com/v2/mcp exposes Asana's Work Graph to AI agents and LLM clients over streamable HTTP. It went generally available in 2026 and authenticates with OAuth, so a connecting client is prompted to authorize access to the user's Asana data. Its tools cover creating and searching tasks, project tracking, and status updates, and the live set is discoverable with the tools/list command.

Best forConnecting an AI agent to Asana through MCP.
Governed byThe OAuth grant and the scopes it carries.
Docs ↗

Webhooks

Asana POSTs events to a target URL registered through the Webhooks API. Setup is a two-part handshake: Asana sends an X-Hook-Secret header that the target echoes back, then signs every later delivery with an X-Hook-Signature HMAC computed from that secret, so the receiver can confirm the request came from Asana. Events report an action and the changed resource, and an app fetches the detail through the REST API.

Best forReceiving Asana events at an app or AI agent.
Governed byThe shared secret on the webhook and the webhooks scopes.
Docs ↗
Authentication

OAuth 2.0

OAuth 2.0 is the recommended way for an app to act on behalf of an Asana user. Since granular scopes shipped, an app requests only the resource and action pairs it needs, like tasks:read or projects:write, rather than full account access. A registered app exchanges an authorization code for an access token and a refresh token, and the token carries exactly the scopes the user consented to.

TokenOAuth access token (Bearer)
Best forApps acting for a user with least-privilege scopes
Docs ↗

Personal access token

A personal access token is a credential a user generates for their own account, sent as a Bearer token. It carries the full permissions of the user who created it and is not scoped, so it suits scripts and a single user's own integrations rather than multi-user apps. It should be guarded like a password.

TokenPersonal access token (Bearer)
Best forScripts and a single user's own integrations
Docs ↗

Service account

A service account is an organization-owned token available on Enterprise and Enterprise+ plans, not tied to a person, used for server-to-server automation and admin-only APIs like SCIM user provisioning, audit logs, and exports. It does not consume a paid seat and is managed by a workspace admin.

TokenService account token (Bearer)
Best forEnterprise server-to-server and admin automation
Docs ↗

Legacy default scope

An app registered with Full permissions can request the default scope, which grants full access to everything the consenting user can reach, the all-or-nothing model that predates granular scopes. An app registered with specific scopes must request them explicitly instead, or a default request returns a forbidden_scopes error.

TokenOAuth access token with the default scope
Best forOlder full-permission apps not yet migrated to granular scopes
Docs ↗
Endpoint reference

Every Asana API method.

Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.

MethodEndpointWhat it doesAccessPermissionVersion

Tasks

List, read, create, update, delete, and search tasks, the core unit of work in Asana.6

Returns compact task objects. A filter such as project, section, assignee with workspace, or tag is required.

Acts ontask
Permission (capability)tasks:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Read-only.

Acts ontask
Permission (capability)tasks:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

A task's workspace is fixed once set, and can be implied by passing projects or a parent.

Acts ontask
Permission (capability)tasks:write
VersionAvailable since the API’s base version
Webhook eventadded
Rate limitStandard limits apply

Only the fields included in the request are changed.

Acts ontask
Permission (capability)tasks:write
VersionAvailable since the API’s base version
Webhook eventchanged
Rate limitStandard limits apply

Needs the separate tasks:delete scope, not tasks:write. The task sits in the trash for 30 days and can be undeleted in that window.

Acts ontask
Permission (capability)tasks:delete
VersionAvailable since the API’s base version
Webhook eventdeleted
Rate limitStandard limits apply

The Search API has its own limit of 60 requests per minute, separate from the standard rate limit.

Acts ontask
Permission (capability)tasks:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit60 requests per minute

Projects

List, read, create, and update projects, and list the tasks within a project.5

Read-only.

Acts onproject
Permission (capability)projects:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Read-only.

Acts onproject
Permission (capability)projects:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

A project must be created in a workspace, and in an organization it must also name a team.

Acts onproject
Permission (capability)projects:write
VersionAvailable since the API’s base version
Webhook eventadded
Rate limitStandard limits apply

Only the fields included in the request are changed.

Acts onproject
Permission (capability)projects:write
VersionAvailable since the API’s base version
Webhook eventchanged
Rate limitStandard limits apply

Reads tasks, so it needs tasks:read rather than projects:read.

Acts ontask
Permission (capability)tasks:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Sections

List the sections in a project and create a new section to group tasks.2

Sections have no scope of their own and use the projects scopes.

Acts onsection
Permission (capability)projects:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Sections have no scope of their own and use the projects scopes.

Acts onsection
Permission (capability)projects:write
VersionAvailable since the API’s base version
Webhook eventadded
Rate limitStandard limits apply

Stories (comments)

List the stories on a task and post a comment, where a story is a comment or an activity-log entry.2

Stories include both human comments and system-generated activity entries.

Acts onstory
Permission (capability)stories:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Only comment stories can be created; activity stories are generated by Asana.

Acts onstory
Permission (capability)stories:write
VersionAvailable since the API’s base version
Webhook eventadded
Rate limitStandard limits apply

Users

Read the authenticated user, read another user by id, and list the users in a workspace.3

A common first call to confirm a token works and learn the caller's workspaces.

Acts onuser
Permission (capability)users:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Returns email, name, and photo for a user the caller shares a workspace with.

Acts onuser
Permission (capability)users:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

A workspace or team filter is required.

Acts onuser
Permission (capability)users:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Workspaces & teams

List the workspaces a token can reach, read one, and list the teams in a workspace.3

Read-only.

Acts onworkspace
Permission (capability)workspaces:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Read-only.

Acts onworkspace
Permission (capability)workspaces:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Returns the teams visible to the authenticated user.

Acts onteam
Permission (capability)teams:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Webhooks

List a workspace's webhooks, establish a new one, read one, and delete one.4

A workspace filter is required.

Acts onwebhook
Permission (capability)webhooks:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Asana POSTs an X-Hook-Secret to the target during this call, and the target must echo it back to confirm the subscription.

Acts onwebhook
Permission (capability)webhooks:write
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Read-only.

Acts onwebhook
Permission (capability)webhooks:read
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Needs the separate webhooks:delete scope, not webhooks:write.

Acts onwebhook
Permission (capability)webhooks:delete
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply
No endpoints match those filters.
Webhooks

Webhook events.

Asana can notify an app when something changes in a workspace, like a task being added or a comment being posted, instead of the app polling for updates. It POSTs events to a registered target URL, and an app verifies each delivery against a shared secret agreed during the setup handshake.

EventWhat it signalsTriggered by
addedFires when a resource is created or added to a parent the webhook watches, like a task added to a project or a comment added to a task./tasks
/projects
/projects/{project_gid}/sections
/tasks/{task_gid}/stories
changedFires when a field on a watched resource is modified, like a task's assignee, due date, or completed state changing./tasks/{task_gid}
/projects/{project_gid}
removedFires when a resource is removed from a parent without being deleted, like a task removed from a project it still otherwise exists in.In-app only
deletedFires when a watched resource is itself deleted and moved to the trash./tasks/{task_gid}
undeletedFires when a previously deleted resource is restored from the trash within its retention window.In-app only
No events match that search.
Rate limits & pagination

Rate limits, pagination & request size.

Asana limits how fast an app can call, by a per-token request rate measured per minute, by a separate cap on concurrent requests, and by a cost quota that charges expensive reads more heavily.

Request rate

Asana meters requests per authorization token, so each token has its own quota and one token's traffic does not affect another. A standard per-minute request limit applies, set to 150 requests per minute for a free domain and 1,500 per minute for a paid domain (Starter through Enterprise+). The Search API is held separately to 60 requests per minute. On top of the request rate, a concurrency cap allows at most 50 GET requests and 15 POST, PUT, PATCH, or DELETE requests in flight at once, and duplication, instantiation, and export jobs are limited to 5 concurrent jobs per user. A cost-based quota also charges expensive reads more, deducting from an allowance after each response is built, based on how much of the work graph the request traversed. Exceeding any of these returns HTTP 429 with a Retry-After header giving the seconds to wait.

Pagination

List endpoints are cursor-paginated. A request sets limit to choose the page size, between 1 and 100, and the response returns a next_page object holding an offset cursor. The offset is passed back on the following request to fetch the next page, and the SDKs can iterate pages automatically. The offset is opaque and must come from a prior response rather than being constructed by hand.

Request size

A list page returns at most 100 objects, the maximum value of limit. A deleted task or other resource stays in the trash and can be undeleted for 30 days before permanent removal. Responses are JSON wrapped in a top-level data field, with optional fields selected through the opt_fields parameter to keep payloads small.

Errors

Status codes & error handling.

The status codes an agent should handle, and what to do about each.

StatusCodeMeaningWhat to do
400Bad RequestThe request was malformed, usually a missing or invalid parameter. The errors array names the problem.Read the error message, fix the parameters, and resend. The request is not retryable as-is.
401UnauthorizedNo valid authentication token was provided with the request.Send a valid Bearer token, and refresh an expired OAuth access token using its refresh token.
402Payment RequiredThe requested object or feature is only available to premium or paid organizations.Upgrade the organization's plan, or avoid the premium-only feature.
403ForbiddenThe token is valid but lacks permission for this request, for example a scope it was not granted or a resource the user cannot reach.Grant the missing OAuth scope, or confirm the user has access to the resource.
404Not FoundThe object the request names does not exist, or is not visible to this token.Verify the object id, and confirm the token has access to it.
429Too Many RequestsA rate limit was exceeded, either the per-minute request rate, the concurrent-request cap, or the cost quota.Wait the number of seconds in the Retry-After header, then retry, and smooth the request rate.
451Unavailable For Legal ReasonsThe request was blocked for legal reasons, often an embargoed IP address.The request cannot proceed from this location; contact Asana support if this is unexpected.
500Internal Server ErrorA problem on Asana's end. The response includes a unique phrase that support can use to find the incident.Retry with backoff, and quote the phrase to Asana support if it persists.
Versioning & freshness

Version history.

Asana runs a single, continuously updated API at version 1.0 with no dated version to pin, and ships dated changes through its developer changelog, flagging deprecations with a warning header.

Version history

What changed, and when

Latest version1.0
1.0Current version
Current API (version 1.0, continuously updated)

Asana runs a single API at version 1.0 with no dated version to pin and no version header. Changes ship continuously and are announced in the developer changelog, with deprecations flagged by an Asana-Deprecation-Warning header during a transition window. The dated entries below are notable changes from that changelog, newest first.

What changed
  • 2026-06-22: V2 MCP server (https://mcp.asana.com/v2/mcp) became generally available.
  • 2026-06-04: sort_by=relevance added to the Search Projects endpoint.
  • 2026-04-27: Out of Office API added and the vacation_dates field deprecated.
  • 2026-04-06: Goals gained privacy settings, default access levels, and stories via the API.
  • 2026-04-01: Categories added for time tracking entries.
2025-04-09Feature update
Granular OAuth permission scopes introduced

Asana moved from an all-or-nothing OAuth model to granular scopes in the resource:action shape, so an app can request only the resource and action pairs it needs, like tasks:read or projects:write, including separate delete scopes and webhook scopes. Apps already registered with Full permissions continued to use the legacy default scope until self-serve granular scopes were rolled out to them.

What changed
  • Introduced 14 granular OAuth scopes in the resource:action format.
  • Separated read, write, and delete into distinct scopes per resource.
  • Kept the legacy default full-permissions scope for apps registered with Full permissions.

There is no version to pin; track the changelog for deprecations and new fields.

Asana API changelog ↗
Questions

Asana API, answered.

OAuth or a personal access token, which should I use?+
OAuth 2.0 is the choice for an app that acts for other users, because the token carries only the granular scopes the user consented to and can be refreshed and revoked. A personal access token is simpler for a script or a single user's own integration, but it is unscoped and carries that user's full account permissions, so a leak exposes everything the user can reach. Enterprise organizations can use a service account for server-to-server automation that is not tied to a person.
How do the granular OAuth scopes work?+
Each scope names one resource and one action, like tasks:read, projects:write, or stories:write, so an app requests only what it needs instead of full account access. Read, write, and delete are separate, so removing a task needs tasks:delete rather than tasks:write. An app registered with Full permissions can still request the legacy default scope for all-or-nothing access, but a request lacking a granted scope returns a 403.
What are the rate limits?+
Limits are per token. The standard request limit is 150 requests per minute on a free domain and 1,500 per minute on a paid domain, while the Search API is capped at 60 per minute. A separate concurrency limit allows at most 50 GET and 15 write requests in flight at once, and a cost-based quota charges expensive reads more heavily. Going over returns HTTP 429 with a Retry-After header that says how many seconds to wait.
How do I receive changes instead of polling?+
Webhooks deliver events to a target URL registered through the Webhooks API. Setup is a handshake: Asana POSTs an X-Hook-Secret header that the target echoes back to confirm the subscription, then signs every later delivery with an X-Hook-Signature HMAC computed from that secret so the receiver can verify it came from Asana. Each event reports an action, like added, changed, removed, deleted, or undeleted, and the changed resource, and the app fetches the detail through the REST API.
Does Asana have a version to pin?+
No. The API runs at a single version, 1.0, that is continuously updated, with no dated version and no version header. Changes are announced in the developer changelog, and a deprecation is flagged with an Asana-Deprecation-Warning header on affected responses during its transition window. An integration tracks the changelog rather than moving between numbered versions.
Does Asana have an MCP server for AI agents?+
Yes. Asana hosts a Model Context Protocol server at https://mcp.asana.com/v2/mcp, generally available and served over streamable HTTP. It authenticates with OAuth, so a client is prompted to authorize access to the user's Asana data, and it exposes tools for creating and searching tasks, project tracking, and status updates, discoverable with the tools/list command. The older beta server is being retired.
How does pagination work?+
List endpoints are cursor-paginated. A request sets limit between 1 and 100 to choose the page size, and the response returns a next_page object with an offset cursor. That offset is passed back on the next request to fetch the following page, and it is opaque, so it must come from a prior response rather than being built by hand. The official client libraries can iterate the pages automatically.
Related

More productivity API guides for agents

What is Bollard AI?

Control what every AI agent can do in Asana.

Bollard AI sits between a team's AI agents and Asana. Grant each agent exactly the access it needs, read or write, resource by resource, and every call is checked and logged.

  • Set read, write, or full access per agent, never a shared Asana token.
  • Denied by default, so an agent reaches only what has been explicitly allowed.
  • Every call recorded in plain English: who, what, where, and the decision.
Asana
Task Triage Agent
Read tasks ResourceOffReadFull use
Comment on tasks ActionOffReadFull use
Delete tasks ActionOffReadFull use
Per-agent access, set in Bollard AI, not in Asana