17 Jan 2025
How to Use the Tandem Data API to Retrieve Asset Data

Digital twins are transforming how users interact with the physical world by creating virtual replicas of real- world assets. The Tandem Data API enables developers to retrieve and integrate asset data into various systems. This article provides details of how to query asset information using the API, with practical tips and examples to streamline your workflows.
Reading elements
The POST scan endpoint allows you to retrieve elements from a facility and get detailed information about each element. It queries the backend database and is designed to handle large models efficiently.
When reading data for the first time, IDs are often unknown. In such cases, querying all elements is necessary. Once element IDs are obtained, they can be used to query additional data.
Key capabilities include:
-
Querying specific properties or families of properties, which affects the amount of data returned.
-
Querying elements for additional references, such as levels or spaces, which provide IDs for further queries.
Facilities typically include multiple models. The scan endpoint processes each model individually, so you’ll need to query models one at a time.
Request
The scan endpoint is a POST request which supports different inputs using a JSON payload:
keys - if we know the element IDs of specific elements we can query for those elements only. The input is an array of element IDs, for example:
{
"keys": [
"H_pwafaOSk2EClLjcqgo1ABb2Dg",
"H_pwafaOSk2EClLjcqgo1ABb16o",
"H_pwafaOSk2EClLjcqgo1ABb1_A",
"H_pwafaOSk2EClLjcqgo1ABb2Dg"
]
}
qualifiedColumns - this field can be used to specify which properties to query. The input is array of qualified property IDs – for example here we query for classification (c:v) and custom property (z:1Bw). The property IDs can be obtained from the model schema.
{
"qualifiedColumns": [
"c:v",
"z:1Bw"
]
}
Note that for common properties we already provide constants, i.e.:
export const QC = {
BoundingBox: `${ColumnFamilies.LMV}:${ColumnNames.BoundingBox}`,
CategoryId: `${ColumnFamilies.Standard}:${ColumnNames.CategoryId}`,
Classification: `${ColumnFamilies.Standard}:${ColumnNames.Classification}`,
OClassification: `${ColumnFamilies.Standard}:${ColumnNames.OClassification}`,
…
};
families - there can be cases when we need to get all properties for a certain family of properties. This field can be used to specify an array of category IDs, i.e. standard (c) and custom (z) properties:
{
"families": [
"c",
"z"
]
}
You can also use predefined constants to specify the family i.e.:
export const ColumnFamilies = {
DtProperties: 'z',
LMV: '0',
Source: 'r',
…
};
includeHistory – this field can be used in cases when we’re interested in the history of element changes. When set to true, the response will contain a complete history of changes for given properties (value + timestamp). In the example below the value of a custom property was changed multiple times:
{
"k": "mxKmiMZOTEWEZXJTDEFykAA2FyI",
"z:1Bw": [
"P006",
1736271334714,
"",
1736271273508,
"P006",
1732545471429,
"P011",
1732525926243,
"",
1732523793425,
"P006",
1718099404736
]
}
The timestamp is represented as an epoch value.
If the includeHistory field is not specified (or set to false) then latest value of the property is returned.
By default, data is wrapped into arrays:
{
"k": "H_pwafaOSk2EClLjcqgo1ABb2Dg",
"n:a": [
0
],
"n:c": [
1140
],
"n:n": [
"IFS CIRCULATOR PUMP"
]
}
skipArrays – the option can be used to simplify results by using name - value pairs rather than arrays.
{
"k": "H_pwafaOSk2EClLjcqgo1ABb2Dg",
"n:a": 0,
"n:c": 1140,
"n:n": "IFS CIRCULATOR PUMP"
}
skipArrays simplifies access in cases when we need the latest data, but it causes us to handle two slightly different schemas:
- Simplified schema when includeHistory is set to false.
- Schema with arrays when includeHistory is set to true.
Additional options are also available – those are used internally by Tandem application and will not provide too much value for external applications:
includeDeleted – controls if the response includes elements which are marked as soft deleted.
includeEmpty – controls if the response should include empty rows.
Response
The response from the endpoint is a JSON array. The first element indicates the schema of the response – currently it is always v1:
[
"v1"
…
]
The response then contains one or more objects. Typically, each objects contains a key – unique ID of an element:
[
"v1",
{
"k":"mxKmiMZOTEWEZXJTDEFykAA2FyI",
…
}
…
]
The ID is in the form of short key which is an ID without flags.
Additionally, the response object includes properties corresponding to the query attributes we used above, for example:
[
"v1",
{
"k": "mxKmiMZOTEWEZXJTDEFykAA2FyI",
"n:!v": "3d",
"n:a": 0,
"n:b": 272,
"n:c": 1140,
"n:n": "IFS CIRCULATOR PUMP",
"n:u": "D3050",
"n:z": "M.Eq",
"z:1Bw": "P006",
"z:zBw": 220,
"z:0Rw": 175,
"z:1Rw": 2300,
"z:zRw": 50
}
]
The properties are specified using qualified IDs - for example n:n is the qualified ID of Name property. Use GET schema endpoint to get the full property details such as category, display name etc.
Examples
This section provides examples of input payloads for common scenarios.
Get name and classification for all elements (without history). Note that we also include overrides (starting with !):
{
"qualifiedColumns": [ "n:n", "n:!n", "n:v", "n:!v" ],
"includeHistory": false
}
Get name and classification for all elements (with history):
{
"qualifiedColumns": [ "n:n", "n:!n", "n:v", "n:!v" ],
"includeHistory": true
}
Get name and classification for specific element (without history):
{
"keys": [
"<element-id>"
],
"qualifiedColumns": [ "n:n", "n:!n", "n:v", "n:!v" ],
"includeHistory": false
}
Get custom properties for all elements (without history):
{
"families": [ "z" ],
"includeHistory": false
}
Recommendations
- Use Keys When Possible: Querying by keys reduces the amount of data returned and improves performance.
-
Store Keys for Reuse: Keys remain globally unique throughout the model’s lifecycle.
-
Check Original and Override Values: For properties like
Name
, which may have user overrides, always check both the original and override values.{ "k": "mxKmiMZOTEWEZXJTDEFykAA2FyI", "n:n": "IFS CIRCULATOR PUMP", "n:!n": " PUMP" }
-
Query Only Required Properties: Minimize the data payload by specifying only the properties you need.
-
Consistent Formatting: When working with history data, consider disabling
skipArrays
to maintain consistent response schemas.
Wrap Up
In this article, you learned how to use the Tandem Data API to retrieve asset data. For more details, visit the official documentation. Code samples are available on GitHub:
- Read asset properties (JavaScript, Python).
- Read asset type properties (JavaScript, Python).
- Read asset tags (JavaScript, Python).
Feel free to contact us with any questions at aps.help@autodesk.com or submit inquiries on StackOverflow using the autodesk-tandem
tag.
Twitter: @liskaj71