Login
Free Sign Up
Docs
/

Schema Field Types Reference

This reference documents all available field types for defining Schemas in Ligantic. Schemas define the structure of your data and are the foundation for both Experiences and Flows.

Field Type Overview

Field Type

Description

Supported Validations

string

Text values

required, minLength, maxLength, pattern, minWords, maxWords

number

Numeric values

required, min, max

boolean

True/false values

required, mustBeChecked, mustNotBeChecked

date

Date and datetime values

required

duration

Time duration values

required

recurrence

Recurring event/period rules (RRULE / RFC 5545)

required

file

File attachments

required, minLength, maxLength

content

Rich text content

required, minLength, maxLength, minBlocks, maxBlocks, minWords, maxWords

geojson

Geographic data

required

object

Nested object structure

required

array

List of values

required, minLength, maxLength

relationship

Link to other Records

required

Common Properties

All field types share these base properties:

Property

Type

Required

Default

Description

type

string

Yes

—

Field type identifier

name

string

Yes

—

Display name (min 1 character)

order

number | null

No

null

Sort order in UI

description

string | null

No

null

Help text for the field

required

boolean | null

No

null

Whether field is required

showInTable

boolean | null

No

true

Show in table views

string

Text values with optional display modes and validation.

Properties

Property

Type

Required

Default

Description

type

"string"

Yes

—

Field type identifier

display

"text" | "textarea" | "select" | "radio"

No

"text"

Input display mode

placeholder

string

No

—

Placeholder text

options

(string | { label: string, value: string })[]

No

—

Options for select display

default

string | null

No

null

Default value

validations

array

No

—

Validation rules

Display Modes

Mode

Description

Use Case

text

Single-line text input

Names, emails, short text

textarea

Multi-line text input

Descriptions, notes

select

Dropdown selection

Predefined choices

radio

Radio button group

Single choice selection

select options support two formats:

  • "Option" (label and value are both "Option")
  • { "label": "Option Label", "value": "option-value" }

Supported Validations

  • required — Field must have a value
  • minLength — Minimum character count
  • maxLength — Maximum character count
  • pattern — Regex pattern match
  • minWords — Minimum word count
  • maxWords — Maximum word count

Example

{
  "type": "string",
  "name": "Email Address",
  "display": "text",
  "placeholder": "Enter your email",
  "validations": [
    {
      "rules": [
        { "type": "required", "message": "Email is required" },
        {
          "type": "pattern",
          "value": "^[^@]+@[^@]+\\.[^@]+$",
          "message": "Invalid email format"
        }
      ]
    }
  ]
}

number

Numeric values (integers or decimals).

Properties

Property

Type

Required

Default

Description

type

"number"

Yes

—

Field type identifier

default

number | null

No

null

Default value

validations

array

No

—

Validation rules

Supported Validations

  • required — Field must have a value
  • min — Minimum value (inclusive)
  • max — Maximum value (inclusive)

Example

{
  "type": "number",
  "name": "Age",
  "default": 18,
  "validations": [
    {
      "rules": [
        { "type": "required" },
        { "type": "min", "value": 0, "message": "Age must be positive" },
        { "type": "max", "value": 150, "message": "Invalid age" }
      ]
    }
  ]
}

Expression Input

In the editor, a number field also accepts arithmetic expressions. Prefix the value with = to evaluate it on blur or Enter, for example, =2 + 3 * 4 commits 14.

  • Operators: +, -, *, /, and x/X for multiplication; parentheses for grouping; unary +/- for signs.
  • Scientific notation is supported, for example, =1.5e-2 commits 0.015.
  • A trailing % divides the number by 100. In additive contexts the percent is relative to the other operand: =100 + 10% commits 110 and =100 - 10% commits 90. In multiplicative contexts it is an absolute fraction: =100 * 10% commits 10.
  • An invalid expression reverts the field to its last committed value on blur or Enter.
  • Pressing Enter on an expression evaluates it without submitting the form; pressing Enter on a plain number commits it and submits the form normally.

boolean

