> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.umnai.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.umnai.com/_mcp/server.

# Datasource lineage

The Datasource lineage view describes the lineage graph for a datasource.

Use it to understand which raw inputs produced a datasource, how ingestion contributed to the datasource, and which branches or increments are represented in the lineage graph.

## When to use

| Use case                     | Description                                                                    |
| ---------------------------- | ------------------------------------------------------------------------------ |
| Audit datasource provenance  | Trace the raw inputs that contributed to a datasource.                         |
| Review ingestion history     | Inspect increments, branches, run IDs, and input file counts.                  |
| Understand data volume       | Review row counts, train/test split counts, masked rows, and size information. |
| Build lineage visualisations | Use nodes and edges to render a graph of the datasource lineage.               |

## Generate the view

Generate the Datasource lineage view from a datasource.

### Request

POST [https://api.hi.umnai.com/datasources/\{datasourceId}/views](https://api.hi.umnai.com/datasources/\{datasourceId}/views)

```curl
curl -X POST https://api.hi.umnai.com/datasources/datasourceId/views \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "data": [
    {
      "view_type": "DATASOURCE_LINEAGE"
    }
  ]
}'
```

```python
import requests

url = "https://api.hi.umnai.com/datasources/:datasourceId/views"

payload = { "data": [{ "view_type": "DATASOURCE_LINEAGE" }] }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.hi.umnai.com/datasources/:datasourceId/views';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"data":[{"view_type":"DATASOURCE_LINEAGE"}]}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.hi.umnai.com/datasources/:datasourceId/views"

	payload := strings.NewReader("{\n  \"data\": [\n    {\n      \"view_type\": \"DATASOURCE_LINEAGE\"\n    }\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.hi.umnai.com/datasources/:datasourceId/views")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"data\": [\n    {\n      \"view_type\": \"DATASOURCE_LINEAGE\"\n    }\n  ]\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.hi.umnai.com/datasources/:datasourceId/views")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"data\": [\n    {\n      \"view_type\": \"DATASOURCE_LINEAGE\"\n    }\n  ]\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.hi.umnai.com/datasources/:datasourceId/views', [
  'body' => '{
  "data": [
    {
      "view_type": "DATASOURCE_LINEAGE"
    }
  ]
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.hi.umnai.com/datasources/:datasourceId/views");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"data\": [\n    {\n      \"view_type\": \"DATASOURCE_LINEAGE\"\n    }\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["data": [["view_type": "DATASOURCE_LINEAGE"]]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.hi.umnai.com/datasources/:datasourceId/views")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "data": [
    {
      "view_type": "DATASOURCE_LINEAGE",
      "view_data": {
        "nodes": {
          "columns": [
            "friendly_label",
            "node_type",
            "label",
            "increment_label",
            "increment_index",
            "branch",
            "source_branch",
            "n_rows",
            "n_rows_train",
            "n_rows_test",
            "n_rows_masked",
            "n_input_files",
            "input_files",
            "increment_size_mb",
            "increment_mask_size_mb",
            "total_increment_size_mb",
            "increment_run_id",
            "incremented_at",
            "datasource_id",
            "dataset_id",
            "datasource_name",
            "dataset_name"
          ],
          "index": [
            0,
            1,
            2
          ],
          "data": [
            [
              "6330f1c8-adult_income-root",
              "DATASOURCE",
              "6330f1c8-adult_income-root",
              "main",
              0,
              "main",
              null,
              48842,
              39137,
              9705,
              0,
              2,
              "[0 1]",
              5.7087664604,
              0,
              5.7087664604,
              "ba4e1314d6a947a2baad05bc0823b2e8",
              "2026-01-29 17:31:22",
              "72ee0da340ef4d4b83fb92d23de60db4",
              null,
              "6330f1c8-adult_income-root",
              null
            ],
            [
              "RAW::0",
              "RAW",
              "0",
              "None",
              null,
              "None",
              null,
              null,
              null,
              null,
              null,
              null,
              "None",
              null,
              null,
              null,
              "None",
              "NaT",
              "None",
              null,
              "None",
              null
            ],
            [
              "RAW::1",
              "RAW",
              "1",
              "None",
              null,
              "None",
              null,
              null,
              null,
              null,
              null,
              null,
              "None",
              null,
              null,
              null,
              "None",
              "NaT",
              "None",
              null,
              "None",
              null
            ]
          ],
          "foreign_keys": [],
          "labels": [],
          "types": [
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "NUMBER",
              "format": "INT64"
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "ANY"
            },
            {
              "data_type": "NUMBER",
              "format": "INT64"
            },
            {
              "data_type": "NUMBER",
              "format": "INT64"
            },
            {
              "data_type": "NUMBER",
              "format": "INT64"
            },
            {
              "data_type": "NUMBER",
              "format": "INT64"
            },
            {
              "data_type": "NUMBER",
              "format": "INT64"
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "NUMBER",
              "format": "FLOAT64"
            },
            {
              "data_type": "NUMBER",
              "format": "INT64"
            },
            {
              "data_type": "NUMBER",
              "format": "FLOAT64"
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "ANY"
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "ANY"
            }
          ]
        },
        "edges": {
          "columns": [
            "link_from",
            "link_to",
            "link_type",
            "source_branch",
            "target_branch"
          ],
          "index": [
            0,
            1
          ],
          "data": [
            [
              "RAW::0",
              "6330f1c8-adult_income-root",
              "INGESTION",
              "",
              "main"
            ],
            [
              "RAW::1",
              "6330f1c8-adult_income-root",
              "INGESTION",
              "",
              "main"
            ]
          ],
          "foreign_keys": [],
          "labels": [],
          "types": [
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            },
            {
              "data_type": "STRING",
              "format": null
            }
          ]
        }
      },
      "views_version": {
        "major_version": 0,
        "minor_version": 5,
        "patch_version": 0,
        "build_version": "dev76"
      },
      "output_version": {
        "major_version": 1,
        "minor_version": 0,
        "patch_version": 3,
        "build_version": null
      }
    }
  ]
}
```

The request only needs `view_type` set to `DATASOURCE_LINEAGE`.

## Output

The response follows the shared [Response structure](../response-structure) format.

The Datasource lineage view returns multiple named dataframes inside `view_data`.

| Dataframe | Description                                                                             |
| --------- | --------------------------------------------------------------------------------------- |
| `nodes`   | Lineage graph nodes, including datasource nodes and raw input nodes.                    |
| `edges`   | Lineage graph edges connecting raw inputs, datasource nodes, and lineage relationships. |

## Interpret the result

The Datasource lineage view is easiest to read as a graph: start with the nodes, then use the edges to understand how those nodes are connected.

### Start with datasource nodes

Use `nodes` to identify the datasource node and its recorded metadata.

Rows with `node_type` set to `DATASOURCE` describe datasource-level lineage information such as row counts, train/test split counts, input file counts, increment metadata, branch information, and datasource identifiers.

### Identify raw inputs

Use rows where `node_type` is `RAW` to identify raw input nodes.

Raw nodes represent upstream inputs that contributed to the datasource. Their labels can be used to connect the raw source to the datasource through the `edges` dataframe.

### Follow edges

Use `edges.link_from` and `edges.link_to` to understand the direction of lineage.

Each edge connects a source node to a target node. `link_type` describes the relationship, such as ingestion. `source_branch` and `target_branch` describe the branch relationship when branch information is available.

### Review increments and branches

Use `increment_label`, `increment_index`, `branch`, and `source_branch` to understand how datasource versions or increments relate to each other.

This is useful when a datasource has been updated over time or when you need to audit which branch produced the current datasource state.

### Check data volume

Use `n_rows`, `n_rows_train`, `n_rows_test`, `n_rows_masked`, `n_input_files`, `increment_size_mb`, `increment_mask_size_mb`, and `total_increment_size_mb` to review the size and split of each datasource increment.

These fields are useful for verifying that the datasource contains the expected amount of data before onboarding, training, or review.

## Field reference

The Datasource lineage view returns dataframes, so individual columns are not documented as standalone API schema properties.

### `nodes`

The `nodes` dataframe contains the graph nodes.

| Field                     | Description                                                    |
| ------------------------- | -------------------------------------------------------------- |
| `friendly_label`          | Human-friendly label for the lineage node.                     |
| `node_type`               | Type of lineage node, such as `DATASOURCE` or `RAW`.           |
| `label`                   | Node label used to identify the node in the lineage graph.     |
| `increment_label`         | Label for the datasource increment, when available.            |
| `increment_index`         | Index of the datasource increment, when available.             |
| `branch`                  | Branch associated with the node.                               |
| `source_branch`           | Source branch associated with the node, when available.        |
| `n_rows`                  | Number of rows associated with the node or increment.          |
| `n_rows_train`            | Number of training rows associated with the node or increment. |
| `n_rows_test`             | Number of test rows associated with the node or increment.     |
| `n_rows_masked`           | Number of masked rows associated with the node or increment.   |
| `n_input_files`           | Number of input files associated with the node or increment.   |
| `input_files`             | Input file references associated with the node or increment.   |
| `increment_size_mb`       | Size of the increment in megabytes.                            |
| `increment_mask_size_mb`  | Size of the increment mask in megabytes.                       |
| `total_increment_size_mb` | Total size of the increment in megabytes.                      |
| `increment_run_id`        | ID of the run that produced the increment.                     |
| `incremented_at`          | Timestamp when the increment was created.                      |
| `datasource_id`           | ID of the datasource associated with the node.                 |
| `dataset_id`              | ID of the dataset associated with the node, when available.    |
| `datasource_name`         | Name of the datasource associated with the node.               |
| `dataset_name`            | Name of the dataset associated with the node, when available.  |

### `edges`

The `edges` dataframe contains the graph edges.

| Field           | Description                                 |
| --------------- | ------------------------------------------- |
| `link_from`     | Source node label for the edge.             |
| `link_to`       | Target node label for the edge.             |
| `link_type`     | Type of lineage relationship.               |
| `source_branch` | Source branch for the edge, when available. |
| `target_branch` | Target branch for the edge, when available. |