Skip to main content

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

  1. Required Fields: Must be present in the request
  2. Data Types: Must match expected types (string, number, etc.)
  3. Format Validation: Email, date, phone number formats
  4. Input Masks: Pattern matching for formatted fields
  5. Length Limits: Minimum and maximum length constraints
  6. 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 TypeExpected JSON TypeValidation Rules
textfieldstringLength limits, pattern matching
textareastringLength limits
emailstringValid email format
numbernumberNumeric value, min/max ranges
datestringISO date format (YYYY-MM-DD)
datetimestringISO datetime format
checkboxbooleantrue or false
selectstringMust match available options
radiostringMust match available options
selectboxesobjectKeys 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 MaskPatternExampleDescription
999-999-9999Phone numbers123-456-7890US phone format
(999) 999-9999Phone numbers(123) 456-7890US phone with parentheses
aa-999Code formatsAB-123Letter-number combination
9999-99-99Date formats2024-01-15Date with dashes
99/99/9999Date formats01/15/2024US date format
AAA-999Product codesABC-123Uppercase 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

  1. Start Simple: Test with minimal required fields
  2. Add Complexity: Gradually add optional and complex fields
  3. Test Edge Cases: Try boundary values and invalid formats
  4. Verify Error Messages: Ensure error messages are helpful
  5. 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.