---
title: "Column-level lineage of a set of dbt relations"
method: GET
path: "/w/{workspace}/assets/column_lineage"
tags: ["asset"]
---

# Column-level lineage of a set of dbt relations

`GET /w/{workspace}/assets/column_lineage`

## Request

- Base URL: `/api` (relative, and the document was published on a file host, not at the API’s origin)
- URL: `/api/w/{workspace}/assets/column_lineage`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `token`

The direct (`copy` / `mod`) column-to-column lineage the given relations' columns sit in — the connected component around them, from the engine's static analysis. Not their own edges, which would stop one hop out since a column trace walks transitively, and not a whole project's, which carries model families the selection cannot reach.
Several relations, answered as one union, because one selection reaches several: a script's output column can derive from columns of several dbt models. Unpinned, the component crosses projects — a relation one project produces is another's source — and the caller's access is decided again for every project it reaches, so a trace ends where their grants do. A pinned answer, by version here or by job on the run route, is one project's.
Its own endpoint rather than a field on the asset graph: the graph is folder-wide and polled by a run page, while this is rendered for one selection at a time. Empty for projects that did not opt into the analysis pass (`column_lineage: true`), which is the ordinary case. The indirect `scan` kind is stored but never served: it reaches every output column of its model.

## Path parameters

- `workspace` string, required

## Query parameters

- `asset_path` string[], required
- `dbt_script_hash` string

## Response `200`

the relations' column-level lineage

- DbtColumnLineage: The direct column-to-column lineage the asked-for relations' columns sit in — the connected component around them — in the terms the canvas draws: relations and columns, never dbt's node ids.
  - `edges` object[], required
    - `from_asset_path` string, required
    - `from_column` string, required
    - `to_asset_path` string, required
    - `to_column` string, required
    - `kind` string, required: dbt's own word for how the value travelled — `copy` (passthrough) or `mod` (transformed). Not an enum: the engine treats the set as open.
  - `truncated` boolean, required: The component reaches further than `edges`, which holds the part nearest the asked-for relations. A trace that stops short is otherwise indistinguishable from one that ends.

## Changes

- **2026-09-08** `f7607d1dbdc1`: 1 breaking
  - for the `query` request parameter `asset_path`, the minItems was increased from `0` to `1`
- **2026-09-08** `dcdd225a763f`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/windmill/apis/windmill-api/changes/w/:workspace/assets/column_lineage/get.md)

---

[API](https://skmtc.dev/windmill/apis/windmill-api.md) - [All operations](https://skmtc.dev/windmill/apis/windmill-api/llms.txt) - [OpenAPI document](https://skmtc.dev/windmill/apis/windmill-api/revisions/2b1f8bcee7bf?raw)
