Form Builder Engine
Form Builder Engine
Overview
A comprehensive platform for creating dynamic forms with multi-page support, automatic data collection, response management, and analytics. The platform serves multiple services (Calls for Applications, Fund Applications, Innovation Programs, etc.) using a unified form builder engine.
Core Concepts
1. Platform Hierarchy
Platform
└── Services (Fund Applications, Calls, Innovation Programs)
└── Forms (Application Forms, Surveys, Feedback)
└── Responses (User Submissions)
2. Key Components
- Services: Programs, calls, or events that require data collection
- Forms: Customizable multi-page forms attached to services
- Responses: User submissions with answers to form fields
- Analytics: Insights and reports from collected responses
3. Null Handling Principle
Throughout this API, null values and omitted properties have specific meanings:
For Objects (settings, validation, cover_page, etc.):
- ❌
"settings": null- INVALID, don't set entire object to null - ✅
"settings": {"accept_responses": true, "require_login": null}- VALID - ✅
"settings": {}- VALID (empty object, use defaults) - ✅ Omit object entirely - VALID (use defaults)
For Individual Properties:
"max_length": null- No validation for this property"max_length": 100- Apply validation with value 100- Omit property entirely - Same as
null, no validation
Key Rule:
- Individual keys can be
null(means "not applicable" or "disabled") - Entire objects should NOT be
null(use empty object{}or omit instead)
Examples:
✅ Correct:
{
"validation": {
"min": null,
"max": 100
}
}
✅ Correct:
{
"validation": {}
}
✅ Correct:
{
// validation omitted entirely
}
❌ Incorrect:
{
"validation": null
}
Services
Service Structure
Services represent the various programs, calls, or initiatives on the platform. Each service can have one or more forms attached to it.
{
"service": {
"id": "uuid",
"name": "FUND_APPLICATION",
"title": "2026 Research Innovation Fund",
"description": "Annual research funding program",
"status": "ACTIVE",
"start_date": "2026-02-01T00:00:00Z",
"end_date": "2026-03-31T23:59:59Z",
"settings": {
"max_applications": 500,
"require_review": true,
"auto_acknowledge": true
},
"created_by": "uuid",
"created_at": "2026-01-01T00:00:00Z"
}
}
Service Types (Enums)
{
"service_types": [
"CALL_FOR_APPLICATIONS",
"FUND_APPLICATION",
"INNOVATION_APPLICATION",
"EVENT_REGISTRATION",
"SURVEY",
"FEEDBACK_FORM",
"SCHOLARSHIP_APPLICATION",
"VENDOR_REGISTRATION",
"MEMBERSHIP_APPLICATION"
]
}
Forms
Form Structure
Forms are the data collection instruments. Each form belongs to a service and contains pages with fields.
{
"form": {
"id": "uuid",
"title": "Startup Funding Application",
"description": "Apply for our startup incubator program",
"service_id": "uuid",
"service_name": "FUND_APPLICATION",
"status": "PUBLISHED",
"created_by": "uuid",
"created_at": "2026-01-10T00:00:00Z",
"cover_page": {
"enabled": true,
"title": "Welcome to Startup Funding 2026",
"description": "Thank you for your interest in our program. This application will take approximately 15 minutes to complete.",
"image_url": "https://example.com/cover-image.jpg",
"button_text": "Start Application"
},
"settings": {
"accept_responses": true,
"require_login": true,
"allow_multiple_submissions": false,
"response_deadline": "2026-03-31T23:59:59Z",
"send_confirmation_email": true,
"allow_save_draft": true
},
"structure": {
"pages": []
}
}
}
Cover Page
The cover page is an optional introduction screen shown before the first page of the form. It provides context and sets expectations for the user.
Cover Page Configuration:
Each property can be:
- Set to a value: Property is used
- Set to
null: Property not used (use defaults) - Omitted entirely: Property not used
Cover Page Properties:
enabled:true= show cover page,falseornull= skip to first pagetitle: String ornull(uses form title as default)description: String ornull(no description shown)image_url: String URL ornull(no image)button_text: String ornull(defaults to "Start")
Example with all properties:
{
"cover_page": {
"enabled": true,
"title": "2026 Research Innovation Fund Application",
"description": "Welcome! We're excited that you're applying for our research funding program. This application consists of 3 sections and will take approximately 20 minutes to complete. You can save your progress and return at any time.",
"image_url": "https://storage.example.com/fund-banner.jpg",
"button_text": "Start Application"
}
}
Example with nulls (minimal cover page):
{
"cover_page": {
"enabled": true,
"title": "Welcome",
"description": null, // No description
"image_url": null, // No image
"button_text": null // Defaults to "Start"
}
}
Example: No cover page:
{
"cover_page": {
"enabled": false,
"title": null,
"description": null,
"image_url": null,
"button_text": null
}
}
OR simply omit the cover_page object entirely.
When cover page is enabled, the user flow is:
- User opens form → sees cover page
- User clicks "Start Application" → navigates to first page
- User completes pages → submits form
When cover page is disabled:
- User opens form → directly loads first page
- User completes pages → submits form
Form Settings
Settings control form behavior and user experience. Each setting can be:
- Set to a value: Setting is applied
- Set to
null: Setting not applicable/disabled - Omitted entirely: Setting not applicable/disabled
IMPORTANT:
- ❌
"settings": null- This is INVALID, don't use this - ✅
"settings": {"accept_responses": true, "require_login": null}- This is VALID - ✅
"settings": {}- This is VALID (all settings disabled/default)
Available Settings:
- accept_responses:
true= accepting submissions,false= closed,null= default (true) - require_login:
true= authenticated only,false= allow anonymous,null= default (false) - allow_multiple_submissions:
true= multiple allowed,false= one per user,null= default (false) - response_deadline: ISO datetime string or
null(no deadline) - send_confirmation_email:
true= send email,false= no email,null= default (false) - allow_save_draft:
true= can save drafts,false= must complete,null= default (false)
Examples:
// All settings specified
{
"settings": {
"accept_responses": true,
"require_login": true,
"allow_multiple_submissions": false,
"response_deadline": "2026-03-31T23:59:59Z",
"send_confirmation_email": true,
"allow_save_draft": true
}
}
// Some settings null (not applicable)
{
"settings": {
"accept_responses": true,
"require_login": true,
"allow_multiple_submissions": false,
"response_deadline": null, // No deadline
"send_confirmation_email": null, // Use default (false)
"allow_save_draft": true
}
}
// Minimal settings (others default)
{
"settings": {
"accept_responses": true,
"require_login": true
}
}
Form Structure
Pages
Forms are organized into pages for better user experience and logical grouping.
{
"structure": {
"pages": [
{
"page_id": "uuid",
"title": "Basic Information",
"description": "Tell us about your company",
"order": 1,
"action": {
"type": "NEXT",
"button_text": "Continue",
"next_page_id": "uuid-page-2"
},
"fields": []
},
{
"page_id": "uuid-page-2",
"title": "Project Details",
"description": "Describe your project",
"order": 2,
"action": {
"type": "SUBMIT",
"button_text": "Submit Application",
"next_page_id": null
},
"fields": []
}
]
}
}
Page Properties:
page_id: Unique identifier (UUID)title: Page heading displayed to usersdescription: Optional help text for the pageorder: Display sequence (1, 2, 3...)action: What happens when user completes this pagefields: Array of field definitions
Page Actions:
Pages can have different actions that determine what happens when the user clicks the button at the bottom of the page.
Action Types:
{
"action": {
"type": "NEXT",
"button_text": "Continue",
"next_page_id": "uuid-of-next-page"
}
}
- SUBMIT_AND_NEXT - Save as draft and go to next page
{
"action": {
"type": "SUBMIT_AND_NEXT",
"button_text": "Save & Continue",
"next_page_id": "uuid-of-next-page"
}
}
- SUBMIT - Final submission (last page)
{
"action": {
"type": "SUBMIT",
"button_text": "Submit Application",
"next_page_id": null
}
}
The action type determines:
Fields
Field Types
Fields are the individual input elements within pages. The platform supports various field types:
Standard Input Fields
TEXT
- Single-line text input
- Use for: names, titles, short answers
- Validation: min_length, max_length
TEXTAREA
- Multi-line text input
- Use for: descriptions, essays, detailed answers
- Validation: min_length, max_length
- Email address with format validation
- Use for: contact emails, business emails
- Validation: email format (automatic)
PHONE
- Phone number input
- Use for: contact numbers, mobile phones
- Validation: phone format (automatic)
NUMBER
- Numeric input
- Use for: age, quantity, amounts
- Validation: min, max
URL
- Website URL with validation
- Use for: company website, portfolio links
- Validation: url format (automatic)
DATE
- Date picker
- Use for: birth dates, project start dates
- Validation: min_date, max_date
TIME
- Time picker
- Use for: meeting times, availability
- Validation: time format (automatic)
DATETIME
- Combined date and time picker
- Use for: event dates, deadlines
- Validation: min_datetime, max_datetime
DROPDOWN
- Select one option from dropdown
- Use for: countries, industries, categories
- Requires: options array with option_id
RADIO
CHECKBOX
- Multiple selection checkboxes
- Use for: skills, interests, technologies
- Requires: options array with option_id
- Validation: min_selections, max_selections
FILE
- File upload
- Use for: resumes, pitch decks, documents
- Validation: accept (file types), max_size_mb
RATING
- Star or numeric rating
- Use for: satisfaction, skill level
- Configuration: max_rating (e.g., 5 stars)
SCALE
- Linear scale (1-10)
- Use for: agreement scales, priority levels
- Configuration: min_value, max_value
SLIDER
- Draggable slider
- Use for: budget ranges, confidence levels
- Configuration: min, max, step
ADDRESS
- Full address input
- Use for: mailing addresses, office locations
- Auto-formats address fields
CURRENCY
- Currency amount input
- Use for: funding amounts, budgets
- Configuration: currency_code
- Validation: min, max
SIGNATURE
- Digital signature capture
- Use for: agreements, authorizations
Display Fields
SECTION_HEADER
- Visual divider with heading text
- Use for: organizing form sections
PARAGRAPH
- Display-only text
- Use for: instructions, disclaimers, information
Auto-Collect Fields
- Auto-fill from user's social profile
- Can pull: email, phone, name, organization, etc.
- User can modify if allowed
SYSTEM_FIELD
- Auto-populated system metadata
- Examples: timestamps, IPs, user IDs, service context
- Never user-modifiable
Field Definition
Complete Field Structure
{
"field": {
"field_id": "uuid",
"order": 1,
"type": "TEXT",
"label": "Company Name",
"description": "Enter your registered company name",
"placeholder": "e.g., Tech Innovations Inc",
"required": true,
"validation": {
"min_length": 2,
"max_length": 100
}
}
}
Field Properties Explained
Core Properties:
field_id: Unique identifier (UUID)order: Display sequence within the pagetype: Field type (TEXT, EMAIL, DROPDOWN, etc.)label: Question or field label shown to userdescription: Help text displayed below the fieldplaceholder: Example text inside inputrequired: Whether field must be answered
Validation:
- Rules to ensure data quality
- Type-specific validators (min_length, max, min_date, etc.)
- System generates appropriate error messages
Options (for selection fields):
- DROPDOWN, RADIO, CHECKBOX require
optionsarray - Each option has:
option_id,label,order
Social Profile Fields
Purpose
Automatically populate user information from their profile to reduce friction and ensure data accuracy.
Configuration
{
"field": {
"field_id": "uuid",
"order": 1,
"type": "SOCIAL_PROFILE",
"label": "Your Information",
"description": "This will be auto-filled from your profile",
"profile_id": "user_profile_id",
"user_can_modify": true,
"required": true
}
}
No need to specify which profile fields to pull! The system automatically returns all available profile data:
- PHONE
- FIRST_NAME
- LAST_NAME
- FULL_NAME
- PROFILE_PICTURE
- DATE_OF_BIRTH
- GENDER
- ADDRESS
- COUNTRY
- CITY
- ORGANIZATION
- JOB_TITLE
- DEPARTMENT
- LANGUAGE
- TIMEZONE
If a field doesn't exist in the user's profile, it will be null or omitted.
User Control
user_can_modify:
true: User can edit the auto-filled valuesfalse: All fields are read-only, user cannot change anything
Privacy & Consent
Sensitive profile fields include:
- PHONE
- DATE_OF_BIRTH
- ADDRESS
How Consent Works:
{
"field": {
"field_id": "uuid",
"order": 1,
"type": "SOCIAL_PROFILE",
"label": "Your Contact Information",
"description": "This will be auto-filled from your profile",
"profile_id": "user_profile_id",
"user_can_modify": true,
"required": true,
"requires_consent": true,
"consent_text": "I consent to sharing my email and phone number for this application."
}
}
Consent Properties:
requires_consent: Set totruefor sensitive dataconsent_text: Custom message explaining what data is being collected and why
When Form Loads:
Non-Sensitive Profile Fields (No Consent Required):
- FIRST_NAME
- LAST_NAME
- FULL_NAME
- PROFILE_PICTURE
- ORGANIZATION
- JOB_TITLE
- DEPARTMENT
- LANGUAGE
- TIMEZONE
- COUNTRY
- CITY (without full address)
You can add multiple SOCIAL_PROFILE fields in the same form with different settings:
{
"fields": [
{
"field_id": "field-uuid-1",
"type": "SOCIAL_PROFILE",
"label": "Primary Contact Information",
"profile_id": "user_profile_id",
"user_can_modify": true
},
{
"field_id": "field-uuid-2",
"type": "SOCIAL_PROFILE",
"label": "Account Details (Read-only)",
"profile_id": "user_profile_id",
"user_can_modify": false
}
]
}
Both pull from the same profile but have different modification permissions.
System Fields
Purpose
Capture system-generated metadata automatically without user input. Used for tracking, auditing, and context.
Configuration
{
"field": {
"field_id": "uuid",
"order": 99,
"type": "SYSTEM_FIELD",
"label": "Submission Timestamp",
"system_field_type": "SUBMISSION_TIMESTAMP",
"user_can_modify": false,
"show_in_form": false
}
}
Available System Field Types
User Context:
- USER_ID: Unique user identifier
- REGISTRATION_DATE: When user registered on platform
Submission Context:
- SUBMISSION_TIMESTAMP: Exact time of form submission
- IP_ADDRESS: User's IP address
- USER_AGENT: Browser and device information
- DEVICE_TYPE: Desktop, Mobile, or Tablet
- BROWSER: Browser name and version
- REFERRER_URL: Page user came from
Service Context:
- SERVICE_ID: Associated service UUID
- SERVICE_NAME: Service type (FUND_APPLICATION, etc.)
- FORM_ID: Form UUID
- FORM_TITLE: Name of the form
Characteristics
- Always
user_can_modify: false - Usually
show_in_form: false(hidden) - Auto-populated at submission time
- Cannot be edited by users
Privacy & Consent
Sensitive system fields require user consent before collection:
Sensitive fields include:
- EMAIL (from user profile)
- PHONE (from user profile)
- IP_ADDRESS
- USER_AGENT
- DEVICE_TYPE
- BROWSER
- REFERRER_URL
How Consent Works:
- Form must display consent checkbox for each sensitive field type being collected
- User must explicitly check the box to accept data collection
- Form cannot be submitted until consent is given
- Consent is recorded with the response
Consent Configuration:
{
"field": {
"field_id": "uuid",
"order": 99,
"type": "SYSTEM_FIELD",
"label": "IP Address",
"system_field_type": "IP_ADDRESS",
"user_can_modify": false,
"show_in_form": false,
"requires_consent": true,
"consent_text": "I agree to share my IP address for security and fraud prevention purposes."
}
}
Multiple Consents Example:
{
"fields": [
{
"field_id": "sys-field-1",
"type": "SYSTEM_FIELD",
"system_field_type": "IP_ADDRESS",
"requires_consent": true,
"consent_text": "I consent to collection of my IP address for security purposes."
},
{
"field_id": "sys-field-2",
"type": "SYSTEM_FIELD",
"system_field_type": "USER_AGENT",
"requires_consent": true,
"consent_text": "I consent to collection of my browser information for analytics."
}
]
}
Non-Sensitive Fields (No Consent Required):
- USER_ID
- SUBMISSION_TIMESTAMP
- SERVICE_ID
- SERVICE_NAME
- FORM_ID
- FORM_TITLE
These are necessary for basic form functionality and don't require explicit consent.
Field Examples
Text Field
{
"field_id": "uuid",
"order": 1,
"type": "TEXT",
"label": "Company Name",
"placeholder": "e.g., Acme Corporation",
"required": true,
"validation": {
"min_length": 2,
"max_length": 100
}
}
Email Field
{
"field_id": "uuid",
"order": 2,
"type": "EMAIL",
"label": "Contact Email",
"placeholder": "name@company.com",
"required": true,
"validation": {
"email_format": true
}
}
Dropdown Field
{
"field_id": "uuid",
"order": 3,
"type": "DROPDOWN",
"label": "Industry",
"placeholder": "Select your industry",
"required": true,
"options": [
{"option_id": "opt-tech-uuid", "label": "Technology", "order": 1},
{"option_id": "opt-health-uuid", "label": "Healthcare", "order": 2},
{"option_id": "opt-finance-uuid", "label": "Finance", "order": 3},
{"option_id": "opt-education-uuid", "label": "Education", "order": 4}
]
}
Response (selected option_id):
{
"answers": {
"field-uuid-industry": {
"value": "opt-tech-uuid",
"answered_at": "2026-01-15T14:28:30Z",
"auto_populated": false,
"edited": false
}
}
}
Radio Button Field
{
"field_id": "uuid",
"order": 4,
"type": "RADIO",
"label": "Company Stage",
"required": true,
"options": [
{"option_id": "opt-idea-uuid", "label": "Idea Stage", "order": 1},
{"option_id": "opt-mvp-uuid", "label": "MVP", "order": 2},
{"option_id": "opt-revenue-uuid", "label": "Revenue Generating", "order": 3}
]
}
Response (selected option_id):
{
"answers": {
"field-uuid-stage": {
"value": "opt-mvp-uuid",
"answered_at": "2026-01-15T14:26:00Z",
"auto_populated": false,
"edited": false
}
}
}
File Upload Field
{
"field_id": "uuid",
"order": 5,
"type": "FILE",
"label": "Pitch Deck",
"description": "Upload your presentation",
"required": true,
"validation": {
"accept": ".pdf,.ppt,.pptx",
"max_size_mb": 10,
"multiple": false
}
}
Number Field (for currency, amounts, etc.)
{
"field_id": "uuid",
"order": 6,
"type": "NUMBER",
"label": "Funding Amount Requested (USD)",
"placeholder": "50000",
"required": true,
"validation": {
"min": 1000,
"max": 100000
}
}
Checkbox Field
{
"field_id": "uuid",
"order": 7,
"type": "CHECKBOX",
"label": "Technologies Used",
"description": "Select all that apply",
"required": true,
"options": [
{
"option_id": "opt-uuid-1",
"label": "Artificial Intelligence",
"order": 1
},
{
"option_id": "opt-uuid-2",
"label": "Blockchain",
"order": 2
},
{
"option_id": "opt-uuid-3",
"label": "Internet of Things",
"order": 3
},
{
"option_id": "opt-uuid-4",
"label": "Cloud Computing",
"order": 4
}
],
"validation": {
"min_selections": 1,
"max_selections": 3
}
}
Response (array of option_ids):
{
"answers": {
"field-uuid-tech": {
"value": ["opt-uuid-1", "opt-uuid-2"],
"answered_at": "2026-01-15T14:25:00Z",
"auto_populated": false,
"edited": false
}
}
}
Validation System
How Validation Works
Validation is defined by individual keys within the validation object. Each key can be:
- Set to a value: Validation is applied
- Set to
null: No validation for that specific rule - Omitted entirely: No validation for that specific rule
IMPORTANT:
- ❌
"validation": null- This is INVALID, don't use this - ✅
"validation": {"min": null, "max": 20}- This is VALID (no min, but max is 20) - ✅
"validation": {}- This is VALID (no validation at all) - ✅ Omit validation object entirely - This is VALID (no validation at all)
Examples
No validation at all:
{
"type": "TEXT"
// No validation object at all
}
OR
{
"type": "TEXT",
"validation": {}
// Empty validation object
}
Only maximum (no minimum):
{
"type": "NUMBER",
"validation": {
"min": null, // No minimum validation
"max": 100 // Maximum is 100
}
}
Only minimum (no maximum):
{
"type": "TEXT",
"validation": {
"min_length": 5, // Minimum 5 characters
"max_length": null // No maximum limit
}
}
Both min and max:
{
"type": "NUMBER",
"validation": {
"min": 1,
"max": 100
}
}
Validation Rules by Field Type
TEXT / TEXTAREA:
{
"validation": {
"min_length": 2, // null or omit = no minimum
"max_length": 100 // null or omit = no maximum
}
}
NUMBER:
{
"validation": {
"min": 1000, // null or omit = no minimum
"max": 100000 // null or omit = no maximum
}
}
DATE:
{
"validation": {
"min_date": "2026-01-01", // null or omit = any past date allowed
"max_date": "2026-12-31" // null or omit = any future date allowed
}
}
FILE:
{
"validation": {
"accept": ".pdf,.doc,.docx", // null or omit = any file type
"max_size_mb": 10, // null or omit = no size limit
"multiple": false // true allows multiple files
}
}
CHECKBOX:
{
"validation": {
"min_selections": 1, // null or omit = no minimum
"max_selections": 3 // null or omit = unlimited selections
}
}
EMAIL / PHONE / URL:
{
"validation": {
"format": true // Always validates format for these types (automatic)
}
}
// Or just omit validation object entirely - format validation is automatic
{
"type": "EMAIL"
// Format validation applied automatically
}
Complete Form Example
{
"form": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Startup Funding Application 2026",
"description": "Apply for our startup incubator program",
"service_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"service_name": "FUND_APPLICATION",
"status": "PUBLISHED",
"cover_page": {
"enabled": true,
"title": "Welcome to Startup Funding 2026",
"description": "Thank you for your interest! This application takes about 15 minutes. You can save and continue later.",
"image_url": "https://storage.example.com/cover.jpg",
"button_text": "Start Application"
},
"structure": {
"pages": [
{
"page_id": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d",
"title": "Applicant Information",
"description": "Tell us about yourself and your company",
"order": 1,
"action": {
"type": "NEXT",
"button_text": "Continue to Project Details",
"next_page_id": "b2c3d4e5-f6a7-4b5c-8d9e-0f1a2b3c4d5e"
},
"fields": [
{
"field_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"order": 1,
"type": "SOCIAL_PROFILE",
"label": "Your Information",
"description": "This will be auto-filled from your profile",
"profile_id": "user_profile_id",
"user_can_modify": true,
"required": true
},
{
"field_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"order": 2,
"type": "TEXT",
"label": "Company Name",
"placeholder": "e.g., Tech Innovations Inc",
"required": true,
"validation": {
"min_length": 2,
"max_length": 100
}
},
{
"field_id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"order": 3,
"type": "URL",
"label": "Company Website",
"placeholder": "https://www.example.com",
"required": false
}
]
},
{
"page_id": "b2c3d4e5-f6a7-4b5c-8d9e-0f1a2b3c4d5e",
"title": "Project Details",
"description": "Tell us about your project and funding needs",
"order": 2,
"action": {
"type": "SUBMIT_AND_NEXT",
"button_text": "Save & Continue to Documents",
"next_page_id": "c3d4e5f6-a7b8-4c5d-9e0f-1a2b3c4d5e6f"
},
"fields": [
{
"field_id": "field-uuid-1",
"order": 1,
"type": "TEXTAREA",
"label": "Project Description",
"description": "Describe your project objectives and expected impact",
"placeholder": "Tell us about your project...",
"required": true,
"validation": {
"min_length": 100,
"max_length": 2000
}
},
{
"field_id": "field-uuid-2",
"order": 2,
"type": "DROPDOWN",
"label": "Industry",
"placeholder": "Select your industry",
"required": true,
"options": [
{
"option_id": "opt-tech-uuid",
"label": "Technology",
"order": 1
},
{
"option_id": "opt-health-uuid",
"label": "Healthcare",
"order": 2
},
{
"option_id": "opt-finance-uuid",
"label": "Finance",
"order": 3
}
]
},
{
"field_id": "field-uuid-3",
"order": 3,
"type": "NUMBER",
"label": "Funding Amount Requested (USD)",
"placeholder": "50000",
"required": true,
"validation": {
"min": 1000,
"max": 100000
}
},
{
"field_id": "field-uuid-4",
"order": 4,
"type": "CHECKBOX",
"label": "Technologies Used",
"description": "Select all that apply",
"required": true,
"options": [
{
"option_id": "tech-ai-uuid",
"label": "Artificial Intelligence",
"order": 1
},
{
"option_id": "tech-bc-uuid",
"label": "Blockchain",
"order": 2
},
{
"option_id": "tech-iot-uuid",
"label": "IoT",
"order": 3
}
],
"validation": {
"min_selections": 1,
"max_selections": 3
}
}
]
},
{
"page_id": "c3d4e5f6-a7b8-4c5d-9e0f-1a2b3c4d5e6f",
"title": "Documents",
"description": "Upload required documents",
"order": 3,
"action": {
"type": "SUBMIT",
"button_text": "Submit Application",
"next_page_id": null
},
"fields": [
{
"field_id": "field-uuid-5",
"order": 1,
"type": "FILE",
"label": "Pitch Deck",
"description": "Upload your presentation",
"required": true,
"validation": {
"accept": ".pdf,.ppt,.pptx",
"max_size_mb": 10,
"multiple": false
}
},
{
"field_id": "field-uuid-6",
"order": 2,
"type": "DATE",
"label": "Proposed Project Start Date",
"required": true,
"validation": {
"min_date": "2026-02-01",
"max_date": "2026-12-31"
}
}
]
}
]
}
}
}
Responses
Response Structure
When a user submits a form, a response is created containing all their answers.
{
"response": {
"id": "9b7d8f6a-3c2e-4b1a-9d8f-7e6c5b4a3d2e",
"form_id": "550e8400-e29b-41d4-a716-446655440000",
"service_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"service_name": "FUND_APPLICATION",
"submitted_by": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"submitted_at": "2026-01-15T14:30:00Z",
"status": "SUBMITTED",
"completion_time_seconds": 245,
"consents": {
"social_profile_email_phone": {
"field_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"consented": true,
"consented_at": "2026-01-15T14:24:30Z",
"consent_text": "I consent to sharing my email and phone number for this application."
},
"ip_address": {
"field_id": "sys-field-ip",
"consented": true,
"consented_at": "2026-01-15T14:24:35Z",
"consent_text": "I consent to collection of my IP address for security purposes."
}
},
"answers": {},
"metadata": {
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"browser": "Chrome",
"device": "Desktop",
"started_at": "2026-01-15T14:24:55Z"
}
}
}
Response Status
Responses can have different statuses throughout their lifecycle:
- DRAFT: User started but hasn't submitted
- SUBMITTED: User completed and submitted
- UNDER_REVIEW: Being reviewed by administrators
- APPROVED: Accepted/approved
- REJECTED: Not accepted
- WITHDRAWN: User withdrew their submission
Answer Format
Object Structure
Answers are stored as an object where keys are field IDs and values contain the answer data.
{
"answers": {
"field_uuid_1": {
"value": "answer value",
"answered_at": "2026-01-15T14:25:00Z",
"auto_populated": false,
"edited": false
},
"field_uuid_2": {
"value": "another answer",
"answered_at": "2026-01-15T14:25:30Z",
"auto_populated": false,
"edited": true,
"edit_count": 2,
"last_edited_at": "2026-01-15T14:26:00Z"
}
}
}
Answer Properties
Core:
value: The actual answer (string, number, array, object, etc.)answered_at: Timestamp when answered
Tracking:
auto_populated: Was this auto-filled?edited: Did user modify it?edit_count: How many times editedlast_edited_at: When last modified
Source (for auto-populated):
source: Where data came from (social_profile, system)profile_id: For social profile fieldssystem_field_type: For system fields
Files:
file_url: URL to uploaded filefile_name: Original filenamefile_size: Size in bytesfile_type: MIME type
Answer Examples by Field Type
Text/Textarea/Email/Phone/URL:
{
"field-uuid": {
"value": "Tech Innovations Inc",
"answered_at": "2026-01-15T14:26:00Z"
}
}
Number:
{
"field-uuid": {
"value": 75000,
"answered_at": "2026-01-15T14:29:00Z"
}
}
Dropdown (stores selected option_id):
{
"field-uuid-industry": {
"value": "opt-tech-uuid",
"answered_at": "2026-01-15T14:28:30Z"
}
}
Radio (stores selected option_id):
{
"field-uuid-stage": {
"value": "opt-mvp-uuid",
"answered_at": "2026-01-15T14:26:00Z"
}
}
Checkbox (stores array of option_ids):
{
"field-uuid-tech": {
"value": ["opt-uuid-1", "opt-uuid-2"],
"answered_at": "2026-01-15T14:25:00Z"
}
}
Date:
{
"field-uuid-date": {
"value": "2026-06-15",
"answered_at": "2026-01-15T14:29:30Z"
}
}
File:
{
"field-uuid-file": {
"value": null,
"answered_at": "2026-01-15T14:29:30Z",
"file_url": "https://storage.example.com/uploads/pitch-deck.pdf",
"file_name": "pitch-deck.pdf",
"file_size": 2048576,
"file_type": "application/pdf"
}
}
Complete Response Example
{
"response": {
"id": "9b7d8f6a-3c2e-4b1a-9d8f-7e6c5b4a3d2e",
"form_id": "550e8400-e29b-41d4-a716-446655440000",
"service_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"service_name": "FUND_APPLICATION",
"submitted_by": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"submitted_at": "2026-01-15T14:30:00Z",
"status": "SUBMITTED",
"completion_time_seconds": 245,
"consents": {
"social_profile_contact": {
"field_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"consented": true,
"consented_at": "2026-01-15T14:24:30Z",
"consent_text": "I consent to sharing my email and phone number for this application."
},
"system_ip_tracking": {
"field_id": "sys-field-ip",
"consented": true,
"consented_at": "2026-01-15T14:24:35Z",
"consent_text": "I consent to collection of my IP address for security purposes."
}
},
"answers": {
"f47ac10b-58cc-4372-a567-0e02b2c3d479": {
"value": {
"EMAIL": "founder@techinnovations.com",
"PHONE": "+1234567890",
"FULL_NAME": "John Doe",
"ORGANIZATION": "Tech Innovations Inc"
},
"answered_at": "2026-01-15T14:25:00Z",
"auto_populated": true,
"source": "social_profile",
"profile_id": "user_profile_id",
"edited": true,
"edited_fields": ["EMAIL"],
"user_can_modify": true
},
"6ba7b810-9dad-11d1-80b4-00c04fd430c8": {
"value": "Tech Innovations Inc",
"answered_at": "2026-01-15T14:26:00Z",
"auto_populated": false,
"edited": false
},
"3f2504e0-4f89-41d3-9a0c-0305e82c3301": {
"value": "https://techinnovations.com",
"answered_at": "2026-01-15T14:26:30Z",
"auto_populated": false,
"edited": false
},
"c3d4e5f6-a7b8-4c5d-9e0f-1a2b3c4d5e6f": {
"value": "Our project aims to revolutionize climate modeling using AI...",
"answered_at": "2026-01-15T14:28:00Z",
"auto_populated": false,
"edited": false
},
"d4e5f6a7-b8c9-4d5e-0f1a-2b3c4d5e6f7a": {
"value": "opt-tech-uuid",
"answered_at": "2026-01-15T14:28:30Z",
"auto_populated": false,
"edited": false
},
"e5f6a7b8-c9d0-4e5f-1a2b-3c4d5e6f7a8b": {
"value": 75000,
"answered_at": "2026-01-15T14:29:00Z",
"auto_populated": false,
"edited": false
},
"field-uuid-4": {
"value": ["tech-ai-uuid", "tech-bc-uuid"],
"answered_at": "2026-01-15T14:29:15Z",
"auto_populated": false,
"edited": false
},
"a7b8c9d0-e1f2-4a5b-3c4d-5e6f7a8b9c0d": {
"value": null,
"answered_at": "2026-01-15T14:29:30Z",
"auto_populated": false,
"edited": false,
"file_url": "https://storage.example.com/uploads/pitch-deck.pdf",
"file_name": "pitch-deck.pdf",
"file_size": 2048576,
"file_type": "application/pdf"
}
},
"metadata": {
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"browser": "Chrome 120.0",
"device": "Desktop",
"location": {
"country": "US",
"city": "San Francisco"
},
"started_at": "2026-01-15T14:24:55Z",
"last_saved_at": "2026-01-15T14:29:45Z"
}
}
}
User Flows
1. Admin Creates Service
Steps:
Result: Active service ready to have forms attached
2. Admin Creates Form
Steps:
Result: Empty form ready for fields
3. Admin Builds Form
Steps:
Add Page:
- Click "Add Page"
- Enter page title and description
- Page receives order number (1, 2, 3...)
Add Regular Field:
- Select page
- Click "Add Field"
- Choose field type (TEXT, EMAIL, DROPDOWN, etc.)
- Configure field:
- Label
- Description/placeholder
- Required/optional
- Validation rules
- Type-specific properties
- Field receives:
- UUID
- Order number within page
- Click "Add Field"
- Choose "Social Profile"
- Select which profile fields to pull:
- PHONE
- FULL_NAME
- etc.
- Configure:
- Can user modify? (yes/no)
- Show in form? (yes/no)
- Read-only display? (yes/no)
- Field is created with
type: SOCIAL_PROFILE
Add System Field:
- Click "Add Field"
- Choose "System Field"
- Select system field type:
- SUBMISSION_TIMESTAMP
- USER_ID
- IP_ADDRESS
- etc.
- System fields are typically:
- Not modifiable
- Hidden from users
- Auto-populated on submission
Reorder:
- Drag and drop to reorder pages
- Drag and drop to reorder fields within pages
- Order numbers update automatically
Result: Complete multi-page form ready for publishing
4. Admin Publishes Form
Steps:
- Review form structure
- Test form (preview mode)
- Change status to "PUBLISHED"
- Form becomes available to users
Result: Users can now access and submit form
5. User Submits Form
Steps:
Form Load:
- User fills in fields on current page
- User clicks page action button (e.g., "Continue", "Save & Continue")
- System validates required fields
- Based on action type:
- NEXT: Move to next page (no save)
- SUBMIT_AND_NEXT: Save as draft, move to next page
- SUBMIT: Final submission
- System navigates to
next_page_id(if specified)
Final Submission:
- User completes last page
- User clicks "Submit Application" button (type: SUBMIT)
- System validates all required fields across all pages
- Response created with status "SUBMITTED"
- Consents recorded:
- All consent decisions saved with timestamps
- Consent text recorded for audit trail
- Cannot be modified after submission
- System fields auto-populated (only if consent was given):
- USER_ID
- SUBMISSION_TIMESTAMP
- IP_ADDRESS (if consented)
- USER_AGENT (if consented)
- etc.
- Confirmation email sent (if enabled)
- User redirected to thank you page
Draft Saving:
- If
allow_save_draft: truein form settings - User can save progress at any time
- Response saved with status "DRAFT"
- User can return and continue later
Result: Complete response stored in system
Key Takeaways
Selection Fields Use option_id
All selection-based fields (DROPDOWN, RADIO, CHECKBOX) use option_id in their configuration:
{
"options": [
{"option_id": "uuid-1", "label": "Option 1", "order": 1},
{"option_id": "uuid-2", "label": "Option 2", "order": 2}
]
}
Responses Store option_id Values
When users select options, responses store the option_id:
- DROPDOWN & RADIO: Single
option_idstring - CHECKBOX: Array of
option_idstrings
{
"answers": {
"dropdown-field": {"value": "opt-uuid-1"},
"radio-field": {"value": "opt-uuid-2"},
"checkbox-field": {"value": ["opt-uuid-1", "opt-uuid-3"]}
}
}
This ensures data integrity and allows option labels to be updated without affecting existing responses.
Privacy & Consent Required
Sensitive data collection requires explicit user consent:
Sensitive Fields:
- EMAIL, PHONE (from social profile)
- IP_ADDRESS, USER_AGENT, BROWSER (system fields)
- DATE_OF_BIRTH, ADDRESS (from social profile)
Consent Flow:
- Field configured with
requires_consent: true - User sees consent checkbox with
consent_text - User must check box to proceed
- Consent decision recorded with timestamp
- Data only collected if consent given
{
"requires_consent": true,
"consent_text": "I consent to collection of my email for communication purposes."
}
Non-Sensitive Fields (no consent needed):
- USER_ID, SUBMISSION_TIMESTAMP, FORM_ID
- FIRST_NAME, LAST_NAME, ORGANIZATION
- COUNTRY, CITY (without full address)