Module Schema Reference
A comprehensive reference for all available options when building module schemas for Stacksync Workflows.
Schema Structure
Root Schema Object
{
"metadata": {
"workflows_module_schema_version": "1.0.0"
},
"fields": [...],
"ui_options": {...}
}Required Properties:
metadata- Schema metadata configurationfields- Array of field definitions
Optional Properties:
ui_options- Global UI configuration options
Metadata Configuration
workflows_module_schema_version
Type: String
Required: Yes
Default: "1.0.0"
Description: Specifies the schema version for compatibility
{
"metadata": {
"workflows_module_schema_version": "1.0.0"
}
}Field Types
String Fields
Basic String Field:
{
"id": "field_name",
"type": "string",
"label": "Display Label",
"description": "Field description",
"default": "Default value"
}Properties:
id(string, required) - Unique field identifiertype(string, required) - Must be "string"label(string, optional) - Display label for the fielddescription(string, optional) - Help text for usersdefault(string, optional) - Default value
Number Fields
Basic Number Field:
{
"id": "count",
"type": "number",
"label": "Count",
"default": 0
}Properties:
id(string, required) - Unique field identifiertype(string, required) - Must be "number"label(string, optional) - Display labeldefault(number, optional) - Default numeric value
Integer Fields
Basic Integer Field:
{
"id": "whole_number",
"type": "integer",
"label": "Whole Number",
"default": 1
}Boolean Fields
Basic Boolean Field:
{
"id": "enable_feature",
"type": "boolean",
"label": "Enable Feature",
"default": false
}Connection Fields
Connection Field:
{
"type": "connection",
"id": "api_connection",
"label": "API Connection",
"allowed_app_types": ["salesforce", "hubspot"],
"allowed_connection_management_types": ["managed", "custom"]
}Properties:
allowed_app_types(array, required) - List of supported connection typesallowed_connection_management_types(array, required) - Connection management options
Supported App Types:
salesforce- Salesforce CRMhubspot- HubSpot CRMpostgres- PostgreSQL databasemysql- MySQL databasecustom_api- Custom API connections
Connection Management Types:
managed- Platform-managed connectionscustom- User-provided credentials
Object Fields
Simple Object Field:
{
"type": "object",
"id": "settings",
"label": "Settings",
"fields": [
{
"id": "name",
"type": "string",
"label": "Name"
}
]
}Object with Choices:
{
"type": "object",
"id": "platform",
"label": "Platform",
"choices": {
"values": [
{
"value": { "id": "linkedin", "label": "LinkedIn" },
"label": "LinkedIn"
}
]
}
}Array Fields
String Array:
{
"type": "array",
"id": "tags",
"label": "Tags",
"items": {
"type": "string",
"label": "Tag"
}
}Object Array:
{
"type": "array",
"id": "users",
"label": "Users",
"items": {
"type": "object",
"fields": [
{
"id": "name",
"type": "string",
"label": "Name"
}
]
}
}UI Widgets
Available Widgets
input (default for strings)
{
"ui_options": {
"ui_widget": "input"
}
}textarea (multi-line text)
{
"ui_options": {
"ui_widget": "textarea"
}
}password (hidden text input)
{
"ui_options": {
"ui_widget": "password"
}
}SelectWidget (dropdown selection)
{
"ui_options": {
"ui_widget": "SelectWidget"
}
}checkbox (boolean checkbox)
{
"ui_options": {
"ui_widget": "checkbox"
}
}CodeblockWidget (code editor)
{
"ui_options": {
"ui_widget": "CodeblockWidget",
"ui_options": {
"language": "json"
}
}
}hidden (hidden field)
{
"ui_options": {
"ui_widget": "hidden"
}
}CodeblockWidget Languages
Supported syntax highlighting languages:
json- JSON formatsql- SQL queriesjavascript- JavaScript codepython- Python codeyaml- YAML configurationxml- XML markuphtml- HTML markupcss- CSS styling
Validation Rules
Basic Validation
required - Field is mandatory
{
"validation": {
"required": true
}
}min_length - Minimum string length
{
"validation": {
"min_length": 3
}
}max_length - Maximum string length
{
"validation": {
"max_length": 100
}
}minimum - Minimum numeric value
{
"validation": {
"minimum": 0
}
}maximum - Maximum numeric value
{
"validation": {
"maximum": 1000
}
}pattern - Regular expression validation
{
"validation": {
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
}
}Format Validation
email - Email address format
{
"format": "email"
}uri - URI format
{
"format": "uri"
}date - Date format (YYYY-MM-DD)
{
"format": "date"
}date-time - Date-time format (ISO 8601)
{
"format": "date-time"
}uuid - UUID format
{
"format": "uuid"
}Dynamic Content
Basic Content Configuration
{
"content": {
"type": ["managed"],
"content_objects": [
{
"id": "users"
}
]
}
}Properties:
type(array, required) - Content management typescontent_objects(array, required) - List of content objects to fetch
Content Management Types:
managed- Platform manages the content loadingcustom- Custom content loading logic
Content Dependencies
Field-dependent content:
{
"content": {
"type": ["managed"],
"content_objects": [
{
"id": "users_in_channel",
"content_object_depends_on_fields": [
{
"id": "channel"
}
]
}
]
}
}Array item dependencies:
{
"content_object_depends_on_fields": [
{
"id": "channels.items"
}
]
}Choices Configuration
Static Choices
Simple string choices:
{
"choices": {
"values": [
{ "value": "option1", "label": "Option 1" },
{ "value": "option2", "label": "Option 2" }
]
}
}Object choices:
{
"choices": {
"values": [
{
"value": { "id": "contact", "label": "Contact" },
"label": "Contact"
},
{
"value": { "id": "lead", "label": "Lead" },
"label": "Lead"
}
]
}
}Dynamic Choices
Empty choices for dynamic loading:
{
"choices": {
"values": []
}
}Schema Rules (Conditional Logic)
Basic Rules Structure
{
"rules": [
{
"if": {
"and": [
{
"id": "field_id",
"operator": "equal",
"value": "expected_value"
}
]
},
"then": {
"fields": [
{
"id": "target_field",
"ui_options": {
"ui_widget": "hidden"
},
"apply_as": "merge"
}
]
}
}
]
}Condition Operators
equal - Exact match
{
"id": "status",
"operator": "equal",
"value": "active"
}not_equal - Not equal to
{
"id": "status",
"operator": "not_equal",
"value": "inactive"
}is_in - Value in array
{
"id": "category",
"operator": "is_in",
"value": ["premium", "enterprise"]
}is_not_in - Value not in array
{
"id": "category",
"operator": "is_not_in",
"value": ["free", "trial"]
}is_empty - Field is empty
{
"id": "optional_field",
"operator": "is_empty"
}is_not_empty - Field has value
{
"id": "required_field",
"operator": "is_not_empty"
}greater_than - Numeric comparison
{
"id": "count",
"operator": "greater_than",
"value": 10
}less_than - Numeric comparison
{
"id": "count",
"operator": "less_than",
"value": 100
}Logic Combinators
and - All conditions must be true
{
"and": [
{ "id": "field1", "operator": "equal", "value": "value1" },
{ "id": "field2", "operator": "equal", "value": "value2" }
]
}or - Any condition must be true
{
"or": [
{ "id": "field1", "operator": "equal", "value": "value1" },
{ "id": "field2", "operator": "equal", "value": "value2" }
]
}Rule Effects
apply_as options:
merge- Merge with existing field configurationfully_replace- Replace entire field configuration
Show/Hide Fields:
{
"then": {
"fields": [
{
"id": "conditional_field",
"ui_options": {
"ui_widget": null
},
"apply_as": "merge"
}
]
}
}Hide Fields:
{
"then": {
"fields": [
{
"id": "conditional_field",
"ui_options": {
"ui_widget": "hidden"
},
"apply_as": "merge"
}
]
}
}UI Layout Options
Global UI Options
Field Ordering:
{
"ui_options": {
"ui_order": ["field1", "field2", "field3"]
}
}Field-Level UI Options
Horizontal Layout:
{
"ui_options": {
"ui_layout": {
"type": "horizontal",
"elements": ["first_name", "last_name"]
}
}
}Advanced Features
Action Handlers
Action handlers define what should happen when users interact with fields. They trigger specific behaviors when field values change.
load_schema
Purpose: Triggers a schema reload when the field value changes, allowing for dynamic updates to other fields based on the new value.
Basic Usage:
{
"id": "country",
"type": "string",
"label": "Country",
"on_action": {
"load_schema": true
}
}What happens when load_schema is triggered:
You change the value of the field
countryA trigger sends an HTTP POST request to the module /schema endpoint with :
the full schema
the full form data
the full content objects
The module returns a new schema
The new schema is merged with the existing schema
The frontend updates the UI to reflect the new schema
Common Use Cases
Use Case 1: Cascading Dropdowns
{
"id": "country",
"type": "object",
"label": "Country",
"on_action": {
"load_schema": true
},
"choices": {
"values": [
{"value": {"id": "us", "label": "United States"}, "label": "United States"},
{"value": {"id": "ca", "label": "Canada"}, "label": "Canada"}
]
}
},
{
"id": "state",
"type": "object",
"label": "State/Province",
"content": {
"type": ["managed"],
"content_objects": [
{
"id": "states_by_country",
"content_object_depends_on_fields": [
{"id": "country"}
]
}
]
}
}Use Case 2: Conditional Field Display
{
"id": "data_source",
"type": "string",
"label": "Data Source",
"on_action": {
"load_schema": true
},
"choices": {
"values": [
{"value": "database", "label": "Database"},
{"value": "api", "label": "API"},
{"value": "file", "label": "File"}
]
}
},
{
"id": "database_config",
"type": "object",
"label": "Database Configuration",
"rules": [
{
"if": {
"and": [
{
"id": "data_source",
"operator": "equal",
"value": "database"
}
]
},
"then": {
"fields": [
{
"id": "database_config",
"ui_options": {
"ui_widget": null
},
"apply_as": "merge"
}
]
}
}
]
}Use Case 3: Dynamic Validation
{
"id": "field_type",
"type": "string",
"label": "Field Type",
"on_action": {
"load_schema": true
},
"choices": {
"values": [
{"value": "email", "label": "Email"},
{"value": "phone", "label": "Phone"},
{"value": "text", "label": "Text"}
]
}
},
{
"id": "field_value",
"type": "string",
"label": "Field Value",
"rules": [
{
"if": {
"and": [
{
"id": "field_type",
"operator": "equal",
"value": "email"
}
]
},
"then": {
"fields": [
{
"id": "field_value",
"format": "email",
"validation": {
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
"apply_as": "merge"
}
]
}
}
]
}Backend Implementation
When load_schema: true is triggered, your /content endpoint receives the updated form data:
@router.route("/content", methods=["POST"])
def content():
try:
request = Request(flask_request)
data = request.data
# Get updated form data after field change
form_data = data.get("form_data", {})
content_object_names = data.get("content_object_names", [])
content_objects = []
for content_name in content_object_names:
if content_name == "states_by_country":
# Get the selected country from updated form data
selected_country = form_data.get("country", {})
country_id = selected_country.get("id") if selected_country else None
if country_id == "us":
states = [
{"value": {"id": "ca", "label": "California"}, "label": "California"},
{"value": {"id": "ny", "label": "New York"}, "label": "New York"}
]
elif country_id == "ca":
states = [
{"value": {"id": "on", "label": "Ontario"}, "label": "Ontario"},
{"value": {"id": "bc", "label": "British Columbia"}, "label": "British Columbia"}
]
else:
states = []
content_objects.append({
"content_object_name": "states_by_country",
"data": states
})
return Response(data={"content_objects": content_objects})
except Exception as e:
return Response.error(str(e))Performance Considerations
Use Sparingly: Only add
load_schema: trueto fields that actually need to trigger updatesOptimize Backend: Ensure your
/contentendpoint responds quickly to avoid UI lagCache When Possible: Cache static data that doesn't change between requests
Batch Updates: If multiple fields need to trigger updates, consider grouping them
Best Practices
Clear User Feedback: Show loading indicators when schema is reloading
Preserve User Input: Ensure field values aren't lost during reload
Error Handling: Gracefully handle failures in content loading
Debouncing: Consider debouncing rapid field changes to avoid excessive requests
Debugging Tips
Check browser network tab to see
/contentrequests when fields changeVerify that
content_object_depends_on_fieldsreferences match your field IDs exactlyTest with browser console open to catch any JavaScript errors
Use simple test data first, then add complexity
Complete Field Example
Here's a comprehensive example showing most available options:
{
"id": "user_email",
"type": "string",
"label": "User Email",
"description": "Enter the user's email address",
"default": "",
"format": "email",
"validation": {
"required": true,
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
},
"validation_messages": {
"required": "Email is required for notifications",
"pattern": "Please enter a valid email address"
},
"ui_options": {
"ui_widget": "input"
},
"on_action": {
"load_schema": true
},
"rules": [
{
"if": {
"and": [
{
"id": "user_email",
"operator": "is_not_empty"
}
]
},
"then": {
"fields": [
{
"id": "send_notification",
"ui_options": {
"ui_widget": null
},
"apply_as": "merge"
}
]
}
}
]
}This specification covers all major aspects of module schema configuration. Refer to this document when building your schemas to understand all available options and their proper usage.
Last updated