# Data models

> Describe the shape of a business entity once — its fields, their types, and its primary key — so workflows and dashboards agree on it.

A data model is the shape of one business entity: an order, a customer, an
inventory item. It is a field list with a type per field, a description where
that helps, and one field marked as the entity's primary key.

Everything downstream leans on it. Workflows map payloads onto it, the warehouse
groups records by its primary key, and dashboard widgets offer its fields as
things to chart. It is the one place where the messy names your sources use get
turned into the names your organization uses.

Data models live under **Warehouse** in the sidebar. That page lists every model
with its **Identifier**, its record count, and when it was last written to.

## Create one

**New Data Model** offers two routes:

- **Create manually** — add fields one at a time with names, types, and
  constraints.
- **From JSON Schema** — paste a sample JSON object and Hodoflow detects fields
  automatically.

Manual creation is a three-step wizard: **Name & Description**, then
**Add Fields**, then **Review**. The **Identifier** is generated from the name
and is what URLs and API references use. Pick it carefully, because it cannot be
changed afterwards.

The import route asks for a **Sample JSON Payload** and infers one field per
top-level key, mapping JSON strings to `string`, whole numbers to `integer`,
decimals to `float`, `true`/`false` to `boolean`, and nested objects to `map`.
Anything else, including arrays and nulls, becomes `string`. Every detected
field comes back marked required, and a key called `id`, a key called `email`,
or a key ending in `_id` is guessed as the primary key. Nested keys are not
walked. **Detect Fields →** drops you into step one of the same wizard with the
results filled in, so you can correct all of that before saving.

## The schema editor

Opening a model's **Schema** page is where the real editing happens. The header
carries **Usage**, **+ Add Field**, **Edit Details**, and **Archive**.

**Edit Details** changes the name and the description. The identifier stays
fixed.

The **View** dropdown switches the section between **Fields** and
**JSON Schema** — a Draft-7 schema generated from your fields, with a **Copy**
button, which is useful when something outside Hodoflow needs to validate the
same shape.

### Field types

Six types, and the type you pick decides which constraints and aggregations are
available later.

| Type | Holds |
|---|---|
| `string` | Text. Can carry a max length and a regex pattern. |
| `integer` | Whole numbers. Can carry a min and a max. |
| `float` | Decimal numbers. Can carry a min and a max. |
| `boolean` | True or false. |
| `datetime` | A timestamp. Can be bounded to **Past only** or **Future only**. |
| `map` | A nested object, kept whole. |

### Adding fields

**+ Add Field** opens a modal with two tabs.

**Single** takes one field at a time: **Field Name** (lowercase letters,
numbers, and underscores, starting with a letter), an optional
**Description**, the **Type**, and then the type's own constraint inputs.
**Save and add another** keeps the modal open so you can work down a list.

Two checkboxes matter more than the rest:

- **Required** — records fail to be created when the field is not populated.
- **Primary Key** — identifies the business entity for grouping and aggregating
  records. Only `string` and `integer` fields are eligible, and a model can have
  only one.

**Bulk add** takes one field per line as `name:type[:required][:pk]`, so
pasting a schema someone sent you is a single operation:

```
email:string:required
age:integer
is_active:boolean
ordered_at:datetime
```

Type-only lines are accepted and default to optional. Lines starting with `#`
are ignored, and any line that fails to parse is reported with its line number
instead of silently dropped.

### Changing fields after data exists

Hodoflow protects records that already exist. Once a model has data, a field's
type can only widen — `integer` to `float` or `string`, `float` to `string`,
`boolean` to `string`, `datetime` to `string` — and the primary key designation
cannot be changed at all.

Renaming or deleting a field that a workflow data mapping references is blocked
outright, with **View usage** offered so you can go fix the mappings first.

## Who is using this model

**Usage** answers the question you have before changing anything: *every
dashboard widget and workflow that references this data model*.

The **Dashboards** tab lists widgets by **Widget**, **Type**, **Source**, and
**Used on**, marking anything that lives in the library but is not currently
placed on a dashboard.

The **Workflows** tab groups by workflow and then by version, showing how many
mappings each version has and whether it is active, published, or a draft, with
links straight into the builder.

When both tabs are empty you get **Not used yet**, and it is safe to archive.

## Archiving

**Archive** is a soft delete with a grace period. The model disappears from the
default list, and after seven days it and all of its records are permanently
deleted. Until then a banner on the page counts down, and **Restore** brings it
back.

Archiving is refused while any dashboard widget or workflow mapping still
references the model. Remove or reassign those first — **View usage** takes you
to the list.

Right after archiving, a toast offers **Undo**. Later, the **State** filter on
the **Warehouse** list switches between **Active** and **Archived** so you can
find it again.

**Delete now** on an archived model skips the wait and removes it and its
records immediately. That one cannot be undone.

## What comes next

A data model on its own holds nothing. A workflow's **Map to Data Model** step
is what fills it — see [Persisting data](/help/data-dashboards/persisting-data) for
writing the mappings, and [Dashboards](/help/data-dashboards/dashboards) for charting the
result.
