Metadata-Version: 2.4
Name: autodesk-platform-sdk
Version: 0.1.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

A typed Python client and command-line interface for the [Autodesk Platform Services](https://aps.autodesk.com/developer/documentation) (APS) APIs.

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** - ten APS services mount as namespaces on a single client, from `client.auth` to `client.tradetapp`, 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 polling, URN encoding, JWT assertion signing, cursor paging, and the six different ways APS reports 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.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.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 reads `APS_API_TIMEOUT` (seconds) and `APS_API_RETRIES` (count) for the same behavior.

## 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.

## Reference Documentation

- [APS documentation](https://aps.autodesk.com/developer/documentation)
- [Authentication (OAuth) v2](https://aps.autodesk.com/en/docs/oauth/v2/reference/http/)
- [OAuth scopes](https://aps.autodesk.com/en/docs/oauth/v2/developers_guide/scopes/)
- [Secure Service Account v1](https://aps.autodesk.com/en/docs/ssa/v1/reference/http/)
- [Data Management and Object Storage v2](https://aps.autodesk.com/en/docs/data/v2/reference/http/)
- [Model Derivative v2](https://aps.autodesk.com/en/docs/model-derivative/v2/reference/http/)
- [Webhooks v1](https://aps.autodesk.com/en/docs/webhooks/v1/reference/http/)
- [ACC Account Admin v1](https://aps.autodesk.com/en/docs/acc/v1/reference/http/admin-projects-GET/)
- [ACC Issues v1](https://aps.autodesk.com/en/docs/acc/v1/reference/http/issues-issues-GET/)
- [BuildingConnected v2/v3](https://aps.autodesk.com/en/docs/buildingconnected/v2/reference/http/)
- [TradeTapp v2](https://aps.autodesk.com/en/docs/buildingconnected/v2/reference/http/tradetapp-users-me-GET/)
- [Official OpenAPI specifications](https://github.com/autodesk-platform-services/aps-sdk-openapi)

## 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. |

### 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. |
