ObjectOS
Reference

Field Types

Every field type you can declare on an object — what it stores, what options it accepts, how it surfaces in REST, Console, and the AI Builder.

Field Types

53 built-in field types, grouped by family. The full Zod schema is in packages/spec/src/data/field.zod.ts — this page is a working summary.

Core properties (every field)

PropertyTypeDefaultPurpose
namestring (snake_case)Machine identifier — REST path segment, SQL column
labelstringDisplay label in Console
typeFieldTypeSee type tables below
requiredbooleanfalseNOT NULL constraint
uniquebooleanfalseUnique index
searchablebooleanfalseIndexed for /api/v1/search
multiplebooleanfalseStore an array of values
defaultValueunknownInitial value (literal or CEL)
columnNamestring= nameOverride physical DB column
hiddenbooleanfalseHide from default Console views
readonlybooleanfalseDisable in forms
systembooleanfalseAuto-injected (id, created_at, …)
indexbooleanfalseCreate a DB index
externalIdbooleanfalseEligible for upsert via external key
inlineHelpTextstringTooltip / helper text
conditionalRequiredP predicateRequired when CEL is true
auditTrailbooleanfalseTrack every change in audit log
encryptionConfigobjectField-level encryption (see Security)
maskingRulestringPII masking pattern

Text family

TypeUse forKey options
textshort stringsmaxLength, minLength
textareamulti-linemaxLength
emailemailformat-validated; lowercased
urlURLformat-validated
phonephoneE.164
passwordsecretshashed; never returned by GET
markdownmarkdown bodyrendered in Console preview
htmlsanitised HTMLDOMPurify on write
richtextWYSIWYGConsole editor + serialised JSON

Numbers

TypeUse forKey options
numberfloatsmin, max, precision, scale
currencymoneycurrencyConfig: { precision, currencyMode: 'fixed' | 'dynamic', defaultCurrency }
percent0–100 %min, max, scale

integer and decimal aren't separate types — use number with scale: 0 for integer, precision+scale for fixed decimal.

Date / time

TypeStoresNotes
datecalendar dateno timezone
datetimeinstantUTC
timewall-clock timeno date

Logic

TypeNotes
booleanCheckbox
toggleSame as boolean, switch UI

Selection

TypeNotes
selectSingle choice — options declared inline or referenced from a picklist
multiselectMany choices, stored as an array
radioUI alias for select with radio rendering
checkboxesUI alias for multiselect with checkbox rendering

Options shape:

options: [
  { value: 'low',    label: 'Low' },
  { value: 'high',   label: 'High',   color: '#e02' },
  { value: 'urgent', label: 'Urgent', color: '#c00' }
]

Relations

TypeCardinalitySemantics
lookupmany-to-oneLoose reference; deleting the parent doesn't delete the child by default
master_detailmany-to-one, cascadingChild cannot exist without parent; permissions inherit from parent
treeself-referenceHierarchical (parent_id on the same object)

Common options:

{
  type: 'lookup',
  reference: 'account',                       // target object name
  referenceFilters: ['status:active'],        // narrow the lookup picker
  deleteBehavior: 'set_null'                  // 'set_null' | 'cascade' | 'restrict'
}

Computed

TypeWhat it doesKey option
formulaDerived value, evaluated on read or recalcexpression: F\record.qty * record.unit_price`` — see CEL
summaryRoll-up over a child relationsummaryOperations: { object, field, function } (count | sum | avg | min | max)
autonumberAuto-incrementing display numberformat (e.g. TKT-{0000}), startAt

Formula example:

{
  name: 'profit_margin',
  type: 'formula',
  expression: F`(record.revenue - record.cost) / record.revenue * 100`
}

Media

TypeUse forKey option
imageimage attachmentsfileAttachmentConfig (see below)
fileany filesame
avatarprofile picturessquare crop, sensible defaults
videovideo uploadsduration + thumbnail capture
audioaudiowaveform preview
fileAttachmentConfig: {
  maxSize: 10_000_000,                        // bytes
  allowedTypes: ['image/png','image/jpeg'],
  virusScan: true,
  storageProvider: 's3',                       // see Configure → Storage
  imageValidation: { minWidth: 200, maxWidth: 4096, generateThumbnails: ['sm','md','lg'] }
}

Structured

TypeStoresNotes
jsonarbitrary JSONStored as JSONB on Postgres
compositesub-record with named fieldsInline struct, not a separate table
repeaterarray of composite valuesOne-to-many without a child object

Enhanced UI

TypeNotes
locationlat/long + accuracy
addressstreet / city / region / postal / country
codesource-code field — language, theme, lineNumbers
colorcolorFormat: 'hex' | 'rgb' | 'rgba' | 'hsl', presetColors[]
rating1–N stars — max, icon
sliderbounded number with slider UI
signaturedrawn signature, stored as image
qrcoderenders the value as a QR — qrErrorCorrection: 'L' | 'M' | 'Q' | 'H'
barcodeEAN/UPC/Code128 — barcodeFormat
progressderived percent rendered as a bar
tagsfree-form tag array with autocomplete
vectorembedding column — vectorConfig: { dimensions, distanceMetric: 'cosine' | 'euclidean', indexed, indexType: 'hnsw' | 'ivfflat' }

System fields (auto-injected on every object)

FieldTypeNotes
idtext (ULID)primary key
created_atdatetimeUTC insert time
updated_atdatetimeUTC last-write time
created_bylookup → userwho inserted
updated_bylookup → userwho last wrote
versionintegeroptimistic-concurrency token

You don't declare these — opt out per object with ObjectSpec.systemFields: false (rarely a good idea).

How fields flow through the stack

*.object.ts (field spec)

   ├─► Postgres / MySQL / SQLite column + index + constraint
   ├─► REST: validated on POST/PATCH, exposed on GET
   ├─► Console: form widget + list column
   ├─► AI Builder: tool argument schema (so the AI knows what to ask)
   └─► Audit: change-tracked if `auditTrail: true`

See also

On this page