Asana models work as collections of resources (workspaces/organizations, teams, projects, portfolios, goals) that contain or reference smaller objects (projects contain sections and tasks; tasks can have subtasks, tags, attachments, dependencies). Most operations act on one resource type and require its global id (a *_gid like workspace_gid, project_gid, task_gid, user_gid, team_gid, portfolio_gid, custom_field_gid, etc.). Knowing which id each step needs — and which endpoints produce those ids — is the key to composing multi-step actions reliably.
Domain map, at a glance
- Workspaces / Organizations: top-level container. Many list endpoints are filtered by
workspaceorworkspace_gid. - Teams: belong to an organization; projects are often created in a team (
createProjectForTeam). - Projects: contain sections (
getSectionsForProject,createSectionForProject) and tasks (getTasksForProject,addTaskForSection). Many project-scoped operations requireproject_gid. - Sections: used to order or place tasks inside a project (
addTaskForSection,insertSectionForProject). - Tasks: central object. Tasks belong to projects and/or sections, can have subtasks, dependencies, tags, attachments, followers, stories. Most task operations require
task_gidor a project/section id when creating or listing. - Users: identified by
user_gid, email, or the special stringmein many endpoints. - Tags / Custom fields / Custom types: workspace-scoped resources that you attach to tasks, projects, goals. Use
getTagsForWorkspaceandgetCustomFieldsForWorkspaceto discover them. - Portfolios & Goals: higher-level groupings with their own membership/followers/custom-field settings endpoints.
- Webhooks and Events: install webhooks (
createWebhook) and pull changes viagetEvents/workspace event endpoints;getEventsreturns a sync token used to resume incremental syncs.
The API intentionally scopes many actions to a container id (workspace, project, team). When in doubt, list resources in the appropriate scope to obtain the id you need.
Entry points — what to call first to get IDs you’ll need
Start by discovering the container IDs you’ll need for most flows. These endpoints return the most commonly required ids and compact objects that include gid and name by default.
getWorkspaces/getWorkspace— getworkspace_gid/organization id.getUsersorgetUser/getUsersForWorkspace— finduser_gid(you can passme).getTeamsForWorkspace/getTeamsForUser— discoverteam_gid.getProjects,getProjectsForTeam,getProjectsForWorkspace— getproject_gidfor creating or listing tasks.getSectionsForProject— findsection_gidwhen you need to place or move tasks into sections.getTasksForProject,getTask,getTasks— findtask_gidwhen operating on tasks.getTagsForWorkspaceandgetCustomFieldsForWorkspace— find tag and custom field ids to attach to tasks/projects.getPortfolios/getPortfolioandgetGoals/getGoal— findportfolio_gidandgoal_gid.getWebhooks/getWebhook— list existing webhooks and theirwebhook_gid.
Most list endpoints return paginated results with a next_page/offset token when results are large. Many list endpoints accept opt_fields to include extra properties (see next section).
Common capabilities and the usual sequences
Below are the practical workflows you’ll use most often and the operations to call in sequence. Each step mentions which id the next step usually needs.
Create and place a task in a project (and optionally a section)
- Create the task with
createTask(includeprojectswithproject_gidorworkspace+projects). This returns the taskgidin the response. - If you must place it into a specific section, call
addTaskForSectionwith thesection_gidand thetask_gid, or useaddProjectForTask+insertSectionForProjectdepending on which placement is needed.
Add or remove tags and followers on a task
- Add:
addTagForTaskoraddFollowersForTask(both requiretask_gid). - Remove:
removeTagForTaskorremoveFollowerForTask(both requiretask_gid). - Inspect current tags/followers with
getTagsForTaskandgetTask(includefollowersinopt_fields).
Subtasks and parents
- Create a subtask:
createSubtaskForTaskwith parenttask_gid. - List subtasks:
getSubtasksForTask. - Change a task’s parent:
setParentForTask(passtask_gidof the child and the new parent in the body).
Dependencies
- Link dependencies:
addDependenciesForTask/addDependentsForTask(pass thetask_gidyou operate on and the other task gids in the body). - Unlink:
removeDependenciesForTask/removeDependentsForTask.
Custom fields (create, attach, remove)
- Create a custom field (workspace scope):
createCustomField. - Attach a custom field to a project/portfolio/goal:
addCustomFieldSettingForProject/addCustomFieldSettingForPortfolio/addCustomFieldSettingForGoal— supply theproject_gid/portfolio_gid/goal_gidand thecustom_field_gid. - Remove with the matching
removeCustomFieldSettingFor*endpoint.
Attachments
- Upload an attachment to a task/project/brief:
createAttachmentForObject(supply theparentobject id as specified by the type). Inspect attachments viagetAttachmentsForObject.
Project templates, duplication, instantiation
- Save a project as a template:
projectSaveAsTemplate(supplyproject_gid). - Instantiate a project or task from a template:
instantiateProject/instantiateTaskor duplicate an existing project/task withduplicateProject/duplicateTask. - Many of these operations can trigger background jobs or export artifacts; the response often includes job/export info. Query
getJobor the specific export endpoint to check status.
Status updates and stories
- Create status updates for a project/portfolio/goal with
createStatusForObject. - Create stories on tasks with
createStoryForTaskand list them withgetStoriesForTask.
Webhooks and Events
- Create a webhook with
createWebhook; update or delete it withupdateWebhook/deleteWebhook. - Use
getEvents(resource + optional sync token) orgetWorkspaceEventsto pull incremental changes.getEventsreturns asynctoken and setshas_more; if a provided sync token is too old, the API returns 412 with a fresh token — treat that as the signal to restart syncing from the returned token.
Goals & portfolios
- Create a goal with
createGoal, attach followers withaddFollowersand custom fields withaddCustomFieldSettingForGoal. - Create goal metrics with
createGoalMetricand relate goals withaddSupportingRelationship/removeSupportingRelationshipand manage relationships viagetGoalRelationships/updateGoalRelationship.
Batched / parallel requests
- Submit parallel requests using
createBatchRequest. The response gives per-request bodies and status codes.
Patterns, naming conventions, and where to look
Operations follow a regular verb/resource pattern: createX, getX, getXForY, addXForY, removeXForY, updateX, deleteX. When you need to attach or remove a relationship, look for add*For* / remove*For* forms. When an operation applies to a contained resource, the path typically contains the container id (e.g., project_gid for section or project-scoped operations).
IDs are stable global gids. Many endpoints accept a user identifier that can be me, an email, or a user_gid — the same flexible user identifier works across getUser, membership, and favorites endpoints.
Lists and opt_fields
- Responses are intentionally compact by default. Use the
opt_fieldsquery parameter to ask for nested properties you need (for example,projects.name,permalink_url,followers,custom_fields). Include only the fields you will examine; many endpoints allow deep nested attributes inopt_fields.
Filtering quirks to remember
- Some list filters require a companion parameter: e.g., when calling
getTaskswithassignee, you must also specifyworkspace. The API notes appear on the signature for such constraints — check for them before calling. - Several endpoints accept comma-separated lists of ids in query filters (
projects.any,tags.any, etc.).
Async / job-backed operations
- Some heavy operations (project duplication, exports, instantiation) return references to background tasks, exports, or graph exports instead of immediately returning the final object. The response commonly includes
new_graph_export,new_resource_export, or job-like fields. If those fields appear, treat the returned reference as the handle to check later (there are dedicated endpoints likegetJobor the specific export endpoints to inspect status).
Events and sync tokens
getEventsandgetWorkspaceEventsreturn asynctoken. If you pass an expired token you’ll receive a412 Precondition Failedwith a fresh sync token in the response. Use the token the API returns to resume a fresh sync; do not try to reuse an old token.
Non-obvious gotchas and practical tips
-
Responses are trimmed by default. If a call returns an object that looks incomplete, add
opt_fieldsto request the nested properties you need. Examples: projectpermalink_url, taskprojectsandmemberships, or goalcustom_field_settings. -
The
meshortcut works for many user parameters (e.g.,getUser, membership, favorites). Passing an email string is also supported in the same places. -
When creating or filtering tasks, watch for required companion parameters: if you specify
assigneeingetTasks, you must also sendworkspace. The method signatures include these notes — follow them to avoid parameter errors. -
Many relationship mutations (add/remove members, followers, tags) return the updated parent resource (project/goal/task) rather than a separate relationship object. When you need to confirm the change, inspect the returned
dataor call the relevantget*endpoint. -
Use the dedicated add/remove endpoints for relationships (e.g.,
addMembersForProject/removeMembersForProject) instead of trying to update membership viaupdateProject— the intent-specific endpoints are the supported pattern. -
Typeahead and searching:
typeaheadForWorkspaceacceptsresource_type(preferred) and a deprecatedtypeparam. Preferresource_type.searchTasksForWorkspaceis powerful but has many filter parameters — it always runs in the context of aworkspace_gid. -
Debugging output:
opt_prettyonly affects response formatting (useful for human debugging) and should be omitted in normal calls. -
Batch requests:
createBatchRequestexecutes many independent operations in parallel and returns an array of per-request responses. Use this for independent writes that can be performed concurrently.
Where APIs commonly surprise agents
-
Partial objects: list endpoints frequently return compact representations (for example,
TaskCompact,ProjectCompact). Ask for the fields you need withopt_fieldsrather than expecting all details by default. -
Asynchrony: duplication, instantiation, and export flows commonly produce job/export handles instead of final resources. Look for
new_graph_export,new_resource_export, orjob_gid-like fields and use the job/export endpoints to learn completion status. -
Events sync semantics: a
412is not an error to retry blindly — it indicates your sync token is stale. Use the token the response provides and restart the sync from that token. -
Parameter coupling: some filters must be combined (e.g.,
assignee+workspace). These coupling rules are documented on the operation signatures; consult them before constructing calls.
Quick mental checklist before making a call
- Do you have the correct scope id? (workspace/team/project/section/task) — if not, fetch it with the matching list/get endpoint.
- Does the operation return a compact object by default? If you need nested fields, include
opt_fields. - Is the change relationship-specific? Prefer
add*For*/remove*For*endpoints for membership/follower/tag changes. - Could the operation be asynchronous (duplication, export, instantiate)? If so, check the response for job/export references and use the appropriate status endpoint.
Following these patterns will let you assemble the small call sequences users ask for most often — create and place tasks, add/remove followers and tags, upload attachments, and perform project-level operations — while avoiding the most common surprises (compact responses, required companion filters, and async jobs).