Introduction โ
Today I'd like to share a small tool I just developed that has been very helpful for me whenever I need to connect to the API services of Autodesk Platform Services.
This is a simple extension allows you to get the APS ACC URL details include:
Project Id : A Project in Autodesk Forge is a specific workspace within a Hub. It's where the actual design and construction data is stored. Each project contains folders, items, and versions. The project id is unique for each project within a hub.
Folder Urn : The folder urn is the unique identifier for a folder in a project. It is used to identify the folder in the project.
Entity Id : The entity id is the unique identifier for an entity in a folder. It is used to identify the entity/item in the folder.
Model View Id : The model view id is the unique identifier for a model view in a folder. It is used to identify the model view in the folder.
Installation โ
Chrome / Edge: Install From Chrome Store
Firefox Install From Firefox Store
How to use โ
- Install the extension
- Open the Project in
Autodesk Construction Cloudand click on the icon to get the URL details

- Copy the URL details and share it with others, you can quickly use it in APS Toolkit
from aps_toolkit import BIM360
bim360 = BIM360(token)
bim360.batch_report_item_versions(projects_id, itemId)Development โ
Firefox โ
Manual Install :
- Clone the repository
- Open
about:debugging#/runtime/this-firefox - Click on
Load Temporary Add-on... - Select the
manifest.jsonfile from the cloned repository - The extension will be installed and you can see the icon in the toolbar
- Open ACC Project and click on the icon to get the URL details
Addon Online Store : URL Details
Chrome / Edge โ
- Manual Install :
- Clone the repository
- Open
chrome://extensions/ - Click on
Load unpacked - Select the cloned repository
- The extension will be installed and you can see the icon in the toolbar
- Open ACC Project and click on the icon to get the URL details
Documentation โ
How to get Urn from ACC โ
With urn, you just need use this command from console to get the info urn detail:
NOP_VIEWER.model.myData.urnoutput: "you derivative urn"

