UNPKG

openapi-directory

Version:

Building & bundling https://github.com/APIs-guru/openapi-directory for easy use from JS

1 lines 377 kB
{"openapi":"3.0.0","servers":[{"description":"Main endpoint.","url":"https://app.asana.com/api/1.0"}],"info":{"contact":{"name":"Asana Support","url":"https://asana.com/support"},"description":"This is the interface for interacting with the [Asana Platform](https://developers.asana.com). Our API reference is generated from our [OpenAPI spec] (https://raw.githubusercontent.com/Asana/developer-docs/master/defs/asana_oas.yaml).","license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0"},"termsOfService":"https://asana.com/terms","title":"Asana","version":"1.0","x-apisguru-categories":["developer_tools"],"x-docs-schema-whitelist":["AsanaResource","AsanaNamedResource","AuditLogEvent","AttachmentResponse","AttachmentCompact","BatchResponse","CustomFieldSettingResponse","CustomFieldSettingCompact","CustomFieldResponse","CustomFieldCompact","EnumOption","EventResponse","ErrorResponse","GoalResponse","GoalCompact","GoalMembershipCompact","GoalMembershipBase","GoalMembershipResponse","GoalRelationshipResponse","GoalRelationshipCompact","JobResponse","JobCompact","OrganizationExportResponse","OrganizationExportCompact","PortfolioMembershipResponse","PortfolioMembershipCompact","PortfolioResponse","PortfolioCompact","ProjectBriefResponse","ProjectBriefCompact","ProjectMembershipResponse","ProjectMembershipCompact","ProjectResponse","ProjectCompact","ProjectStatusResponse","ProjectStatusCompact","ProjectTemplateCompact","ProjectTemplateResponse","SectionResponse","SectionCompact","StatusUpdateResponse","StatusUpdateCompact","StoryResponse","StoryCompact","TagResponse","TagCompact","TaskResponse","TaskCompact","TaskCountResponse","TeamMembershipResponse","TeamMembershipCompact","TeamResponse","TeamCompact","TimePeriodResponse","TimePeriodCompact","UserTaskListResponse","UserTaskListCompact","UserResponse","UserCompact","WebhookFilter","WebhookResponse","WebhookCompact","WorkspaceMembershipResponse","WorkspaceMembershipCompact","WorkspaceResponse","WorkspaceCompact"],"x-logo":{"url":"https://d1gwm4cf8hecp4.cloudfront.net/images/favicons/apple-touch-icon-57x57.png"},"x-origin":[{"format":"openapi","url":"https://raw.githubusercontent.com/Asana/developer-docs/master/defs/asana_oas.yaml","version":"3.0"}],"x-providerName":"asana.com","x-public-description":"This is the interface for interacting with the [Asana Platform](https://developers.asana.com). Our API reference is generated from our [OpenAPI spec] (https://raw.githubusercontent.com/Asana/developer-docs/master/defs/asana_oas.yaml)."},"security":[{"personalAccessToken":[]},{"oauth2":[]}],"tags":[{"description":"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.","name":"Attachments"},{"description":"Asana's audit log is an immutable log of [important events](/docs/supported-auditlogevents) in your organization's Asana instance.\n\nThe audit log API allows you to monitor and act upon important security and compliance-related changes. Organizations might use this API endpoint to:\n\n* Set up proactive alerting with a Security Information and Event Management (SIEM) tool like [Splunk](https://asana.com/guide/help/api/splunk)\n* Conduct reactive investigations when a security incident takes place\n* Visualize key domain data in aggregate to identify security trends\n\nNote that since the API provides insight into what is happening in an Asana instance, the data is [read-only](/docs/get-audit-log-events). That is, there are no \"write\" or \"update\" endpoints for audit log events.\n\nOnly [Service Accounts](https://asana.com/guide/help/premium/service-accounts) in [Enterprise Domains](https://asana.com/enterprise) can access audit log API endpoints. Authentication with a Service Account's [personal access token](/docs/personal-access-token) is required.\n\nFor a full list of supported events, see [supported AuditLogEvents](/docs/supported-auditlogevents).","name":"Audit log API"},{"description":"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:\n\n* Modern browsers limit the number of requests that a single web page can\n make at once.\n* Mobile apps will use more battery life to keep the cellular radio on\n when making a series of requests.\n* There is an overhead cost to developing software that can make multiple\n requests in parallel.\n* Some cloud platforms handle parallelism poorly, or disallow it\n entirely.\n\n\nTo 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.\n\n#### Making a batch request\n\nTo 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.\n\n**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`.\n\nWhen 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).\n\nThe 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)\n\nThe 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.\n\n#### Rate limiting\n\nThe 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.\n\nIf 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.\n\n#### Restrictions\n\nNot 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:\n\n* Uploading attachments\n* Creating, getting, or deleting organization exports\n* Any SCIM operations\n* Nested calls to the batch API","name":"Batch API"},{"description":"_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 which data users will have access in different circumstances, review the section below on access control._\n\nIn the Asana application, tasks, projects, and portfolios can hold user-specified [custom fields](https://asana.com/guide/help/premium/custom-fields) which provide extra information (e.g., a \"priority\" property with an associated 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.\n`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.\n\n#### Characteristics of custom fields\n\n* 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.\n* 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., `null` data). For portfolio custom fields, every project (row) in the portfolio (table) will contain information for the custom field.\n* Custom field settings only go one child deep. This means that a custom field setting on a portfolio will give each project the custom field, but not each task within those projects.\n* Tasks have custom field _values_ assigned to them.\n\n#### Types of custom fields\n\nIntegrations using custom fields need to be aware of the six basic types that a custom field can adopt. These types are:\n\n* `text` - an arbitrary, relatively short string of text\n* `number` - a number with a defined level of precision\n* `enum` - a selection of a single option from a defined list of options (i.e., mutually exclusive selections)\n* `multi_enum` - a selection of one or more options from a defined list of options (i.e., mutually inclusive selections)\n* `date` - a reference date with an optional time value\n* `people` - a list of active contributors (i.e., where their relationship to the work is defined in the custom field title)\n\n#### Example use case\n\nConsider an organization that 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.\n\nA 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\".\n\nA 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`.\n\n#### Custom fields in the API\n\nThese 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 requests 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.\n\nText fields are currently limited to 1024 characters. On tasks, their custom field value will have a `text_value` property to represent this field.\n\nNumber fields can have an arbitrary `precision` associated with them; for example, a precision of `2` would round its value to the second (hundredths) place (e.g., `1.2345` would round to `1.23`). On tasks, the custom field value will have a `number_value` property to represent this field.\n\n#### Enum fields\n\nEnum 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:\n\n* `gid` - the GID of this enum option. Note that this is the GID of the individual _option_. The custom field itself has a separate `gid`.\n* `name` - the name of the option (e.g., \"Choice #1\")\n* `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.\n* `color` - a color associated with this choice.\n\nOn 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.\n\n#### Querying an organization for its custom fields\n\nFor custom fields shared across the workspace or organization, the workspace [can be queried](/docs/get-a-workspaces-custom-fields) 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`.\n\n#### Accessing custom field definitions\n\nThe [custom fields](/docs/get-a-custom-field) 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.\n\n#### Associating custom fields with a project or portfolio\n\nA mapping between a custom field and a project or portfolio is handled with a [custom field settings](/docs/asana-custom-field-settings) object. This object contains a reference for each of the custom fields and the project or portfolio, as well as additional information about the status of that particular custom field (e.g., `is_important`, which defines whether or not the custom field will appear in the list/grid on the Asana application).\n\n#### Accessing custom field values on tasks or projects\n\nThe [tasks](/docs/get-a-task) 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.\n\nOf 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.\n\nCustom fields can be set just as in the Asana-defined fields on a task via `POST` or `PUT` requests. You can see an example in the [update a task](/docs/update-a-task) endpoint.\n\nCustom fields on projects follow this same pattern.\n\n#### Warning: Program defensively with regards to custom field definitions\n\nAsana 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 is 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 are what it expects.\n\nStoring the state of the custom field metadata for too long if you dynamically create a model for it can cause your model to become out of sync with the model stored in Asana. For example, if you encounter 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.\n\n#### Enabled and disabled values\n\nWhen 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.\n\n_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._\n\nMoving 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.\n\nIn 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.\n\nNote 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.\n\n#### Custom field access control\n\nCustom 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 is 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.","name":"Custom fields"},{"description":"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.","name":"Custom field settings"},{"description":"An event is an object representing a change to a resource that was observed by an event subscription. Event streams rely on the same infrastructure as webhooks, which ensures events are delivered within a minute (on average). This system is designed for at most once delivery, meaning in exceptional circumstances a small number of events may be missing from the stream. For this reason, if your use case requires strong guarantees about processing all changes on a resource and cannot tolerate any missing events, regardless of how rare that might be, we recommend building a fallback polling system that fetches the resource periodically as well. Note that while webhooks cannot be replayed once delivered, events are retrievable from the event stream for 24 hours after being processed.\n\nIn general, requesting events on a resource is faster and subject to higher rate limits than requesting the resource itself. Additionally, change events \"bubble up\" (e.g., listening to events on a project would include when stories are added to tasks in the project, and even to subtasks).\n\nEstablish an initial sync token by making a request with no sync token. The response will be a `412 Precondition Failed` error - the same as if the sync token had expired.\n\nSubsequent requests should always provide the sync token from the immediately preceding call.\n\nSync 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.\n\nWhen 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.\n\nSync tokens always expire after 24 hours, but may expire sooner, depending on load on the service.","name":"Events"},{"description":"A goal is an object in the goal-tracking system that helps your organization drive measurable results.","name":"Goals"},{"description":"A goal relationship is an object representing the relationship between a goal and another goal, a project, or a portfolio.","name":"Goal relationships"},{"description":"Jobs represent processes that handle asynchronous work. A job created when an endpoint requests an action that will be handled asynchronously, such as project or task duplication.\n\nOnly the creator of the duplication process can access the duplication status of the new object.\n\n*Note*: With any work that is handled asynchronously (e.g., [project instantation from a template](/docs/instantiate-a-project-from-a-project-template), duplicating a [task](/docs/duplicate-a-task) or [project](/docs/duplicate-a-project), etc.), the *intermittent states* of newly-created objects may not be consistent. That is, object properties may return different values each time when polled until the job `status` has returned a `succeeded` value.","name":"Jobs"},{"description":"An `organization_export` object represents a request to export the complete data of an organization in JSON format.\n\nTo export an organization using this API:\n\n* Create an `organization_export`\n [request](/docs/create-an-organization-export-request)\n and store the ID that is returned.\n* Request the `organization_export` every few minutes, until the\n `state` field contains ‘finished’.\n* Download the file located at the URL in the `download_url` field. * Exports can take a long time, from several minutes to a few hours\n for large organizations.\n\n\n*Note: These endpoints are only available to [Service Accounts](https://asana.com/guide/help/premium/service-accounts) of an [Enterprise](https://asana.com/enterprise) organization.*","name":"Organization exports"},{"description":"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 [status update](/docs/asana-statuses).\nPortfolios have some restrictions on size. Each portfolio has a max of 500 items and, like projects, a maximum of 20 custom fields.","name":"Portfolios"},{"description":"This object determines if a user is a member of a portfolio.","name":"Portfolio memberships"},{"description":"A project represents a prioritized list of tasks in Asana or a board with columns of tasks represented as cards. A project exists in a single workspace or organization and is accessible to a subset of users in that workspace or organization, depending on its permissions.\n\nProjects in organizations are shared with a single team. Currently, the team of a project cannot be changed via the API. Non-organization workspaces do not have teams and so you should not specify the team of project in a regular workspace.\n\nFollowers 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.\n\n**Note:** You can use certain project endpoints to operate on [user task lists](/docs/user-task-lists) ([My Tasks](https://asana.com/guide/help/fundamentals/my-tasks)) by substituting the `{project_gid}` with the `{user_task_list_gid}`. For example, you can perform operations on the custom fields of a [user task list](/docs/user-task-lists) by using the following projects endpoints: [Add a custom field to a project](/docs/add-a-custom-field-to-a-project), [Remove a custom field from a project](/docs/remove-a-custom-field-from-a-project) and [Get a project's custom fields](/docs/get-a-projects-custom-fields)","name":"Projects"},{"description":"A project brief object represents a rich text document that describes a project.\n\nPlease note that this API is in *preview*, and is expected to change. This API is to be used for development and testing only as an advance view into the upcoming rich text format experience in the task description. For more information, see [this post](https://forum.asana.com/t/project-brief-api-now-available-as-a-preview/150885) in the developer forum.","name":"Project briefs"},{"description":"With the introduction of “comment-only” projects in Asana, a user’s membership in a project comes with associated permissions. These permissions (i.e., whether a user has full access to the project or comment-only access) are accessible through the project memberships endpoints described here.","name":"Project memberships"},{"description":"*Deprecated: new integrations should prefer using [status updates](/docs/asana-statuses)*\n\nA project status is an update on the progress of a particular project,\nand is sent out to all project followers when created. These updates\ninclude both text describing the update and a color code intended to\nrepresent the overall state of the project: \"green\" for projects that\nare on track, \"yellow\" for projects at risk, \"red\" for projects that\nare behind, and \"blue\" for projects on hold.\n\nProject statuses can be created and deleted, but not modified.","name":"Project statuses"},{"description":"A project template is an object that allows new projects to be created\nwith a predefined setup, which may include tasks, sections, rules, etc.\nIt simplifies the process of running a workflow that involves a similar\nset of work every time.\n\n\nProject templates in organizations are shared with a single team. Currently, the\nteam of a project template cannot be changed via the API.","name":"Project templates"},{"description":"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.\n\nSections are largely a shared idiom in Asana’s API for both list and board views of a project regardless of the project’s layout.\n\nThe ‘memberships’ property when [getting a task](/docs/get-a-task) will return the information for the section or the column under ‘section’ in the response.","name":"Sections"},{"description":"A status update is an update on the progress of a particular object,\nand is sent out to all followers when created. These updates\ninclude both text describing the update and a `status_type` intended to\nrepresent the overall state of the project. These include: `on_track` for projects that\nare on track, `at_risk` for projects at risk, `off_track` for projects that\nare behind, and `on_hold` for projects on hold.\n\nStatus updates can be created and deleted, but not modified.","name":"Status updates"},{"description":"*See [our forum post](https://forum.asana.com/t/no-more-parsing-story-text-new-fields-on-stories/42924) for more info on when conditional fields are returned.*\n\nA 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.","name":"Stories"},{"description":"A tag is a label that can be attached to any task in Asana. It exists in a single workspace or organization.\n\nTags 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.","name":"Tags"},{"description":"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.\n\nSections 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.\n\n[Queries](/docs/get-multiple-tasks) return a [compact representation of each task object](/docs/task-compact). To retrieve *all* fields or *specific set* of the fields, use [field selectors](/docs/input-output-options) to manipulate what data is included in a response.","name":"Tasks"},{"description":"A team is used to group related projects and people together within an organization. Each project in an organization is associated with a team.","name":"Teams"},{"description":"This object determines if a user is a member of a team.","name":"Team memberships"},{"description":"A time period is an object that represents a domain-scoped date range that can be set on [goals](/docs/goals).","name":"Time periods"},{"description":"The typeahead search API provides search for objects from a single workspace.","name":"Typeahead"},{"description":"A user object represents an account in Asana that can be given access to various workspaces, projects, and tasks.\n\nLike 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 (e.g, `GET /users/me`).","name":"Users"},{"description":"A user task list represents the tasks assigned to a particular user. This list is the user's [My Tasks](https://asana.com/guide/help/fundamentals/my-tasks) list.","name":"User task lists"},{"description":"Webhooks allow you to subscribe to notifications about events that occur on Asana resources (e.g., tasks, projects, stories, etc.).\n\nFor a more detailed explanation of webhooks see the [overview of webhooks](/docs/overview-of-webhooks).","name":"Webhooks"},{"description":"A *workspace* is the highest-level organizational unit in Asana. All projects and tasks have an associated workspace.\n\nAn *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.\n\nOver 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.","name":"Workspaces"},{"description":"This object determines if a user is a member of a workspace.","name":"Workspace memberships"}],"paths":{"/attachments":{"get":{"description":"Returns the compact records for all attachments on the object.\n\nThere are three possible `parent` values for this request: `project`, `project_brief`, and `task`. For a project, an attachment refers to a file uploaded to the \"Key resources\" section in the project Overview. For a project brief, an attachment refers to inline files in the project brief itself. For a task, an attachment refers to a file directly associated to that task.","operationId":"getAttachmentsForObject","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"description":"Globally unique identifier for object to fetch statuses from. Must be a GID for a `project`, `project_brief`, or `task`.","example":"159874","in":"query","name":"parent","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AttachmentCompact"},"type":"array"}},"type":"object"}}},"description":"Successfully retrieved the specified object's attachments."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Get attachments from an object","tags":["Attachments"]},"parameters":[{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"}],"post":{"description":"Upload an attachment.\n\nThis method uploads an attachment on an object and returns the compact\nrecord for the created attachment object. This is possible by either:\n\n- Providing the URL of the external resource being attached, or\n- Downloading the file content first and then uploading it as any other attachment. Note that it is not possible to attach\nfiles from third party services such as Dropbox, Box, Vimeo & Google Drive via the API\n\nThe 100MB size limit on attachments in Asana is enforced on this endpoint.\n\nThis endpoint expects a multipart/form-data encoded request containing the full contents of the file to be uploaded.\n\nRequests made should follow the HTTP/1.1 specification that line\nterminators are of the form `CRLF` or `\\r\\n` outlined\n[here](http://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01#Basic-Rules) in order for the server to reliably and properly handle the request.","operationId":"createAttachmentForObject","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/AttachmentRequest"}}},"description":"The file you want to upload.\n\n*Note when using curl:*\n\nBe sure to add an `‘@’` before the file path, and use the `--form`\noption instead of the `-d` option.\n\nWhen uploading PDFs with curl, force the content-type to be pdf by\nappending the content type to the file path: `--form\n\"file=@file.pdf;type=application/pdf\"`.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/AttachmentResponse"}},"type":"object"}}},"description":"Successfully uploaded the attachment to the parent object."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Upload an attachment","tags":["Attachments"]}},"/attachments/{attachment_gid}":{"delete":{"description":"Deletes a specific, existing attachment.\n\nReturns an empty data record.","operationId":"deleteAttachment","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EmptyResponse"}},"type":"object"}}},"description":"Successfully deleted the specified attachment."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Delete an attachment","tags":["Attachments"]},"get":{"description":"Get the full record for a single attachment.","operationId":"getAttachment","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/AttachmentResponse"}},"type":"object"}}},"description":"Successfully retrieved the record for a single attachment."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"424":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"501":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}},"summary":"Get an attachment","tags":["Attachments"]},"parameters":[{"$ref":"#/components/parameters/attachment_path_gid"},{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"}]},"/batch":{"parameters":[{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"}],"post":{"description":"Make multiple requests in parallel to Asana's API.","operationId":"createBatchRequest","requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/BatchRequest"}},"type":"object"}}},"description":"The requests to batch together via the Batch API.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/BatchResponse"},"type":"array"}},"type":"object"}}},"description":"Successfully completed the requested batch API operations."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Submit parallel requests","tags":["Batch API"]}},"/custom_fields":{"parameters":[{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"post":{"description":"Creates a new custom field in a workspace. Every custom field is required\nto be created in a specific workspace, and this workspace cannot be\nchanged once set.\n\nA custom field’s name must be unique within a workspace and not conflict\nwith names of existing task properties such as `Due Date` or `Assignee`.\nA custom field’s type must be one of `text`, `enum`, `multi_enum`, `number`,\n`date`, or `people`.\n\nReturns the full record of the newly created custom field.","operationId":"createCustomField","requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CustomFieldRequest"}},"type":"object"}}},"description":"The custom field object to create."},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CustomFieldResponse"}},"type":"object"}}},"description":"Custom field successfully created."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Create a custom field","tags":["Custom fields"]}},"/custom_fields/{custom_field_gid}":{"delete":{"description":"A specific, existing custom field can be deleted by making a DELETE request on the URL for that custom field.\nLocked custom fields can only be deleted by the user who locked the field.\nReturns an empty data record.","operationId":"deleteCustomField","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EmptyResponse"}},"type":"object"}}},"description":"The custom field was successfully deleted."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Delete a custom field","tags":["Custom fields"]},"get":{"description":"Get the complete definition of a custom field’s metadata.\n\nSince custom fields can be defined for one of a number of types, and\nthese types have different data and behaviors, there are fields that are\nrelevant to a particular type. For instance, as noted above, enum_options\nis only relevant for the enum type and defines the set of choices that\nthe enum could represent. The examples below show some of these\ntype-specific custom field definitions.","operationId":"getCustomField","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CustomFieldResponse"}},"type":"object"}}},"description":"Successfully retrieved the complete definition of a custom field’s metadata."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Get a custom field","tags":["Custom fields"]},"parameters":[{"$ref":"#/components/parameters/custom_field_path_gid"},{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"}],"put":{"description":"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\nWhen 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.\nA custom field’s `type` cannot be updated.\nAn 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`.\nLocked custom fields can only be updated by the user who locked the field.\nReturns the complete updated custom field record.","operationId":"updateCustomField","requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CustomFieldRequest"}},"type":"object"}}},"description":"The custom field object with all updated properties."},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CustomFieldResponse"}},"type":"object"}}},"description":"The custom field was successfully updated."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Update a custom field","tags":["Custom fields"]}},"/custom_fields/{custom_field_gid}/enum_options":{"parameters":[{"$ref":"#/components/parameters/custom_field_path_gid"},{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"post":{"description":"Creates an enum option and adds it to this custom field’s list of enum options. A custom field can have at most 500 enum options (including disabled options). By default new enum options are inserted at the end of a custom field’s list.\nLocked custom fields can only have enum options added by the user who locked the field.\nReturns the full record of the newly created enum option.","operationId":"createEnumOptionForCustomField","requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EnumOptionRequest"}},"type":"object"}}},"description":"The enum option object to create."},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EnumOption"}},"type":"object"}}},"description":"Custom field enum option successfully created."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Create an enum option","tags":["Custom fields"]}},"/custom_fields/{custom_field_gid}/enum_options/insert":{"parameters":[{"$ref":"#/components/parameters/custom_field_path_gid"},{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"}],"post":{"description":"Moves a particular enum option to be either before or after another specified enum option in the custom field.\nLocked custom fields can only be reordered by the user who locked the field.","operationId":"insertEnumOptionForCustomField","requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EnumOptionInsertRequest"}},"type":"object"}}},"description":"The enum option object to create."},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EnumOption"}},"type":"object"}}},"description":"Custom field enum option successfully reordered."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Reorder a custom field's enum","tags":["Custom fields"]}},"/enum_options/{enum_option_gid}":{"parameters":[{"description":"Globally unique identifier for the enum option.","example":"124578","in":"path","name":"enum_option_gid","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"}],"put":{"description":"Updates an existing enum option. Enum custom fields require at least one enabled enum option.\nLocked custom fields can only be updated by the user who locked the field.\nReturns the full record of the updated enum option.","operationId":"updateEnumOption","requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EnumOptionRequest"}},"type":"object"}}},"description":"The enum option object to update"},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/EnumOption"}},"type":"object"}}},"description":"Successfully updated the specified custom field enum."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Update an enum option","tags":["Custom fields"]}},"/events":{"get":{"description":"Returns the full record for all events that have occurred since the sync\ntoken was created.\n\nA `GET` request to the endpoint `/[path_to_resource]/events` can be made in\nlieu of including the resource ID in the data for the request.\n\nAsana limits a single sync token to 100 events. If more than 100 events exist\nfor a given resource, `has_more: true` will be returned in the response, indicating\nthat there are more events to pull. \n\n*Note: The resource returned will be the resource that triggered the\nevent. This may be different from the one that the events were requested\nfor. For example, a subscription to a project will contain events for\ntasks contained within the project.*","operationId":"getEvents","responses":{"200":{"content":{"application/json":{"schema":{"description":"The full record for all events that have occurred since the sync token was created.","properties":{"data":{"items":{"$ref":"#/components/schemas/EventResponse"},"type":"array"},"has_more":{"description":"Indicates whether there are more events to pull.","example":true,"type":"boolean"},"sync":{"description":"A sync token to be used with the next call to the /events endpoint.","example":"de4774f6915eae04714ca93bb2f5ee81","type":"string"}},"type":"object"}}},"description":"Successfully retrieved events."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalServerError"}},"summary":"Get events on a resource","tags":["Events"]},"parameters":[{"description":"A resource ID to subscribe to. The resource can be a task or project.","example":"12345","in":"query","name":"resource","required":true,"schema":{"type":"string"}},{"description":"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.\n*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.*","example":"de4774f6915eae04714ca93bb2f5ee81","in":"query","name":"sync","required":false,"schema":{"type":"string"}},{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"}]},"/goal_relationships":{"get":{"description":"Returns compact goal relationship records.","operationId":"getGoalRelationships","parameters":[{"$ref":"#/components/parameters/pretty"},{"$ref":"#/components/parameters/fields"},{"description":"Globally unique identifier for the supported goal in the goal relationship.","example":"12345","in":"query",