Share a Lightdash dashboard outside the dbt team
Lightdash's premise is good: metrics are defined in dbt, in version control, reviewed like code, and the BI layer reads those definitions instead of inventing its own. The number in the dashboard and the number in the warehouse cannot drift, because there is only one definition.
Then somebody in finance asks for the number, and the whole apparatus stops at a login.
The options are the usual bad three: give them a seat and warehouse access for one figure, expose a share link, or paste a screenshot into an email — losing, in the process, exactly the property that made Lightdash worth adopting, since a screenshot carries no definition at all.
Publish a snapshot with its definition
Pull the results through the API:
curl -fsS -X POST "https://lightdash.internal/api/v1/projects/$PROJECT_UUID/explores/orders/runQuery" \
-H "Authorization: ApiKey $LIGHTDASH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"dimensions":["orders_month"],
"metrics":["orders_net_revenue","orders_count"],
"filters":{},"sorts":[{"fieldId":"orders_month","descending":true}],
"limit":24}' > results.json
Render the rows into a table or a chart, then publish — and attach the dbt
model's schema.yml fragment as an asset on the same report:
curl -fsS -X POST "https://commareports.com/api/v1/reports" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html report.html \
--arg t "Net revenue by month — as of $(date +%F)" \
'{title: $t, html: $html}')"
That pairing is the whole point. The reader gets:
- the number,
- the definition it came from, in the form the analytics team maintains it,
- and a date.
Which is a materially better artifact than the dashboard screenshot, because it answers the follow-up question before it is asked.
Refresh it where the models refresh
dbt build --select +orders
lightdash deploy
# then export and PATCH the snapshot
curl -fsS -X POST ".../runQuery" … > results.json
# …render report.html…
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html report.html \
--arg t "Net revenue by month — $(date +%F)" '{title: $t, html: $html}')"
Putting the snapshot in the dbt job is the correct cadence: the published number changes exactly when the model that produces it changes, and never in between. A dashboard refreshed on a timer can show a partially-rebuilt model; this cannot.
See scheduled HTML reports for the hosted version of the same loop.
Access
Reports are private by default:
- Domain-gated — anyone at
company.comor a partner's domain. No seats to provision, revoked automatically when someone leaves. - Named reviewers — for a board pack or anything narrower.
- Team — for internal readers who are not in the analytics group.
See the sharing model. None of these grant warehouse access, which is the property that makes this safe to do casually.
What review adds
- Anchored threads on a metric — "net of refunds?" answered once, on the record, next to the number. See commenting on HTML.
- Revisions, so a restated figure has a visible history and a reason.
- The dbt definition attached, so the metric is auditable by the person reading it.
Limits
- Entry HTML: 5 MB. Assets: 25 MB per file, 250 MB and 500 files total.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.