# Field Types

Fields (columns) are the schema of an [Object](/docs/concepts/objects) or [Table](/docs/concepts/tables). Every field has a `type` and an optional per-type `metadata` object, plus the constraints and defaults described at the bottom of this page.

Create a field with:

```bash
frontline object field create <object> --data '{"name":"<label>","type":"<type>","metadata":{ ... }}'
# Tables use the same shape:
frontline table field create <table> --data '{"name":"<label>","type":"<type>","metadata":{ ... }}'
```

Or via the Public API: `POST /public/v1/objects/{name}/fields`.

> The create/update body is **strict** — unknown top-level keys return a `400`.


## Data types & metadata

| Type | `metadata` keys | Example |
|  --- | --- | --- |
| `string` | `format`: `text` | `email` | `url` | `phone_number`; `extendedField` (bool) | `{"format":"text","extendedField":true}` |
| `number` | `format`: `integer` | `decimal` | `percent` | `currency`; `decimals`; `currency` | `{"format":"currency","currency":"USD","decimals":2}` |
| `boolean` | *(none)* | `{}` |
| `date` | `timezone` (IANA); `format`; `timeFormat` | `{"timezone":"America/New_York"}` |
| `dateOnly` | `format` | `{}` |
| `select` (`tags`) | `mode`: `singleSelect` | `multiSelect` | `{"mode":"singleSelect"}` |
| `relation` | `mode`: `single` | `multi`; `relatedTableId`; `displayColumn` | `{"mode":"multi","relatedTableId":123,"displayColumn":45}` |
| `prismaRelation` | `prismaModel`: `User` | `Conversation`; `displayField`; `mode`: `single`|`multi` | `{"prismaModel":"User","displayField":"fullName","mode":"multi"}` |
| `file` | `showPreview` (bool); `allowedFileTypes` (string[]); `maxFileSize` (bytes) | `{"showPreview":true}` |
| `avatar` | *(none)* | `{}` |
| `formula` | `expression` (object, required); `applyIf` (object, optional); `numberConfig`, `dateConfig`, `stringConfig` (objects, optional) | `{"expression":{"type":"constant","value":42}}` |


> `select` maps internally to a `tags` field, but the API still returns `"type":"select"`.
Internal-only types (`autoIncrement`, `kanbanViewOrder`) and the `composedField` string format are reserved for the platform and rejected by the API.


> **Metadata validation.** When you include a `metadata` object, it is validated with the **same rules as the in-app field editor**. If you provide `metadata`, the type's key fields are required: `string`/`number` need `format`, `date` needs `timezone` (which must be a valid IANA timezone name from the allowed list, e.g., `UTC`, `America/New_York`, `America/Chicago`, etc.), `select` needs `mode`, `relation` needs `relatedTableId` + `displayColumn` + `mode`, `prismaRelation` needs `prismaModel` + `displayField` + `mode`, and `formula` needs `expression`. To accept defaults, **omit `metadata`** rather than sending `{}` (an empty object fails for types that require a key).


## Text: normal vs long

Both use `"format":"text"`. The `extendedField` flag controls how it renders:

| Value | UI | Use for |
|  --- | --- | --- |
| `{"format":"text"}` | Single-line input | Names, short labels |
| `{"format":"text","extendedField":true}` | Multi-line area | Descriptions, notes, summaries |


```bash
# Long-text Description field
frontline object field create tickets --data '{
  "name": "Description",
  "type": "string",
  "metadata": { "format": "text", "extendedField": true }
}'
```

On read, a long-text field surfaces `"extended_field": true` in the field output.

## Select options

`select` (single- or multi-select) options **cannot be created inline** — the create call only sets `mode`. Create the field first, then add each option:

```bash
frontline object field create deals --data '{"name":"Priority","type":"select","metadata":{"mode":"singleSelect"}}'
frontline object option create deals <field-id> --data '{"name":"High","color":"Magenta"}'
```

Passing `metadata.options`, `metadata.tags`, or a top-level `options`/`tags` array on create is rejected (`400`). On **update**, replace options via the top-level `tags` array.

## relation vs prismaRelation

