Skip to main content

Connect PowerBI or Tableau

Goal​

You'll point a business-intelligence tool — Microsoft PowerBI or Tableau — at Measured Cloud's BI feeds and pull data-quality metrics into a live, refreshable table. The feeds return flat, tabular JSON rows (one row per data asset, or one row per validation run) over the authenticated REST API, so a BI connector maps them straight into a table you can pivot, chart, and schedule a refresh on. No warehouse export, no CSV shuffling — the dashboard reads the API directly.

Two feeds cover the two natural BI fact tables:

FeedOne row per…Use it for
Asset statusdata asset"Every asset, its owner, its current health, and when it last ran." A snapshot of the estate.
Runsvalidation runThe time-series fact table — trend pass/fail over time, per asset / validation.

Prereqs​

  • A personal API key (dqk_…) or a scoped service account (dqsa_…). BI tools can't refresh Measured Cloud's short-lived login JWTs, so a long-lived key is the right token. Mint a personal key in Settings → API keys — see Create an API token. The key acts with your org role and, if scoped, your workspace access.
  • Viewer role or higher (the feeds are gated by the same can_view_results permission as the Results list). A billing-only seat can't read them.
  • The org id (and, for the workspace-scoped feeds, the workspace id) from the URL of any Measured Cloud page.

The feed URLs​

Both feeds come in a workspace-scoped form and an org-wide form. The org-wide form rolls up every workspace you can access and is super admin only (super_admin); a workspace member gets a 403 on it and should use the workspace URL instead.

Asset status — one flat row per data asset, keyed on its latest validation result:

GET /api/v1/organizations/{org_id}/workspaces/{workspace_id}/bi/asset-status
GET /api/v1/organizations/{org_id}/bi/asset-status # super admin only

Columns: asset_id, asset_name, asset_type, datasource_id, datasource_name, workspace_id, owner_email (nullable), tags (list), is_restricted (bool), status (passing / failing / never_run), last_run_time (nullable), last_result_id (nullable), rule_suite_id, rule_suite_name (deprecated: always null since rule suites were retired).

status follows "latest result wins" — a table that failed once and has passed since reads passing; a table with no run at all reads never_run.

Runs — one flat row per validation run, newest first:

GET /api/v1/organizations/{org_id}/workspaces/{workspace_id}/bi/runs
GET /api/v1/organizations/{org_id}/bi/runs # super admin only

Columns: result_id, run_time, created_at, workspace_id, team_id (nullable), asset_id/asset_name (nullable), rule_suite_id/rule_suite_name (legacy: set only on results written before rule suites were retired), checkpoint_id/checkpoint_name (legacy: set only on runs from retired checkpoints, null for validation runs), rule_group_id/rule_group_name (the validation), success (bool), status (passed / failed), batch_kind, partition_value.

Filters on the runs feed: ?since=<ISO8601> and ?until=<ISO8601> (inclusive run_time window; a naive timestamp is read as UTC). Both feeds accept ?team_id=<uuid> on the workspace form to narrow to one team.

Every response is wrapped in the standard envelope:

{ "data": [ { …row… }, { …row… } ], "next_cursor": null }

Steps​

Connect from PowerBI​

  1. In Power BI Desktop, choose Get Data → Web, then switch to Advanced.
  2. Paste the feed URL (e.g. https://<your-host>/api/v1/organizations/<org_id>/workspaces/<ws_id>/bi/asset-status).
  3. Under HTTP request header parameters, add a header with name Authorization and value Bearer dqk_… (your personal key).
  4. Click OK. PowerBI fetches the JSON; expand the data list into rows and the row object into columns. The flat columns land as a table.
  5. Load and build your visuals. Set up a Scheduled refresh in the Power BI service to keep the table current.

Connect from Tableau​

  1. In Tableau Desktop, use the Web Data Connector (or Connect → To a Server → Web Data Connector / Tableau's REST-JSON path).
  2. Point it at the feed URL and add the request header Authorization: Bearer dqk_….
  3. Map the flat columns from the data array. Tableau reads each object in data as a row.
  4. Publish the data source and schedule an extract refresh for a live dashboard.

Page through large feeds​

Pagination is opt-in:

  • Omit ?limit= and the endpoint returns the whole filtered set in one response, with next_cursor: null. A simple connector that can't chase cursors still gets everything.
  • Supply ?limit=<n> (up to 5000) to page. The response's next_cursor is an opaque token; pass it back as ?cursor=<token> (alongside the same ?limit=) to fetch the next page. Keep going until next_cursor is null. Both PowerBI and Tableau connectors support following a cursor in their paging logic.

The asset-status feed pages on the asset key and the runs feed pages newest-first, so a walk covers every row exactly once.

Verify​

  • curl -H "Authorization: Bearer dqk_…" https://<host>/api/v1/organizations/<org_id>/workspaces/<ws_id>/bi/asset-status returns {"data": [...], "next_cursor": ...} with one row per asset — each carrying an asset_name, a datasource_name, and a status of passing / failing / never_run.
  • A never-run asset shows status: "never_run" with last_run_time: null.
  • The runs feed with ?since=<last-week> returns only runs newer than that timestamp.
  • In your BI tool, refreshing the data source pulls the current numbers — a fresh validation run shows up as new runs rows and flips the asset's status on the next refresh.

Notes and limits​

  • No secrets are ever returned. The feeds name the datasource but never expose its connection config, and they never surface the raw validation-result payload — only the flat descriptive and outcome columns above.
  • Run-level columns in v1. The runs feed carries run-level pass/fail today. Per-expectation pass-rate and severity-count columns need the heavy result payload and are a planned follow-up.
  • OData / warehouse-view alternatives (a native $metadata-discoverable OData feed, or read-only SQL views straight against Postgres) are possible future paths, not shipped — the REST feeds above are the supported way to connect a BI tool today.