True/false toggle values.

Properties

Property

Type

Required

Default

Description

type

"boolean"

Yes

—

Field type identifier

default

boolean | null

No

null

Default value

validations

array

No

—

Validation rules

Supported Validations

  • required — Field must have a value (true or false, not null)
  • mustBeChecked — Field must be true; intended for consent or terms-and-conditions style checkboxes
  • mustNotBeChecked — Field must be false; intended for flows where a checkbox must remain unchecked

Validation Semantics

  • required only enforces that the stored value is not null or undefined. Both true and false satisfy this rule.
  • mustBeChecked enforces an explicit true value. false, null, and undefined fail validation.
  • mustNotBeChecked enforces an explicit false value. true, null, and undefined fail validation.
  • Use mustBeChecked for opt-in consent flows. Leave the field without validations when the checkbox is optional.
  • Use mustNotBeChecked when the unchecked state is the valid submission requirement.

Example

{
  "type": "boolean",
  "name": "Accept Terms",
  "default": false,
  "validations": [
    {
      "rules": [{ "type": "mustBeChecked", "message": "You must accept the terms" }]
    }
  ]
}

date

Date and datetime values. Supports per-value timezone storage via IANA timezone identifiers (for example, 2024-05-15T23:20:16+10:00[Australia/Melbourne]), configurable display formats, and timezone display preferences.

When a datetime includes both an offset and an IANA timezone annotation, the annotated timezone is treated as authoritative for wall-clock scheduling. If they conflict, the value is normalised by preserving the provided wall time in the annotated timezone (the offset is adjusted to match the zone).

Properties

Property

Type

Required

Default

Description

type

"date"

Yes

—

Field type identifier

includeTime

boolean

No

false

Include time component

default

string | "now" | "today" | null

No

null

Default value or special value

defaultFormat

object

No

—

Default display format for this field (see below)

timezoneDisplay

"source" | "viewer"

No

—

Show dates in the stored (source) or viewer's timezone

validations

array

No

—

Validation rules

Date Format

The defaultFormat property controls how date values are displayed. It uses a discriminated union:

Type

Properties

Description

"preset"

preset: string

One of the built-in format presets (see below)

"custom"

pattern: string

A custom CLDR/Unicode date format pattern

Format Presets

Preset

Example Output

Notes

"short"

1/15/24

Date only

"medium"

Jan 15, 2024

Date only

"long"

January 15, 2024

Date only

"full"

Monday, January 15, 2024

Date only

"shortDateTime"

1/15/24, 2:30 PM

Requires includeTime: true

"mediumDateTime"

Jan 15, 2024, 2:30 PM

Requires includeTime: true

"longDateTime"

January 15, 2024 at 2:30:00 PM EST

With timezone name

"fullDateTime"

Monday, January 15, 2024 at 2:30:00 PM Eastern Standard Time

Full date + time + timezone

"timeOnly"

2:30 PM

Time only, requires includeTime

Custom Pattern

Uses CLDR/Unicode date format tokens. When timezoneDisplay resolves a timezone ("source" or "viewer"), custom patterns are rendered in that timezone. If no display timezone can be resolved, formatting falls back to the runtime local timezone. Common tokens:

  • yyyy — 4-digit year, MM — 2-digit month, dd — 2-digit day
  • HH — 24-hour, hh — 12-hour, mm — minutes, ss — seconds
  • a — AM/PM, EEEE — full weekday name, MMMM — full month name

Example: "dd/MM/yyyy HH:mm" → 15/01/2024 14:30

Timezone Display

When includeTime is true, the timezoneDisplay property controls which timezone is used for rendering:

  • "source" (default): Display in the timezone stored with the value
  • "viewer": Convert to the viewer's timezone (from user preferences or browser)

Format Cascade

When displaying a date value, formats are resolved in this order:

  1. Variable-level format — format specified on the variable reference in a content template
  2. Field-level defaultFormat — the Schema field's configured default format
  3. ISO fallback — raw ISO string if no format is configured

Default Values

Value

Description