- **`relation`** links a record to records in **another Object** (e.g. a Deal → a Company). Requires `relatedTableId` (the target object's numeric `id`) and `displayColumn` (the field id to show as the label).
- **`prismaRelation`** links a record to a **platform entity**, most commonly an account **User** (assignee/owner). Requires `prismaModel` (`"User"` or `"Conversation"`) and `displayField` (e.g. `"fullName"`). The built-in `Users` field on People, Deals, and Tickets is a `prismaRelation`.


```bash
# Assignee field that points to platform users
frontline object field create deals --data '{
  "name": "Owner",
  "type": "prismaRelation",
  "metadata": { "prismaModel": "User", "displayField": "fullName", "mode": "single" }
}'

# Assign users on a record — array of numeric user IDs
frontline object record update deals <record-id> --data '{ "Owner": [42, 57] }'
```

On read, a `prismaRelation` field surfaces `prisma_model`, `display_field`, and `relation_mode`.

## Formulas: dynamic calculated fields

Formula fields enable spreadsheet-like calculated values for both standard CRM objects and custom tables. They automatically recalculate when dependent fields, relations, or back-relations are modified.

A formula field metadata requires an `expression` object (the AST representing the calculation) and an optional `applyIf` [QueryDSL filter](/docs/concepts/querying) (the condition under which the formula is executed).

```json
{
    "name": "Total Cost",
    "type": "formula",
    "metadata": {
        "expression": {
            "type": "operator",
            "operator": "multiply",
            "arguments": [
                { "type": "field", "field": "[Quantity]", "fallbackValue": 0 },
                { "type": "field", "field": "[Unit Price]", "fallbackValue": 0 }
            ]
        },
        "applyIf": {
            "path": "[Status]",
            "operator": "equals",
            "value": "Active"
        }
    }
}
```

### AST Node Types

Formula expressions are built recursively using the following node types:

1. **`constant`**: A static literal value.
  - `value` (string or number)
2. **`field`**: References a local field (`"[Field Name]"`) or direct relation field (`"[Relation Name].[Field Name]"`).
  - `field` (string)
  - `fallbackValue` (optional, string or number)
  - **Percent scaling**: When referencing a standard `number` column with `"format": "percent"`, its value (or `fallbackValue`) is automatically divided by `100` during evaluation so that a whole number like `10` behaves mathematically as `0.1`.
3. **`operator`**: Performs mathematical or string operations.
  - `operator`: `"add"`, `"subtract"`, `"multiply"`, `"divide"`, or `"concat"`
  - `arguments`: Array of formula nodes
4. **`aggregate`**: Aggregates records across relations or back-relations.
  - `operation`: `"count"`, `"sum"`, `"avg"`, `"min"`, `"max"`, or `"sumProduct"`
  - `field` (required field to aggregate in the target table)
  - `relation` (required for direct relations; optional for back-relations)
  - `isBackRelation` (optional, boolean)
  - `backRelationColumnId` (optional, number, the target table's relation column pointing back)
  - `arguments` (optional array of formula weight nodes for `"sumProduct"`)
  - `filter` (optional [QueryDSL filter](/docs/concepts/querying) to scope aggregated records)
5. **`padLeft`**: Pads a string calculation to a specific length.
  - `value` (formula node returning base value)
  - `length` (number)
  - `char` (single character string)
6. **`ifElse`**: Evaluates condition branches inside the expression.
  - `filter` ([QueryDSL filter](/docs/concepts/querying))
  - `then` (formula node)
  - `else` (formula node)
7. **`timeOperator`**: Performs date/time addition, subtraction, or difference operations.
  - `operator`: `"add"`, `"subtract"`, or `"diff"`
  - `arguments`: Array containing exactly two formula nodes
  - `unit`: `"second"`, `"minute"`, `"hour"`, `"day"`, `"month"`, or `"year"`


For details on the QueryDSL structure and supported operators by field type, see the **[Querying and Filtering](/docs/concepts/querying)** guide.

### Constraints and Limitations

- **Nesting Depth**: A formula AST cannot exceed a nesting depth of 3.
- **Flat Model Constraint**: A formula column cannot reference another formula column (no formula chaining).
- **Standalone Relations**: A relation column cannot be referenced as a standalone field in a formula.
- **Strict Typing**: Mathematical operators (`add`, `subtract`, `multiply`, `divide`) and mathematical aggregations (`sum`, `avg`, `sumProduct`) only accept numeric inputs.
- **Read-Only**: Formula fields are read-only (`readOnly: true`). You cannot manually write or update a formula column's value through the record update API.


### Previewing Formula Evaluation

You can preview the output of a formula on existing data before creating the field:

- **Objects**: `POST /public/v1/objects/{name}/fields/preview-formula`
- **Tables**: `POST /public/v1/tables/{name}/fields/preview-formula`


## Constraints

Set on create or update:

| Key | Meaning | Example |
|  --- | --- | --- |
| `required` | Field must have a value on every record | `"required": true` |
| `unique` | Value must be unique across all records | `"unique": true` |


```bash
frontline object field update <object> <field-id> --data '{"required": true, "unique": true}'
```

## Defaults

Pass `defaultValue` to backfill new records (and existing rows on creation):

```bash
frontline object field create deals --data '{"name":"Priority Score","type":"number","metadata":{"format":"integer"},"defaultValue":0}'
```

- For `select` fields, `defaultValue` is the option **name**.
- Date fields accept the dynamic placeholders `NOW` and `TODAY`, which resolve at record-creation time rather than being frozen at field-creation time.
- `relation`, `prismaRelation`, `file`, and `avatar` fields cannot have a default value.


## Record types (Objects only)

By default a new field is added to **all** record types of the object. Pass `record_type_id` to scope it to a single record type. See [Record Types](/docs/concepts/record-types).

## See also

- [Objects](/docs/concepts/objects) — overview and sub-resources.
- [Standard Objects](/docs/concepts/objects#standard-objects) — the predefined People / Companies / Deals / Tickets and their standard fields.
- [API Reference](/reference/openapi) — every field endpoint.