A custom form action renders a structured form from a JSON Schema (and optional UI Schema) to collect multiple fields of data from the user in a single step.
This action renders a multi-field form using JSON Forms. The merchant supplies a JSON Schema describing the data shape and validation rules, and an optional UI Schema describing layout. The customer fills out the form and submits the values, which become available in the action state.
Use Cases:
- Customer Onboarding: Capture first name, last name, email, and address in a single step.
- Surveys: Render structured surveys with mixed input types (text, number, date, select).
- KYC / Compliance: Collect a structured set of identity attributes with validation.
- Custom Metadata: Capture an arbitrary, schema-validated metadata object on the business process.
Supported Capabilities:
- JSON Schema (
schema) validation of submitted data. - JSON Forms UI Schema (
uischema) for layout customization. - Initial form data (
data) to pre-populate fields. - Customizable submit button label.
- Read-only and disabled rendering modes.
How to create schema and uischema:
Use these two reference patterns:
- Normal object form:
normalSchema+normalUiSchema - Array item form:
schema+uischemawithitemsandoptions.detail
1) Normal object schema pattern:
- Root must be
type: "object" - Put required keys in
required - Define fields in
propertieswith stable ids like#root/<fieldName> - Use explicit types:
string,number,integer,boolean; for checkbox fields useboolean - Use
enumfor select/dropdown fields (enum values are shown as options) - Add validation only where needed:
pattern,minimum,maximum
2) Normal object uischema pattern:
- Use
VerticalLayoutfor standard forms - Add one
Controlper property - Use scope
#/properties/<fieldName> - Use display options like
options.multifor multiline text
Normal form example:
{
"schema": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "$id": "#root/name", "type": "string", "default": "" },
"age": { "$id": "#root/age", "type": "integer", "minimum": 18, "default": 18 },
"category": { "$id": "#root/category", "type": "string", "enum": ["Gold", "Silver", "Lead"], "default": "Silver" },
"isActive": { "$id": "#root/isActive", "type": "boolean", "default": true }
}
},
"uischema": {
"type": "VerticalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/name", "label": "Name" },
{ "type": "Control", "scope": "#/properties/age", "label": "Age" },
{ "type": "Control", "scope": "#/properties/category", "label": "Category" },
{ "type": "Control", "scope": "#/properties/isActive", "label": "Active" }
]
}
}Enum note: category renders as a select box and enum values become dropdown options.
3) Array schema pattern:
- Parent field is
type: "array"(example:items) itemsmust betype: "object"when each row has multiple fields- Row fields go in
items.properties - Row required keys go in
items.required
4) Array uischema pattern:
- Add array control scope:
#/properties/items - Configure row rendering in
options.detail - Inside
detail.elements, keep scopes relative to row, for example#/properties/label - Choose
HorizontalLayoutorVerticalLayoutbased on row density
Array form example:
{
"schema": {
"type": "object",
"properties": {
"items": {
"$id": "#root/items",
"type": "array",
"items": {
"$id": "#root/items/items",
"type": "object",
"required": ["label", "quantity"],
"properties": {
"label": { "$id": "#root/items/items/label", "type": "string" },
"quantity": { "$id": "#root/items/items/quantity", "type": "integer", "default": 1 }
}
}
}
}
},
"uischema": {
"type": "VerticalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/items",
"options": {
"detail": {
"type": "HorizontalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/label", "label": "Label" },
{ "type": "Control", "scope": "#/properties/quantity", "label": "Quantity" }
]
}
}
}
]
}
}Quick checklist:
- Schema property names and uischema scopes must match exactly
- Keep ids unique and predictable
- Use
enumfor select/dropdown fields (enum values are shown as options) - Use
initialDataFromSchema(schema)forschemaInitialDatain stories
Related Actions
This action pairs well with the following actions:
State
The structured form data submitted by the customer, keyed by the property names defined in the JSON Schema.
Union
When unioned there will be no submit button shown in the gui when this action is unionized. Instead, the unionized action will be the trigger to 'save' the current entered values.
Macro level details for how union attribute behaves can be found within the Union documentation.
Features (required)
| Name | Type | Description | Rules |
|---|---|---|---|
| name | string | Name for the form. When set to 'metadata', submitted values are emitted as a metadata event. Examples: "metadata". | MaxLength: 50 MinLength: 3 Pattern: ^(?!\s*$).+ |
| label | string | Label rendered above the form. Examples: "Customer information". | MaxLength: 100 MinLength: 1 Pattern: ^(?!\s*$).+ |
| schema | object | (required) JSON Schema describing the data shape and validation rules for the form. | See schema |
| uischema | object | JSON Forms UI Schema describing layout and rendering hints for the form. | |
| data | object | Initial form data used to populate the rendered form. | |
| submitLabel | string | Label for the submit button. Examples: "Submit". | |
| required | boolean | Whether form submission is required. | |
| disabled | boolean | Whether the form is disabled (non-interactive). | |
| readonly | boolean | Whether the form is rendered read-only. |
schema
| Name | Type | Description | Rules |
|---|---|---|---|
| $id | string | ||
| $schema | string | ||
| title | string | ||
| description | string | ||
| type | string | (required) Top-level form schema must be an object. | Possible values: object. |
| required | array | Names of properties that must be provided. | |
| properties | object | (required) Map of field name to its property schema. |
Example
Below is an example payload for adding an Custom-form action to a business process or blueprint.
{
"type": "custom-form",
"union": 0,
"features": {
"schema": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"$id": "#root/name",
"type": "string",
"default": ""
},
"age": {
"$id": "#root/age",
"type": "integer",
"minimum": 18,
"default": 18
},
"category": {
"$id": "#root/category",
"type": "string",
"enum": [
"Gold",
"Silver",
"Lead"
],
"default": "Silver"
},
"isActive": {
"$id": "#root/isActive",
"type": "boolean",
"default": true
}
}
},
"uischema": {
"type": "VerticalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/name",
"label": "Name"
},
{
"type": "Control",
"scope": "#/properties/age",
"label": "Age"
},
{
"type": "Control",
"scope": "#/properties/category",
"label": "Category"
},
{
"type": "Control",
"scope": "#/properties/isActive",
"label": "Active"
}
]
}
}
}