22 May 2025
Generate Your Own APS Clients Using OpenAPI and Microsoft Kiota

We're back with another interesting use case for OpenAPI specifications for APS that were recently published. If you're building tools or integrations on top of APS using a programming language we don't provide SDK for, you can now automatically generate client SDKs using Microsoft Kiota, an open-source project for creating strongly-typed API clients from OpenAPI descriptions.
In this post, we’ll walk through how to generate a Python SDK for several APS APIs using Kiota and demonstrate a simple use case.
Why Use Kiota?
Kiota is a code generator that takes in an OpenAPI spec and outputs a typed client library in languages like Python, C#, Java, TypeScript, Go, and others. Compared to hand-written wrappers or generic HTTP clients, Kiota-generated SDKs give you:
-
Strong typing and IDE support
-
Automatic request building and serialization
-
Error handling and response models
-
Authentication hooks
This means less boilerplate and more confidence when calling APS endpoints.
Installing Kiota
There are several ways to use Kiota:
-
Install it as a global
.NET
tool usingdotnet tool install
-
Install it as a standalone CLI using
npm
-
Run it via Docker which doesn’t require installing anything on your system except Docker itself
In this example, we'll use Docker which is great for quick experiments and repeatable builds. No setup required, just run docker run
with the right parameters.
Accessing the OpenAPI Specs
We’ve published OpenAPI specifications for Autodesk Platform Services on GitHub. You can either:
-
Clone the GitHub repo if you want to explore or modify the specs locally, or
-
Reference the raw YAML files directly via their GitHub URLs
In this example, we’ll use the raw URLs for simplicity.
Generating the SDK
Here’s a simple bash script - let's call it gen_sdk.sh - that uses Docker to generate SDKs for four APS APIs: Data Management, OSS, Model Derivative, and ACC Issues. It pulls the specs directly from GitHub, and outputs the generated code to a local directory.
#!/usr/bin/env bash
KIOTA_IMAGE="mcr.microsoft.com/openapi/kiota:1.26.1"
KIOTA_ARGS="--language python"
OPENAPI_BASE_URL="https://raw.githubusercontent.com/autodesk-platform-services/aps-sdk-openapi/09dfeb71fab0daf032cf1b343ef3dcac8ba1800c" # Hard-coding a specific commit/version of the specs
generate_sdk() {
local output_dir="$1"
local openapi_path="$2"
local class_name="$3"
docker run --volume "$output_dir":/app/output $KIOTA_IMAGE generate $KIOTA_ARGS --openapi "$OPENAPI_BASE_URL/$openapi_path" --class-name "$class_name"
}
generate_sdk "./src/aps/oss" "oss/oss.yaml" "OssClient"
generate_sdk "./src/aps/md" "modelderivative/modelderivative.yaml" "ModelDerivativeClient"
generate_sdk "./src/aps/dm" "datamanagement/datamanagement.yaml" "DataManagementClient"
generate_sdk "./src/aps/acc/issues" "construction/issues/Issues.yaml" "IssuesClient"
Run the script with:
chmod +x gen_sdk.sh
./gen_sdk.sh
Don't forget to also install Kiota dependencies for Python:
pip install microsoft-kiota-abstractions
pip install microsoft-kiota-http
pip install microsoft-kiota-serialization-json
pip install microsoft-kiota-serialization-text
pip install microsoft-kiota-serialization-form
pip install microsoft-kiota-serialization-multipart
Handling Authentication
The SDKs generated by Kiota do not include built-in authentication logic, and that’s a good thing. This gives you full control over how tokens are fetched and refreshed in your environment.
To use the APS APIs, you’ll need to provide an authentication provider that attaches a valid OAuth 2.0 access token to each request. Here's some examples of how these providers might look like in Python:
- Generating two-legged access tokens on-the-fly:
import os
import requests
from kiota_abstractions.authentication.anonymous_authentication_provider import AuthenticationProvider, RequestInformation
class ClientCredentialsAuthenticationProvider(AuthenticationProvider):
"""
Kiota authentication provider used to authenticate requests to APS using the "client credentials" OAuth flow.
It requires a client ID and client secret, which can be provided directly or through environment variables.
"""
def __init__(self, client_id: str | None = None, client_secret: str | None = None, scopes: str = "data:read") -> None:
self.client_id = client_id or os.environ.get("APS_CLIENT_ID")
self.client_secret = client_secret or os.environ.get("APS_CLIENT_SECRET")
self.scopes = scopes
if not self.client_id or not self.client_secret:
raise ValueError("Please provide a valid client ID and client secret")
async def authenticate_request(self, request: RequestInformation, additional_authentication_context = {}) -> None:
access_token = self.generate_access_token(self.client_id, self.client_secret, self.scopes)
request.headers.add("Authorization", f"Bearer {access_token}")
def generate_access_token(self, client_id, client_secret, scopes) -> str:
url = "https://developer.api.autodesk.com/authentication/v2/token"
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
data = {
"client_id": client_id,
"client_secret": client_secret,
"grant_type": "client_credentials",
"scope": scopes
}
response = requests.post(url, headers=headers, data=data)
response.raise_for_status()
access_token = response.json().get("access_token")
if not access_token:
raise ValueError("Failed to generate access token")
return access_token
- Simply using a hard-coded token (could be 2-legged or 3-legged):
import os
from kiota_abstractions.authentication.anonymous_authentication_provider import AuthenticationProvider, RequestInformation
class BearerTokenAuthenticationProvider(AuthenticationProvider):
"""
Kiota authentication provider used to authenticate requests to APS using an existing access token.
The access token can be provided directly or through an environment variable.
"""
def __init__(self, access_token: str | None = None) -> None:
self.access_token = access_token or os.environ.get("APS_ACCESS_TOKEN")
if not self.access_token:
raise ValueError("Please provide a valid access token")
async def authenticate_request(self, request: RequestInformation, additional_authentication_context = {}) -> None:
# TODO: check whether the token is valid for the request
request.headers.add("Authorization", f"Bearer {self.access_token}")
Examples
Listing Buckets with the OSS API
import asyncio
from kiota_http.httpx_request_adapter import HttpxRequestAdapter
from aps import OssClient, ClientCredentialsAuthenticationProvider # Adjust as needed based on your code structure
# Assuming APS_CLIENT_ID and APS_CLIENT_SECRET are set in environment variables
adapter = HttpxRequestAdapter(ClientCredentialsAuthenticationProvider(scopes="bucket:read data:read"))
oss_client = OssClient(adapter)
async def main():
try:
response = await oss_client.oss.v2.buckets.get() # Follows the API endpoint path, e.g., /oss/v2/buckets
buckets = response.items if response and response.items else []
for bucket in buckets:
print(f"Bucket: {bucket.bucket_key}")
except Exception as e:
print(f"Error fetching buckets: {e}")
asyncio.run(main())
Listing Hubs with the Data Management API
import asyncio
from kiota_http.httpx_request_adapter import HttpxRequestAdapter
from aps import DataManagementClient, BearerTokenAuthenticationProvider # Adjust as needed based on your code structure
# Assuming APS_ACCESS_TOKEN is set in environment variables
adapter = HttpxRequestAdapter(BearerTokenAuthenticationProvider())
data_management_client = DataManagementClient(adapter)
async def main():
try:
response = await data_management_client.project.v1.hubs.get() # Follows the API endpoint path, e.g., /project/v1/hubs
hubs = response.data if response and response.data else []
for hub in hubs:
print(f"Hub: {hub.attributes.name} ({hub.id})")
except Exception as e:
print(f"Error fetching hubs: {e}")
asyncio.run(main())
Full Code Sample
We have a complete, ready-to-run code sample on GitHub: https://github.com/autodesk-platform-services/aps-kiota-python-sample.
Wrap-Up
By combining Autodesk Platform Services' new OpenAPI specs with Microsoft Kiota, you can generate modern, strongly-typed SDKs in the language of your choice. No need to wait for official client libraries.
Get started today:
And let us know what you build!