Power BI
Power BI is the most common way Ditio customers build their own dashboards — hours per project, machine use, absence, HSE follow-up. Ditio’s Power BI template signs in with your API client and loads your data through the Data Extraction API, so you can go from credentials to your first report without writing queries.
Download
Section titled “Download”Download the Power BI template (Ditio-PowerBI-mal.pbit)
- The report is in Norwegian. Fields have the same names as in Ditio’s Excel export (“Kostpris maskin”, “Stilling”, “Prosjektnr” …).
- User guide (Norwegian): setup, publishing and troubleshooting, step by step.
- Field glossary: every field (report name, API field, Excel column) and every measure.
The template contains no data, credentials or tokens. You enter them when you open it. The template version is shown on the report’s start page.
What’s in the template
Section titled “What’s in the template”| Table | Contents | Endpoint |
|---|---|---|
| Timeføringer | Hours for people, machines and vehicles, with project, work order, approval, payroll approval, cost and price | v1/time-registrations |
| Maskinregistreringer | Machine hours per machine, driver and project | v1/machine-registrations |
| Fravær | Absence per person and day, with absence type and approval | v1/absence-registrations |
| Varsler | HSE, quality, environment and machine alerts with status | v1/incident-registrations |
| Sjekklister | Checklists and forms with status, template and deviations | v1/checklist-registrations |
| Massetransport | Trips with quantity, mass type, load and dump area, cycle time and distance | v1/flow-trip-registrations |
| Varetransaksjoner | Item consumption, sales, purchases and adjustments | v1/item-registrations/web-query |
| Prosjekter, Arbeidsordrer, Ressurser, Brukere | Lookup tables to filter and group by | v1/project, v1/project/work-breakdown-structure, v1/resource, v1/user |
| Dato | Calendar with ISO weeks (Monday first), months and years | — |
The template also includes:
- 45 ready-made measures in the Målinger table, grouped into folders:
- hours (person, machine and vehicle hours; approved, payroll-approved, and unapproved for more than 14 days);
- machines;
- absence;
- HSE and quality (alerts per 100,000 person hours, checklists with deviations);
- mass transport (tonnes and m³ are never added together);
- items;
- economy (cost, sales, contribution margin, and how complete prices are);
- data status (rows and newest change per table, used by the start page).
- A relational model. Every registration table is linked to the date table, and all except item transactions to projects. Hours are also linked to work orders, resources and users; absence to users; machine registrations to resources; alerts and mass transport to work orders. A date slicer filters every table; a project slicer filters every table except item transactions.
- A start page that shows the loaded period, the last refresh, and the rows and newest change in each table, so you can see at a glance that the data is complete and fresh.
- Brukere has one row per person. People with profiles in several companies (project companies, subsidiaries) are shown with the profile from their employer company.
Prerequisites
Section titled “Prerequisites”- Power BI Desktop (Windows).
- An API client. An administrator
creates it in
Ditio Web.
- Create a dedicated client for Power BI with only the
reportingapiv1scope. Don’t reuse a client that also hasditioapiv3. - The user it acts as must be an administrator to read projects, resources and users. Because of that, everyone who can view the published report sees all loaded data, including absence and cost prices, regardless of their own access in Ditio. Limit who can view the report, or add row-level security in Power BI.
- Create a dedicated client for Power BI with only the
Set up
Section titled “Set up”When you open the template, Power BI asks for these parameters. Values in parentheses are for the test environment; use an API client created in the same environment.
| Parameter | Value |
|---|---|
| ReportingApiUrl | https://integration.ditio.no/reporting (test: https://core-api.ditio.dev/reporting) |
| IdentityUrl | https://identity.ditio.app (test: https://identity.ditio.dev). Must be the same environment as ReportingApiUrl. |
| CoreApiUrl | https://integration.ditio.no (test: https://core-api.ditio.dev/core). Only used by queries you add against the Integration API. |
| ClientId / ClientSecret | Your API client. The template requests a fresh token on every refresh, as long as AccessToken is empty. |
| AccessToken | Leave empty. If set, it overrides ClientId/ClientSecret and is never renewed, so scheduled refresh fails once it expires. |
| RangeStart / RangeEnd | The period loaded in Power BI Desktop, for example 01.04.2026 00:00 to 01.07.2026 00:00 (RangeStart included, RangeEnd not). A few months is enough if you publish: the Power BI service then loads the last 24 months itself — see How data stays current. If you only use Power BI Desktop, set the whole period you want. |
| CompanyId | Optional: only load data registered in one company of your group. Leave blank if unsure. |
When Power BI asks how to connect to the two Ditio addresses, choose Anonymous: the template signs in by itself. Set the privacy level of both to Organizational.
Every endpoint except item transactions is read page by page, so long periods work. Each table gets a fresh token, so it must finish loading within the token lifetime; if it doesn’t, the refresh fails with HTTP 401 — shorten the period.
How data stays current
Section titled “How data stays current”The registration tables (hours, machine registrations, absence, alerts, checklists, mass transport and items) use Power BI incremental refresh:
- In Power BI Desktop only RangeStart–RangeEnd is loaded.
- In the Power BI service each table is split into monthly partitions. The first refresh after publishing loads the last 24 months — it takes the longest. Every later refresh re-reads the current month and the two months before it; older months are kept as they are.
- Projects, work orders, resources and users are always reloaded in full.
Each partition is fetched with its own date range and paged with the API’s
continuationToken, so a refresh downloads about three months of
registrations instead of the whole history. Alerts and checklists are read as
“changed since the partition start” and then limited to the partition.
- Changing the policy: to keep more months or re-read more, right-click the table in Power BI Desktop → Incremental refresh, before publishing.
- Keep your .pbix file. A model with incremental refresh can’t be downloaded back from the Power BI service. Until the first refresh after a republish has finished, the report shows only the Desktop period.
- First refresh too slow? Power BI Pro stops a refresh after 2 hours. If the first 24-month load times out, lower the number of stored months before publishing.
Scheduled refresh
Section titled “Scheduled refresh”After publishing to the Power BI service, open the semantic model’s Settings → Data source credentials. For both the Reporting API and the identity server:
- Authentication method: Anonymous
- Privacy level: Organizational
Good to know
Section titled “Good to know”- Alerts per 100,000 person hours is a reporting rate, not H1/H2. Ditio doesn’t register lost-time injuries.
- Economy measures are only as complete as the prices registered in Ditio. The measure Andel timer med kost (share of hours with a cost price) shows how complete they are.
- Dates are shown as the API returns them, without time-zone conversion.
- Item transactions have no ids, only names and project numbers, and a
double quote (
") in an item name or description currently breaks parsing of that row.
Upgrading from the v1 template
Section titled “Upgrading from the v1 template”Templates before v2 (Ditio api - data source examples v1.x.pbit) read Ditio
endpoints that are not part of the public API and can change or stop working
without notice. Move your reports to the new template.
The README
maps every v1 table to its replacement. Each query is also available as a
separate file you can paste into an existing report.
Common issues
Section titled “Common issues”| Issue | Cause | Fix |
|---|---|---|
| ”Ditio-pålogging mangler” | Neither ClientId/ClientSecret nor AccessToken is filled in | Fill in ClientId and ClientSecret under Transform data → Edit parameters |
”Ditio-pålogging feilet” with invalid_client | Wrong ClientId/ClientSecret, or credentials from the other environment | Check the values and that IdentityUrl matches the environment the client was created in |
”Ditio-pålogging feilet” with invalid_scope | The API client lacks the reportingapiv1 scope | Contact [email protected] |
| ”Ditio API-kall feilet” with HTTP 401 | IdentityUrl and ReportingApiUrl point to different environments; a pasted AccessToken has expired or lacks reportingapiv1; or one table took longer than the token’s lifetime to load | Use matching production (or test) values for both URLs; clear AccessToken and use ClientId/ClientSecret; shorten the period. See Error Handling |
| ”Ditio API-kall feilet” with HTTP 403 | The API client’s user isn’t an administrator | Ask an administrator to check the API client in Ditio |
| Formula.Firewall error | Privacy levels not set, or set to Private | Set both Ditio addresses to Organizational (File → Options and settings → Data source settings) |
| “Test connection failed” in the Power BI service | The test is sent without the token | Check Skip test connection |
| A table has 0 rows on the start page | The company doesn’t use that part of Ditio, or the period is wrong | Check RangeStart/RangeEnd and CompanyId |
Related
Section titled “Related”- Power Query Examples — the template’s queries, to reuse in your own reports
- Data Extraction API — every endpoint and field
- Authentication — creating API credentials
- Export Time Data — the API-first alternative for data warehouses