Skip to content

Form Field Types Reference

Complete reference for all supported form field types in ApprovalML workflows.


TypeCategoryDescription
textTextSingle-line text input
textareaTextMulti-line text input
emailTextEmail with format validation
richtextTextWYSIWYG rich text editor
markdownTextMarkdown editor with live preview
numberNumericInteger or decimal input
currencyNumericMoney amount with symbol
dateDate & TimeCalendar date picker (date only)
datetimeDate & TimeDate and time picker
dropdown / selectSelectionSingle-choice dropdown
multiselectSelectionMulti-choice dropdown
radioSelectionRadio buttons or button group
checkboxSelectionBoolean toggle
autocompleteSelectionSearch-as-you-type with data source
user_lookupSelectionInternal employee search-as-you-type
file_upload / fileFile & MediaFile or image attachment (use accept: ".pdf" for PDF-only)
imageFile & MediaDisplay-only image — Media Gallery asset, company logo, or direct URL
signatureFile & MediaDigital signature capture
line_itemsAdvancedRepeating row table
autonumberAdvancedSequential auto-generated number
jsonAdvancedStructured JSON data with tree view
hiddenAdvancedNon-displayed metadata field

Single-line text input for short responses.

- name: employee_name
type: text
label: "Full Name"
required: true
placeholder: "Enter your full name"
min_length: 2
max_length: 100

Common Uses: Names, titles, short descriptions, IDs, reference codes


Multi-line text input for longer responses.

- name: description
type: textarea
label: "Description"
required: true
rows: 4
placeholder: "Enter detailed description..."
min_length: 10
max_length: 1000

Common Uses: Descriptions, comments, justifications, policy notes


Email address input with built-in format validation.

- name: contact_email
type: email
label: "Email Address"
required: true
placeholder: "user@company.com"

Validation: Automatically enforces user@domain.tld format.

Common Uses: Contact emails, approver addresses, notification recipients


WYSIWYG rich text editor with HTML formatting and image embedding.

- name: detailed_description
type: richtext
label: "Detailed Description"
required: false
placeholder: "Enter formatted text with images..."

Features:

  • Bold, italic, underline, heading formatting
  • Bullet lists and numbered lists
  • Hyperlinks
  • Image upload (auto-converted to base64)
  • Stored as HTML

Storage: Saved to S3 at companies/{company_id}/workflows/{workflow_id}/instances/{instance_id}/richtext/{field_name}.html

Common Uses: Policy documents, detailed proposals, formatted instructions


Markdown editor with toolbar and live preview. Values are stored as plain Markdown text.

- name: notes
type: markdown
label: "Notes"
required: false
placeholder: "Enter notes using Markdown..."
min_length: 10
max_length: 5000

Features:

  • Bold, italic, headings
  • Bullet and numbered lists
  • Hyperlinks
  • Thematic breaks
  • Live side-by-side preview
  • Stored as plain Markdown in request_data

Validation: Supports required, min_length, and max_length.

Common Uses: Structured notes, documentation, comments, changelog entries


Numeric input accepting integers or decimals.

- name: quantity
type: number
label: "Quantity"
required: true
placeholder: "0"
min_value: 1
max_value: 1000

Properties:

PropertyDescription
min_valueMinimum allowed value
max_valueMaximum allowed value

Common Uses: Quantities, counts, percentages, ratings, days


Money amount with automatic currency symbol formatting.

- name: total_amount
type: currency
label: "Total Amount"
required: true
currency: "USD"
min_value: 0.01
max_value: 1000000

Properties:

PropertyDescriptionDefault
currencyISO 4217 currency code"USD"
min_valueMinimum amount
max_valueMaximum amount
readonlyPrevent editing (use with formula)false
calculatedMarks field as computedfalse
formulaExpression to calculate value

Supported currencies: USD, EUR, GBP, JPY, SGD, IDR, MYR, AUD, and all ISO 4217 codes.

Common Uses: Purchase amounts, budgets, salaries, invoice totals, line-item subtotals


Calendar date picker — captures date only, no time component. Stored as YYYY-MM-DD.

- name: start_date
type: date
label: "Start Date"
required: true
min_date: "2024-01-01"
max_date: "2025-12-31"

Properties:

PropertyDescription
min_dateEarliest selectable date (YYYY-MM-DD)
max_dateLatest selectable date (YYYY-MM-DD)

Common Uses: Deadlines, start/end dates, travel dates, expiry dates


