This tutorial guides you through pulling time series tag data from TrendMiner into Power BI or Excel using Power Query. It follows the same structure and authentication pattern as the TrendMiner ContextHub article, replacing the context item endpoint with the tag index data endpoint.
We will cover the following steps:
- Finding the Time Series UUID of your tag.
- Setting up parameters to make the queries dynamic.
- Writing queries for API interaction.
- Configuring the output table.
Step 1: Find Your Tag's Time Series UUID
The API identifies tags by a UUID (Universally Unique Identifier), not by the tag name. You need to look this up once per tag. The easiest way is directly from the browser while using TrendMiner.
How to Find the UUID
- Open TrendMiner in your browser (Chrome recommended).
- Open the Developer Tools by pressing F12, or right-click anywhere on the page and choose Inspect.
- Click the Network tab at the top of the Developer Tools panel.
- In the TrendHub, search for your tag in the “Search tags & attributes” menu and click on it to load it.
- In the Network tab, you will see a list of requests appear. Look for a request whose name starts with the UUID format — a long string of letters and numbers separated by dashes, for example:
a36e0d19-5883-402e-ba44-fe14e54aa2b3
| 💡 | Each tag has its own UUID. Repeat this process for every tag you want to pull into Power BI. |
Step 2: Define Parameters
To make the queries dynamic, define the necessary parameters in Power Query Editor. Make sure to name them exactly as shown — the script references them by name.
How to Add Parameters
- Open Power Query Editor.
- Go to the Manage Parameters section in the toolbar.
- Click New Parameter to define a parameter.
Required Parameters
| Name | Type | Description / Example |
| ServerURL | Text | Base URL of your TrendMiner server e.g. https://myserver.trendminer.com |
| ClientID | Text | Your OAuth client ID — ask your admin to create one in ConfigHub |
| ClientSecret | Text | Your OAuth client secret from ConfigHub |
| TimeSeriesId | Text | The UUID of the tag found in Step 1 e.g. a36e0d19-5883-402e-ba44-fe14e54aa2b3 |
| StartDate | Text | Start of the time window in ISO 8601 UTC e.g. 2026-03-11T00:00:00.000Z |
| EndDate | Text | End of the time window in ISO 8601 UTC e.g. 2026-03-11T08:42:52.000Z |
| NumIntervals | Text | Number of data points to return, e.g. 150 |
| Interpolation | Text | linear or stepped |
| 💡 | Client credentials (ClientID and ClientSecret) are created by your admin in ConfigHub. For more details, consult your admin or check the TrendMiner documentation. |
Step 3: Write the Queries
Below are the queries you need to interact with the TrendMiner API. Make sure to name them exactly as shown, otherwise the script won't work.
1. Request Token
This function authenticates with TrendMiner and returns a Bearer token. It uses RelativePath so that Power Query treats the auth call and data call as the same data source — this avoids the privacy level conflict and keeps Anonymous authentication working.
() =>
let
token_body = [
grant_type = "client_credentials",
client_id = ClientID,
client_secret = ClientSecret
],
token_request = Json.Document(
Web.Contents(
ServerURL,
[
RelativePath = "/auth/realms/trendminer/protocol/openid-connect/token",
Headers = [ #"Content-Type" = "application/x-www-form-urlencoded" ],
Content = Text.ToBinary(Uri.BuildQueryString(token_body))
]
)
),
token = token_request[access_token]
in
tokenName: requestToken
| 💡 | When prompted for credentials by Power Query, always choose Anonymous. Authentication is handled by the Bearer token inside the script — Power Query's built-in auth system is not used. |
2. Get Tag Data
This function fetches index data for a given tag over a specified time window. It calls GET /compute/data/index and handles the stream+json response, which delivers data as newline-delimited JSON chunks. Each chunk contains a points array of { ts, value } objects.
(timeSeriesId as text, startDate as text, endDate as text, numIntervals as text, interpolation as text) =>
let
AuthKey = "Bearer " & requestToken(),
RawBytes = Web.Contents(
ServerURL,
[
RelativePath =
"/compute/data/index"
& "?timeSeriesId=" & Uri.EscapeDataString(timeSeriesId)
& "&interpolationType=" & Uri.EscapeDataString(interpolation)
& "&startDate=" & Uri.EscapeDataString(startDate)
& "&endDate=" & Uri.EscapeDataString(endDate)
& "&numberOfIntervals=" & numIntervals,
Headers = [
#"Accept" = "application/json",
#"Authorization" = AuthKey
]
]
),
RawText = Text.FromBinary(RawBytes, TextEncoding.Utf8),
Lines = Text.Split(RawText, "#(lf)"),
NonEmpty = List.Select(Lines, each Text.Trim(_) <> ""),
Parsed = List.Transform(NonEmpty, each Json.Document(_)),
AllPoints = List.Combine(
List.Transform(
Parsed,
each if Record.HasFields(_, "points") then _[points] else {}
)
),
PointsTable = Table.FromList(
AllPoints,
Splitter.SplitByNothing(),
{"PointRecord"}
),
Expanded = Table.ExpandRecordColumn(
PointsTable, "PointRecord",
{"ts", "value"},
{"Timestamp", "Value"}
),
Typed = Table.TransformColumnTypes(
Expanded,
{
{"Timestamp", type datetimezone},
{"Value", type number}
}
)
in
TypedName: getTagData
Step 4: Create the Output Table
This final query calls getTagData with your parameters and produces the output table. Create a new blank query, paste this in, and name it Tag_Data.
let
Source = getTagData(
TimeSeriesId,
StartDate,
EndDate,
NumIntervals,
Interpolation
)
in
SourceName: Tag_Data
You should now have a table with the following columns:
- Timestamp — the timestamp of each data point (datetimezone)
- Value — the numeric value of the tag at that timestamp
This table can be directly used in your Power BI reports or Excel workbooks for charting, filtering, and further analysis.
