---
title: "Get the asset graph as one run saw it"
method: GET
path: "/w/{workspace}/jobs/dbt_graph/{id}"
tags: ["job"]
---

# Get the asset graph as one run saw it

`GET /w/{workspace}/jobs/dbt_graph/{id}`

The workspace asset graph with its dbt half pinned to what a single run built. Only a dynamic descriptor (a `{{ }}` placeholder in `vars`) leaves a per-run snapshot; without one for this job the pinned version's own graph answers, so a run page may use this route unconditionally. Authorized through the job, the same gate as `run_progress` — pinning to a run is job-scoped, which is why `assets/graph` cannot do it.

## Path parameters

- `workspace` string, required
- `id` string, uuid, required

## Query parameters

- `asset_kinds` string
- `folder` string
- `dbt_script_hash` string

## Response `200`

asset graph nodes, lineage edges and trigger edges

- AssetGraph
  - `assets` object[], required
    - `kind` 's3object' | 'resource' | 'ducklake' | 'datatable' | 'volume' | 'dbt', required
    - `path` string, required
    - `fork_materialization` 'fork' | 'deferred' — Fork workspaces only — 'fork' when this ducklake asset was materialized in the fork itself, 'deferred' when reads fall back to the parent workspace's current table via a defer view. Omitted otherwise.
    - `dbt` DbtAssetProvenance — What dbt says about the model, snapshot, seed or source that produces (or, for a source, is read at) this relation. A dbt project is one runnable node with many model assets, so per-model metadata belongs here rather than on the script.
      - `unique_id` string, required — dbt's own node id, e.g. `model.jaffle_shop.customers`.
      - `resource_type` 'model' | 'snapshot' | 'seed' | 'source', required
      - `materialized` string — dbt's own word (`table`, `view`, `incremental`, `snapshot`).
      - `materialize_strategy` string — The Windmill write strategy it maps to, absent for `view` and `ephemeral`, which have none.
      - `tags` string[]
      - `description` string
      - `data_tests` object[]
        - `kind` string, required — One of the four generic tests, or a package test's namespaced name (`dbt_utils.accepted_range`).
        - `column` string
        - `args` object
        - `severity` string — Lowercased. dbt's severity decides whether a failure fails the run.
      - `columns` object — Declared column metadata (name -> description). NOT column lineage — `manifest.json` carries none.
      - `freshness` object — A source's declared freshness policy, for the staleness chip.
      - `raw_code` string — The model's SQL as written, at the deploy this graph belongs to. Omitted when the caller cannot read the script.
      - `original_file_path` string — Its path inside the dbt project, e.g. `models/staging/stg_orders.sql`.
  - `runnables` object[], required
    - `path` string, required
    - `usage_kind` 'script' | 'flow' | 'job', required
    - `in_pipeline` boolean — True iff the script is a pipeline member (deployed with `// pipeline`). Omitted when false.
    - `macros` object[] — Macros this script provides to the workspace registry (deployed `// macros` library). Omitted when empty.
      - `name` string, required
      - `params` string, required — verbatim parameter list
      - `is_table` boolean, required
    - `dbt` object — Set on a `dbt` script, which owns a whole project rather than a single output. Omitted otherwise.
      - `model_count` integer, required
  - `edges` object[], required
    - `runnable_path` string, required
    - `runnable_kind` 'script' | 'flow' | 'job', required
    - `asset_kind` 's3object' | 'resource' | 'ducklake' | 'datatable' | 'volume' | 'dbt', required
    - `asset_path` string, required
    - `access_type` 'r' | 'w' | 'rw', nullable
  - `triggers` union[], required
    - union
      - object — Asset trigger edge (`// on <asset>`)
        - `trigger_kind` 'asset', required
        - `asset_kind` 's3object' | 'resource' | 'ducklake' | 'datatable' | 'volume' | 'dbt', required
        - `asset_path` string, required
        - `runnable_kind` 'script' | 'flow' | 'job', required
        - `runnable_path` string, required
      - object — Native trigger edge (schedule, email, kafka, ...). `path` is the trigger row's path.
        - `trigger_kind` 'schedule' | 'email' | 'kafka' | 'mqtt' | 'nats' | 'postgres' | 'sqs' | 'gcp', required
        - `path` string, required
        - `runnable_kind` 'script' | 'flow' | 'job', required
        - `runnable_path` string, required
  - `macro_edges` object[] — Macro-library → consumer edges (deploy-recorded call detection plus `// use`). Omitted when empty.
    - `lib_path` string, required
    - `consumer_path` string, required
    - `macro_names` string[], required
    - `via_use` boolean, required
  - `test_edges` object[] — Ordering-only "must-run-after" edges — a `// data_test relationships` (or custom test reading a pipeline asset) requires the referenced asset's producer to run before the tested script. Not a data-consumption edge; fed into the cascade topo-sort so cold runs order correctly. Omitted when empty.
    - `producer_kind` 'script' | 'flow' | 'job', required
    - `producer_path` string, required
    - `runnable_kind` 'script' | 'flow' | 'job', required
    - `runnable_path` string, required
    - `asset_kind` 's3object' | 'resource' | 'ducklake' | 'datatable' | 'volume' | 'dbt', required
    - `asset_path` string, required
  - `dbt_edges` object[] — `ref()` lineage BETWEEN two dbt models, in the terms the canvas draws — the relations, not dbt's node ids. Without it every model hangs off the one dbt runnable and the project reads as a flat fan-out. Omitted when empty.
    - `from_asset_path` string, required
    - `to_asset_path` string, required
  - `dbt_snapshot_job` string, uuid — The job whose own snapshot the dbt half was resolved from, when one was asked for and found. A run page polls the graph while its job runs, because a dynamic descriptor's snapshot is written mid-run, and this is what tells it to stop. Omitted when the answer came from the version's deployed graph.
  - `dbt_graph_ingested_at` string, date-time — When the dbt half on screen was parsed, for a graph pinned to a job. What the dbt editor labels its provenance with — "parsed from the editor at 14:32" against "as of last deploy" — since the two are drawn identically and the ambiguity would otherwise just move into the editor. Omitted for the unpinned workspace graph, which spans every project and so has no one time.

---

[API](https://skmtc.net/windmill/apis/windmill-api.md) · [All operations](https://skmtc.net/windmill/apis/windmill-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/windmill/windmill-api/versions/155a35b3caff/schema)
