Fields (columns) are the schema of an Object or Table. 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:
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.
| 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 (Luxon display pattern); timeFormat (12h | 24h) | {"timezone":"America/New_York","format":"MM/dd/yyyy","timeFormat":"12h"} |
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}} |
selectmaps internally to atagsfield, but the API still returns"type":"select". Internal-only types (autoIncrement,kanbanViewOrder) and thecomposedFieldstring format are reserved for the platform and rejected by the API.
Metadata validation. When you include a
metadataobject, it is validated with the same rules as the in-app field editor. Unknown keys are rejected with suggestions (for exampletime_format→ usetimeFormat,timeZone→ usetimezone). If you providemetadata, the type's key fields are required:string/numberneedformat,dateneedstimezone(which must be a valid IANA timezone name from the allowed list, e.g.,UTC,America/New_York,America/Chicago, etc.),selectneedsmode,relationneedsrelatedTableId+displayColumn+mode,prismaRelationneedsprismaModel+displayField+mode, andformulaneedsexpression. To accept defaults, omitmetadatarather than sending{}(an empty object fails for types that require a key).Date
formatvalues. Fortype: "date",metadata.formatmust be a Luxon display pattern accepted by the UI Date Format dropdown — not legacy column-kind values likedatetime,date, ortime. Allowed:MM/dd/yyyy,dd/MM/yyyy,yyyy-MM-dd,MMM d, yyyy,d MMM yyyy. OptionaltimeFormat:12hor24h. Field list/get responses include ametadataobject (in addition to promoted top-level keys liketimezoneandtime_format) so CLI round-trips work.
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 |
# 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 (single- or multi-select) options cannot be created inline — the create call only sets mode. Create the field first, then add each option:
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.
relationlinks a record to records in another Object (e.g. a Deal → a Company). RequiresrelatedTableId(the target object's numericid) anddisplayColumn(the field id to show as the label).prismaRelationlinks a record to a platform entity, most commonly an account User (assignee/owner). RequiresprismaModel("User"or"Conversation") anddisplayField(e.g."fullName"). The built-inUsersfield on People, Deals, and Tickets is aprismaRelation.
# 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.
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 (the condition under which the formula is executed).
{
"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"
}
}
}Formula expressions are built recursively using the following node types:
constant: A static literal value.value(string or number)
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
numbercolumn with"format": "percent", its value (orfallbackValue) is automatically divided by100during evaluation so that a whole number like10behaves mathematically as0.1.
operator: Performs mathematical or string operations.operator:"add","subtract","multiply","divide", or"concat"arguments: Array of formula nodes
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 to scope aggregated records)
padLeft: Pads a string calculation to a specific length.value(formula node returning base value)length(number)char(single character string)
ifElse: Evaluates condition branches inside the expression.filter(QueryDSL filter)then(formula node)else(formula node)
timeOperator: Performs date/time addition, subtraction, or difference operations.operator:"add","subtract", or"diff"arguments: Array containing exactly two formula nodesunit:"second","minute","hour","day","month", or"year"
For details on the QueryDSL structure and supported operators by field type, see the Querying and Filtering guide.
- Nesting Depth: A formula AST cannot exceed a maximum depth of 5 (root-to-leaf node count; the root node is depth 1;
fieldandconstantleaves are depth 1). Depth countsarguments,then/else, andpadLeft.valuesub-trees; QueryDSL filters inapplyIf,ifElse.filter, oraggregate.filterdo not count. - 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.
String output formatting. When the inferred output type is string, optional stringConfig controls display: format may be text, email, url, or phone_number. Set extendedField: true together with format: "text" for long (multi-line) text, matching standard string columns.
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
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 |
frontline object field update <object> <field-id> --data '{"required": true, "unique": true}'Pass defaultValue to backfill new records (and existing rows on creation):
frontline object field create deals --data '{"name":"Priority Score","type":"number","metadata":{"format":"integer"},"defaultValue":0}'- For
selectfields,defaultValueis the option name. - Date fields accept the dynamic placeholders
NOWandTODAY, which resolve at record-creation time rather than being frozen at field-creation time. relation,prismaRelation,file, andavatarfields cannot have a default value.
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.
- Objects — overview and sub-resources.
- Standard Objects — the predefined People / Companies / Deals / Tickets and their standard fields.
- API Reference — every field endpoint.