Date and time picker — captures both date and time in local time. Stored as YYYY-MM-DDTHH:mm.

- name: meeting_datetime
type: datetime
label: "Meeting Date & Time"
required: true

Properties:

PropertyDescription
min_dateEarliest selectable datetime (YYYY-MM-DDTHH:mm)
max_dateLatest selectable datetime (YYYY-MM-DDTHH:mm)

Display: Shown using the company date format for the date portion followed by HH:mm — e.g. 15/05/2026 14:00.

Common Uses: Meeting schedules, appointment booking, event timestamps, payment cut-off times

When to choose date vs datetime:

  • Use date when only the calendar day matters (payment date, deadline, travel date)
  • Use datetime when the time of day is relevant (meeting time, submission cut-off, event schedule)

Single-choice dropdown with predefined or dynamic options. dropdown and select are aliases — use whichever reads more naturally.

- name: department
type: dropdown
label: "Department"
required: true
options:
- label: "Engineering"
value: "engineering"
- label: "Sales"
value: "sales"
- label: "Marketing"
value: "marketing"

Common Uses: Departments, categories, statuses, priorities, countries


Multi-choice dropdown — user can select one or more options.

- name: required_skills
type: multiselect
label: "Required Skills"
required: false
options:
- label: "JavaScript"
value: "javascript"
- label: "Python"
value: "python"
- label: "Java"
value: "java"

Common Uses: Skills, tags, cost centers, systems affected, roles


Radio button group for single selection. Supports a compact button-style layout.

- name: urgency
type: radio
label: "Urgency Level"
required: true
display_as: "buttons" # Optional: renders as styled button group
options:
- label: "Low"
value: "low"
- label: "Medium"
value: "medium"
- label: "High"
value: "high"
- label: "Critical"
value: "critical"

Properties:

PropertyDescription
display_as"buttons" for button-group style; omit for classic radio circles

Common Uses: Priority levels, approval types, yes/no, rating scales


Single boolean toggle for true/false responses.

- name: agree_to_terms
type: checkbox
label: "I agree to the terms and conditions"
required: true

Common Uses: Agreements, acknowledgements, opt-ins, feature flags


Search-as-you-type field backed by a dynamic Data Processor. Requires a configured Data Processor — static options are not supported.

- name: employee
type: autocomplete
label: "Select Employee"
required: true
options:
data_processor:
source_id: "src_employees"
value_field: "id"
label_field: "name"
display: "{name} - {department}"
search:
min_length: 2 # Start searching after 2 characters
debounce_ms: 300 # Delay before querying (default: 300ms)

Properties:

PropertyDescription
options.data_processor.source_idRegistered Data Processor ID
options.data_processor.value_fieldField used as the stored value
options.data_processor.label_fieldField shown in the dropdown
options.data_processor.displayTemplate for display text (e.g. "{name} - {dept}")
search.min_lengthCharacters required before search fires (default: 2)
search.debounce_msMilliseconds to wait between keystrokes (default: 300)

Common Uses: Employee picker, product search, customer lookup, location select


Internal employee search-as-you-type field. Unlike autocomplete, this field uses a dedicated company-scoped people directory — no Data Processor configuration required. The stored value is a rich snapshot that remains human-readable in PDFs and approval emails without extra database queries.

- name: assessment_lead
type: user_lookup
label: Assessment Lead
required: true
options:
filter:
employee_type: [internal] # internal | external | contractor
department: ["Quality Assurance"] # optional — OR logic between values
company_roles: [qa_manager, qa_supervisor] # optional — employee must hold at least one
hierarchy:
scope: all # all | same_department | subordinates | direct_reports
display: "{name} — {role}, {department}"
search:
min_length: 2
debounce_ms: 300
max_results: 20

Stored value — always an object snapshot:

{
"id": 42,
"name": "Alice Tan",
"email": "alice@company.com",
"role": "QA Manager",
"department": "Quality Assurance",
"employee_type": "internal"
}

Properties:

PropertyRequiredDescriptionDefault
options.filter.employee_type❌ NoList of employment types to include: internal, external, contractorAll types
options.filter.department❌ NoRestrict results to employees in these departments (OR logic)All departments
options.filter.company_roles❌ NoRestrict results to employees holding at least one of these roles (OR logic)All roles
options.hierarchy.scope❌ NoLimit search to a reporting scope: all, same_department, subordinates, direct_reportsall
display❌ NoTemplate for the text shown inside the field after selection (e.g. "{name} — {role}, {department}")"{name}"
search.min_length❌ NoCharacters required before the search fires2
search.debounce_ms❌ NoMilliseconds to wait between keystrokes before querying300
search.max_results❌ NoMaximum number of results shown in the dropdown20