"now"

Current date and time

"today"

Current date at midnight

ISO string

Specific date/time value

"today" uses the calendar date in the viewer's timezone when one is available (for example, Flows that create Records use the triggering user's timezone). Otherwise it uses the runtime's timezone, which is the browser timezone in forms. Date-only fields get a plain date such as 2026-04-08. Fields with includeTime: true get midnight in that timezone with its IANA identifier, such as 2026-04-08T00:00:00+10:00[Australia/Brisbane].

Supported Validations

  • required — Field must have a value

Example

{
  "type": "date",
  "name": "Event Date",
  "includeTime": true,
  "default": "now",
  "defaultFormat": {
    "type": "preset",
    "preset": "longDateTime"
  },
  "timezoneDisplay": "viewer",
  "validations": [
    {
      "rules": [{ "type": "required" }]
    }
  ]
}

duration

Time duration values (ISO 8601 duration format).

Properties

Property

Type

Required

Default

Description

type

"duration"

Yes

—

Field type identifier

validations

array

No

—

Validation rules

Supported Validations

  • required — Field must have a value. A zero duration (PT0S) counts as a value and satisfies required.

Duration supports no other constraints: there is no minimum, maximum, allowed-unit or precision option.

Duration Format

Durations use ISO 8601 designator format: P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S

Examples:

  • PT1H — 1 hour
  • PT30M — 30 minutes
  • P1D — 1 day
  • P1W — 1 week
  • P1Y2M3D — 1 year, 2 months, 3 days
  • -PT1H30M — negative 1 hour 30 minutes
  • PT0.5S — half a second

What is accepted:

Zero

Yes — PT0S

Negatives

Yes, with a leading - on the whole value

Weeks

Yes

Fractional values

Yes, on the smallest unit present, down to nanosecond precision

Mixed signs

No — P1M-1D is rejected

Only ISO 8601 is accepted. Values such as "90 minutes", "1:30" and a bare number are rejected. The API, CSV import, the editor, and AI-driven Flows accept exactly the same set of values.

Entry and Display

Durations are entered through a segmented control with a field per unit — years, months, weeks, days, hours, minutes, seconds — plus a sign toggle that appears when the value is negative or when you engage the control. Negative durations are legal.

Values are stored exactly as authored and are never normalised. A duration entered as PT90M stays PT90M; it is shown as 90 minutes in the control and displayed as 90m, not 1h 30m.

Stepping a field with the arrow keys carries into the next unit — 60s to 1m, 60m to 1h, 24h to 1d, 30d to 1mo, 12mo to 1y. Typing a value directly is never rewritten: type 31 into days and the value stays 31 days.

Display uses compact unit notation, largest unit first, with zero components omitted: 1y 2mo 3d 4h 5m 6s. Negatives take a leading minus (-1h 30m). A zero duration displays as 0s; an unset field displays as empty.

Sorting and Filtering

Durations sort and compare by elapsed time, not by the text of the stored value. Calendar units have no fixed length, so comparison uses a fixed conversion: one month counts as 30 days, and one day counts as 24 hours.

Consequences worth knowing:

  • P1M, P30D and PT720H all compare as equal.
  • P1Y counts as 360 days, so P1Y is less than P365D.
  • eq matches on elapsed time, so filtering a field for P1M also returns Records storing P30D.

Equality follows the same rule as ordering, so filtering for eq P1M returns the same Records as gte P1M AND lte P1M.

Records that tie on elapsed time fall back to the stored text for a stable, repeatable order.

The comparison operators eq, ne, gt, gte, lt, lte, in and nin all use this rule. isNull and isNotNull test only for the presence of a value.

Import, Export and AI

CSV export writes the bare ISO 8601 string as stored (P1M, not 1mo), and CSV import accepts the same, so a round trip is lossless. An empty cell imports as unset; an unparseable one is reported as an invalid file rather than being silently guessed at.

In generated JSON Schema — including the tool schemas handed to AI models — a duration field is emitted as a string with format: "duration" and a matching pattern.

Example

