Connecting your BI tool
The feed is standard OData v4, so most BI and ETL tools consume it without any custom code. Point the connector at the service root, give it a bearer token, and let it read $metadata to map the schema.
What every tool needs
| Setting | Value |
|---|---|
| Service root / URL | https://<your-api-host>/api/ticketinghub/odata/v1 |
| Auth | Authorization: Bearer <token> header |
| Token endpoint | https://<identity-host>/connect/token |
| Grant | client_credentials, scope ticketinghub-api |
| OData version | v4 |
The service root sits on the same host as your other ADITUS APIs, so whatever network path, proxy exception or firewall rule already lets your tooling reach those covers this too.
The catch with every tool below: the token is valid for one hour, and none of these connectors know how to run a
client_credentialsflow on their own. Whatever tool you use, something has to fetch the token before the refresh runs — a pipeline step, a small script, or a secret your orchestrator rotates.
Power BI
Use Get Data → OData feed, then supply the token as a header in the advanced editor:
let
Token = "...", // fetched by your refresh pipeline, not hard-coded
Source = OData.Feed(
"https://<your-api-host>/api/ticketinghub/odata/v1",
null,
[ Headers = [ Authorization = "Bearer " & Token ],
Implementation = "2.0" ]
)
in
Source
Power Query folds $select and $filter into the request, so removing columns and filtering rows in the query editor genuinely reduces what is transferred. Do both before loading — this is where the 10 KB-per-row figure bites.
Because the status columns are plain strings rather than OData enum types, they arrive as ordinary text and every connector handles them without special configuration. Model them as dimension columns and use Column values to build the lookup tables.
Power BI's scheduled refresh cannot itself perform the token flow. Most teams land the data in a warehouse with a pipeline and point Power BI at that instead, which also gives them history.
Tableau
Tableau's OData connector expects a URL it can call directly. In practice the same token problem applies, so the common patterns are:
- Extract to a warehouse or file with a pipeline, then connect Tableau to that. Recommended.
- Use Tableau's Web Data Connector with a small script that fetches the token.
Azure Data Factory / Synapse
ADF has a first-class OData linked service. The usual shape:
- A Web activity calls the token endpoint with the four form fields.
- A Copy activity with an OData source uses
@activity('GetToken').output.access_tokenin anAuthorizationheader. - Set the sink to Parquet or your warehouse table.
ADF follows @odata.nextLink automatically, so paging needs no configuration.
Fivetran, Airbyte and similar
Use the generic OData or HTTP/REST source. Configure:
- Base URL:
https://<your-api-host>/api/ticketinghub/odata/v1 - Auth: bearer token, refreshed by the connector's OAuth2 client-credentials support if it has one
- Streams:
Tickets,TicketUsages,StatisticGroups,Surveys - Pagination: follow
@odata.nextLink - Incremental cursor:
LastRefreshedAtforTicketUsagesandSurveysonly
dbt and modelling
Once the four datasets are landed, the modelling is straightforward — and the traps are documented rather than discovered:
- Stage each dataset one-to-one, applying
SaleIsTest eq falseat extract or stage. - Build a ticket fact from
Tickets, keepingCurrencyShortnext to every measure. - Build a usage fact from
TicketUsages; remember it is scans, not people. - Treat
StatisticGroupsas a bridge table, not a dimension — the many-to-many is the whole point. - Treat
Surveysat selection grain, aggregating to answer or submission grain in a model above it. - Seed the token sets from Column values as small lookup tables, so a status you have never seen before shows up as an unmatched key rather than disappearing.
Getting the numbers right lists every rule these models need to encode.