Filter logic:

  • employee_type — applied as an IN clause; list all types you want included.
  • department — OR logic between values; employee must be in at least one.
  • company_roles — OR logic; employee must hold at least one of the listed roles.
  • All three filters are AND-combined when specified together.

Hierarchy scopes:

ScopeSearches
allAll employees matching the filter (default)
same_departmentOnly employees in the requestor’s department
subordinatesAll direct and indirect reports of the requestor
direct_reportsOnly the requestor’s immediate direct reports

Security: On submission, the server re-fetches the selected employee using id + company_id and replaces the client-supplied snapshot with the canonical database record. Submitting an employee ID from a different company is rejected with HTTP 400. The search endpoint is also company-scoped via the session token.

When to use user_lookup vs autocomplete:

  • Use user_lookup for picking internal or external employees — it works without any Data Processor setup and enforces company isolation automatically.
  • Use autocomplete for non-employee entities (products, customers, locations) that come from an external data source via a Data Processor.

Common Uses: Assigning assessment leads, selecting requestors, choosing reviewers from a specific department, peer nomination, manager assignment


File attachment field. file_upload and file are aliases.

- name: receipt
type: file_upload
label: "Upload Receipt"
required: true
accept: ".pdf,.jpg,.png"
multiple: false
max_file_size: "5MB"

PDF-only upload:

- name: contract_document
type: file_upload
label: "Contract PDF"
required: true
accept: ".pdf,application/pdf"
max_file_size: "10MB"
help_text: "Upload the signed contract in PDF format"

Mobile camera capture:

- name: site_photo
type: file_upload
label: "Take a Photo"
accept: "image/*"
capture: "environment" # "environment" = rear camera, "user" = front camera

Properties:

PropertyDescription
acceptComma-separated MIME types or extensions (e.g. ".pdf,.docx")
multipleAllow more than one file (true/false)
captureForce camera on mobile: "environment" or "user"
max_file_sizeHuman-readable size limit (e.g. "5MB", "10MB")

Common Uses: Receipts, invoices, contracts, photos, supporting documents


Digital signature capture field. Pulls the user’s stored signature from their profile.

- name: requestor_signature
type: signature
label: "Your Signature"
required: true
help_text: "Sign to confirm your submission"

Test mode: Automatically uses /images/samplesignature.png — no real signatures needed during development or demos.

Production: Captures the logged-in user’s saved signature (text, drawn, or uploaded). Stored securely with the instance record.

Common Uses: Contract execution, policy acknowledgement, expense certification, approval sign-off


Display-only image field for logos, header images, and visual branding. Images can be sourced from the Media Gallery (System Settings → Media Gallery), a direct URL, or form data.

- name: company_logo
type: image
label: "Company Logo"
source: "company"
show_label: false
readonly: true
height: 64px
position: left

Upload any image in Admin → System Settings → Media Gallery and give it a name (e.g. approval_banner). Reference it in your YAML using that exact name as the source value:

- name: header_image
type: image
label: "Header Banner"
source: "approval_banner" # name of the asset in the Media Gallery
show_label: false
height: 120px
width: 100%
object_fit: cover
position: center

Use placement: background or placement: cover to render the image as a CSS background fill rather than an <img> tag. Useful for hero banners behind form content:

- name: banner
type: image
source: "hero_banner" # Media Gallery asset name
placement: cover # fills the container edge-to-edge
height: 160px
show_label: false

placement: background uses background-size: contain; placement: cover uses background-size: cover.

All properties:

