# Data Graph YAML Reference


This reference documents the YAML schema for defining a [Data Graph]({{< ref "/audiences/data-graph/" >}}) with the [Rudder CLI]({{< ref "/dev-tools/rudder-cli/" >}}). Use it alongside the CLI to author, version-control, and sync data graph definitions as code.

## File structure

A data graph YAML file has the following top-level structure:

```yaml
version: "rudder/v1"
kind: "data-graph"
metadata:
  name: "ecommerce-data-graph"
spec:
  id: "ecommerce-data-graph"
  account_id: "<warehouse-account-id>"
  models:
    - ...
```

### Top-level fields

| Field | Type | <div style="width: 350px;">Description</div> |
|---|---|---|
| `version` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Schema version. Use `rudder/v1`. |
| `kind` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Resource kind. Must be `data-graph`. |
| `metadata.name` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Human-readable name for the data graph |
| `spec.id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Unique ID for the data graph. Used as its stable identifier across syncs. |
| `spec.account_id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | The ID of the warehouse account the data graph reads from. |
| `spec.models` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | List | List of entity and event models that make up the data graph. See [Models](#models) for more information. |

## Models

The `spec.models` list contains all the entities and events the data graph exposes to the Audience Builder. Each model points at a warehouse table and optionally declares relationships to other models.

### Model fields

| Field | Type | <div style="width: 350px;">Description</div> |
| :--- | :--- | :--- |
| `id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Unique ID for the model within this data graph. Used as the target of relationships (see [Relationships](#relationships)). |
| `display_name` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Name shown in the Audience Builder UI (for example, `Customers`, `Sales`). |
| `type` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Either `entity` (dimension-style table) or `event` (timestamped fact table). |
| `table` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Fully qualified warehouse table name, for example, `ECOMMERCE_DB.E_MART.DIM_CUSTOMERS`. |
| `description` | String | Human-readable description of the model. Shown as a tooltip in the builder. |
| `primary_id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Column that uniquely identifies a row in the table. Required for entities, **Optional** for events. |
| `timestamp` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Column holding the event timestamp. Required when `type: event`. Used for time-window filtering in the Audience Builder. **Optional** for entities. |
| `relationships` <br/> <span style="color: #4D4DFF;font-size:12px;">Optional</span> | List | List of relationships this model has to other models. See [Relationships](#relationships) for more information. |
| `columns` <br/> <span style="color: #4D4DFF;font-size:12px;">Optional</span> | List | Per-column overrides that give warehouse columns a marketer-friendly alias (`display_name`) and an optional `description` (both surfaced in the Audience Builder), and a PII flag (`pii_mask`) that masks the column's values in the Data Graph preview. <br /><br />See [Column metadata](#column-metadata) for more information. |

### Entity vs. event

- **Entity**: A dimension-like table representing a business object (`Customers`, `Products`, `Stores`). Use `type: entity` and set `primary_id`.
- **Event**: A fact-like table where each row represents something that happened at a point in time (`Sales`, `Customer Interactions`, `Loyalty Points`). Use `type: event` and set `timestamp`. Events can be filtered with a time window in the Audience Builder.

## Relationships

Relationships connect two models so marketers can filter one model using conditions on related records (for example, "customers with 3 or more orders"). Relationships are declared on the **source** model under its `relationships` list.

### Relationship fields

| Field | Type | <div style="width: 350px;">Description</div> |
| :--- | :--- | :--- |
| `id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Unique ID for the relationship within the source model. |
| `display_name` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Name shown in the Audience Builder UI (for example, `Has Sales`, `Belongs To Account`). |
| `cardinality` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | One of `one-to-many`, `many-to-one`, or `one-to-one`. See [Current limitations]({{< ref "/audiences/data-graph/_index.md#current-limitations" >}}). |
| `target` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Reference to the target model in the form `#data-graph-model:<model-id>`. |
| `source_join_key` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Column on the source model used in the join. |
| `target_join_key` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Column on the target model used in the join. |

### Target reference format

Relationship targets use the `#data-graph-model:<model-id>` reference format, where `<model-id>` is the `id` of another model in the same data graph. For example:

```yaml
target: "#data-graph-model:sales"
```

## Column metadata

By default, the Audience Builder shows the raw warehouse column names (for example, `EMAIL_ADDRESS` or `CREATED_TS`). Use the optional `columns` block on a model to give specific columns a marketer-friendly **alias** (`display_name`) and an optional **description** — both surface when building audiences and expressions, making the underlying warehouse columns easier to read and choose. You can also flag a column as **PII** with `pii_mask: true` to mask its sample values in the Data Graph preview.

The `columns` block is **sparse** — list only the columns you want to override. Columns you don't list keep their raw warehouse names.

```yaml
models:
  - id: "customers"
    display_name: "Customers"
    type: "entity"
    table: "ECOMMERCE_DB.E_MART.DIM_CUSTOMERS"
    primary_id: "CUSTOMER_KEY"
    columns:
      - name: "EMAIL_ADDRESS"                         # Warehouse column name (must match the table).
        display_name: "Email"                         # Friendly name shown in the Audience Builder.
        description: "Primary contact email"
        pii_mask: true                                # Mask this column's values in the preview.
      - name: "CUSTOMER_KEY"
        display_name: "Customer ID"                   # Alias only — no description.
      - name: "LOYALTY_NOTES"
        description: "Free-form loyalty notes"        # Description only — no alias.
      - name: "SSN"
        pii_mask: true                                # PII only — no alias or description.
```

### Column fields

| Field | Type | <div style="width: 350px;">Description</div> |
| :--- | :--- | :--- |
| `name` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | String | Warehouse column name — must match a column in the model's `table`. |
| `display_name` <br/> <span style="color: #4D4DFF;font-size:12px;">Conditional</span> | String | Friendly name shown in the Audience Builder instead of the raw column name. Required unless `description` or `pii_mask` is set. <br /><br />Maximum 255 characters — should be case-insensitive and unique within the model. |
| `description` <br/> <span style="color: #4D4DFF;font-size:12px;">Conditional</span> | String | Human-readable note shown alongside the column in the Audience Builder. Required unless `display_name` or `pii_mask` is set. <br /><br />Maximum 255 characters. |
| `pii_mask` <br/> <span style="color: #4D4DFF;font-size:12px;">Optional</span> | Boolean | When `true`, marks the column as PII so its values are masked (`***`) in the Data Graph preview. Defaults to `false`. <br /><br />Marking a column as PII is an **enterprise-only** capability — the server rejects `pii_mask: true` on other plans. |

Note that:

- Each `columns` entry must set at least one of `display_name`, `description`, or `pii_mask`. 
- To clear one field while keeping the others, omit it from the entry. 
- To remove all metadata for a column, drop its entry — the next `apply` clears it, since the `columns` block is the source of truth.
- In the Data Graph preview, `pii_mask` columns render as `***`. Users with the **PII rETL Data Access** permission (and enterprise admins) can reveal the clear text.

## Complete example

The following example defines a small e-commerce data graph with two entities (`Customers`, `Accounts`), one event (`Sales`), and the relationships between them:

```yaml
version: "rudder/v1"
kind: "data-graph"
metadata:
  name: "ecommerce-data-graph"
spec:
  id: "ecommerce-data-graph"
  account_id: "<warehouse-account-id>" # RudderStack generates this ID when you connect a warehouse to your RudderStack workspace.
  models:
    # --- Customers (entity) ---
    - id: "customers"
      display_name: "Customers"
      type: "entity"
      table: "ECOMMERCE_DB.E_MART.DIM_CUSTOMERS"
      description: "Customers with demographics and loyalty info"
      primary_id: "CUSTOMER_KEY"
      columns:
        - name: "EMAIL_ADDRESS"
          display_name: "Email"
          description: "Primary contact email"
          pii_mask: true
        - name: "LOYALTY_TIER"
          display_name: "Loyalty Tier"
      relationships:
        - id: "customer-has-sales"
          display_name: "Has Sales"
          cardinality: "one-to-many"
          target: "#data-graph-model:sales"
          source_join_key: "CUSTOMER_KEY"
          target_join_key: "CUSTOMER_KEY"
        - id: "customer-belongs-to-account"
          display_name: "Belongs To Account"
          cardinality: "many-to-one"
          target: "#data-graph-model:accounts"
          source_join_key: "ACCOUNT_KEY"
          target_join_key: "ACCOUNT_KEY"

    # --- Accounts (entity) ---
    - id: "accounts"
      display_name: "Accounts"
      type: "entity"
      table: "ECOMMERCE_DB.E_MART.DIM_ACCOUNTS"
      description: "Customer account records for individual, household, and corporate grouping"
      primary_id: "ACCOUNT_KEY"

    # --- Sales (event) ---
    - id: "sales"
      display_name: "Sales"
      type: "event"
      table: "ECOMMERCE_DB.E_MART.FACT_SALES"
      description: "Sales transactions with amounts, status, and store/channel links"
      timestamp: "CREATED_AT"
```

## Validate the data graph

Validate your data graph YAML before syncing it to your workspace:

```bash
rudder-cli validate -l data-graph.yaml
```

This command returns validation errors and warnings if the YAML is invalid.

{{% validation-rules-explorer kind="data-graph" heading="Validation rules" %}}

## Sync to your workspace

Once validation passes, sync the data graph to your workspace:

```bash
rudder-cli apply -l data-graph.yaml
```

## See also

- [Data Graph Overview]({{< ref "/audiences/data-graph/" >}}): Introduction to data graph and how it maps warehouse data for the Audience Builder
- [Rudder CLI Overview]({{< ref "/dev-tools/rudder-cli/" >}}): Rudder CLI overview and supported resources
