Please note that AEC DM Geometry API and DataSDK is currently in beta testing, API calls are subject to changes based on the feedback received. We recommend avoiding using this API to build production software during this phase. If you have an urgent requirement, please contact our team before utilizing the API.
You are required to participate in the AEC Data Model Public Beta Program, follow the instructions, download the DataSDK, and provide your feedback there.
A comprehensive sample application demonstrating how to integrate Autodesk's Data SDK (Autodesk.Data 0.2.2-beta) with AECDM (Architecture, Engineering, Construction, and Design Manufacturing) data. This application shows how to navigate hubs and projects, query AECDM elements, process geometry, and export to IFC format.
This sample demonstrates the complete workflow for working with AECDM data:
- Authentication - Secure connection to Autodesk APIs using OAuth 2.0
- Navigation - Interactively browse Hubs → Projects → Element Groups using the Navigation API
- Data Querying - Retrieve elements from an Element Group using filters or fetch all elements at once
- SDK Integration - Add elements to the Data SDK's
ElementGroupabstraction for processing - Export - Convert all elements to IFC format (geometry processing is handled by the SDK)
- Geometry Display - Retrieve and display mesh geometry information for each element, with optional BRep-to-mesh conversion options
- Visual Studio 2022 or Visual Studio Code with C# extension
- .NET Framework 4.8 or .NET 8.0 SDK
- Internet connection for API access
Autodesk.Data 0.2.2-beta is a private beta package — You can download it from the AEC Data Model Public Beta Program portal and add it as a local NuGet source before running dotnet restore.
-
Create Autodesk Developer Account
- Go to Autodesk Developer Portal
- Sign up for a free developer account
-
Create an Application
- Navigate to "My Apps" in the developer portal
- Click "Create App"
- Fill in application details:
- App Name: Your application name
- App Description: Brief description
- Callback URL:
http://localhost:65314/api/auth/callback/(for testing)
- Select APIs: Check "AEC Data Model API"
- Save the application
- Provide access to your APS App client ID in your Forma Hub by following the steps mentioned in the Provisioning access in other products page.
-
Get Your Credentials
- Client ID: Copy from your app's details page
- Client Secret: Copy from your app's details page (keep this secure!)
Region: When the application starts it will ask you to pick a region — US, EMEA, or AUS. Make sure you know which region your Autodesk Hub is hosted in before running. See Region Selection for details.
# Clone the repository
git clone <your-repository-url>
cd aps-aecdm-data-sdk-code-sample
# Restore NuGet packages
dotnet restore SampleApp.csproj
# Create configuration file
cp App.config.template App.config- Copy
App.config.templatetoApp.configin the project root - Fill in your Autodesk credentials in the new
App.configfile:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Required: Your Autodesk app credentials -->
<add key="AuthClientID" value="YOUR_CLIENT_ID_HERE" />
<add key="AuthClientSecret" value="YOUR_CLIENT_SECRET_HERE" /> <!-- Ignore this key for PKCE app -->
<!-- Required: OAuth callback URL -->
<add key="AuthCallBack" value="http://localhost:8080/api/auth/callback" />
<!-- Optional: Application settings -->
<add key="ApplicationName" value="AECDMSampleApp" />
<add key="ApplicationDataPath" value="" />
<add key="LogLevel" value="Info" />
</appSettings>
</configuration># Build the application
dotnet build
# Run the application
dotnet runWhen the application starts, it first asks you to select a region, then uses the Navigation API to let you interactively browse your data:
Select a region:
1. US (default)
2. EMEA
3. AUS
Enter choice (1-3) [default: 1]: 1
========================================
AECDM Navigation: Browse Element Groups
========================================
Fetching Hubs...
Found 2 hub(s):
1. My Company Hub (ID: a.YnVzaW5lc3M6...)
2. Personal Hub (ID: a.cGVyc29uYWw6...)
Select a hub (1-2) [default: 1]: 1
→ Using hub: My Company Hub
Fetching Projects...
Found 3 project(s):
1. Office Building (ID: b.project1...)
2. Residential Tower (ID: b.project2...)
...
Select a project (1-3) [default: 1]: 1
Fetching Element Groups (Revit models)...
Found 1 element group(s):
1. Building Model v3 (ID: urn:adsk.dtm:...)
→ Selected: Building Model v3
Do you want to include Extended Properties? (Yes/No): No
No hardcoded IDs are needed — the app discovers your available data at runtime. The selected region is applied consistently to all Navigation API calls and all ElementGroup operations throughout the session.
At startup the application prompts you to choose a region:
Select a region:
1. US (default)
2. EMEA
3. AUS
Enter choice (1-3) [default: 1]:
The chosen region is used consistently for:
- All three Navigation API calls (
GetHubsAsync,GetProjectsAsync,GetElementGroupsAsync) - Every
ElementGroupinstantiation (new ElementGroup(client, region))
Supported values from Autodesk.Data.Enums.Region:
| Choice | Region | Notes |
|---|---|---|
| 1 | Region.US |
Default — routes to US |
| 2 | Region.EMEA |
Europe, Middle East, Africa |
| 3 | Region.AUS |
Australia |
Entering nothing or an invalid value defaults to US. Specify the region that matches where your Hub and data are hosted.
aps-aecdm-data-sdk-code-sample/
├── Program.cs # Main application entry point with workflow orchestration
├── App.config # Configuration file for credentials and settings (gitignored)
├── App.config.template # Template configuration file for easy setup
├── SampleApp.csproj # Project file with dependencies
├── README.md # This documentation
└── GeometryFiles/ # Created at runtime for downloaded geometry files
| Setting | Description | Example |
|---|---|---|
AuthClientID |
Your Autodesk app's Client ID | abc123def456... |
AuthClientSecret |
Your Autodesk app's Client Secret (Not required for PKCE Auth) | xyz789uvw012... |
AuthCallBack |
OAuth callback URL | http://localhost:8080/api/auth/callback |
ApplicationName |
Custom application name | MyAECDMApp |
ApplicationDataPath |
Custom data directory | C:\MyApp\Data |
LogLevel |
Logging verbosity | Info, Debug, Error |
The application follows this high-level flow:
// 1. Create the SDK client
// Autodesk.Data.AECDM.Client is the main entry point for all SDK operations.
// It is created via DataSdkClientFactory using credentials from App.config.
var clientFactory = new DataSdkClientFactory();
Autodesk.Data.AECDM.Client aecdmClient = clientFactory.CreateAecdmClient(sdkOptions);
// 2. Prompt the user to select a region (US / EMEA / AUS)
// The chosen region is passed into every Navigation API call and ElementGroup constructor.
var region = PromptForRegion();
// 3. Navigate to an element group interactively (Hubs → Projects → Element Groups)
// Returns an ElementGroupInfo object that identifies the selected model.
var elementGroupInfo = await SelectElementGroupViaNavigationAsync(aecdmClient, region);
// 4. Optionally include extended properties in element data
// false (default): only standard Revit properties
// true: includes any AECDM extended properties if available.
// — expect larger payloads and slower responses, especially for large element groups
Console.Write("Do you want to include Extended Properties? (Yes/No): ");
var includeExtendedProperties = Console.ReadLine();
// 5. Run IFC conversion and mesh geometry workflows using the selected ElementGroupInfo
await ConvertFilteredAECDMElementsToIFCAsync(aecdmClient, elementGroupInfo, includeExtendedProperties == "Yes", region);
await ConvertCompleteAECDMElementGroupToIFCAsync(aecdmClient, elementGroupInfo, includeExtendedProperties == "Yes", region);
await GetMeshGeometriesForFilteredAECDMElementsAsync(aecdmClient, elementGroupInfo, region);
await GetMeshGeometriesForCompleteAECDMElementGroupAsync(aecdmClient, elementGroupInfo, region);
await GetMeshGeometriesExampleWithOptions(aecdmClient, elementGroupInfo, region);The SelectElementGroupViaNavigationAsync method uses the Navigation API to browse the account hierarchy and returns an ElementGroupInfo that is passed into all downstream workflows:
// aecdmClient is Autodesk.Data.AECDM.Client
// region is the Region enum value selected by the user at startup
// Step 1: Get all hubs accessible to the account
var hubs = await aecdmClient.GetHubsAsync(region); // returns List<HubInfo>
// Step 2: Get all projects within the chosen hub
var projects = await aecdmClient.GetProjectsAsync(selectedHub, region); // returns List<ProjectInfo>
// Step 3: Get all element groups (Revit models) within the chosen project
var elementGroups = await aecdmClient.GetElementGroupsAsync(selectedProject, region); // returns List<ElementGroupInfo>
// The selected ElementGroupInfo is returned and used by all IFC/mesh methods
return selectedElementGroup; // ElementGroupInfoThe generated .ifc file is saved to:
%AppData%\{ConnectorName}\{user}\Geometry\{ExchangeID}\Geometries\{ifcFileId}.ifc
The full path is printed to the console on completion. ifcFileId is the string you pass to ConvertToIfc(...) — if omitted, a GUID is used.
await ConvertFilteredAECDMElementsToIFCAsync(client, elementGroupInfo, includeExtendedProperties: true, region);await ConvertCompleteAECDMElementGroupToIFCAsync(client, elementGroupInfo, includeExtendedProperties: false, region);await GetMeshGeometriesForFilteredAECDMElementsAsync(client, elementGroupInfo, region);await GetMeshGeometriesForCompleteAECDMElementGroupAsync(client, elementGroupInfo, region);await GetMeshGeometriesExampleWithOptions(client, elementGroupInfo, region);ElementPropertyFilter reference — PropertyName and Operator are free-form strings passed directly to the AECDM GraphQL API.
Common property names:
| Property | Example values |
|---|---|
category |
"Walls", "Doors", "Windows", "Roofs" |
Element Context |
"Instance", "Type" |
name |
Any element name string |
Area |
Numeric string, e.g. "100" |
Revit Element ID |
Revit element ID string |
Supported operators: ==, !=, >, <, >=, <=
Composition: AllOf(...) = AND, AnyOf(...) = OR. These can be nested freely.
Inside this method, elements are retrieved first, then filtered, and geometry is fetched with custom tessellation options:
var elements = await elementGroup.GetElementsAsync(elementGroupInfo);
var wallElements = elements.Where(e => e.Category == "Walls");
var elementGeometryMap = await elementGroup.GetElementGeometriesAsMeshAsync(wallElements, new Autodesk.Data.Geometry.BRepToMeshOptions()
{
SurfaceTolerance = 1.0,
NormalTolerance = 15,
MaxEdgeLength = 2.0,
GridAspectRatio = 0.1,
});BRepToMeshOptions reference — all values use model units (meters/feet) except NormalTolerance (degrees). Pass null to use SDK defaults.
| Parameter | Unit | What it controls | Tighter = |
|---|---|---|---|
SurfaceTolerance |
Model units | Max gap between mesh and original surface | More triangles on curves |
NormalTolerance |
Degrees | Max angle between adjacent triangle normals | Smoother curved surfaces |
MaxEdgeLength |
Model units | Max triangle edge length | More uniform density |
GridAspectRatio |
Ratio | Max triangle aspect ratio (prevents slivers) | Better mesh quality |
Quick guidance: for visualization, tighten SurfaceTolerance (0.001–0.01) and NormalTolerance (5–10). For lightweight preview, loosen them (0.5–1.0, 30–45). Use MaxEdgeLength when you need predictable triangle sizes for analysis pipelines.
This section documents all breaking changes and new features introduced in 0.2.2-beta.
The Client constructor is replaced by DataSdkClientFactory. The returned type is Autodesk.Data.AECDM.Client, which is the main entry point for all SDK operations.
Before (0.1.7-beta):
using Autodesk.Data;
var sdkOptions = new SDKOptionsDefaultSetup { ... };
return new Client(sdkOptions);After (0.2.2-beta):
using Autodesk.Data;
var sdkOptions = new SDKOptionsDefaultSetup { ... };
var clientFactory = new DataSdkClientFactory();
Autodesk.Data.AECDM.Client aecdmClient = clientFactory.CreateAecdmClient(sdkOptions);
return aecdmClient;This applies to both the standard (ClientSecret) and PKCE authentication setups.
ElementGroup.Create(...) is replaced by the new ElementGroup(...) constructor. The Region enum has also moved from a nested type on ElementGroup to the Autodesk.Data.Enums namespace.
Before (0.1.7-beta):
// Region was nested inside ElementGroup
var elementGroup = ElementGroup.Create(client, ElementGroup.Region.US);
// Default (no region)
var elementGroup = ElementGroup.Create(client);After (0.2.2-beta):
using Autodesk.Data.Enums;
// Region is now in Autodesk.Data.Enums
var elementGroup = new ElementGroup(client, Region.US);In 0.1.7-beta, all methods accepted raw string IDs that had to be copied from the portal and hardcoded. In 0.2.2-beta, the Navigation API discovers your data at runtime. Navigation API methods accept a type-safe Region? enum directly — no string conversion needed.
Before (0.1.7-beta):
// IDs had to be hardcoded as string constants
await ConvertCompleteAECDMElementGroupToIFCAsync(client, "Your_GraphQLElementGroupId");
await GetMeshGeometriesForFilteredAECDMElementsAsync(client, "Your_GraphQLElementGroupId");After (0.2.2-beta):
// Prompt user for region (returns Region enum value — US, EMEA, or AUS)
var region = PromptForRegion();
var elementGroupInfo = await SelectElementGroupViaNavigationAsync(client, region);
// Pass the resolved ElementGroupInfo and region to all methods
await ConvertCompleteAECDMElementGroupToIFCAsync(client, elementGroupInfo, includeExtendedProperties, region);
await GetMeshGeometriesForFilteredAECDMElementsAsync(client, elementGroupInfo, region);The Navigation API methods accept Region? directly — no string conversion needed:
var hubs = await aecdmClient.GetHubsAsync(region); // Region? — type-safe
var projects = await aecdmClient.GetProjectsAsync(selectedHub, region); // Region? — type-safe
var groups = await aecdmClient.GetElementGroupsAsync(selectedProject, region); // Region? — type-safeAll methods that previously accepted a raw string element group ID now accept ElementGroupInfo.
Before (0.1.7-beta):
private static async Task ConvertFilteredAECDMElementsToIFCAsync(Client client, string GraphQLElementGroupId)
{
var elementGroup = ElementGroup.Create(client);
await elementGroup.GetElementsAsync(GraphQLElementGroupId, filter);
...
}After (0.2.2-beta):
private static async Task ConvertFilteredAECDMElementsToIFCAsync(Autodesk.Data.AECDM.Client client, ElementGroupInfo elementGroupInfo, bool includeExtendedProperties, Region region)
{
var elementGroup = new ElementGroup(client, region);
await elementGroup.GetElementsAsync(elementGroupInfo, filter, includeExtendedProperties);
...
}GetElementsAsync now accepts an includeExtendedProperties flag for IFC conversion workflows.
Before (0.1.7-beta):
await elementGroup.GetElementsAsync(GraphQLElementGroupId);
await elementGroup.GetElementsAsync(GraphQLElementGroupId, filter);After (0.2.2-beta):
// With filter and extended properties
await elementGroup.GetElementsAsync(elementGroupInfo, filter, includeExtendedProperties: true);
// Without filter, with extended properties as named parameter
await elementGroup.GetElementsAsync(elementGroupInfo, includeExtendedProperties: false);GetElementsAsync now returns the collection of elements directly, instead of requiring access via elementGroup.Elements.
Before (0.1.7-beta):
await elementGroup.GetElementsAsync(GraphQLElementGroupId);
var wallElements = elementGroup.Elements.Where(e => e.Category == "Walls");After (0.2.2-beta):
var elements = await elementGroup.GetElementsAsync(elementGroupInfo);
var wallElements = elements.Where(e => e.Category == "Walls");The following methods that operated on individual elements by raw string ID have been removed in 0.2.2-beta:
| Removed Method | Reason |
|---|---|
ConvertSingleAECDMElementToIFCAsync(client, string elementId) |
Use filtered GetElementsAsync with an element group |
ConvertMultipleAECDMElementsToIFCAsync(client, List<string> elementIds) |
Use filtered GetElementsAsync with an element group |
GetMeshGeometryForSingleAECDMElementAsync(client, string elementId) |
Use GetElementGeometriesAsMeshAsync with an element group |
GetMeshGeometriesForMultipleAECDMElementsAsync(client, List<string> elementIds) |
Use GetElementGeometriesAsMeshAsync with an element group |
Before (0.1.7-beta):
using Autodesk.Data;
using Autodesk.Data.DataModels;
using System.Configuration;After (0.2.2-beta):
using Autodesk.Data;
using Autodesk.Data.DataModels;
using Autodesk.Data.Enums; // For Region enum (Region.US, Region.EMEA, Region.AUS)
using System.Configuration;
using System.Data;
// Autodesk.Data.AECDM.Client is used as the fully qualified type — no alias neededProblem: Required authentication configuration 'AuthClientID' is missing
Solution: Ensure all authentication values are filled in App.config
Problem: Token request failed with status 401
Solution:
- Verify your Client ID and Client Secret are correct
- Ensure your app has the required API permissions
Problem: No hubs found. Make sure AECDM is enabled on your account.
Solution: Ensure your Autodesk account has AECDM enabled and your credentials have access to at least one hub. Make sure your APS App is already integrated with Forma Hub, either by Custom Integration or Install from App Gallery.
Problem: No element groups found. Make sure Revit 2024+ models were uploaded after AECDM activation.
Solution: Element Groups (Revit models) only appear if they were uploaded to the project after AECDM was activated on the account. Re-upload models if needed.
Problem: Failed to connect to authentication service
Solution:
- Check your internet connection
- Verify API endpoints are accessible
- Check if your firewall is blocking the requests
- Check the Console Output: The application provides detailed logging
- Verify Configuration: Double-check all values in
App.config - Test Authentication: Ensure your credentials work in the Autodesk Developer Portal
Once you have this sample running:
- Explore the Data: Examine the AECDM data structure and properties
- Customize Filters: Modify the
ElementPropertyFilterexpressions to target your specific element categories - Tune Mesh Options: Adjust
BRepToMeshOptions(surface tolerance, normal tolerance, edge length) to balance quality and performance - Add Features: Implement additional geometry processing or export formats
- Scale Up: Process larger datasets or integrate with your existing workflows
Happy coding! 🚀
This sample is licensed under the terms of the MIT License. Please see the LICENSE file for full details.