Metadata-Version: 2.4
Name: autodesk-platform-sdk
Version: 0.3.0
Summary: Autodesk Platform Services (APS) Python API Client
Keywords: autodesk,aps,forge,api,client,cli,bim,acc
Author: SB&O Inc
Author-email: SB&O Inc <contact@sboinc.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: click>=8.0.0
Requires-Dist: cryptography>=42.0.0
Requires-Dist: httpx>=0.20.0
Requires-Dist: pydantic>=2.10.0
Requires-Python: >=3.12
Project-URL: Download, https://github.com/sbo-inc/autodesk-platform-sdk/releases
Project-URL: Homepage, https://github.com/sbo-inc/autodesk-platform-sdk
Project-URL: Issues, https://github.com/sbo-inc/autodesk-platform-sdk/issues
Project-URL: Repository, https://github.com/sbo-inc/autodesk-platform-sdk
Description-Content-Type: text/markdown

[![CI](https://github.com/sbo-inc/autodesk-platform-sdk/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/sbo-inc/autodesk-platform-sdk/actions/workflows/ci.yaml)
[![PyPI](https://img.shields.io/pypi/v/autodesk-platform-sdk.svg)](https://pypi.org/project/autodesk-platform-sdk/)
[![Python versions](https://img.shields.io/pypi/pyversions/autodesk-platform-sdk.svg)](https://pypi.org/project/autodesk-platform-sdk/)
[![License](https://img.shields.io/pypi/l/autodesk-platform-sdk.svg)](https://github.com/sbo-inc/autodesk-platform-sdk/blob/main/LICENSE)

# Autodesk Platform Services Python client

An unofficial typed Python client and command-line interface for the [Autodesk Platform Services](https://aps.autodesk.com/developer/documentation) (APS) APIs. No affiliation with Autodesk is implied or intended.

APS spans many services behind one host and one OAuth server. This package wraps them in an ergonomic, fully type-hinted client built on [Pydantic](https://docs.pydantic.dev/) models, plus an `aps` CLI for quick access from the terminal.

## Features

- **One client, every API** - thirty-eight APS services mount as namespaces on a single client, from `client.auth` to `client.webhooks`, sharing one connection pool and one token cache.
- **Typed models** - every response is parsed into Pydantic models with descriptive fields.
- **Python client and CLI** - use it as a library or straight from the shell via `aps`.
- **Sync and async** - `Client` and `AsyncClient` mount the same services under the same names over `httpx`.
- **Both OAuth flows** - 2-legged client credentials and the full 3-legged authorization code flow with PKCE.
- **Sensible defaults** - caches access tokens per scope set and refreshes them before they expire.
- **The awkward parts handled** - multipart uploads to signed S3 URLs, translation and workitem polling, URN encoding, JWT assertion signing, cursor paging, and every vocabulary APS uses to report an error.

## Services

Each APS API is mounted on the client as its own namespace.

| Namespace | API | Reference |
| --- | --- | --- |
| `client.auth` | Authentication (OAuth) v2 | [docs](https://aps.autodesk.com/en/docs/oauth/v2/reference/http/) |
| `client.service_accounts` | Secure Service Account v1 | [docs](https://aps.autodesk.com/en/docs/ssa/v1/reference/http/) |
| `client.oss` | Object Storage Service v2 | [docs](https://aps.autodesk.com/en/docs/data/v2/reference/http/) |
| `client.model_derivative` | Model Derivative v2 | [docs](https://aps.autodesk.com/en/docs/model-derivative/v2/reference/http/) |
| `client.design_automation` | Design Automation v3 | [docs](https://aps.autodesk.com/en/docs/design-automation/v3/reference/http/) |
| `client.data_management` | Data Management v2 | [docs](https://aps.autodesk.com/en/docs/data/v2/reference/http/) |
| `client.account_admin` | ACC Account Admin v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/admin-projects-GET/) |
| `client.issues` | ACC Issues v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/issues-issues-GET/) |
| `client.rfis` | ACC RFIs v3 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/rfis-rfi-search-POST/) |
| `client.model_properties` | ACC Model Properties v2 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/index-v2-index-status-get/) |
| `client.cost_management` | ACC Cost Management v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/cost-budgets-GET/) |
| `client.submittals` | ACC Submittals v2 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/submittals-items-GET/) |
| `client.sheets` | ACC Sheets v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/sheets-sheets-GET/) |
| `client.model_coordination` | ACC Model Coordination v3 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/mc-modelset-service-v3-get-model-sets-GET/) |
| `client.data_connector` | ACC Data Connector v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/data-connector-requests-GET/) |
| `client.takeoff` | ACC Takeoff v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/takeoff-projects-project_id-packages-GET/) |
| `client.assets` | ACC Assets v1/v2 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/assets-assets-v2-GET/) |
| `client.forms` | ACC Forms v1/v2/v3 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/forms-forms-(New--Beta)-GET/) |
| `client.reviews` | ACC Reviews v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/reviews-reviews-GET/) |
| `client.files` | ACC Files v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/v1-files-export-pdf-files-POST/) |
| `client.locations` | ACC Locations v2 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/locations-nodes-GET/) |
| `client.photos` | ACC Photos v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/photos-getphoto-GET/) |
| `client.relationships` | ACC Relationships v2 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/relationship-service-v2-get-relationship-by-id-GET/) |
| `client.transmittals` | ACC Transmittals v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/reference/http/transmittals-listtransmittals-GET/) |
| `client.autospecs` | ACC AutoSpecs v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/autospecs/) |
| `client.classifications` | ACC Classifications v1 | [docs](https://aps.autodesk.com/en/docs/acc/v1/classifications/) |
| `client.parameters` | Parameters v1 | [docs](https://aps.autodesk.com/en/docs/parameters/v1/reference/http/parameters-listgroups-GET/) |
| `client.tandem` | Tandem Data v1 | [docs](https://aps.autodesk.com/en/docs/tandem/v1/reference/http/quick_reference/) |
| `client.applications` | Application Management v1 | [docs](https://aps.autodesk.com/en/docs/applications/v1/reference/http/application-management-api-listclients-GET/) |
| `client.informed_design` | Informed Design v1 (beta) | [docs](https://aps.autodesk.com/en/docs/informed-design/v1/reference/http/informed-design-api-getproducts-GET/) |
| `client.sustainability` | Sustainability Data v3 (beta) | [docs](https://aps.autodesk.com/en/docs/sustainability/v3/reference/http/sustainability-getdatasets-GET/) |
| `client.token_flex` | Token Flex Usage Data v1 | [docs](https://aps.autodesk.com/en/docs/tokenflex/v1/reference/http/contract-GET/) |
| `client.insights` | Business Success Plan Reporting v1 | [docs](https://aps.autodesk.com/en/docs/insights/v1/reference/http/contexts-GET/) |
| `client.forma` | Forma Site Design v1alpha (alpha) | [docs](https://aps.autodesk.com/en/docs/forma/v1/reference/http/http-reference/) |
| `client.flow_graph` | Flow Graph Engine v1 | [docs](https://aps.autodesk.com/en/docs/flow_graph_engine/v1/reference/http/quick_reference/) |
| `client.building_connected` | BuildingConnected v2/v3 | [docs](https://aps.autodesk.com/en/docs/buildingconnected/v2/reference/http/) |
| `client.tradetapp` | TradeTapp v2 | [docs](https://aps.autodesk.com/en/docs/buildingconnected/v2/reference/http/tradetapp-users-me-GET/) |
| `client.webhooks` | Webhooks v1 | [docs](https://aps.autodesk.com/en/docs/webhooks/v1/reference/http/) |

## Installation

```bash
pip install autodesk-platform-sdk
# or, with uv:
uv add autodesk-platform-sdk
```

Requires Python 3.12+.

## Configuration

Credentials are read from environment variables (or can be passed directly to `Client`):

| Variable | Description |
| --- | --- |
| `APS_CLIENT_ID` | The application's Client ID. |
| `APS_CLIENT_SECRET` | The application's Client Secret. |
| `APS_CALLBACK_URL` | A registered Callback URL, used by the 3-legged flow. |
| `APS_ACCESS_TOKEN` | A 3-legged access token to act as a user with. |
| `APS_REFRESH_TOKEN` | A 3-legged refresh token, exchanged as needed. |
| `APS_BASE_URL` | Overrides the APS API host. |

```bash
export APS_CLIENT_ID="your-client-id"
export APS_CLIENT_SECRET="your-client-secret"
export APS_CALLBACK_URL="http://localhost:53682/callback"
```

Create an app and its credentials at [aps.autodesk.com/myapps](https://aps.autodesk.com/myapps). The client credentials grant needs an app registered as **Server-to-Server** or **Traditional Web App**; the 3-legged flow additionally needs the callback URL registered on that app, matched **exactly** - a trailing slash is a different URL.

### Timeouts and retries

Every request carries a timeout (default `(5, 30)` seconds for connect and read) so a stalled connection can't hang the caller forever. Pass `timeout=` to override it (a single float, a `(connect, read)` tuple, or `None` to disable), and `retries=` to retry connection-establishment failures:

```python
client = Client(timeout=60, retries=3)
```

`retries` retries only the connection stage, before any bytes reach the server, so a token is never minted twice. The CLI takes both from the environment instead.

## Quick start

### The application acts as itself

The 2-legged grant covers most of the platform. Tokens are cached per scope set and reused until they near expiry, so ask for one whenever you need it.

```python
from autodesk_platform_sdk import Client
from autodesk_platform_sdk.services.oss.schemas import PolicyKey

client = Client()

bucket = client.oss.create_bucket("my-app-bucket", PolicyKey.transient)
client.oss.upload_object(bucket.bucket_key, "model.rvt", data)
```

### Acting as a user

Most of APS is scoped to a person rather than an application, and BuildingConnected and TradeTapp accept nothing else. Install a 3-legged token once and every mounted service acts as that user.

```python
from autodesk_platform_sdk import Scope

token = client.auth.authorize_interactively([Scope.data_read, Scope.openid])
client.auth.use_token(token)

client.data_management.list_hubs()  # would report no hubs without this
client.building_connected.list_projects()  # refuses a 2-legged token outright
```

For an unattended job, a saved refresh token is enough on its own - it is exchanged on first use and again whenever it expires. Refresh tokens are single-use, so persist the replacement:

```python
client = Client(refresh_token=load())
client.auth.on_refresh = lambda token: save(token.refresh_token)
```

### The awkward parts

Several APS workflows take three or four calls and a rule you have to know. Those are wrapped in one method each, so `upload_object` runs the whole signed-S3 flow with automatic multipart splitting, and `wait_for_translation` polls to completion:

```python
import pathlib

from autodesk_platform_sdk.services.modelderivative.schemas import OutputType

uploaded = client.oss.upload_object(
    bucket_key, "tower.rvt", pathlib.Path("tower.rvt").read_bytes()
)

client.model_derivative.translate(uploaded.object_id, [OutputType.svf2])
manifest = client.model_derivative.wait_for_translation(uploaded.object_id)
assert manifest.is_successful()
```

`AsyncClient` mirrors `Client` method for method - same arguments, same return types, awaited.

Each service's docstring carries what is peculiar to it: which calls need a subscription, where an empty listing means a permissions failure rather than no data, which IDs carry a `b.` prefix. Read it in your editor, or with `help(client.data_management)`.

## CLI

Every service is a command group. Connection settings come from the same `APS_*` variables.

```bash
aps auth login --scope data:read          # 3-legged, opens a browser
aps oss buckets
aps derivative translate <urn> --output svf2
aps bc projects --include-closed
```

`aps --help` lists the groups. `aps <group> --help` lists its commands.

The CLI reads four more variables of its own:

| Variable | Description |
| --- | --- |
| `APS_API_TIMEOUT` | Per-request timeout in seconds. |
| `APS_API_RETRIES` | How many times to retry a failed connection. |
| `APS_API_HEADERS` | Extra request headers, as a JSON object, to reach APS through a proxy. |
| `APS_CLI_DISABLE` | Command paths to hide and refuse, comma separated, such as `oss.delete-bucket`. |

## API reference

### Authentication (`client.auth`)

| Method | Description |
| --- | --- |
| `get_access_token` | Mint or reuse a 2-legged token for a scope set. |
| `get_active_token` | The token every service acts with, refreshing if needed. |
| `use_token` | Install a 3-legged token for the whole client to act as a user. |
| `clear_token` | Discard the installed token, reverting to 2-legged. |
| `get_authorization_url` | Build the 3-legged authorization URL. No I/O. |
| `authorize_interactively` | Run the whole 3-legged flow via a browser and local listener. |
| `exchange_code` | Exchange an authorization code for a 3-legged token. |
| `refresh_access_token` | Exchange a refresh token for a new token pair. |
| `introspect_token` | Status and metadata for one of this app's tokens. |
| `revoke_token` | Revoke one of this app's tokens. |
| `get_keys` | The JWKS used to verify token signatures offline. |
| `get_oidc_spec` | The OpenID Connect discovery document. |
| `get_user_info` | The profile of the user a 3-legged token belongs to. |
| `exchange_jwt_assertion` | Exchange a signed assertion for a service account token. |
| `get_logout_url` | Build the logout URL. No I/O. |

### Service accounts (`client.service_accounts`)

| Method | Description |
| --- | --- |
| `create_account` | Create an account this application can act as. |
| `list_accounts` | The service accounts this application owns. |
| `get_account` | One service account. |
| `set_account_status` | Enable or disable an account. |
| `delete_account` | Delete an account and all its keys. |
| `create_key` | Create a signing key. Returns the private key once. |
| `list_keys` | An account's keys, without their private halves. |
| `set_key_status` | Enable or disable one key. |
| `delete_key` | Delete one key. |
| `build_assertion` | Sign a JWT assertion without exchanging it. No I/O. |
| `get_token` | Sign an assertion and exchange it for a token. |

### Object storage (`client.oss`)

| Method | Description |
| --- | --- |
| `list_buckets` | Buckets this application owns, one page at a time. |
| `create_bucket` | Create a bucket. The policy is permanent. |
| `get_bucket_details` | One bucket's policy, owner, and permissions. |
| `delete_bucket` | Delete a bucket and everything in it. |
| `list_objects` | Objects in a bucket, one page at a time. |
| `get_object_details` | One object's size, hash, and URN. |
| `upload_object` | Upload, running the whole signed-S3 flow. |
| `download_object` | Resolve the signed URL and fetch the bytes. |
| `get_signed_upload` | Signed URLs to upload parts to. Step one of three. |
| `complete_upload` | Assemble uploaded parts into an object. Step three. |
| `get_signed_download` | A signed URL to hand to a browser. |
| `copy_object` | Copy within one bucket. |
| `delete_object` | Delete one object. |

### Model Derivative (`client.model_derivative`)

| Method | Description |
| --- | --- |
| `get_formats` | Which source formats translate into which outputs. |
| `translate` | Start a translation job. Returns once accepted, not finished. |
| `get_manifest` | Everything generated from a design, and how far it has got. |
| `wait_for_translation` | Poll the manifest until translation finishes. |
| `delete_manifest` | Delete a design's derivatives. The source is untouched. |
| `get_model_views` | The viewables inside a translated design. |
| `get_object_tree` | A view's object hierarchy. `None` while extracting. |
| `get_all_properties` | Properties of every object in a view. `None` while extracting. |
| `get_thumbnail` | A design's thumbnail as PNG bytes. |
| `get_derivative_url` | A signed URL for one generated derivative file. |

### Design Automation (`client.design_automation`)

| Method | Description |
| --- | --- |
| `list_engines` | The engines available to run activities on. |
| `get_engine` | One engine's product version and retirement date. |
| `get_engine_health` | Whether a product's engines are accepting workitems. |
| `get_engine_stats` | How long a product's engines are making work wait. |
| `list_activities` | The activities this application can run. |
| `create_activity` | Create a job definition. |
| `get_activity` | One activity, by fully qualified id. |
| `delete_activity` | Delete an activity, its versions, and its aliases. |
| `list_activity_aliases` | The aliases on one of your activities. |
| `create_activity_alias` | Point a new alias at a version. |
| `get_activity_alias` | Which version an alias points at. |
| `update_activity_alias` | Move an alias to another version. Releases it. |
| `delete_activity_alias` | Delete one alias. |
| `list_activity_versions` | The versions one of your activities has. |
| `create_activity_version` | Add a version, described in full. |
| `get_activity_version` | One numbered version. |
| `delete_activity_version` | Delete one version. |
| `list_app_bundles` | The app bundles this application can load. |
| `create_app_bundle` | Create a bundle and reserve somewhere for its zip. |
| `get_app_bundle` | One bundle, by qualified id, with a URL to its zip. |
| `delete_app_bundle` | Delete a bundle, its versions, and its aliases. |
| `upload_app_bundle` | Upload the zip, running the whole signed-S3 form POST. |
| `list_app_bundle_aliases` | The aliases on one of your bundles. |
| `create_app_bundle_alias` | Point a new alias at a version. |
| `get_app_bundle_alias` | Which version an alias points at. |
| `update_app_bundle_alias` | Move an alias to another version. |
| `delete_app_bundle_alias` | Delete one alias. |
| `list_app_bundle_versions` | The versions one of your bundles has. |
| `create_app_bundle_version` | Add a version and reserve somewhere for its zip. |
| `get_app_bundle_version` | One numbered version. |
| `delete_app_bundle_version` | Delete one version. |
| `create_workitem` | Start one run of an activity. Returns `pending`. |
| `wait_for_workitem` | Poll a workitem until it finishes. |
| `get_workitem` | How far one workitem has got. |
| `get_workitem_statuses` | How far several have got, in one call. |
| `create_workitem_batch` | Start several runs in one call. |
| `combine_workitems` | Run parts in parallel, then one that merges them. |
| `list_workitems` | Your workitems since a moment in time. |
| `delete_workitem` | Cancel a workitem that has not finished. |
| `get_nickname` | The nickname standing in for the client ID. |
| `set_nickname` | Claim a nickname. Only while you own nothing. |
| `delete_app_data` | Delete every activity, bundle, and nickname you own. |
| `get_service_limits` | The quotas this application runs under. |
| `set_service_limits` | Lower your own quotas. |
| `list_shares` | What you have shared with other applications. |

Every input and output is an HTTP URL, so OSS feeds a workitem directly:

```python
from autodesk_platform_sdk.services.designautomation.schemas import Argument, Verb

source = client.oss.get_signed_download(bucket_key, "tower.dwg")
target = client.oss.get_signed_upload(bucket_key, "tower.pdf")

workitem = client.design_automation.create_workitem(
    "AutoCAD.PlotSheetsetToPDF+prod",
    {
        "SheetSet": Argument(url=source.url),
        "Result": Argument(url=target.urls[0], verb=Verb.put),
    },
)
finished = client.design_automation.wait_for_workitem(workitem.id)
assert finished.is_successful(), finished.report_url

client.oss.complete_upload(bucket_key, "tower.pdf", target.upload_key)
```

A signed upload URL is one part of a multipart upload, so the object only appears once `complete_upload` runs. On any failed status, `report_url` is the engine's log and the only place the failure explains itself.

Activities, app bundles, and engines are addressed two ways, and the service refuses one where it wants the other. `get_activity` and a workitem's activity take the fully qualified `owner.Name+alias`. Every alias and version call takes the bare name instead. `QualifiedId` models the first, and both are checked before the request leaves.

### Data Management (`client.data_management`)

| Method | Description |
| --- | --- |
| `list_hubs` | The ACC, BIM 360, and Fusion accounts the caller can reach. |
| `get_hub` | One hub. |
| `list_projects` | The projects in a hub. |
| `get_project` | One project. |
| `get_top_folders` | The folders at the top of a project. Where a traversal starts. |
| `get_folder` | One folder. |
| `get_folder_contents` | What is directly inside a folder, plus each file's tip version. |
| `get_folder_parent` | The folder one level up. |
| `search_folder` | Search a folder and everything under it, recursively. |
| `get_item` | One file, without its contents. |
| `get_item_tip` | A file's latest version. |
| `get_item_versions` | A file's versions, newest first. |
| `get_item_parent` | The folder a file lives in. |
| `get_version` | One specific version of a file. |
| `get_version_item` | The file a version belongs to. |
| `get_version_download_formats` | The formats a version can be exported as. |
| `create_storage` | Reserve a place in OSS for a file's bytes. |
| `create_folder` | Create a subfolder. |
| `create_item` | Create a file and its first version from uploaded bytes. |
| `create_version` | Add a version to a file that already exists. |
| `create_download` | Start exporting a version as a given file type. |
| `get_download_job` | Check on an export job. |

### BuildingConnected (`client.building_connected`)

| Method | Description |
| --- | --- |
| `get_current_user` | Get the user the token belongs to. |
| `get_user` | Get one user at your company. |
| `list_users` | List the users at your company. |
| `list_offices` | List your company's offices. |
| `get_office` | Get one of your company's offices. |
| `list_primary_contacts` | List the users designated as an office's primary contacts. |
| `list_certificate_types` | List the certificate types BuildingConnected recognizes. |
| `list_certificate_agencies` | List the agencies that issue certificates. |
| `list_projects` | List the BuildingConnected projects you can reach. |
| `get_project` | Get one project. |
| `create_project` | Create a project. |
| `update_project` | Change a project, sending only the fields given. |
| `delete_project` | Delete a project. |
| `list_project_costs` | List a project's internal cost breakdown. |
| `create_project_costs` | Add cost lines to a project. |
| `update_project_costs` | Change cost lines on a project. |
| `delete_project_costs` | Remove cost lines from a project. |
| `upload_nda` | Upload an NDA document, in both steps. |
| `delete_nda` | Delete an NDA document. |
| `get_project_nda` | Get the NDA required on a project. |
| `sign_project_nda` | Sign a project's NDA as the calling user. |
| `list_team_members` | List project team members. |
| `get_team_member` | Get one project team member. |
| `add_team_member` | Add somebody to a project's team. |
| `update_team_member` | Change a project team member, sending only the fields given. |
| `remove_team_member` | Remove somebody from a project's team. |
| `list_bid_packages` | List bid packages. |
| `get_bid_package` | Get one bid package. |
| `create_bid_package` | Create a bid package on a project. |
| `update_bid_package` | Change a bid package, sending only the fields given. |
| `delete_bid_package` | Delete a bid package. |
| `publish_bid_packages` | Publish a project's bid packages, making them visible to their bidders. |
| `unseal_bid_packages` | Unseal a project's bid packages, making their sealed bids readable. |
| `get_bid_package_stats` | Get the response counts for one bid package. |
| `get_bid_package_stats_batch` | Get the response counts for several bid packages at once. |
| `list_bid_package_activities` | List the recorded activity on bid packages. |
| `list_invites` | List invites to bid. |
| `get_invite` | Get one invite. |
| `update_invite` | Change an invite, sending only the fields given. |
| `invite_bidders` | Invite people to a bid package, by email address or user ID. |
| `import_emails` | Invite bidders to a bid package by email address alone. |
| `remove_invitee` | Remove one person from an invite. |
| `get_invite_certificate` | Get a certificate file held by an invited company. |
| `list_bids` | List bids. |
| `get_bid` | Get one bid. |
| `create_bid` | Submit a bid against an invite. |
| `delete_bid` | Delete a bid. |
| `list_bid_line_items` | List a bid's priced line items. |
| `upload_bid_attachment` | Upload a file to attach to a bid, in both steps. |
| `get_bid_attachment` | Get one of a bid's attachments, and where to download it. |
| `delete_bid_attachment` | Delete a bid attachment. |
| `get_bidding_stats` | Get how one bidder company has performed across your projects. |
| `get_bidding_stats_batch` | Get bidding performance for several companies at once. |
| `list_project_bid_forms` | List project bid forms. |
| `get_project_bid_form` | Get one project bid form. |
| `create_project_bid_form` | Create a project's bid form. |
| `update_project_bid_form` | Replace a project bid form's line items. |
| `list_project_bid_form_line_items` | List a project bid form's line items. |
| `create_project_bid_form_line_items` | Add line items to a project bid form. |
| `update_project_bid_form_line_items` | Change line items on a project bid form. |
| `delete_project_bid_form_line_items` | Remove line items from a project bid form. |
| `list_scope_specific_bid_forms` | List scope-specific bid forms. |
| `get_scope_specific_bid_form` | Get one scope-specific bid form. |
| `create_scope_specific_bid_form` | Create a bid package's scope-specific bid form. |
| `update_scope_specific_bid_form` | Replace a scope-specific bid form's line items. |
| `list_scope_specific_bid_form_line_items` | List a scope-specific bid form's line items. |
| `create_scope_specific_bid_form_line_items` | Add line items to a scope-specific bid form. |
| `update_scope_specific_bid_form_line_items` | Change line items on a scope-specific bid form. |
| `delete_scope_specific_bid_form_line_items` | Remove line items from a scope-specific bid form. |
| `list_opportunities` | List your Bid Board opportunities. |
| `get_opportunity` | Get one opportunity. |
| `create_opportunity` | Create an opportunity on your Bid Board. |
| `update_opportunity` | Change an opportunity, sending only the fields given. |
| `delete_opportunity` | Delete an opportunity. |
| `list_opportunity_comments` | List the comments on an opportunity. |
| `list_opportunity_project_pairs` | List the links between opportunities and projects. |
| `get_opportunity_project_pair` | Get one opportunity-project pair. |
| `create_opportunity_project_pair` | Link an opportunity to a project. |
| `update_opportunity_project_pair` | Change which opportunity or project a pair links. |
| `list_contacts` | List your company's trade partner and client contacts. |
| `get_contact` | Get one contact. |
| `list_preferred_contacts` | List the people your offices prefer to deal with at bidder offices. |
| `get_contact_certificate` | Get a certificate file held by a contact. |

### TradeTapp (`client.tradetapp`)

| Method | Description |
| --- | --- |
| `get_current_user` | Get the user the token belongs to, and their company. |
| `list_qualifications` | List your subcontractors' submitted questionnaires. |
| `get_qualification` | Get one subcontractor's questionnaire in full. |
| `list_office_addresses` | List a subcontractor's office addresses. |
| `list_custom_questions` | List a subcontractor's answers to your custom questions. |
| `list_financials` | List your subcontractors' financial and risk data. |
| `get_financial` | Get one subcontractor's financial and risk data in full. |
| `list_flags` | List the flags raised against your subcontractors. |
| `get_flag` | Get one flag. |
| `create_flag` | Raise a flag against a subcontractor. |
| `update_flag` | Change a flag, sending only the fields given. |
| `delete_flag` | Delete a flag. |
| `list_flag_state_history` | List every state a flag has passed through. |

### Webhooks (`client.webhooks`)

| Method | Description |
| --- | --- |
| `list_hooks` | Every webhook the calling token can see. |
| `list_app_hooks` | Every webhook this application owns, whoever created it. |
| `list_system_hooks` | The webhooks for one APS service. |
| `list_event_hooks` | The webhooks for one event type, optionally by scope. |
| `get_hook` | One webhook. |
| `create_hook` | Subscribe a callback URL to one event type. |
| `create_system_hooks` | Subscribe to every event in a service at once. |
| `update_hook` | Change a webhook's status, filter, or attributes. |
| `delete_hook` | Delete a webhook. |
| `create_token` | Set the application-wide notification secret. |
| `update_token` | Replace the notification secret. |
| `delete_token` | Remove the notification secret. |

### ACC Account Admin (`client.account_admin`)

| Method | Description |
| --- | --- |
| `list_projects` | An account's projects, filtered and paged. |
| `get_project` | One project. IDs here have no `b.` prefix. |
| `create_project` | Create a project, optionally cloning a template. |
| `list_project_users` | A project's members. |
| `get_project_user` | One project membership. |
| `assign_project_user` | Add someone to a project by email. |
| `update_project_user` | Change a member's company, roles, or products. |
| `remove_project_user` | Remove someone from a project. |
| `list_companies` | An account's companies. |
| `get_company` | One company. |
| `list_project_companies` | The companies on one project. |
| `list_account_users` | The people in an account's directory. |
| `get_account_user` | One person from the directory. |
| `search_account_users` | Search the directory by name, email, or company. |
| `list_user_projects` | The projects one person is on. |
| `list_user_products` | The products one person has access to. |
| `list_user_roles` | The roles one person holds, and where. |
| `get_business_units` | An account's business unit hierarchy. |

### ACC Issues (`client.issues`)

| Method | Description |
| --- | --- |
| `get_permissions` | What the calling user may do with a project's issues. |
| `list_issue_types` | A project's issue types and their subtypes. |
| `list_root_cause_categories` | The root causes an issue can be attributed to. |
| `list_attribute_definitions` | The custom attributes defined for issues. |
| `list_attribute_mappings` | Which issue types each custom attribute applies to. |
| `list_issues` | A project's issues, filtered and paged. |
| `get_issue` | One issue in full, including what the caller may change. |
| `create_issue` | Create an issue against a subtype. |
| `update_issue` | Change an issue, sending only the fields given. |
| `list_comments` | An issue's comments. |
| `create_comment` | Add a comment to an issue. |
| `list_attachments` | An issue's attachments. |
| `delete_attachment` | Remove one attachment. |

### ACC RFIs (`client.rfis`)

Takes the bare project UUID, as Account Admin, Issues, and Submittals do, while Data Management returns the same project as `b.<uuid>`. Every method strips the prefix.

Listing is `search_rfis`, a POST: paging, ordering, and filtering travel in the body. Its date filters take a range of two second-precision timestamps joined by `..`, and refuse a single one.

All 16 endpoints are implemented.

| Method | Description |
| --- | --- |
| `get_permissions` | Who the caller is on a project and what its RFIs let them do. |
| `get_workflow` | Which review path a project follows, and who may take each part. |
| `search_rfis` | A project's RFIs, filtered, ordered, and paged. |
| `get_rfi` | One RFI in full, with its responses and the moves open to the caller. |
| `create_rfi` | Raise an RFI in one of the statuses open to the caller. |
| `update_rfi` | Change an RFI, move it through the workflow, and publish the official response that closes it. |
| `create_response` | Answer an RFI as one of its reviewers, and `update_response` rewrite that answer. |
| `list_comments` | The remarks on an RFI, and `create_comment` add one. |
| `list_attachments` | The files on an RFI and on its responses. |
| `upload_attachment` | Upload a local file into an RFI's folder, ready to attach to a response. |
| `list_rfi_types` | The kinds of RFI a project recognises, with the defaults for each. |
| `list_custom_attributes` | The fields a project adds to its RFIs, with `create_custom_attribute` and `update_custom_attribute`. |
| `get_custom_identifier` | The last RFI number used and the next one free. |

### ACC Model Properties (`client.model_properties`)

Indexes the BIM properties of the models on a project and answers queries across all of them. `client.model_derivative` reads one design at a time; this reads many.

Nothing is indexed until it is asked for. `batch_index_status` names the file versions wanted and starts the missing indexes as a side effect, so the first call both requests and reports. An index is cached for 30 days from its last use, and the same versions asked for twice give back the same index.

Queries are JSON documents in Autodesk's own [query language](https://aps.autodesk.com/en/docs/acc/v1/tutorials/model-properties/query-ref/), passed as dictionaries. An index row keys its properties by field key, so `get_index_fields` is what turns `p153cb174` back into `name`.

Takes the bare project UUID, as Account Admin, Issues, RFIs, and Submittals do, while Data Management returns the same project as `b.<uuid>`. Every method strips the prefix. A 2-legged token is refused outright, where Submittals and RFIs answer one the same way they answer any caller.

All 16 endpoints are implemented, plus four helpers over them.

| Method | Description |
| --- | --- |
| `batch_index_status` | The index of each file version, building the ones that are missing. |
| `get_index` | How far one index has got, and where its resources live. |
| `wait_for_index` | Poll an index until it stops building. |
| `get_index_manifest` | Which files and viewables an index was built from. |
| `get_index_fields` | The columns an index holds, and the key each one is stored under. |
| `get_index_properties` | Every row of an index. |
| `create_index_query` | Start a query over an index, with `get_index_query` for its progress. |
| `get_index_query_properties` | The rows one query matched. |
| `run_index_query` | Start a query, wait for it, and return the rows, in one call. |
| `batch_diff_status` | The diff of each version pair, building the ones that are missing. |
| `get_diff` | How far one diff has got, and how much it found changed. |
| `wait_for_diff` | Poll a diff until it stops building. |
| `get_diff_manifest` | Which pair of file versions a diff compared. |
| `get_diff_fields` | The columns a diff holds. |
| `get_diff_properties` | Every added, removed, and changed design element. |
| `create_diff_query` | Start a query over a diff, with `get_diff_query` for its progress. |
| `get_diff_query_properties` | The changes one query matched. |
| `run_diff_query` | Start a query, wait for it, and return the changes, in one call. |

### ACC Cost Management (`client.cost_management`)

Keyed by container ID, not project ID. On an ACC project the container is the project's own UUID, and every method strips Data Management's `b.` prefix. On a BIM 360 project the two can differ, so read the right one with `client.data_management.get_container_id(hub_id, project_id, Container.cost)`.

All 98 endpoints are implemented. The table names the entry point of each group; each has the `get`, `create`, `update`, and `delete` methods its resource supports.

| Method | Description |
| --- | --- |
| `list_budgets` | The owner-approved budget lines, with their rolled-up amounts. |
| `list_templates` | The budget code templates, and `list_segments` their grammar. |
| `list_values` | The allowed values of one budget code segment. |
| `list_contracts` | The supplier contracts, the commitment side of the picture. |
| `link_budgets` | Link budgets to contracts, and unlink others, in one call. |
| `list_main_contracts` | The prime contracts, and `list_main_contract_items` their lines. |
| `list_change_order_workflows` | Which of the five change order types the project runs. |
| `list_change_orders` | The change orders of one type. |
| `list_cost_items` | The priced lines of a change order. |
| `list_sub_cost_items` | One cost item's breakdown, per estimate stage. |
| `list_schedule_of_values` | A contract's schedule of values. |
| `list_expenses` | Costs recorded outside a contract, and their items. |
| `list_payments` | The payment applications, and `list_payment_items` their lines. |
| `list_attachments` | The files attached to cost items, and `list_documents` the generated ones. |
| `list_properties` | The custom attributes defined for a kind of cost item. |
| `list_taxes` | The tax formulas applied to a cost object. |
| `list_performance_tracking_items` | The budgets enrolled in performance tracking. |
| `list_time_sheets` | Quantities tracked against them over a period. |
| `list_actions` | What one item can do next, and `list_action_histories` what it has done. |

### ACC Submittals (`client.submittals`)

Takes the bare project UUID, as Account Admin and Issues do, while Data Management returns the same project as `b.<uuid>`. Submittals answers a prefixed ID with a 500 rather than a readable error, so every method strips the prefix.

All 33 endpoints are implemented.

| Method | Description |
| --- | --- |
| `get_permissions` | What the calling user may do with a project's submittals. |
| `get_metadata` | Every vocabulary a project has configured, in one call. |
| `list_items` | A project's submittal items, filtered and paged. |
| `get_item` | One item in full, including the workflow moves open to the caller. |
| `create_item` | Create an item against a type, a spec section, and a start state. |
| `update_item` | Change an item, sending only the fields given. |
| `transition_item` | Move an item to another state in the review workflow. |
| `list_revisions` | The past rounds of submission an item has been through. |
| `get_next_custom_identifier` | The next number free to assign, and `validate_custom_identifier` whether one is. |
| `change_sequence_type` | Switch a project between global and per-spec numbering. Beta. |
| `list_attachments` | The files on an item. |
| `upload_attachment` | Attach a local file, running the reserve, upload, and complete calls. |
| `create_attachment` | Link a file version that is already in the Files tool. |
| `update_attachment` | Mark a local upload complete. |
| `list_steps` | The rounds of review an item goes through, and `get_step` one of them. |
| `list_tasks` | The reviews one step waits on, and `get_task` one of them. |
| `close_task` | Close a review task by giving its response. |
| `list_packages` | The packages items are grouped into, and `get_package` one of them. |
| `list_responses` | The verdicts a reviewer can pick, and `get_response` one of them. |
| `list_specs` | A project's spec sections, with `get_spec` and `create_spec`. |
| `list_item_types` | The kinds of submittal a project recognises, and `get_item_type` one. |
| `list_templates` | The review templates an item can be created against. |
| `list_mappings` | Who holds the submittal manager role, with `create_mapping` and `delete_mapping`. Both writes are beta. |
| `get_async_job` | The progress of work Submittals runs in the background. Beta. |

### ACC Sheets (`client.sheets`)

Holds the published drawing sets of a project: the version sets that date each issue, the sheets inside them, and the upload that produces them.

Takes the bare project UUID. This API accepts Data Management's `b.<uuid>` form too, where Submittals, RFIs, and Model Properties all refuse it, but every method strips the prefix anyway.

Getting a drawing in is a five-call flow across two APIs. `upload_sheets` runs the first three: reserve OSS storage, put the bytes there, and start the extraction. Sheets then splits the file into review sheets, reading a number and a title off each title block by OCR. Correct them with `update_review_sheets`, then `publish_review_sheets` turns each into a sheet. Nothing reaches the project until that last call.

A sheet number is unique within a version set, not within a project, so the same number appears once per issue. `list_sheets` returns only the copy in the latest-dated version set unless asked otherwise.

All 22 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_version_sets` | The dated issues a project's sheets are grouped into, and `get_version_sets` up to 200 by ID. |
| `create_version_set` | Open a new dated issue, and `update_version_set` rename or redate one. |
| `delete_version_sets` | Delete up to 10 version sets, and every sheet inside them. |
| `upload_sheets` | Put local PDFs into a version set, running the reserve, upload, and extract calls. |
| `create_storage` | Reserve the OSS object a file's bytes go into, and `create_upload` start the extraction. |
| `list_uploads` | A project's uploads, and `get_upload` one of them. |
| `wait_for_upload` | Poll an upload until it reaches review, publication, or failure. |
| `list_review_sheets` | The pages an upload pulled out of its files, before publishing. |
| `update_review_sheets` | Correct the number, title, or tags OCR read off the title blocks. |
| `get_thumbnails` | Preview images of up to 100 review sheets at once. |
| `publish_review_sheets` | Turn an upload's review sheets into sheets in its version set. |
| `list_sheets` | A project's published sheets, filtered and paged, and `get_sheets` up to 200 by ID. |
| `update_sheets` | Renumber, retag, or reissue up to 200 sheets in one call. |
| `delete_sheets` | Delete up to 200 sheets, and `restore_sheets` put them back. |
| `create_export` | Render up to 1000 sheets into one PDF, and `wait_for_export` poll for its link. |
| `get_export` | How far an export has got, and its download link once it is done. |
| `list_collections` | The collections a project's sheets can be grouped into, and `get_collection` one. |

### ACC Model Coordination (`client.model_coordination`)

Holds the coordination spaces a project clash tests against, and the results of those tests.

Takes the container ID, not the project ID. On an ACC project the container is the project's own UUID: the web app allocates it under the Docs project ID, so no relationship lookup is needed and every method strips a `b.` prefix anyway. A project whose administrator has not yet configured a coordination space has no container at all, and answers 404 whatever the caller does.

Two services sit behind one namespace. Model sets, versions, and views come from `/bim360/modelset/v3`. Clash tests and clash groups come from `/bim360/clash/v3`.

Nothing here runs a clash test. The service takes a model set version whenever the documents under the model set's folder change, then clash tests it on its own. So the read path is `get_latest_model_set_version`, then `list_version_clash_tests`, then `list_clash_test_resources` and `download_clash_resource`.

Clash results are files rather than JSON: three gzipped documents holding the clashing object pairs, the Viewer objects behind them, and the documents those objects live in. Their links expire, so ask for them again rather than storing one.

Every write is asynchronous and answers with a job. `wait_for_container_job` polls the one a new model set starts, and `wait_for_model_set_job` polls every other model set write.

All 43 endpoints are implemented. The screenshot pair is documented twice, on both service roots, and is written once.

| Method | Description |
| --- | --- |
| `list_model_sets` | The coordination spaces on a project, and `get_model_set` one with its folder and tip version. |
| `create_model_set` | Open a coordination space over one Docs folder, and `update_model_set` rename or hide it. |
| `list_model_set_versions` | The versions a model set has captured, with `get_model_set_version` and `get_latest_model_set_version`. |
| `create_model_set_version` | Sample the folder now, for when automatic versioning is off. |
| `enable_model_set_versions` | Resume versioning on every Docs change, and `disable_model_set_versions` stop it. |
| `list_views` | The saved views on a model set, with `get_view`, `create_view`, `update_view`, and `delete_view`. |
| `search_view_lineages` | The views tracking a given set of document lineages. Deprecated by Autodesk. |
| `list_view_versions` | Which models every view resolved to at one model set version, and `get_view_version` for one. |
| `list_clash_tests` | The clash tests run on a model set, and `list_version_clash_tests` those on one version. |
| `get_clash_test` | One clash test and whether its results are ready. |
| `list_clash_test_resources` | The signed links to a finished test's three result files. |
| `download_clash_resource` | Fetch one result file and gunzip it. |
| `close_clash_groups` | Close batches of clashes needing no work, and `reopen_clash_groups` put them back. |
| `assign_clash_groups` | Raise batches of clashes as issues for somebody to fix. |
| `search_closed_clash_groups` | A model set's closed groups, and `search_assigned_clash_groups` its assigned ones. |
| `list_test_closed_clash_groups` | Replay closed groups against a later test, splitting each into still-clashing and resolved. |
| `get_closed_clash_groups` | Up to 20 groups with the data needed to draw them, and `get_assigned_clash_groups` by group or issue ID. |
| `get_grouped_clashes` | Every clash already closed or assigned, to subtract from a test's results. |
| `add_model_set_issues` | Raise inspection issues pinned to points in the coordinated model. |
| `get_issue_view_context` | The documents to load to reopen an issue, and `get_assigned_clash_group_view_context` for a clash issue. |
| `add_screenshot` | Upload a PNG for an issue, a clash group, or a view to claim, and `get_screenshot` read one back. |
| `get_container_job` | The job a new model set started, with `get_model_set_job`, `get_view_job`, and `get_clash_group_job`. |
| `wait_for_container_job` | Poll a job until it settles, and `wait_for_model_set_job` for every other model set write. |

### ACC Takeoff (`client.takeoff`)

Reads the quantities a project has taken off its drawings and models, package by package.

Project keyed rather than container keyed, so there is no relationship lookup. The reference says a `b.` prefix works, and it does, but every method strips one anyway so that one form reaches the wire.

Almost all of it is read only. Settings, packages, and the assigned classification structures accept a write. Takeoff types and takeoff items do not, because only the web app can measure something.

A takeoff type is the template and a takeoff item is one measurement made against it. Classifications live on the type, so an item is classified by reading the type its `takeoff_type_id` names.

The six classification system endpoints are deprecated and are not implemented. A migrated project answers them `409 Conflict` and keeps its classifications in the Classifications API, reached from here through `list_assigned_structures`.

All 14 live endpoints are implemented.

| Method | Description |
| --- | --- |
| `get_settings` | The units a project measures in, and `update_settings` to change them. |
| `list_packages` | The takeoff packages a project holds, and `get_package` one. |
| `create_package` | Open a new package, and `update_package` rename one. |
| `list_takeoff_types` | The measurable things defined in a package, and `get_takeoff_type` one. |
| `list_takeoff_items` | The measurements made in a package, and `get_takeoff_item` one. |
| `list_content_views` | The sheets and model views a project can be taken off against. |
| `list_assigned_structures` | The classification trees assigned to a project's takeoffs. |
| `add_assigned_structures` | Assign up to five trees, and `remove_assigned_structure` unassign one. |

### ACC Assets (`client.assets`)

Tracks the physical equipment on a project, and the categories, statuses, and custom attributes that describe it.

Project keyed rather than container keyed, so there is no relationship lookup. The reference says a `b.` prefix works, and it does, but every method strips one anyway so that one form reaches the wire.

The API is versioned per resource: the asset endpoints are on `v2` and everything else is still on `v1`. Both roots take the same project ID.

Almost every write is a batch. An asset is created, changed, and deleted only through `create_assets`, `update_assets`, and `delete_assets`, each of which takes up to 100 assets and is all or nothing. Deletion is soft everywhere, so a deleted record keeps its ID and comes back to any read that passes `include_deleted`.

A category decides both the statuses an asset may hold and the custom attributes it may carry, and a child category inherits both. An asset's `custom_attributes` are keyed by an attribute's `name`, such as `ca1`, so `list_custom_attributes` is the lookup table.

`list_error_codes` and `get_error_code` need no token and no project. They turn the `errorCode` on a failure into a reason a caller can act on.

All 24 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_assets` | A project's assets, filtered and paged by cursor, and `get_assets` up to 100 by ID. |
| `create_assets` | Create up to 100 assets, `update_assets` patch them by ID, and `delete_assets` remove them. |
| `list_categories` | A project's whole category tree, and `get_categories` some of it by ID. |
| `create_category` | Add a category under an existing one. |
| `list_status_sets` | The status sets a project defines, each with its statuses, and `get_status_sets` by ID. |
| `create_status_set` | Create a status set and its statuses in one call. |
| `get_category_status_sets` | Which status set each category draws from, and `assign_status_set` to change one. |
| `list_statuses` | Every status across every set, and `get_statuses` some by ID. |
| `create_status` | Add a status to an existing set. |
| `list_custom_attributes` | Every custom attribute a project defines, and `get_custom_attributes` by ID or name. |
| `create_custom_attribute` | Define an attribute, and `update_custom_attribute` change one. |
| `list_category_custom_attributes` | What one category offers, and `assign_custom_attribute` to add to it. |
| `list_error_codes` | The Assets error catalogue, and `get_error_code` one entry. |

### ACC Forms (`client.forms`)

Reads the daily logs, checklists, and inspection records filled in on site, and the templates they are made from.

Project keyed rather than container keyed, so there is no relationship lookup. Every method strips the `b.` prefix Data Management adds.

**The API is versioned per endpoint and three roots run side by side.** The 2026 April release put a new forms listing, new value writes, and the section reader on `v2`, left their deprecated twins and everything else on `v1`, and gave weather a `v3` root of its own.

Two calls therefore exist twice. `list_forms` and `update_values` are the deprecated v1 pair, which Autodesk removes on **2026-12-29**; `list_forms_v2` and `update_values_v2` replace them and are in public beta. The two answer differently shaped records - `Form` against `FormV2` - and different status vocabularies, so migrating is a real change rather than a rename. Both are here so a caller can move at their own pace.

A template defines the questions and a form is one instance of it. Read a native template's structure with `get_layout` and then `get_section` per section, which is the only place a custom table's column IDs are published. A PDF template answers through `pdf_values` instead; the API can neither create a template nor replace a form's PDF.

Values are typed by the template rather than by the SDK, so an answer carries one of `text_val`, `number_val`, `toggle_val` and the rest, and `value_name` says which. Writing is a merge, not a replace: a call touches only the fields it names, and at most 10 of them, so a long form is filled in over several calls.

All 13 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_templates` | The form templates a project defines, with their permissions. |
| `get_layout` | A template's structure and its sections, and `get_section` one section in full. |
| `list_forms` | A project's forms with their answers inline. Deprecated; removed 2026-12-29. |
| `list_forms_v2` | A project's forms, with `include` deciding how much of each one comes back. |
| `create_form` | Create a form from a template, and `update_form` change it or move it through its workflow. |
| `update_values` | Fill in fields and built-in table rows. Deprecated; removed 2026-12-29. |
| `update_values_v2` | Fill in fields and table rows, custom tables included. |
| `delete_values` | Remove table rows from a form. |
| `list_values` | A form's non-tabular answers, paged, and `list_table_values` one table's rows. |
| `get_weather` | The weather captured for a form's date. |

### ACC Reviews (`client.reviews`)

Reads the document approval workflows that gate a file version's status in ACC Docs, and the reviews running on them.

Project keyed rather than container keyed, so there is no relationship lookup. The API takes the project UUID with or without the `b.` prefix, and every method strips the prefix so one form reaches the wire.

**The API is read mostly.** `create_workflow` and `create_review` are the only writes. Nothing here approves, rejects, claims, voids, or advances a review, and nothing here edits or deletes a workflow. Those happen in the ACC UI, and this API watches them.

A workflow is the template and a review is one run of it over a set of file versions. `get_review_workflow` reads the snapshot the review captured when it started, which is why it can differ from `get_workflow` on the same ID.

`list_version_approval_statuses` is the bridge to `client.data_management`: it takes a Data Management version URN and answers what every review decided about it. A version reads `IN_REVIEW` while any review holding it is still open.

Every method takes `user_id`, which sends `x-user-id`. Autodesk requires it on a 2-legged call, since a review is always somebody's.

All 10 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_workflows` | A project's approval workflows, active ones unless asked otherwise. |
| `get_workflow` | One approval workflow as it stands now. |
| `create_workflow` | Create an approval workflow. It cannot be edited or deleted afterwards. |
| `list_reviews` | A project's reviews, narrowed by status, workflow, dates, or who owes the next step. |
| `create_review` | Start a review over up to 1000 file versions. |
| `get_review` | One review, its status, and who owes its current step. |
| `get_review_workflow` | The workflow snapshot a review captured when it started. |
| `list_review_progress` | What happened at each step of a review, newest first. |
| `list_review_versions` | The file versions in the current round of a review. |
| `list_version_approval_statuses` | What every review decided about one file version. |

### ACC Files (`client.files`)

Covers the parts of the ACC Files tool that `client.data_management` does not reach: PDF export, folder permissions, custom attributes on documents, file naming standards, file packages, and the Revit models linked into a published model.

**This is one documentation tab over four services.** The endpoints sit on four roots: `construction/files/v1` for export and project custom attributes, `bim360/docs/v1` for permissions, folder attributes, and naming standards, `construction/packages/v1` for packages, and `construction/rcm/v1` for linked Revit files. All four take the project UUID with or without the `b.` prefix, and every method strips the prefix so one form reaches the wire.

**Nothing here lists folders, items, or versions.** Data Management owns those. `get_versions` is the one deliberate overlap: it reads up to 50 versions in one call and adds the approval status and the custom attribute values that JSON:API leaves out. There is no upload here either, because a file reaches the Files tool through `client.data_management` and `client.oss`.

Seven endpoints are beta: the six custom attribute calls and the naming standard.

Every method except `get_naming_standard` takes `user_id`, which sends `x-user-id`. The two export methods **need** it on a 2-legged call, though their reference calls user context optional; without it the wire answers `400 ERR_BAD_INPUT, User ID is required`. `get_naming_standard` takes a region instead, and it is the only endpoint here that does.

All 16 endpoints are implemented, plus `wait_for_export` and `download_export`.

| Method | Description |
| --- | --- |
| `export_files` | Start a PDF export of up to 200 file versions. |
| `get_export` | Where a PDF export job has got to, and its signed download link. |
| `wait_for_export` | Poll an export job until it stops, whatever the outcome. |
| `download_export` | Resolve the signed link and fetch the exported PDF or ZIP. |
| `list_folder_permissions` | What every user, role, and company may do in one folder. |
| `create_folder_permissions` | Grant folder permissions to subjects that have none. |
| `update_folder_permissions` | Replace the permissions a subject holds. They are not added to. |
| `delete_folder_permissions` | Remove every direct permission a subject holds on a folder. |
| `get_versions` | Up to 50 file versions with their approval status and custom attributes. |
| `list_folder_attribute_definitions` | The custom attribute definitions one folder carries. |
| `create_folder_attribute_definition` | Add a custom attribute definition to a folder. |
| `list_custom_attribute_definitions` | The custom attribute definitions a whole project carries. |
| `list_custom_attribute_items` | The options of a large drop-down custom attribute. |
| `update_version_attributes` | Write custom attribute values onto a file version. A null clears one. |
| `get_naming_standard` | One file naming standard and the format it enforces. |
| `list_packages` | A project's file packages, narrowed by creator, date, or version type. |
| `list_package_resources` | The file versions one package holds, with their approval status. |
| `list_linked_files` | The Revit models linked into a published model, each with a signed URL. |

### ACC Locations (`client.locations`)

Reads and edits the location breakdown structure a project tags its work against: a tree of building areas, up to 20 tiers deep and 10,000 nodes in all.

**This is the lookup for the location IDs the other services return.** Issues, assets, forms, photos, RFIs, and submittals each carry a node ID. Nothing else turns one into a name. `list_nodes(project_id, node_ids=[...])` answers with the node and its ancestors.

Every path is tree scoped as well as project scoped. Autodesk accepts the literal `default` as the tree ID and nothing else, since a project holds one tree, so `tree_id` defaults to it.

Locations refuses the `b.` prefix Data Management adds, with a 400, so every method strips one. Autodesk does not serve BIM 360 projects here.

The root node is created with the project and cannot be created or deleted. Read its ID off `list_nodes`, where it is the one node with no parent.

`delete_node` deletes the whole subtree below the node as well, and everything tagged against any of those nodes loses its location.

All 4 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_nodes` | A project's location nodes, all of them or the ones named. |
| `create_node` | Add a node under a parent, last among its siblings or beside a named one. |
| `update_node` | Rename a node, rebarcode it, or both. |
| `delete_node` | Delete a node and every node below it. |

### ACC Photos (`client.photos`)

Reads the photos and videos captured against a project: stills, infrared, photospheres, and video, each with where and when it was taken, who added it, and which tool it came from.

Nothing here writes. Photos publishes a read of one record and a filtered listing of many, and media is added through the Photos tool itself.

Both endpoints need a 3-legged token. An application token answers `401 Authorization failed` on every path.

The listing is a POST, and its paging goes in the body rather than the query string. Read the next cursor off `Page.next_cursor()` and pass it back as `cursor_state`, which makes Autodesk ignore every other argument.

Asking for `PhotoInclude.signed_urls` adds storage links to the image bytes. They carry their own credentials and expire in about a minute, so fetch with them and never store them. `download_photo` does the read and the fetch in one call.

Both reference pages show a curl URL with no `v1` segment. That path is a gateway 404; the one in the "Method and URI" row is the one that answers.

All 2 endpoints are implemented.

| Method | Description |
| --- | --- |
| `get_photo` | One photo, optionally with signed links to its bytes. |
| `filter_photos` | A project's photos, narrowed by ID, author, kind, title, or date. |
| `download_photo` | Resolve a photo's signed link and fetch the bytes. |

### ACC Relationships (`client.relationships`)

Reads and writes the links that join a record in one ACC service to a record in another: an asset to a document, an RFI to a sheet, a form to a photo.

A relationship is an ID joining two entities, and each entity is a domain, a type, and an ID. The link is read in either direction and holds no other data. Holding one grants no access to either record, because the owning service still applies its own permissions when the record is read.

Every path but one takes a container ID. The relationships container is created with the ACC Docs project and carries that project's own ID. So the container is the bare project UUID, and no lookup is needed. Autodesk refuses Data Management's `b.` prefix with a 400, so every method strips it.

Every endpoint needs a 3-legged token, including `get_writable_domains`, which takes no container. An application token answers 403 on every path.

Call `get_writable_domains` before writing. It reports which domain and entity type pairs the caller may link, and it is the only complete record of what the service supports: a live answer names eight domains the querying tutorial's tables leave out.

Two calls are not what their HTTP verb suggests. `delete_relationships` is a POST that deletes, and `intersect_relationships` is a POST that reads.

`delete_relationships` cannot be undone, and a deleted relationship leaves no trace in either record it joined.

Autodesk's own examples for `sync_relationships` send an empty body, which the service refuses with "At least one parameter SyncToken or Domains need to be completed". `SyncRequest` matches the service and refuses it locally.

All 9 endpoints are implemented.

| Method | Description |
| --- | --- |
| `get_writable_domains` | The domain and entity type pairs this user may link. |
| `add_relationships` | Link up to 20 pairs of records in one call. |
| `delete_relationships` | Delete up to 50 relationships by ID. Cannot be undone. |
| `get_relationship` | One relationship by ID. |
| `get_relationships` | Up to 50 relationships by ID. |
| `search_relationships` | Relationships matching one entity, or a pair of them. |
| `intersect_relationships` | What a batch of up to 20 known records is related to. |
| `sync_relationships` | Replicate a container's relationships, or the changes since a token. |
| `get_sync_status` | Whether up to 3 sync tokens have anything waiting behind them. |

### ACC Transmittals (`client.transmittals`)

Reads the transmittals a project has issued: the formal handover of a set of documents to a set of recipients, with a cover note and a tracked receipt.

A transmittal is a snapshot. It records the document versions and folders as they stood when it went out, and who it was addressed to. `list_recipients` adds when each recipient received, viewed, and downloaded it.

Nothing here writes, and nothing here sends. Autodesk publishes five reads and no other verb, so a transmittal is created and issued in the ACC Transmittals tool. The API also cannot change a transmittal's settings, add a recipient, or export a package.

A transmittal takes a moment to package. While `Transmittal.status` is `SENDING`, the three sub-reads answer `202 Accepted` with nothing in them. All three methods return None to say so, rather than an empty result.

`recipients` on a transmittal is the addressing that was chosen, by user, company, and role. `list_recipients` is the people it resolved to, with their receipt timestamps.

The three paged listings sort by three different sets of fields, and each takes its own enum. The direction is always sent, because the pages disagree about what a bare field name means.

All 5 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_transmittals` | The transmittals a project has issued. |
| `get_transmittal` | One transmittal, with its sender and addressing. |
| `list_recipients` | Everyone the transmittal reached, with receipt timestamps. |
| `list_folders` | The folders the transmittal included. |
| `list_documents` | The document versions the transmittal included. |

### ACC AutoSpecs (`client.autospecs`)

Reads the draft submittal log AutoSpecs extracts from a project's specification.

Somebody uploads a spec book to the project in the ACC AutoSpecs tool. AutoSpecs reads the submittal requirements out of it into a Smart Register. That register is the list of submittals the specification asks for, before anyone turns them into real ACC submittals through `client.submittals`.

Nothing here writes. Autodesk publishes four reads and no other verb, so a spec book is uploaded, extracted, and edited in the AutoSpecs tool. The API also cannot filter submittals, edit the Smart Register, or reach the Spec View and Product Data tools.

Every read but `get_metadata` is scoped by a specification version, and `get_metadata` is where the version IDs come from. A version ID is an AutoSpecs number such as `2268`, not a Data Management version URN. The service refuses anything that is not a signed 32-bit integer.

Reading a spec book takes minutes and AutoSpecs publishes no webhook. Autodesk says the Smart Register is available only once `SpecVersion.status` reads `Completed`, and the field guide says to poll `get_metadata` for it. `wait_for_extraction` does that polling.

Every submittal type, submittal group, and region is a plain string. Autodesk's own examples contradict its own field tables on the case of all three. The Retrieve a Smart Register tutorial goes further and answers a submittal type the reference does not list.

All 4 endpoints are implemented, plus `wait_for_extraction`.

| Method | Description |
| --- | --- |
| `get_metadata` | A project's specification versions and their extraction status. |
| `wait_for_extraction` | Poll one version until AutoSpecs stops reading it. |
| `get_smart_register` | Every submittal the specification asks for. |
| `get_requirements` | Those submittals counted by division, section, and group. |
| `get_submittals_summary` | Those submittals counted by group and by type. |

### ACC Classifications (`client.classifications`)

Reads and writes the classification trees a project tags its work against: the versioned taxonomies such as Uniformat and MasterFormat.

**This is the lookup for the classification IDs Takeoff returns.** A migrated Takeoff project reports a `structureId` and `nodeId` pair on every quantity definition. Nothing else turns that pair into a code and a name, and the Takeoff `structureId` is the tree ID here.

Autodesk marks the whole module beta and may change it without a migration guide.

A node cannot be created, renamed, moved, or deleted on its own. Every change to the shape of a tree goes through `import_tree` or `reimport_tree`, which publish a whole new version. Autodesk's own Delete a Node and Restore a Node guides are both a reimport.

`reimport_tree` replaces the tree rather than adding to it. Every node missing from its payload is marked deleted in the new version, so send the whole tree and give each node its existing `id`. An empty payload deletes every node, so `allow_empty` guards it and defaults to False.

Only the tip version is readable. `list_nodes` answers from the latest published version, and Autodesk publishes no way to read an older one. `include_deleted` adds the nodes an earlier reimport dropped.

Classifications refuses the `b.` prefix Data Management adds, with a 400, so every method strips one.

All 6 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_trees` | The classification trees in a project. |
| `get_tree` | One tree, with where it came from. |
| `update_tree` | Rename a tree, redescribe it, or both. |
| `import_tree` | Create a tree and publish its first version. |
| `reimport_tree` | Replace a tree's nodes and publish a new tip version. |
| `list_nodes` | The nodes of a tree's latest published version. |

### Tandem Data (`client.tandem`)

Reads and writes the digital twin data Autodesk Tandem holds: facilities, their models, the properties on every element, the documents attached to them, and the live sensor streams.

Tandem calls a facility a twin, and the two words mean the same thing. A facility is built from source models. Every logical element lives in its default model, whose URN is the facility URN with `dtm` in place of `dtt`, and `default_model_id` renders it.

Permission comes from the Tandem product rather than from the OAuth scope. A user or an application reaches nothing until a Tandem administrator adds it to a facility or to a team, whatever scopes its token carries. Add an application by client ID: the User tab of a facility, or the Team tab of the Manage page for a whole account.

**Property data speaks qualified property names rather than JSON keys.** A name is a column family and a column. `n:n` is the common name and `z:3wc` is a user-defined parameter. `get_model_schema` maps those onto the names a person recognises. They are chosen per model, so a facility of three models needs three scans.

`mutate_elements` writes them back, pairing a list of element keys with a list of mutations. Two of its four operations destroy rather than change: `delete_row` deletes the element and, on a stream, every reading it holds, and `delete` outside family `z` clears a property the source model owns. `allow_destructive` guards both and defaults to False.

`reset_stream_secrets` issues new secrets and stops every sensor still posting with the old ones. Read a secret with `get_stream_secrets` instead. `delete_stream_data` destroys readings, so it needs either the substreams to clear or an explicit `all_substreams`.

Tandem is deployed in US, EMEA, and AUS only. The gateway refuses the other five members of `Region` with a 400, so `region` refuses them first.

All 32 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_groups` | The Tandem accounts you can reach. |
| `get_group` | One account, with its facilities and members. |
| `get_group_history` | What changed across an account. |
| `set_group_user_access` | Set what one person may do with an account. |
| `list_twins` | The facilities of an account, keyed by URN. |
| `create_twin` | Create a facility in an account. |
| `get_twin` | One facility, with its models, documents, and template. |
| `check_twin_access` | What you may do with a facility, from the headers. |
| `create_default_model` | The model that holds logical elements and streams. |
| `get_twin_history` | What changed in a facility. |
| `list_twin_users` | Who may see a facility. |
| `list_views` | The saved views of a facility. |
| `get_inline_template` | The facility template, classification and all. |
| `add_document` | Attach a document to a facility. |
| `get_document` | One document, with a signed link to the file. |
| `delete_document` | Remove Tandem's copy of a document. |
| `get_model_schema` | The property definitions of one model. |
| `scan_properties` | Read properties off the elements of one model. |
| `mutate_elements` | Write properties onto the elements of one model. |
| `create_element` | Add an element, such as a stream. |
| `get_model_history` | What changed in one model. |
| `list_stream_configs` | How every stream in a model reads its values. |
| `get_stream_config` | How one stream reads its values. |
| `update_stream_configs` | Change several stream configurations at once. |
| `save_stream_config` | Replace one stream's whole configuration. |
| `get_stream_secrets` | The secrets that sign the ingestion URLs. |
| `reset_stream_secrets` | Issue new secrets, invalidating the old ones. |
| `get_latest_stream_data` | The last known reading of each named stream. |
| `get_stream_data` | The readings one stream recorded over a range. |
| `send_stream_data` | Record one reading against a stream. |
| `send_stream_webhook` | Record readings for several streams at once. |
| `delete_stream_data` | Delete readings from named streams. |

### Application Management (`client.applications`)

Reads the APS applications you own or collaborate on, the API products they may reach, and what they consumed day by day. It also rotates their client secrets.

**`commit_secret_rotation` retires a live credential and cannot be undone.** Rotation runs in two steps. `prepare_secret_rotation` issues a second secret while the current one keeps working, and `commit_secret_rotation` makes the new one active and the old one dead. Deploy the new secret everywhere first, with each caller trying it and falling back to the old one, then commit. A caller still on the old secret is locked out the moment the commit lands.

Each rotation call needs a client assertion, which is a JWT the application signs with a key published at its own JWKS URI. Set that URI on https://aps.autodesk.com/myapps before the first rotation.

The reads want a 3-legged token carrying `application:client:read`, or a Secure Service Account token, which `client.service_accounts` mints for a headless server. The three rotation calls want the application's own 2-legged token carrying `application:client:rotate_secret`, so clear any user token first with `client.auth.clear_token()`.

Nothing here registers, edits, or deletes an application. Autodesk publishes eight operations and documents no others, and the `application:client:write` scope its API Basics page names has no v1 endpoint.

The listings page by URL alone. There is no offset and no cursor, so `Page.next_url()` reports where the next page lives and the listing ends when that comes back None.

All 8 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_api_products` | The API products an application can be given access to. |
| `list_applications` | The APS applications you own or collaborate on. |
| `get_application` | One application, without its client secret. |
| `list_collaborators` | Who else has access to one application. |
| `get_usage_daily_totals` | What one application consumed, day by day. |
| `prepare_secret_rotation` | Issue a second secret, leaving the current one live. |
| `commit_secret_rotation` | Make the prepared secret active and retire the old one. |
| `cancel_secret_rotation` | Discard a prepared secret. |

### Informed Design (`client.informed_design`)

Publishes a configurable manufactured product from an Inventor or Fusion model, then generates design outputs from configurations of it. This API is beta, and Autodesk says not to build production software on it yet.

Four resources form a chain, and Autodesk's walkthrough runs them in order. A product holds releases, a release holds variants, and a variant holds outputs. Create the product, upload its design data and rules, create a release over them, create a variant that sets the parameters, then generate outputs.

Every call but the three rules ones needs an `access_type` and an `access_id`, which decide what the caller may see. For `ACC`, `BIM360`, and `FUSION` the ID is `<projectId>|<folderUrn>`, and for `USER` it is the Autodesk user ID. Autodesk authorizes on this pair as well as on the token, so a wrong one is refused before the resource is looked up. `list_upload_requests` is the only endpoint that takes `USER`.

Every call needs a 3-legged token carrying `data:read`, `data:write`, `data:create`, and `account:read`. Autodesk recommends a Secure Service Account for a headless server, which `client.service_accounts` mints.

Output generation and output upload are asynchronous. Both answer a request whose `status` starts at `PENDING`, and `wait_for_outputs` and `wait_for_upload` poll until it settles. Variant creation is not asynchronous, whatever the walkthrough's ordering suggests.

`update_release` replaces the whole output settings list, so an empty one leaves the release able to generate nothing. `allow_empty` defaults to False and has to say so on purpose.

All 31 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_products` | The configurable products in one container. |
| `create_product` | Create a configurable product. |
| `get_product` | One configurable product. |
| `update_product` | Change a product's name, state, default release, or description. |
| `delete_product` | Delete a product and everything under it. |
| `get_upload_urls` | Signed links for uploading one file in parts. |
| `complete_upload` | Mark every part of a file as arrived. |
| `get_download_url` | A signed link to one uploaded file. |
| `delete_upload` | Delete one uploaded file. |
| `download_product_file` | Sign a link and fetch the bytes behind it. |
| `list_releases` | The releases of one product. |
| `create_release` | Create a release from an uploaded design data set. |
| `get_release` | One release, with its parameters and output settings. |
| `update_release` | Change a release's state, notes, or output settings. |
| `delete_release` | Delete a release and every variant under it. |
| `list_variants` | The variants of one release. |
| `create_variant` | Create a variant by setting a release's parameters. |
| `get_variant` | One variant and the values it was configured with. |
| `delete_variant` | Delete a variant and every output from it. |
| `list_outputs` | Generated outputs, narrowed by at least one filter. |
| `create_outputs` | Start generating outputs from one variant. |
| `get_output` | One generated output. |
| `delete_output` | Delete one generated output. |
| `get_outputs_request` | One generation run and how far it has got. |
| `wait_for_outputs` | Poll a generation run until it settles. |
| `list_upload_requests` | The runs that copied outputs into a folder. |
| `create_upload_request` | Start copying outputs into an ACC, BIM 360, or Fusion folder. |
| `get_upload_request` | One upload run and how far it has got. |
| `wait_for_upload` | Poll an upload run until it settles. |
| `create_download_request` | Signed links to a set of generated outputs. |
| `get_download_request` | One download request again, with fresh links. |
| `evaluate_rules` | Run a rules document over a set of parameter values. |
| `validate_rules` | Check whether a rules document is well formed. |
| `get_rules` | Read a rules document. |

### Sustainability Data (`client.sustainability`)

Reads embodied carbon and other environmental impact figures for construction materials, through one interface over several third-party providers. This API is beta and Autodesk says its paths may change at general release.

Start with `list_datasets`. A dataset is one provider's collection, and its `supported_data_types` say which of the five resources it serves: baselines, generic estimates, product EPDs, industry EPDs, and activities. Calling a resource a dataset does not serve answers `424 Failed Dependency` rather than an empty page.

Every resource offers the same shapes. A `filter_*` call lists records, a `get_*` call reads one, and a `filter_*_impacts` call reads its life cycle impact figures. Product EPDs and industry EPDs add a statistics summary, and activities add exchanges instead of categories.

Read `get_*_filters` before building a filter. Filter support varies by dataset. A filter the dataset does not know is dropped rather than refused, so check `ignored_filters` on the page that comes back. A dataset can also narrow a filter it does accept, which it reports in `applied_filters`.

```python
from autodesk_platform_sdk.services.sustainability.schemas import FilterClause

page = client.sustainability.filter_product_epds(
    dataset_id,
    filters={"jurisdictions": FilterClause(op="IN", value=["US"])},
    limit=100,
)
```

Nothing here writes. Every listing is a POST because the filter goes in the body, and paging is `limit` and `offset` in the query.

Every call needs a 3-legged token carrying `data:read`, and the application needs the Sustainability Data API added to it on https://aps.autodesk.com/myapps. A client ID without that answers `403 AUTH-001` on every path. Each provider also grants a separate data licence, so a dataset appears in `list_datasets` only once yours is in place.

The base path is split. The five construction resources are served under `/sustainability/v3beta` and activities and flows under `/sustainability/v3`. Autodesk's Quick Reference page writes all seven activity and flow routes under `v3beta`, and that prefix is a 404 for every one of them.

All 34 endpoints are implemented.

| Method | Description |
| --- | --- |
| `list_datasets` | The datasets this application may read. |
| `filter_baselines` | The baselines in one dataset. |
| `filter_baseline_categories` | The categories the baselines are filed under. |
| `get_baseline_filters` | Which filters this dataset accepts for baselines. |
| `get_baseline_filter_values` | The values one baseline filter accepts. |
| `get_baseline` | One baseline in full. |
| `filter_baseline_impacts` | The impact figures for one baseline. |
| `filter_generic_estimates` | The generic estimates in one dataset. |
| `filter_generic_estimate_categories` | The categories the generic estimates are filed under. |
| `get_generic_estimate_filters` | Which filters this dataset accepts for generic estimates. |
| `get_generic_estimate_filter_values` | The values one generic estimate filter accepts. |
| `get_generic_estimate` | One generic estimate in full. |
| `filter_generic_estimate_impacts` | The impact figures for one generic estimate. |
| `filter_product_epds` | The product EPDs in one dataset. |
| `filter_product_epd_categories` | The categories the product EPDs are filed under. |
| `filter_product_epd_statistics` | The impact figures summarised across the matching product EPDs. |
| `get_product_epd_filters` | Which filters this dataset accepts for product EPDs. |
| `get_product_epd_filter_values` | The values one product EPD filter accepts. |
| `get_product_epd` | One product EPD in full. |
| `filter_product_epd_impacts` | The impact figures for one product EPD. |
| `filter_industry_epds` | The industry EPDs in one dataset. |
| `filter_industry_epd_categories` | The categories the industry EPDs are filed under. |
| `filter_industry_epd_statistics` | The impact figures summarised across the matching industry EPDs. |
| `get_industry_epd_filters` | Which filters this dataset accepts for industry EPDs. |
| `get_industry_epd_filter_values` | The values one industry EPD filter accepts. |
| `get_industry_epd` | One industry EPD in full. |
| `filter_industry_epd_impacts` | The impact figures for one industry EPD. |
| `filter_activities` | The activities in one dataset. |
| `get_activity_filters` | Which filters this dataset accepts for activities. |
| `get_activity_filter_values` | The values one activity filter accepts. |
| `get_activity` | One activity in full. |
| `filter_activity_impacts` | The impact figures for one activity. |
| `filter_activity_exchanges` | The flows into and out of one activity. |
| `get_flow` | One flow definition an exchange refers to. |

### Token Flex Usage Data (`client.token_flex`)

Reads how an Autodesk Token Flex contract is being consumed: the contract and its token pools, monthly usage totals, ad hoc queries over the raw records, and bulk CSV exports.

Every call needs a 3-legged token, and the person who authorized it must be a Token Flex administrator. Anyone else reads an empty list from `list_contracts` and is refused everywhere else, because every other path is keyed by a contract number. So start with `list_contracts`.

A 2-legged token is refused outright. Autodesk can tie a client ID to one administrator so a server can call without a user, which a Customer Success Manager arranges.

A read wants `data:read` and a write wants `data:write`. `submit_query` is the one POST Autodesk documents under `data:read`.

Queries and exports both run asynchronously.

```python
submitted = client.token_flex.submit_query(
    contract_number,
    fields=["usageCategory", "productName"],
    metrics=["tokensConsumed"],
    where="contractYear = 1",
)
result = client.token_flex.wait_for_query(contract_number, submitted.id)
print(result.result.columns, result.result.rows)
```

`UsageField` and `Metric` name what a query may ask for. Autodesk documents a field marked session level in `UsageField` as export only. Use an export too when a query would exceed the five minute cap Autodesk puts on its running time.

```python
export = client.token_flex.create_export_request(
    contract_number,
    fields=["usageDate", "userName", "productName"],
    metrics=["tokensConsumed"],
    usage_category=["DESKTOP_PRODUCT"],
)
client.token_flex.wait_for_export(contract_number, export.request_key)
csv = client.token_flex.download_export(contract_number, export.request_key)
```

An export's download link is pre-signed, so anyone holding it can read the file. It expires quickly, and `refresh_export_url` issues another.

`update_export_schedule` is a `PUT` and replaces the whole schedule, so read it first and send back what should stay. An empty `reports` schedules a run that produces no file, so `allow_empty` guards both writes and defaults to False.

Token Flex allows five requests a minute per user, so both `wait_for_*` helpers poll every fifteen seconds by default.

All 21 endpoints are implemented, plus `wait_for_query`, `wait_for_export`, and `download_export`.

| Method | Description |
| --- | --- |
| `list_contracts` | The Token Flex contracts you administer. |
| `get_contract` | One contract, with its token pools year by year. |
| `list_enrichment_categories` | The labels a contract gave its ten custom fields. |
| `list_enrichment_values` | The distinct values under one custom field. |
| `list_field_values` | The distinct product, user, machine, or server names. |
| `get_usage_summary` | Monthly consumption totals. |
| `get_last_usage` | How current the data is, per usage and charge category. |
| `submit_query` | Submit an ad hoc query over the usage data. |
| `get_query` | Where one query has got to, and its rows once done. |
| `wait_for_query` | Poll a query until it stops. |
| `create_export_request` | Ask for the usage data as a CSV file. |
| `list_export_requests` | The export requests made in one window. |
| `get_export_request` | Where one export request has got to. |
| `wait_for_export` | Poll an export request until it stops. |
| `download_export` | The CSV file one export produced. |
| `retry_export_request` | Run a failed export request again. |
| `refresh_export_url` | A fresh download link for a finished export. |
| `mark_export_requests_read` | Mark exports read, as opening them would. |
| `delete_export_request` | Delete one export request and its file. |
| `list_export_schedules` | The recurring exports on one contract. |
| `create_export_schedule` | Create a recurring export. |
| `get_export_schedule` | One recurring export. |
| `update_export_schedule` | Replace one recurring export. |
| `delete_export_schedule` | Delete one recurring export. |

### Business Success Plan Reporting (`client.insights`)

Reads how an organisation consumes Autodesk products: seat usage for single user subscriptions and token consumption for Flex. A query returns rows of JSON, and an export writes a CSV, Excel, or JSON file.

The caller must administer a team that carries Business Success Plan benefits. `list_contexts` names those teams, and Autodesk describes `ReportingAPIAccess` as the benefit that covers this API. So start with `list_contexts`.

Every call needs a 3-legged token. Autodesk also accepts a 2-legged token beside a personal access token, which the caller generates on the Autodesk Account security page. Pass it as `pat` and the SDK sends it in `ADSK-PAT`.

A read wants `data:read` and both POSTs want `data:write`.

Queries and exports both run asynchronously.

```python
submitted = client.insights.submit_query(
    fields=["productName", "usageMonth"],
    metrics=["uniqueUsers", "totalTokens"],
    where="productName LIKE 'AutoCAD%'",
    order_by="productName DESC",
)
result = client.insights.wait_for_query(submitted.id)
print(result.columns, result.rows)
```

`UsageField` and `Metric` name what a query may ask for. Six `UsageField` members carry personal data and cannot appear in a `where` clause. An administrator who has hashed personal data cannot request them at all.

```python
export = client.insights.create_export(
    output_format="CSV",
    reports=["USAGE"],
    start_date=date(2025, 1, 1),
    end_date=date(2025, 6, 30),
)
client.insights.wait_for_export(export.id)
payload = client.insights.download_export(export.id, report="USAGE")
```

`USAGE` and `USAGE_REPORT` both need a date range, and Autodesk documents a limit of a year on it. `USAGE_REPORT` also needs `usage_reports`, and `report_filters` narrows it further. Each requirement raises a `ValueError` before the request leaves.

An export's download link is pre-signed, so anyone holding it can read the file. It expires within minutes, and `download_export` resolves a fresh one on every call. Autodesk keeps an export for two weeks and then deletes it.

Autodesk allows ten export requests a minute per user and ten outstanding exports, so both `wait_for_*` helpers poll every ten seconds by default.

All 6 endpoints are implemented, plus `wait_for_query`, `wait_for_export`, and `download_export`.

| Method | Description |
| --- | --- |
| `list_contexts` | The teams you administer, and what each may report on. |
| `submit_query` | Submit an ad hoc query over the usage data. |
| `get_query` | Where one query has got to, and its rows once done. |
| `wait_for_query` | Poll a query until it stops. |
| `list_exports` | The exports you asked for in the last two weeks. |
| `create_export` | Ask for the usage data as a downloadable file. |
| `get_export` | Where one export has got to, and its download links. |
| `wait_for_export` | Poll an export until it stops. |
| `download_export` | One file a finished export produced. |

### Forma Site Design (`client.forma`)

Reads and writes the scene graph behind a Forma site: elements, the blobs their geometry lives in, proposals, terrain, and sun analyses.

Every path is alpha. Autodesk says an alpha endpoint can change or disappear without notice, so pin a version of this SDK before relying on it.

Forma publishes nine services behind one prefix, and each answers on its own root, so there is no single base path. The SDK reaches the eight that are not deprecated, over nine roots: Integrate answers on `v1alpha` and on `v2alpha`.

Every call but `get_site` names an `authcontext`, which is a Forma hub ID or project ID. Omitting it is a `401` even with a valid token. IDs are region specific: Forma runs in `US` and `EMEA`, so pass `region` for a European hub.

Autodesk designs these endpoints for an extension embedded in the Forma web client. The calling application must be registered as a service account on that extension. 15 endpoints want a 3-legged token and the other 5 accept either kind. The 8 reads want `data:read` and the 12 writes want `data:read` and `data:write` together.

An element is immutable. Editing one writes a new revision under a new URN, and a parent only sees the change once its own reference is rewritten.

```python
found = client.forma.get_element(urn, "pro_abcd", recursive=True)
for child_urn, element in found.elements.items():
    print(child_urn, element.properties.get("name"))
```

A representation whose type is `linked` names a blob rather than carrying the data, so fetch it separately. `get_blobs` reads a batch and answers a partial result when the batch grows too large, marking the rest `skipped`.

```python
mesh = found.elements[urn].representations["volumeMesh"]
glb = client.forma.get_blob(mesh.blob_id, "pro_abcd")
```

Writing geometry is a three step flow: reserve a link, upload the payload, then reference the blob ID it gave back.

```python
link = client.forma.get_upload_link("pro_abcd")
client.forma.upload_payload(link.url, glb)
created = client.forma.create_element(
    "pro_abcd",
    properties={"name": "Block A", "category": "building"},
    representations={
        "volumeMesh": RepresentationInput(type="linked", blobId=link.blob_id)
    },
)
```

`update_element` merges one level deep: each named property and each named representation replaces its counterpart, and anything not named is kept. Map a name to `None` to remove it. `children` is not merged, so whatever is passed replaces the whole list.

```python
client.forma.update_element(
    created.urn,
    "pro_abcd",
    properties={"name": "Block B", "category": None},
)
```

`ingest_elements` writes up to 1000 creates and updates at once. Items in one batch may reference each other, so a whole hierarchy goes up in one call. It reports each item separately, so read `succeeded()` per result rather than assuming the batch passed.

`update_proposal` is a replacement, not a merge. The terrain, the base, and every child become exactly what is passed. All three are required arguments, so no default can quietly empty a proposal. Read the current revision with `list_revisions` first.

Proposals page by cursor, and Forma reports only the next URL, so `ProposalPage.next_cursor()` reads the cursor back out of it.

Terrain is reserved, uploaded, and then marked. `upload_terrain` gzips the GLB first, which Autodesk requires. `mark_terrain_uploaded` takes an `authcontext` that its reference page does not document, because the live service answers `401` without one.

```python
reserved = client.forma.create_terrain("pro_abcd", [[0, 0, 0], [500, 500, 90]])
client.forma.upload_terrain(reserved.presigned_s3_url, glb)
client.forma.mark_terrain_uploaded(reserved.element_id, reserved.revision, "pro_abcd")
```

A sun analysis runs asynchronously, so `trigger_analysis` returns an ID and `wait_for_analysis` polls it. A finished analysis links to a msgpack file of per point sunlit hours, and `GroundGridFormat` documents how to read it.

The deprecated Project API and the deprecated V1 write endpoints are left out. Use `get_site` in place of the first, and `create_element`, `update_element`, and `ingest_elements` in place of the second.

All 20 live endpoints are implemented, plus `wait_for_analysis`, `upload_payload`, and `upload_terrain`.

| Method | Description |
| --- | --- |
| `get_element` | One element revision, and optionally its subtree. |
| `get_elements` | Several element revisions in one call. |
| `get_blob` | The data behind one linked representation. |
| `get_blobs` | Several blobs in one call, as a multipart body. |
| `create_geometries` | Write polygons, extruded polygons, and lines. |
| `create_element` | Write a new element into the integrate system. |
| `update_element` | Write a new revision, merging one level deep. |
| `ingest_elements` | Write up to 1000 creates and updates at once. |
| `get_upload_link` | Reserve somewhere to put a payload. |
| `upload_payload` | PUT a payload to a pre-signed Forma URL. |
| `create_library_item` | Save an element to the library. |
| `create_proposal` | Write a new proposal onto a site. |
| `list_proposals` | The proposals of one site. |
| `update_proposal` | Replace the whole content of a proposal. |
| `list_revisions` | The revisions of one proposal. |
| `get_site` | One site, and how it is projected. |
| `get_analysis` | Where one sun analysis has got to. |
| `trigger_analysis` | Start a sun analysis over an element. |
| `wait_for_analysis` | Poll a sun analysis until it stops. |
| `create_terrain` | Reserve a terrain revision and its upload link. |
| `upload_terrain` | Gzip a terrain GLB and PUT it to that link. |
| `mark_terrain_uploaded` | Tell Forma the GLB is behind the revision. |
| `download_terrain` | The GLB of one terrain revision. |

### Flow Graph Engine (`client.flow_graph`)

Runs compute jobs in the cloud, and moves the files they read and write. Autodesk aims this API at media and entertainment pipelines rather than at the AEC surfaces the rest of this client covers. Its one executor, `bifrost`, runs the Bifrost graphs Maya artists build.

There are two roots: jobs answer under `/flow/compute/v1` and files under `/flow/storage/v1`. A job never carries its own data, so the order is always upload, submit, wait, download.

Either kind of token works on every endpoint. Ten job endpoints check no scope at all, `create_job` wants `code:all`, the four storage reads want `data:read`, and the six storage writes want `data:write`. Each of those was proved against the live API, one scope per token.

`queue_id` defaults to `@default`, which is the only queue Autodesk serves. A space ID is `{provider}:{spaceKey}`: write to `scratch:@default` and read a job's own results from `outputs:{jobId}`. Both storage providers delete a resource after 30 days, and job details go the same way.

Upload the inputs first. `upload_resource` runs the whole pre-signed flow: reserve the URLs, PUT each part, then complete the upload.

```python
stored = client.flow_graph.upload_resource(
    "scratch:@default", "plane.usd", pathlib.Path("plane.usd").read_bytes()
)
```

A job is a list of tasks. Each task names an executor and carries that executor's own payload, and references its inputs by the URN storage gave back.

```python
job = client.flow_graph.create_job(
    [
        TaskSpec(
            name="execute bifrost graph",
            executor="bifrost",
            inputs=[
                InputSpec(
                    source=SourceInput(uri=stored.urn),
                    target=TargetInput(path="plane.usd"),
                )
            ],
            payload={"action": "Evaluate"},
            requirements=RequirementsInput(cpu=4, memory=30720),
        )
    ],
    name="add trees",
)
finished = client.flow_graph.wait_for_job(job.id)
```

Running a job consumes Flow tokens. Autodesk allows 10 job submissions a minute and 60 reads a minute, and caps a task at 16 vCPUs, 122880 MB, and 48 hours.

The job lists its outputs and logs, and storage serves them. An entry names a space and a resource rather than carrying the bytes.

```python
for output in client.flow_graph.list_job_outputs(finished.id).results:
    data = client.flow_graph.download_resource(output.space_id, output.resource_id)
```

`list_job_updates` and `list_task_execution_updates` follow a queue or a job by change time. Autodesk documents both `after` and `before` and refuses them together, which no reference page says, so `list_job_updates` catches the pair before the request leaves.

Listings page by an opaque token that Autodesk reports only inside `pagination.nextUrl`, so `next_token()` reads it back out and `pagination_token` sends it.

Do not send a part's entity tag when completing an upload. Autodesk's request schema demands a quoted tag and then compares it against the unquoted hash it stores, so every value it accepts answers `400`. `complete_upload` names each part by its number, which `numbered()` builds, and `upload_resource` does the same.

All 21 documented endpoints are implemented, plus `wait_for_job`, `upload_part`, `upload_resource`, and `download_resource`.

| Method | Description |
| --- | --- |
| `list_jobs` | The jobs in a queue. |
| `list_job_updates` | The jobs that changed inside one time window. |
| `get_job` | One job, with its status and progress. |
| `create_job` | Submit one or more tasks to run. |
| `cancel_job` | Stop a job that has not finished. |
| `delete_job` | Delete a finished job and the record of its run. |
| `wait_for_job` | Poll a job until it stops. |
| `list_tasks` | The tasks a job was submitted with. |
| `list_task_executions` | The runs of a job's tasks. |
| `list_task_execution_updates` | The runs that changed after one moment. |
| `list_job_outputs` | The files a job produced. |
| `list_job_logs` | The log files a job produced. |
| `get_space` | One storage space. |
| `get_resource` | The size, checksum, and URN of one stored file. |
| `get_download_url` | A pre-signed URL to read one file from. |
| `batch_get_download_urls` | Download URLs for several files in one space. |
| `download_resource` | The contents of one stored file. |
| `get_upload_urls` | Pre-signed URLs to write the parts of one file to. |
| `batch_get_upload_urls` | Upload URLs for several files in one space. |
| `create_upload` | Reserve an upload, and optionally its URLs. |
| `batch_create_uploads` | Reserve several uploads in one call. |
| `upload_part` | PUT one part to a pre-signed URL. |
| `complete_upload` | Assemble the parts into a stored resource. |
| `batch_complete_uploads` | Assemble several uploads in one call. |
| `upload_resource` | Upload a file, running the whole flow. |