{
  "type": "duration",
  "name": "Meeting Length",
  "validations": [
    {
      "rules": [{ "type": "required" }]
    }
  ]
}

recurrence

A recurring event or period, grounded in RRULE / RFC 5545. A recurrence is a rule + a DTSTART anchor + an optional extent (duration). With no extent it is a point event ("deliver every Monday"); with an extent it is a period ("a delivery window each Monday, 09:00–12:00"). This is the RFC 5545 model: a period is an event with a DURATION.

Occurrence expansion is driven by rrule-temporal (Temporal-native), so every generated occurrence is the platform's own Temporal.ZonedDateTime and wall-clock time is preserved across DST — a rule anchored at 09:00[America/Chicago] fires at 09:00 local wall time on every occurrence, including across a spring-forward. The full RFC 5545 grammar is supported, including BYSETPOS ("the 2nd / last Friday").

Properties

Property

Type

Required

Default

Description

type

"recurrence"

Yes

—

Field type identifier

includeTime

boolean

No

false

Anchor carries a time component. When false (all-day), the anchor must be at midnight

validations

ValidationGroup[]

No

—

Validation rules

Supported Validations

  • required — Field must have a value

Value Shape

The stored value is a structured, JSON-safe object holding the RFC 5545 recurrence parts, a ZonedDateTime ISO anchor, and an optional ISO-8601 duration extent (reusing the duration representation):

Field

Type

Description

dtstart

ZonedDateTime ISO string

The anchor (required). Carries an IANA zone annotation

freq

YEARLY…SECONDLY

Recurrence frequency (required)

interval

number (≥ 1)

Every n-th freq unit

count

number (≥ 1)

Stop after n occurrences. Mutually exclusive with until (RFC 5545)

until

UTC ZonedDateTime ISO string

Stop after this instant. Must be UTC when the anchor carries a zone (RFC 5545)

byDay

string[]

Weekday tokens: MO, 2FR, -1SU (ordinal + weekday)

byMonth

number[] (1–12)

Restrict to these months

byMonthDay

number[] (−31…31, ≠ 0)

Restrict to these days of month (negative = from end)

byYearDay

number[] (−366…366, ≠ 0)

Restrict to these days of year

byWeekNo

number[] (−53…53, ≠ 0)

Restrict to these week numbers

bySetPos

number[] (−366…366, ≠ 0)

Select the n-th / last item after the other BY* filters

byHour

number[] (0–23)

Restrict to these hours

byMinute

number[] (0–59)

Restrict to these minutes

bySecond

number[] (0–60)

Restrict to these seconds (60 = leap second)

wkst

MO…SU

Week start day (default MO)

exdate

ZonedDateTime ISO string[]

Explicitly excluded occurrences

rdate

ZonedDateTime ISO string[]

Additional (one-off) occurrences

duration

ISO 8601 duration

The extent — makes the recurrence a period rather than a point

The RFC 5545 RRULE string is a derived interop form of this value, not the canonical storage. It can be produced with recurrenceToRRuleString (emits the DTSTART;TZID=… + RRULE lines) and parsed with parseRRuleString(rruleString, dtstart) — the dtstart anchor is a required parameter, and RSCALE/SKIP parts (RFC 7529) are rejected rather than silently dropped.

Example

{
  "type": "recurrence",
  "name": "Delivery Schedule",
  "includeTime": true,
  "validations": [{ "rules": [{ "type": "required" }] }]
}

A value for that field — "every Monday at 09:00 America/Chicago, for a 3-hour window, up to 10 times":

{
  "dtstart": "2024-01-01T09:00:00-06:00[America/Chicago]",
  "freq": "WEEKLY",
  "byDay": ["MO"],
  "count": 10,
  "duration": "PT3H"
}

file

File attachments with type restrictions.

Properties

Property

Type

Required

Default

Description

type

"file"

Yes

—

Field type identifier

multiple

boolean

No

false

Allow multiple files

displayMediaPreview

boolean

No

false

Show media and document previews

allowedTypes

array

