Forms (new) Step
Collects user input via an ordered list of form components. Use this step to build interactive forms and capture structured data (text, numbers, selections), lay out pages/sections, and include static content such as headings and dividers.
Top-level properties
| name | type | required | constraints | description |
|---|---|---|---|---|
type | string | no | enum: data-capture | Optional discriminator used by some orchestrators. |
presentation | object | no | Container-level presentation metadata for the entire form. | |
components | array | yes | items: union of component variants | Ordered list of components defining the form’s content and layout. |
Presentation
| name | type | required | constraints |
|---|---|---|---|
presentation.form | object | no | Container-level form display settings |
form.label | string | yes | maxLength: 60 |
Component: text
textUse for single-line or multi-line text input. This is also used with the "format" option for fields such as email and phone.
| name | type | required | constraints | |
|---|---|---|---|---|
id | string | no | format: uuid; special-case all-zero/ffff allowed | Stable identifier for the component (for mapping/data pipelines). |
type | string | yes | enum: text | Discriminator for the component variant. |
label | string | yes | Machine-readable field key (often snake_case), used for data mapping. | |
validation.required | boolean | no | Whether input is mandatory. | |
validation.min | number | no | minimum: 0 | Minimum character length. |
validation.max | number | no | minimum: 1 | Maximum character length. |
presentation.form | object | no | UI rendering hints for this field. | |
form.label | string | yes if presentation.form present | maxLength: 60 | Human-readable label shown to end users. |
form.type | string | yes if presentation.form present | enum: input, richtext, select, textarea; default: input | Input control type. |
form.placeholder | string | no | Example text shown inside the input. | |
form.helpText | string | no | Helper text displayed near the input. |
Component: number
numberUse for numeric input with optional formatting and range constraints.
| name | type | required | constraints | |
|---|---|---|---|---|
id | string | no | format: uuid | Stable component id. |
type | string | yes | enum: number | Discriminator for numeric fields. |
label | string | yes | Machine-readable field key. | |
validation.required | boolean | yes if validation present | default: false | Whether value is mandatory. |
validation.min | number | no | Minimum allowed value. | |
validation.max | number | no | Maximum allowed value. | |
presentation.form | object | no | UI control settings. | |
form.label | string | yes if presentation.form present | maxLength: 60 | Human-readable label. |
form.type | string | yes if presentation.form present | enum: input; default: input | Input control type. |
form.placeholder | string | no | Example numeric value. | |
form.helpText | string | no | Helper copy for guidance. |
Component: options
optionsUse for single or multi-select choices populated from a static list or a dynamic endpoint. Dropdowns, Radio or Checkboxes
| name | type | required | constraints | |
|---|---|---|---|---|
id | string | no | format: uuid | Stable component id. |
type | string | yes | enum: options | Discriminator for option fields. |
label | string | yes | Machine-readable key. | |
validation.source | string | yes | enum: endpoint, static_list | Where options come from. |
validation.required | boolean | yes | default: false | Whether a selection is mandatory. |
validation.options | array[Option] | no | minItems: 1 | Static choices when source is static_list. |
presentation.form | object | yes | UI settings for select control. | |
form.label | string | yes | maxLength: 60 | Human-readable label. |
form.type | string | yes | enum: checkbox, dropdown; default: dropdown | Select control type. |
form.placeholder | string | no | Placeholder for dropdown. | |
form.helpText | string | no | Helper copy. |
Option
| name | type | required | |
|---|---|---|---|
id | string | no (nullable) | Optional stable option id |
label | string | yes | Display text shown to users |
value | string | yes | Value stored on selection |
Component: static_content
static_contentUse to display non-interactive content such as header field or description areas.
| name | type | required | constraints | |
|---|---|---|---|---|
id | string | no | format: uuid | Stable id for reference |
type | string | yes | enum: static_content | Discriminator for display-only blocks |
label | string | yes | Internal key for this block | |
presentation.form | object | no | UI rendering hints | |
form.type | string | yes if presentation.form present | enum: heading, html | Display variant |
form.label | string | yes if presentation.form present | maxLength: 60 | Title for headings or accessibility label |
form.content | string | yes if presentation.form present | Body content (HTML/Markdown/string) |
Component: group
groupUse to create and update grouped options such as Pages and grouped fields like "Name"
| name | type | required | constraints | |
|---|---|---|---|---|
id | string | no | format: uuid | Stable group id |
type | string | yes | enum: group | Discriminator for groups |
label | string | yes | Internal key for this group | |
presentation.form | object | no | Group-level UI settings | |
form.label | string | yes if presentation.form present | maxLength: 60 | Visible label/title for the group |
form.type | string | yes if presentation.form present | enum: full_name, grid, group, none, page, section | Layout mode controlling rendering |
form.gridOptions[] | array | no | each item requires gridColumnStart, gridColumnEnd, gridRowStart, gridRowEnd | Grid position hints for nested components |
components[] | array | no | items: same component union as top-level | Nested components within the grou |
Assignment
The taskAssignment property configures how form completion notifications are sent to users.
| name | type | required | constraints | description |
|---|---|---|---|---|
type | string | yes | enum: email, phone, inheritFromPreviousStep | Assignment method. |
name | string | yes if type is email or phone | Task assignment name. | |
config | object | yes if type is email or phone | Configuration object specific to the assignment type. |
Email Assignment Config (type: "email"):
| name | type | required | constraints | description |
|---|---|---|---|---|
recipients | array(string) | yes | Array of email addresses to notify. | |
from | string | no | Sender email address. | |
replyTo | string | no | Reply-to email address. | |
subject | string | yes | Email subject line. | |
message | string | yes | Email body message. | |
buttonLabel | string | yes | Label for the action button in the email. |
Phone Assignment Config (type: "phone"):
| name | type | required | constraints | description |
|---|---|---|---|---|
recipients | array(string) | yes | Array of phone numbers to notify. | |
message | string | yes | SMS message text. |
Example (JSON)
{
"type": "data-capture",
"presentation": {
"form": {
"label": "Customer Intake"
}
},
"components": [
{
"id": "00000000-0000-0000-0000-000000000000",
"type": "text",
"label": "Email Address",
"validation": {
"required": true,
"format": "email",
"min": 5,
"max": 255,
"errorMessage": "Please enter a valid email address"
},
"presentation": {
"form": {
"label": "Email Address",
"type": "input",
"placeholder": "[email protected]",
"helpText": "We will send your receipt here."
}
}
},
{
"id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
"type": "number",
"label": "Quantity",
"validation": {
"format": "integer",
"required": true,
"min": 1,
"max": 100
},
"presentation": {
"form": {
"label": "Quantity",
"type": "input",
"placeholder": "1",
"helpText": "Enter a value between 1 and 100"
}
}
},
{
"id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
"type": "options",
"label": "Plan",
"validation": {
"source": "static_list",
"required": false,
"options": [
{ "id": "basic", "label": "Basic", "value": "basic" },
{ "id": "pro", "label": "Pro", "value": "pro" }
],
"endpoint": "https://api.example.com/plans",
},
"presentation": {
"form": {
"label": "Plan",
"type": "dropdown",
"placeholder": "Select a plan",
"helpText": "Choose your subscription plan"
}
}
},
{
"id": "cccccccc-cccc-4ccc-8ccc-cccccccccccc",
"type": "static_content",
"label": "Terms",
"validation": {},
"presentation": {
"form": {
"type": "md",
"label": "Terms & Conditions",
"content": "By continuing you agree to the terms."
}
}
},
{
"id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
"type": "group",
"label": "Personal Information",
"validation": {},
"presentation": {
"form": {
"label": "Personal Information",
"type": "grid",
"gridOptions": [
{
"gridColumnStart": "1",
"gridColumnEnd": "3",
"gridRowStart": "1",
"gridRowEnd": "1"
}
]
}
},
"components": [
{
"id": "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee",
"type": "text",
"label": "ZIP Code",
"validation": {
"required": true,
"format": "zip",
"min": 5,
"max": 10,
"errorMessage": "Enter a valid ZIP code"
},
"presentation": {
"form": {
"label": "ZIP Code",
"type": "input",
"placeholder": "90210",
"helpText": "Five or nine digits"
}
}
}
]
}
]
}Updated 22 days ago
