Form Validation
Dynamic Validation
The API automatically validates submitted data against the workflow's form configuration. Validation rules are dynamically applied based on the form builder settings.
Validation Types
- Required Fields: Must be present in the request
- Data Types: Must match expected types (string, number, etc.)
- Format Validation: Email, date, phone number formats
- Input Masks: Pattern matching for formatted fields
- Length Limits: Minimum and maximum length constraints
- Custom Rules: Additional validation rules defined in the form
Required Field Validation
Configuration
Fields marked as required in the form builder must be included in API requests:
{
"name": "John Doe", // Required field
"email": "john@example.com", // Required field
"phone": "+1234567890" // Optional field
}
Error Response
Missing required fields trigger validation errors:
{
"error": "Invalid input data: Validation failed for 'Name': This field is required",
"code": "VALIDATION_ERROR"
}
Data Type Validation
Supported Types
| Form Field Type | Expected JSON Type | Validation Rules |
|---|---|---|
textfield | string | Length limits, pattern matching |
textarea | string | Length limits |
email | string | Valid email format |
number | number | Numeric value, min/max ranges |
date | string | ISO date format (YYYY-MM-DD) |
datetime | string | ISO datetime format |
checkbox | boolean | true or false |
select | string | Must match available options |
radio | string | Must match available options |
selectboxes | object | Keys must match available options |
Type Validation Examples
✅ Correct Types
{
"name": "John Doe", // string for textfield
"age": 30, // number for number field
"is_active": true, // boolean for checkbox
"birth_date": "1990-05-15", // ISO date string
"category": "electronics" // string matching select option
}
❌ Incorrect Types
{
"name": 123, // number instead of string
"age": "30", // string instead of number
"is_active": "true", // string instead of boolean
"birth_date": 1642204800, // timestamp instead of ISO date
"category": ["electronics"] // array instead of string
}
Format Validation
Email Validation
Email fields must contain valid email addresses:
{
"email": "user@example.com" // ✅ Valid
// "email": "invalid-email" // ❌ Invalid
// "email": "user@" // ❌ Invalid
// "email": "@example.com" // ❌ Invalid
}
Date Validation
Date fields must use ISO format:
{
"birth_date": "1990-05-15", // ✅ Valid ISO date
"appointment": "2024-01-15T14:30:00", // ✅ Valid ISO datetime
// "birth_date": "05/15/1990", // ❌ Invalid format
// "birth_date": "15-05-1990", // ❌ Invalid format
}
URL Validation
URL fields must contain valid URLs:
{
"website": "https://example.com", // ✅ Valid
"profile": "http://linkedin.com/in/user", // ✅ Valid
// "website": "not-a-url", // ❌ Invalid
// "website": "ftp://example.com", // ❌ May be invalid depending on config
}
Input Masks
Form fields with input masks are validated against specific patterns:
Common Input Mask Patterns
| Input Mask | Pattern | Example | Description |
|---|---|---|---|
999-999-9999 | Phone numbers | 123-456-7890 | US phone format |
(999) 999-9999 | Phone numbers | (123) 456-7890 | US phone with parentheses |
aa-999 | Code formats | AB-123 | Letter-number combination |
9999-99-99 | Date formats | 2024-01-15 | Date with dashes |
99/99/9999 | Date formats | 01/15/2024 | US date format |
AAA-999 | Product codes | ABC-123 | Uppercase letters with numbers |
Input Mask Validation Examples
Phone Number Mask: 999-999-9999
{
"phone": "123-456-7890" // ✅ Matches pattern
// "phone": "1234567890" // ❌ Missing dashes
// "phone": "123-45-6789" // ❌ Wrong dash positions
}
Product Code Mask: AAA-999
{
"product_code": "ABC-123" // ✅ Matches pattern
// "product_code": "ab-123" // ❌ Lowercase letters
// "product_code": "ABC123" // ❌ Missing dash
}
Length Constraints
Text Field Limits
{
"short_description": "Brief text", // Must meet minimum length
"detailed_description": "Longer text...", // Must not exceed maximum
"exact_code": "ABC123" // Must be exact length if specified
}
Validation Error Examples
{
"error": "Invalid input data: Validation failed for 'Description': Field must be at least 10 characters long",
"code": "VALIDATION_ERROR"
}
{
"error": "Invalid input data: Validation failed for 'Summary': Field cannot exceed 100 characters",
"code": "VALIDATION_ERROR"
}
Select and Radio Validation
Option Validation
Select and radio fields must contain values from predefined options:
{
"category": "electronics", // ✅ Valid option
"priority": "high", // ✅ Valid option
// "category": "invalid", // ❌ Not in options list
// "priority": "urgent", // ❌ Not in options list
}
Selectboxes Validation
Selectboxes must have keys matching available options:
{
"features": {
"feature_a": true, // ✅ Valid option key
"feature_b": false, // ✅ Valid option key
// "invalid_feature": true // ❌ Invalid option key
}
}
Custom Validation Rules
Conditional Validation
Some fields may have conditional requirements:
{
"employment_type": "contractor",
"contract_end_date": "2024-12-31", // Required when employment_type is "contractor"
"hourly_rate": 75.00 // Required for contractors
}
Cross-Field Validation
Validation may involve multiple fields:
{
"start_date": "2024-01-15",
"end_date": "2024-12-31", // Must be after start_date
"total_amount": 10000,
"deposit_amount": 2000 // Must be less than total_amount
}
Validation Error Handling
Error Message Format
Validation errors follow a consistent format:
"Invalid input data: Validation failed for '{field_label}': {specific_error_message}"
Parsing Validation Errors
function parseValidationError(errorMessage) {
const regex = /Validation failed for '(.+?)': (.+)/;
const match = errorMessage.match(regex);
if (match) {
return {
field: match[1],
message: match[2],
type: 'validation'
};
}
return {
field: 'unknown',
message: errorMessage,
type: 'general'
};
}
// Usage
const error = parseValidationError(
"Invalid input data: Validation failed for 'Email': The field must be a valid email address"
);
console.log(error);
// Output: { field: 'Email', message: 'The field must be a valid email address', type: 'validation' }
Multiple Validation Errors
When multiple fields fail validation, errors are typically returned for the first failed field:
{
"error": "Invalid input data: Validation failed for 'Name': This field is required",
"code": "VALIDATION_ERROR"
}
Fix the first error and resubmit to see additional validation issues.
Testing Validation
Validation Test Cases
// Test required field validation
const testMissingRequired = {
// "name": "John Doe", // Intentionally missing required field
"email": "john@example.com"
};
// Test data type validation
const testWrongTypes = {
"name": "John Doe",
"age": "thirty", // String instead of number
"is_active": "yes" // String instead of boolean
};
// Test format validation
const testInvalidFormats = {
"name": "John Doe",
"email": "invalid-email", // Invalid email format
"phone": "123456789", // Missing dashes for mask 999-999-9999
"birth_date": "01/15/1990" // Wrong date format
};
// Test length constraints
const testLengthLimits = {
"name": "Jo", // Too short
"description": "A".repeat(1001), // Too long
"code": "ABC12345" // Wrong length for exact match
};
Validation Testing Strategy
- Start Simple: Test with minimal required fields
- Add Complexity: Gradually add optional and complex fields
- Test Edge Cases: Try boundary values and invalid formats
- Verify Error Messages: Ensure error messages are helpful
- Document Patterns: Keep track of successful validation patterns
Best Practices
1. Validate Client-Side First
Implement client-side validation to catch errors early:
function validateBeforeSubmit(data, formSchema) {
const errors = [];
// Check required fields
formSchema.required.forEach(field => {
if (!data[field]) {
errors.push(`${field} is required`);
}
});
// Check data types
Object.keys(data).forEach(field => {
const expectedType = formSchema.fields[field]?.type;
const actualType = typeof data[field];
if (expectedType && expectedType !== actualType) {
errors.push(`${field} must be ${expectedType}, got ${actualType}`);
}
});
return errors;
}
2. Handle Validation Gracefully
async function submitWithValidation(data) {
try {
const response = await submitData(data);
return response;
} catch (error) {
if (error.response?.status === 400) {
const validationError = parseValidationError(error.response.data.error);
// Log specific field error
console.error(`Validation failed for ${validationError.field}: ${validationError.message}`);
// Return structured error for UI handling
return {
success: false,
field: validationError.field,
message: validationError.message
};
}
throw error;
}
}
3. Cache Validation Rules
Cache form validation rules to avoid repeated API calls:
class FormValidator {
constructor() {
this.cache = new Map();
}
async getValidationRules(workflowId) {
if (this.cache.has(workflowId)) {
return this.cache.get(workflowId);
}
const rules = await fetchFormSchema(workflowId);
this.cache.set(workflowId, rules);
return rules;
}
async validate(workflowId, data) {
const rules = await this.getValidationRules(workflowId);
return this.validateAgainstRules(data, rules);
}
}
Proper validation handling ensures data quality and provides clear feedback when submissions don't meet form requirements.