Yes

—

Allowed file type categories

maxSize

number

No

5242880

Max file size in bytes (5MB default)

validations

array

No

—

Validation rules

File Type Categories

Category

Extensions

image

jpg, jpeg, png, gif, webp, svg

video

mp4, webm, mov, avi

audio

mp3, wav, ogg, m4a

document

pdf, doc, docx, txt, rtf

spreadsheet

xls, xlsx, csv

presentation

ppt, pptx

archive

zip, rar, 7z, tar, gz

code

js, ts, py, java, html, css, json

Supported Validations

  • required — At least one file must be uploaded
  • minLength — Minimum number of uploaded files when multiple: true
  • maxLength — Maximum number of uploaded files when multiple: true

Validation Semantics

  • required ensures the field is not empty.
  • minLength and maxLength count the number of uploaded files, not the length of file names.
  • Count validations are only intended for file fields with multiple: true.
  • When a maxLength validation group has an activation rule, the editor only disables additional uploads while that activation rule matches the current form values.
  • maxSize continues to apply to each file individually.
  • Once maxLength is reached, the UI normally blocks further uploads; in rare cases, more files can still be uploaded.

Preview

When displayMediaPreview is true, supported images, video, audio, DOCX, PDF, and PPTX files are rendered inline. DOCX and PDF files are displayed as paginated document previews; PPTX files are displayed as a scrollable slide preview. In Record tables, document files remain filename links instead of rendering inline; a preview button opens the full document in a modal. The same button appears in the top-left of an inline document preview. PDFs remain file links when the browser does not support canvas rendering. Other file types remain file links with a download action.

Example

{
  "type": "file",
  "name": "Profile Photo",
  "multiple": true,
  "displayMediaPreview": true,
  "allowedTypes": ["image"],
  "maxSize": 10485760,
  "validations": [
    {
      "rules": [
        { "type": "required", "message": "Please upload supporting files" },
        { "type": "minLength", "value": 2, "message": "Upload at least two files" },
        { "type": "maxLength", "value": 5, "message": "Upload no more than five files" }
      ]
    }
  ]
}

content

Rich text content, stored as an array of blocks.

Properties

Property

Type

Required

Default

Description

type

"content"

Yes

—

Field type identifier

allowedBlocks

array

No

All blocks

Allowed block types

allowedMarks

array

No

All marks

Allowed mark types

placeholder

string

No

—

Placeholder text

hoveringToolbar

boolean

No

true

Show floating toolbar on selection

validations

array

No

—

Validation rules

Block Types

Block

Description

paragraph

Standard paragraph

heading1 to heading6

Heading levels

block-quote

Block quote

numbered-list

Numbered list

bulleted-list

Bulleted list

list-item

List item

code

Code block

link

Hyperlink

image

Embedded image

video

Embedded video

audio

Embedded audio

Mark Types

Mark

Description

bold

Bold text

italic

Italic text

underline

Underlined text

deleted

Strikethrough text

code

Inline code

Writing Content Values

When creating, patching, JSON-patching, or replacing a Record through the API, a content field's value can be either the block array or a plain markdown string. A markdown string is converted to blocks, so the stored value is always a block array. This applies at any depth inside object and array fields.

Supported Validations

  • required — Content must not be empty
  • minLength — Minimum character count
  • maxLength — Maximum character count
  • minBlocks — Minimum block count
  • maxBlocks — Maximum block count
  • minWords — Minimum word count
  • maxWords — Maximum word count

Example

{
  "type": "content",
  "name": "Article Body",
  "allowedBlocks": [
    "paragraph",
    "heading1",
    "heading2",
    "block-quote",
    "numbered-list",
    "bulleted-list",
    "image"
  ],
  "allowedMarks": ["bold", "italic", "code"],
  "placeholder": "Write your article here...",
  "hoveringToolbar": true,
  "validations": [
    {
      "rules": [
        { "type": "required" },
        {
          "type": "minWords",
          "value": 100,
          "message": "Article must be at least 100 words"
        }
      ]
    }
  ]
}