Now you can quick check with APS Toolkit or another tool to get the info from urn:
from aps_toolkit import Auth
from aps_toolkit import PropDbReaderRevit
auth = Auth()
token = auth.auth2leg()
urn = "<Derivative URN>"
prop_reader = PropDbReaderRevit(urn, token)
df = prop_reader.get_data_by_category("Ducts")
df.save_to_excel("result.xlsx")How to get URN from Bucket Uploaded โ
With Bucket, you need to do three step to get the urn:
- Upload file to bucket
using Autodesk.Forge;
using Autodesk.Forge.Core;
using Autodesk.Forge.DesignAutomation;
using Autodesk.Forge.Model;
using NUnit.Framework;
[TestCase("chuong_1212121", "./Resources/rac_basic_sample_project.rvt")]
public async Task UploadFileToBucket(string bucketKey, string filePath)
{
// Create a bucket if it doesn't exist
BucketsApi bucketsApi = new BucketsApi();
bucketsApi.Configuration.AccessToken = Token.AccessToken;
var bucketPayload = new PostBucketsPayload(bucketKey, null, PostBucketsPayload.PolicyKeyEnum.Transient);
// check if bucket exists
dynamic bucketExists = await bucketsApi.GetBucketDetailsAsync(bucketKey);
if (bucketExists == null)
{
dynamic bucket = await bucketsApi.CreateBucketAsync(bucketPayload, "US");
}
else
{
Console.WriteLine("Bucket already exists");
}
// Upload file to the bucket
ObjectsApi objectsApi = new ObjectsApi();
objectsApi.Configuration.AccessToken = Token.AccessToken;
using (StreamReader streamReader = new StreamReader(filePath))
{
string fileFullPath = Path.GetFullPath(filePath);
if (!File.Exists(fileFullPath))
{
throw new Exception("The file does not exist");
}
string name = Path.GetFileName(filePath);
streamReader.BaseStream.Seek(0, SeekOrigin.Begin);
dynamic upload = await objectsApi.UploadObjectAsync(bucketKey,name ,
(int)streamReader.BaseStream.Length, streamReader.BaseStream, "application/octet-stream");
Console.WriteLine("File uploaded to bucket");
}
}- Translate file to derivative
using Autodesk.Forge;
using Autodesk.Forge.Core;
using Autodesk.Forge.DesignAutomation;
using Autodesk.Forge.Model;
using NUnit.Framework;
[TestCase("urn:adsk.objects:os.object:chuong_1212121/rac_basic_sample_project.rvt")]
public async Task CreateTranslationJob(string objectId)
{
DerivativesApi derivativesApi = new DerivativesApi();
derivativesApi.Configuration.AccessToken = Token.AccessToken;
// get translation job
objectId = Base64Encode(objectId);
JobPayload job = new JobPayload(
new JobPayloadInput(objectId),
new JobPayloadOutput(
new List<JobPayloadItem>
{
new JobPayloadItem(JobPayloadItem.TypeEnum.Svf, new List<JobPayloadItem.ViewsEnum> { JobPayloadItem.ViewsEnum._3d })
}));
dynamic jobResult = await derivativesApi.TranslateAsync(job);
Console.WriteLine("Translation job created");
}
private static string Base64Encode(string str)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(str);
return System.Convert.ToBase64String(bytes).TrimEnd('=');
}- Get the urn from the derivative
using Autodesk.Forge;
using Autodesk.Forge.Core;
using Autodesk.Forge.DesignAutomation;
using Autodesk.Forge.Model;
using NUnit.Framework;
[TestCase("urn:adsk.objects:os.object:chuong_1212121/rac_basic_sample_project.rvt")]
public async Task GetManifest(string objectId)
{
DerivativesApi derivativesApi = new DerivativesApi();
derivativesApi.Configuration.AccessToken = Token.AccessToken;
objectId = "urn:adsk.wipprod:fs.file:vf.Od8txDbKSSelToVg1oc1VA?version=33";
objectId = Base64Encode(objectId);
dynamic manifest = await derivativesApi.GetManifestAsync(objectId);
string urn = manifest.urn;
Console.WriteLine(manifest);
}Let's look to the json output from manifest to see more details.
{
"type": "manifest",
"hasThumbnail": "true",
"status": "success",
"progress": "complete",
"region": "US",
"urn": "dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLk9kOHR4RGJLU1NlbFRvVmcxb2MxVkE_dmVyc2lvbj0zMw",
"version": "1.0",
"derivatives": [
{
"name": "MyHouse.rvt",
"hasThumbnail": "true",
"status": "success",
"progress": "complete",
"properties": {
"Document Information": {
"RVTVersion": "2024",
"Project Name": "Project Name",
"Project Number": "Project Number",
"Author": "",
"Project Address": "Enter address here",
"Project Issue Date": "Issue Date",
...How to snoop model name ? โ
let's use this command from console :
NOP_VIEWER.model.getData().loadOptions.bubbleNode.getRootNode().children[0].name()Convert URN To Meaning โ
With the urn, you can convert to meaning with this command from console:
static string Base64Decode(string base64EncodedData)
{
// Validate Base64 string
if (string.IsNullOrEmpty(base64EncodedData))
throw new ArgumentNullException(nameof(base64EncodedData), "Input cannot be null or empty.");
// Use regex to check if the string is a valid Base64
if (!Regex.IsMatch(base64EncodedData, @"^[a-zA-Z0-9\+/]*={0,2}$"))
throw new FormatException("Input is not a valid Base64 string.");
// Pad the Base64 string to ensure it is a valid length
base64EncodedData = base64EncodedData.PadRight(base64EncodedData.Length + (4 - base64EncodedData.Length % 4) % 4, '=');
// Decode the Base64 string
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}Note: In the case you have character "_" in urn, you need to replace it with "/"
var result = Base64Decode("dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLk9kOHR4RGJLU1NlbFRvVmcxb2MxVkE/dmVyc2lvbj0zMw");
Console.WriteLine(result);
string afterBase = Base64Encode(result);
Console.WriteLine(afterBase);The output meaning will be : urn:adsk.wipprod:fs.file:vf.Od8txDbKSSelToVg1oc1VA?version=33
Open Source โ
This extension is open source and available on GitHub. I'm so lazy to write more feature, but if you have any idea, please feel free to contribute.
Change Log โ
1.1.0 - Initial release, ACC URL Details
1.2.0 - Add support BIM360-ACC URL Details