Platform Reference

Field Types Reference

Every field type in the FlowOS data model — how values are stored, how to filter by them, and how to write them in workflow expressions.

Scalar Types

stringString

Plain UTF-8 text. Used for names, descriptions, codes, and free-form fields. No length limit unless documented.

Examples: name, title, code, description, resolution

Query: filter[title][ilike]=%outage% — case-insensitive substring match

numberNumber

64-bit floating point. Used for counts, durations, costs, scores, and thresholds.

Examples: durationMinutes, score, costAmount, effortHours

Query: filter[durationMinutes][lte]=60 — numeric comparison

booleanBoolean

true or false. Used for flags and toggles.

Examples: isActive, isAutomated, isLocked, mfa_enabled

Query: filter[isActive]=true

dateDate / Timestamp

ISO 8601 UTC timestamp with millisecond precision. Stored as RFC 3339. All dates are UTC — convert to user timezone in the UI.

Examples: createdAt, resolvedAt, dueAt, plannedStartAt

Query: filter[createdAt][gte]=2026-06-01T00:00:00Z

Structured Types

listList (Enum)

A field with a fixed set of allowed values defined in the table's field definition. The choices array defines valid values and their display labels.

Examples: status, priority, impact, urgency, environment, recordSource

Query: filter[status]=open OR filter[status][in]=open,investigating

jsonJSON / JSONB

Arbitrary JSON object or array. Used for configurations, payloads, metadata, and structured data that doesn't need its own table.

Examples: details, configuration, conditions, actions, metadata, payload

Query: filter[metadata.runId][exists]=true — dot-notation for nested keys

referenceReference

A foreign key pointing to a record in another table. Stored as the target record's ID string. Can be expanded to inline the full record via ?expand=fieldName.

Examples: assignedTo (→ users), groupId (→ groups), ciId (→ cmdb_cis), workflowId (→ workflows)

Query: filter[assignedTo]=usr_01... OR filter[assignedTo.email]=alice@acme.com

Reference fields with multiple: true store an array of IDs. Filter withfilter[field][in]=id1,id2 to match records where any of the IDs is in the array.

List Type — Choices Deep Dive

Every list field has a choices array. Standard choices are seeded by the system but can be extended per workspace. The value is what's stored; the label is for display only. One choice may have isDefault: true — it's used when no value is provided on create.

json
{
  "field": "status",
  "type": "list",
  "choices": [
    { "value": "new",         "label": "New",         "isDefault": true },
    { "value": "in_progress", "label": "In Progress" },
    { "value": "resolved",    "label": "Resolved" },
    { "value": "closed",      "label": "Closed" }
  ]
}

The choices table stores workspace-level overrides and additions. You can add custom choices to any list field without changing the schema.

Status Field Patterns

The status field uses one of three standard choice sets depending on the table type. These patterns repeat consistently across all 1,151 tables:

Process tables
new | in_progress | pending | on_hold | resolved | closed | cancelled

tasks, checklists, watchers, communications, risk_registers, security_incidents

Execution tables
draft | ready | running | paused | completed | failed | retired

playbooks, runbooks, approvals, plans, workflows, jobs, scripts

Event tables
new | processed | failed | ignored

timelines, escalations, alerts, notifications, event_links

Reference Type — Expanding & Dot Notation

Reference fields support three query patterns:

bash
# 1. Filter by the referenced record's ID
GET /api/v1/tables/incidents/records?filter[assignedTo]=usr_01...

# 2. Filter by a field on the referenced record (dot notation)
GET /api/v1/tables/incidents/records?filter[assignedTo.email]=alice@acme.com
GET /api/v1/tables/incidents/records?filter[groupId.name]=Platform+Team

# 3. Expand to inline the full referenced record
GET /api/v1/tables/incidents/records?expand=assignedTo,groupId

Dot notation traverses up to 3 levels deep: filter[assignedTo.department.name]=Engineering.

JSON Type — Querying Nested Data

JSON fields can be queried using dot notation for nested keys and the [exists] operator:

bash
# Check if a nested key exists
filter[metadata.runId][exists]=true

# Exact match on a nested string value
filter[configuration.region]=us-east-1

# Numeric comparison on nested value
filter[details.retryCount][gte]=3
JSON field queries do not use indexes unless a dedicated stored generated column backs them. For high-frequency JSON queries, consider promoting the field to a first-class column via DB Studio.

Readonly Fields

Fields marked readonly: true in the schema cannot be set via the API. They are auto-managed by the platform. Attempting to set them in a create or update payload returns a 422 error.

  • id — ULID assigned at create time.
  • number — Auto-incremented (e.g. INC-0042). Set by sys_counters.
  • tenantId, workspaceId — Set from API token context.
  • createdAt, updatedAt — Auto-managed timestamps.
  • createdBy, updatedBy — Set from the authenticated user.
  • hashedKey — API key hash. Never returned in responses.

Field Validation Rules

RuleBehaviour
required: trueField must be present on create. Returns 422 if missing or null.
readonly: trueField is ignored on create/update. Set by the platform.
type: listValue must match one of the defined choices. Returns 422 for unknown values.
type: referenceID must reference an existing record in the target table (same workspace). Returns 422 if not found.
multiple: trueField stores an array. POST an array of values.
isDefault: trueChoice used when field is omitted on create.