geojson

Geographic data stored either as raw GeoJSON or, in map editors, as standard geography references.

Properties

Property

Type

Required

Default

Description

type

"geojson"

Yes

—

Field type identifier

geometryTypes

array

No

All types

Allowed geometry types

propertySchemaConfig

object

No

—

Schema for feature properties

display

object

No

{ display: "inputs" }

Display configuration

validations

array

No

—

Validation rules

Geometry Types

Type

Description

Point

Single coordinate

LineString

Line of coordinates

Polygon

Closed polygon

MultiPoint

Multiple points

MultiLineString

Multiple lines

MultiPolygon

Multiple polygons

Display Configurations

Inputs Display:

{
  "display": "inputs"
}

Map Display:

{
  "display": "map",
  "defaultZoom": 13,
  "defaultCenter": {
    "latitude": 40.7128,
    "longitude": -74.006
  }
}

Supported Validations

  • required — GeoJSON data must be provided

Example

{
  "type": "geojson",
  "name": "Store Location",
  "geometryTypes": ["Point"],
  "display": {
    "display": "map",
    "defaultZoom": 15,
    "defaultCenter": {
      "latitude": 51.5074,
      "longitude": -0.1278
    }
  },
  "validations": [
    {
      "rules": [{ "type": "required" }]
    }
  ]
}

When the map editor is used in geography-reference mode, values are stored as:

{
  "mode": "geography-reference",
  "rows": [
    {
      "id": "AU",
      "label": "Australia",
      "sources": [
        {
          "type": "reference",
          "geographySet": "world-country-ne-v1",
          "geographyCode": "AU"
        }
      ],
      "properties": {
        "displayCount": 10,
        "detailLevel": "Continental"
      }
    }
  ]
}

Row-level property data can be supplied either as additional top-level row keys or inside rows[].properties. Both are merged into the rendered feature's GeoJSON properties object. When using the map editor in geography-reference mode, clicking a selected geography keeps the current viewport and exposes inline label editors for the selected rows.

When shaping geography-reference values, you must choose the correct rows[].sources[].geographySet from the identifier level of your data (for example, country codes vs. subdivision codes). For detailed instructions on data shaping and a complete list of available geography sets, see Visualisation — Geography-Reference Data Shaping.

For one row to one shipped geography unit, the minimal reference-source shape is:

{
  "id": "US-CA",
  "sources": [
    {
      "type": "reference",
      "geographySet": "world-admin1-north-america-ne-v1",
      "geographyCode": "US-CA"
    }
  ]
}

object

Nested object with its own schema structure.

Properties

Property

Type

Required

Default

Description

type

"object"

Yes

—

Field type identifier

properties

object

Yes

—

Nested field definitions

validations

array

No

—

Validation rules

Supported Validations

  • required — Object must have values

Default Evaluation Order

When an object field contains conditional required rules, Ligantic evaluates property defaults in dependency order. If a property's required condition references another property, the referenced property's default is applied first, including when that dependency is introduced by nested object fields.

Example

{
  "type": "object",
  "name": "Address",
  "showInTable": false,
  "properties": {
    "street": {
      "type": "string",
      "name": "Street",
      "display": "text"
    },
    "city": {
      "type": "string",
      "name": "City",
      "display": "text"
    },
    "country": {
      "type": "string",
      "name": "Country",
      "display": "select",
      "options": ["United States", "United Kingdom", "Canada", "Australia"]
    },
    "postalCode": {
      "type": "string",
      "name": "Postal Code",
      "display": "text"
    }
  }
}

array

List of values with a defined item schema.

Properties

Property

Type

Required

Default

Description

type

"array"

Yes

—

Field type identifier

display

"form" | "table" | "checkboxes" | null

No

null

Array input display mode

items

object

Yes

—

Schema for array items

validations

array

No

—

Validation rules

Note: In Studio, selecting array display = "checkboxes" auto-configures items to a string select schema and shows the options editor at the array level (the nested item schema editor is hidden in this mode). If items is not a string schema, Studio shows a warning confirmation before applying this conversion.

