Here’s a how-to from the Zello team, hope it helps!
We built a pipeline in Pipedream that consumes Omni’s APIs and automatically outputs dbt exposures for dashboards.
Step 1. Dashboards and Queries
- Call
/api/v1/documentsto list dashboards. - For each dashboard, call
/api/v1/documents/{id}/queriesto get its queries. - Store both dashboards and queries in Snowflake for further processing.
Step 2. Decide Path Based on query.table
For each query, we make a decision based on the query.table field:
- If
query.tablestarts withomni_dbt_*__→ normalize it into a dbt model ref. E.g. omni_dbt_intermediate__dim_networks → ref(‘dim_networks’) - If
query.tableis a non-dbt Omni model → usequery.modelId+query.tableto fetch the YAML from/api/unstable/models/{modelId}/yaml.- Extract only the top-level
sql:block and parse dependencies from that SQL.
- Extract only the top-level
- If
query.tableis empty → parse dependencies directly fromquery.userEditedSQL.
Step 3. Additional Dependency Signals
query.fields[]→ when a field looks liketable.column, we use the prefix to infer joins or sources.${...}macros in SQL are parsed as dbt model refs.- FROM/JOIN clauses in SQL are parsed as fully qualified relations.
Step 4. Generate Exposures
- Merge all dependencies per dashboard, dedupe, and sort alphabetically.
- For each dashboard we output a dbt exposure YAML with:
- Name, label, URL (
https://zello.omniapp.co/dashboards/{id}) - Owner (from dashboard metadata. Would be nice to have an email there, but did not want to make users call here to API)
- Maturity + refresh cadence tag (derived from
views) - Deterministic
depends_onlist from the rules above
- Name, label, URL (
Result
Every Omni dashboard now has a dbt exposure, with dependencies coming directly from Omni’s queries API ( query.table , query.fields , query.userEditedSQL , query.modelId ) and, when needed, the Omni model YAML API.