PropertyValuesDefaultDescription
sourceasset name, "company", URLImage to display. A bare string matches a named Media Gallery asset; "company" uses the company logo from settings; a full URL (https://…) is used directly.
heightCSS value80pxMax height (e.g. "64px", "200px").
widthCSS value100%Max width (e.g. "300px", "50%").
object_fitcontain | cover | fill | scale-downcontainHow the image is resized within its box.
placementinline | background | coverinlineinline renders an <img>; background/cover render a CSS background div.
positionleft | center | rightleftHorizontal alignment for inline placement.
show_labeltrue | falsetrueSet to false to hide the field label above the image.

Common Uses: Company branding in headers, workflow banners, product images, illustration separators



Dynamic repeating-row table. Users can add and remove rows; each row contains the configured item_fields. Supports calculated columns within rows.

- name: items
type: line_items
label: "Order Items"
required: true
min_items: 1
max_items: 20
item_fields:
- name: description
type: text
label: "Item Description"
required: true
- name: qty
type: number
label: "Qty"
required: true
min_value: 1
- name: unit_price
type: currency
label: "Unit Price"
required: true
currency: "USD"
- name: total
type: currency
label: "Total"
readonly: true
calculated: true
formula: "qty * unit_price"
currency: "USD"

Supported field types inside item_fields: text, number, currency, dropdown, select, textarea, autocomplete

Properties:

PropertyDescriptionDefault
min_itemsMinimum required rows0
max_itemsMaximum allowed rows (hard cap: 100)
item_fieldsColumn definitions (required)

Summary totals: Place a currency field outside line_items with formula: "sum(items.column_name)" to sum a column across all rows.

- name: grand_total
type: currency
label: "Grand Total"
readonly: true
calculated: true
formula: "sum(items.total)"
currency: "USD"

Common Uses: Purchase orders, invoices, expense reports, timesheets, material lists


Automatically generates a sequential, unique reference number at form submission. The number is assigned server-side — it is never editable by the user. Each workflow field maintains its own independent counter per company.

- name: po_number
type: autonumber
label: "PO Number"
prefix: "PO-"
pad_length: 5 # → PO-00001, PO-00042, PO-10000
start_value: 1

Properties:

PropertyRequiredDescriptionDefault
prefix❌ NoText prepended to the number (e.g. "PO-", "EXP-", "INV-")""
pad_length❌ NoZero-pad the number to this many digits (e.g. 500042)No padding
start_value❌ NoFirst number in the sequence1

How it works:

  1. The field renders as read-only with an “Auto-generated on submit” placeholder while the user fills out the form.
  2. On submission the server atomically increments the counter for (company_id, workflow_id, field_name) and formats the number as {prefix}{zero-padded number}.
  3. The generated value (e.g. PO-00001) is stored in the form data and visible to all approvers throughout the workflow.

Thread safety: Uses an atomic INSERT … ON CONFLICT DO UPDATE … RETURNING to guarantee uniqueness under concurrent submissions.

Database table: workflow_field_sequences (company_id, workflow_id, field_name, last_value)

Common Uses: Purchase order numbers, expense claim numbers, invoice numbers, ticket IDs, contract references

Examples:

# PO-00001, PO-00002, …
prefix: "PO-"
pad_length: 5
# EXP-2026-001, EXP-2026-002, … (manually include year in prefix)
prefix: "EXP-2026-"
pad_length: 3
# Plain numbers: 1, 2, 3, …
# (omit prefix and pad_length)

Fields that store metadata or pre-computed values. Included in form data but never shown to the user. Use type: text (or other appropriate type) and set hidden: true.

- name: source_system
type: text
hidden: true
default: "HR-Portal"

Common Uses: Tracking codes, system IDs, computed values passed between steps, version markers


Every field type accepts these properties:

PropertyRequiredDescription
name✅ YesUnique snake_case identifier within the form
type✅ YesField type (see table above)
label✅ YesDisplay label shown to the user
required❌ NoWhether the field must be filled (true/false, default false)
placeholder❌ NoHint text shown inside empty input
help_text❌ NoExplanatory text shown below the field
default_value❌ NoPre-filled value
readonly❌ NoPrevent user edits (combine with formula for calculated fields)

Set directly on the field (not nested under validation:):

- name: amount
type: number
min_value: 0
max_value: 100000
- name: notes
type: text
min_length: 10
max_length: 500
pattern: "^[A-Za-z0-9 ]+$" # Regex
- name: receipt
type: file_upload
max_file_size: "5MB"

Note: A validation: block in YAML is also accepted and is automatically unwrapped to the direct properties above.

Combine readonly: true, calculated: true, and formula to derive a value from other fields:

- name: total
type: currency
label: "Total"
readonly: true
calculated: true
formula: "qty * unit_price" # Inside line_items
currency: "USD"
- name: grand_total
type: currency
label: "Grand Total"
readonly: true
calculated: true
formula: "sum(items.total)" # Sum a line_items column
currency: "USD"

Supported operations: +, -, *, /, sum(), avg(), min(), max()

Show or hide a field based on another field’s value:

- name: other_reason
type: textarea
label: "Please specify"
conditional:
show_if: "reason == 'other'"
style: "warning" # "warning" | "danger" | "success" | "info"

options:
- label: "Option 1"
value: "opt1"
- label: "Option 2"
value: "opt2"

Compatible with: dropdown, select, multiselect, radio

options:
data_processor:
source_id: "src_employees" # Registered Data Processor
value_field: "id" # Stored value
label_field: "name" # Display text
display: "{name} - {dept}" # Optional rich display template

Compatible with: autocomplete (required), dropdown, select, multiselect


I need to collect…Use
A name, title, or short texttext
A long description or notetextarea
An email addressemail
Formatted text with imagesrichtext
A count or quantitynumber
A monetary amountcurrency
A calendar date (day only)date
A date with a specific timedatetime
One choice from a listdropdown or select
Multiple choices from a listmultiselect
A true/false togglecheckbox
One choice displayed as buttonsradio with display_as: "buttons"
An internal employee (search by name, department, role)user_lookup
A searchable entity from an external source (product, customer…)autocomplete
An uploaded document or imagefile_upload or file
A captured signaturesignature
Repeating rows (purchase items, expenses…)line_items
An auto-generated sequential reference numberautonumber
Hidden tracking metadatatype: text + hidden: true

  • Use descriptive name values (e.g. employee_name, not field1)
  • Set required: true only for fields that are truly mandatory
  • Choose the most specific type (use email not text for email addresses)
  • Use dropdown for any field with ≤ 20 fixed options
  • Add placeholder and help_text to guide users
  • Put autonumber as the first field so it appears at the top of the form
  • Use min_items: 1 on line_items when at least one row is required
  • Use text when a specific type (email, date, currency) exists
  • Make every field required — it frustrates users
  • Define autocomplete with static options (use dropdown instead)
  • Forget validation bounds on number and currency fields
  • Use complex formula expressions without testing them

form:
fields:
# Auto-generated reference number
- name: expense_number
type: autonumber
label: "Expense Claim No."
prefix: "EXP-"
pad_length: 5
# Requestor details
- name: employee_name
type: text
label: "Employee Name"
required: true
- name: employee_email
type: email
label: "Email Address"
required: true
# Category selection
- name: category
type: dropdown
label: "Expense Category"
required: true
options:
- label: "Travel"
value: "travel"
- label: "Meals"
value: "meals"
- label: "Equipment"
value: "equipment"
- label: "Other"
value: "other"
# Conditional: only shown when category is "other"
- name: other_category
type: text
label: "Specify Category"
conditional:
show_if: "category == 'other'"
# Date and urgency
- name: expense_date
type: date
label: "Expense Date"
required: true
- name: urgency
type: radio
label: "Urgency"
required: true
display_as: "buttons"
options:
- label: "Normal"
value: "normal"
- label: "Urgent"
value: "urgent"
# Line items with calculated totals
- name: items
type: line_items
label: "Expense Items"
required: true
min_items: 1
max_items: 30
item_fields:
- name: description
type: text
label: "Description"
required: true
- name: amount
type: currency
label: "Amount"
required: true
currency: "USD"
- name: total_amount
type: currency
label: "Total Amount"
readonly: true
calculated: true
formula: "sum(items.amount)"
currency: "USD"
# Justification and receipt
- name: justification
type: textarea
label: "Business Justification"
required: true
rows: 3
- name: receipt
type: file_upload
label: "Receipt(s)"
required: true
accept: ".pdf,.jpg,.jpeg,.png"
multiple: true
max_file_size: "10MB"
# Signature and hidden metadata
- name: requestor_signature
type: signature
label: "Employee Signature"
required: true
- name: submitted_via
type: text
hidden: true
default: "web-form"

Structured data field for storing and displaying JSON objects or arrays. In edit mode, it provides a code editor with validation; in read-only mode, it supports an interactive, expandable tree view.

- name: api_payload
type: json
label: "Technical Details"
display_as: "tree" # → Interactive expandable tree view
required: true
default_value: '{"status": "pending", "meta": {}}'

Properties:

PropertyRequiredDescriptionDefault
display_as❌ NoHow to render the data in read-only mode: "tree" (expandable), "code" (syntax highlighted), or "pretty" (formatted text)."pretty"

Common Uses: API request/response logs, system configurations, complex metadata, audit logs from external systems



Version: 1.2 Last Updated: 2026-06-30 Status: Production Ready ✅