Note: In Studio, array validation rule selection supports required, minLength, and maxLength, including when display = "checkboxes". Use minLength to require multiple checkbox selections.

Supported Validations

  • required — Array value must be present (can be empty)
  • minLength — Minimum item count
  • maxLength — Maximum item count

Example

{
  "type": "array",
  "name": "Tags",
  "items": {
    "type": "string",
    "name": "Tag",
    "display": "text"
  },
  "validations": [
    {
      "rules": [
        {
          "type": "minLength",
          "value": 1,
          "message": "At least one tag required"
        },
        {
          "type": "maxLength",
          "value": 10,
          "message": "Maximum 10 tags allowed"
        }
      ]
    }
  ]
}

Array of Objects Example

{
  "type": "array",
  "name": "Team Members",
  "items": {
    "type": "object",
    "name": "Member",
    "properties": {
      "name": {
        "type": "string",
        "name": "Name",
        "display": "text"
      },
      "role": {
        "type": "string",
        "name": "Role",
        "display": "select",
        "options": [
          { "label": "Developer", "value": "developer" },
          { "label": "Designer", "value": "designer" },
          { "label": "Manager", "value": "manager" }
        ]
      },
      "email": {
        "type": "string",
        "name": "Email",
        "display": "text"
      }
    }
  }
}

Validation Groups

Validations are organised into groups. Each group has:

  • condition (optional): when to apply these rules.
  • rules: the rules to apply.

Conditional Validation Example

{
  "type": "string",
  "name": "Company Name",
  "validations": [
    {
      "condition": {
        "type": "property",
        "path": ["isBusinessAccount"],
        "operator": "eq",
        "value": { "type": "literal", "value": true }
      },
      "rules": [
        {
          "type": "required",
          "message": "Company name required for business accounts"
        }
      ]
    }
  ]
}

relationship

Links a Record to one or more Records in another Schema. The field's value is the linked Record ID or IDs.

Properties

Property

Type

Required

Default

Description

type

"relationship"

Yes

—

Field type identifier

targetSchemaId

string (CUID2)

Yes

—

The Schema ID of the related Records

cardinality

"one" | "many"

Yes

—

Whether the field holds one or many references

targetLabel

string

No

Source Schema name

Label shown on the target Record's relationship side

displayTemplate

array

No

—

Template for rendering related Record labels

Behaviour

  • Cardinality "one": The field value is a single Record ID string (or null if empty).
  • Cardinality "many": The field value is an array of Record ID strings.
  • Target-side label default: The default is the source Schema name, pluralized when the target side has many-cardinality. On save, targetLabel is trimmed; omitted, empty, whitespace-only, or default-equivalent values are omitted so the cardinality-aware default applies.
  • Clearing the target-side label: Submitting an empty or default-equivalent targetLabel for a field that sends the property is an explicit revert — the relationship's label is reset to the cardinality-aware default, discarding any custom label previously set from the field or the relationship editor. A field that omits targetLabel entirely leaves the existing label untouched.
  • Target-side rendering: Record detail relationship sections and relationship table columns use the custom target-side label when present, otherwise they use the cardinality-aware default.
  • Querying: Relationship fields support property filters with operators eq, ne, in, isNull, and isNotNull.

Relationship Sides

A relationship field can be declared on either side of the relationship. The direction of the relationship does not depend on which Schema declares the field.

Saving the Schema updates only the target-side label, from targetLabel. It does not change the relationship's direction or the label and settings on the other side.

The Schema editor shows the target-side label currently in use, including changes made in the relationship editor.

Conversion Between Standalone and Field Forms

  • Converting a standalone relationship to a field adds a relationship field to the chosen Schema and keeps its direction, names, and cardinality.
  • Converting a field to a standalone relationship keeps its existing links and direction.
  • Changing a relationship field's targetSchemaId replaces the relationship with a new one. Links to the old target are not carried over.

Validations

Validation

Type

Description

required

boolean

Record must have at least one link