Forms API
Overview
The Forms API provides comprehensive management of web forms for lead capture, data collection, and customer engagement. Built on the powerful SurveyJS framework, Stack9 Forms enable you to create sophisticated multi-page forms with advanced logic, custom themes, and seamless integration with your marketing automation workflows.
Resource Description
Forms in Stack9 consist of:
- Form Configuration: Core form settings including name, type, and CORS configuration
- SurveyJS Schema: Complete form structure with pages, questions, validation rules, and conditional logic
- Form Themes: Visual styling and branding options for consistent user experience
- Submission Management: Capture and process form responses with automatic subscriber creation
- Post-Submit Actions: Configurable actions triggered after form submission
- Analytics & Tracking: Monitor form performance, conversion rates, and user behavior
Key Features
- Visual Form Builder: Create forms using SurveyJS's powerful drag-and-drop interface
- Advanced Question Types: Support for 20+ question types including matrices, ratings, and file uploads
- Conditional Logic: Show/hide questions based on previous answers
- Multi-Page Forms: Create wizard-style forms with progress indicators
- Custom Themes: Apply branded themes with full control over colors, fonts, and layout
- CORS Configuration: Secure form embedding with domain whitelist controls
- Real-Time Validation: Client-side and server-side validation rules
- Submission Tracking: Complete audit trail of all form submissions
- Lead Capture Integration: Automatic subscriber creation from form submissions
- Journey Triggers: Initiate marketing automation workflows on form completion
Authentication
All endpoints require API key authentication:
X-API-Key: your-api-key-here
Form Settings
Get Form Settings
Retrieve configuration options and metadata for form management.
GET /api/forms/settings
Example Request
curl -X GET \
https://apis.app.stack9.co/api/forms/settings \
-H 'X-API-Key: your-api-key-here'
Example Response
{
"formTypes": [
{
"key": "embedded_form",
"name": "Embedded Form",
"description": "Form that can be embedded in external websites"
}
],
"postSubmitActionTypes": [
{
"key": "redirect",
"name": "Redirect to URL",
"description": "Redirect user to a specific URL after submission"
},
{
"key": "show_message",
"name": "Show Message",
"description": "Display a custom thank you message"
},
{
"key": "trigger_journey",
"name": "Trigger Journey",
"description": "Start a marketing automation journey"
}
],
"surveyLicenseKey": "xxxxx-xxxxx-xxxxx"
}
Form Management
Create Form
Create a new form with SurveyJS configuration and settings.
POST /api/forms
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the form |
allowed_origins | array | Yes | Domains allowed to embed this form. Use ["*"] for all domains |
active | boolean | Yes | Whether form accepts submissions |
form_type | string | Yes | Type of form (must be "embedded_form") |
business_unit | string | No | Business unit identifier |
surveyJsOptions | object | Yes | Complete SurveyJS form configuration |
surveyJsOptions.title | string | No | Form title displayed to users |
surveyJsOptions.description | string | No | Form description or instructions |
surveyJsOptions.logo | string | No | Logo URL for form header |
surveyJsOptions.pages | array | Yes | Array of form pages with questions |
surveyJsOptions.completedHtml | string | No | HTML shown after form completion |
surveyJsOptions.showProgressBar | string | No | Progress bar display ("top", "bottom", "both", "none") |
Example Request
curl -X POST \
https://apis.app.stack9.co/api/forms \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"name": "Newsletter Signup",
"allowed_origins": ["https://example.com", "https://www.example.com"],
"active": true,
"form_type": "embedded_form",
"business_unit": "marketing",
"surveyJsOptions": {
"title": "Join Our Newsletter",
"description": "Get weekly updates and exclusive content",
"logo": "https://example.com/logo.png",
"logoWidth": "200px",
"logoHeight": "60px",
"logoPosition": "right",
"showProgressBar": "top",
"completedHtml": "<h3>Thank you!</h3><p>You have been successfully subscribed.</p>",
"pages": [
{
"name": "page1",
"title": "Contact Information",
"elements": [
{
"type": "text",
"name": "email",
"title": "Email Address",
"inputType": "email",
"isRequired": true,
"validators": [
{
"type": "email",
"text": "Please enter a valid email address"
}
]
},
{
"type": "text",
"name": "firstName",
"title": "First Name",
"isRequired": true
},
{
"type": "text",
"name": "lastName",
"title": "Last Name",
"isRequired": false
},
{
"type": "dropdown",
"name": "interests",
"title": "What are you interested in?",
"choices": [
"Product Updates",
"Industry News",
"Tips & Tutorials",
"Case Studies"
],
"isRequired": true
}
]
},
{
"name": "page2",
"title": "Preferences",
"elements": [
{
"type": "radiogroup",
"name": "frequency",
"title": "How often would you like to hear from us?",
"choices": [
"Weekly",
"Bi-weekly",
"Monthly"
],
"defaultValue": "Weekly"
},
{
"type": "checkbox",
"name": "consent",
"title": "I agree to receive marketing communications",
"isRequired": true,
"validators": [
{
"type": "expression",
"text": "You must agree to continue",
"expression": "{consent} = true"
}
]
}
]
}
]
}
}'
Example Response
{
"code": "form_Xk9mNp2Q"
}
List Forms
Retrieve a paginated list of forms with advanced filtering options.
POST /api/forms/list
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | number | Yes | Page number (1-based) |
limit | number | Yes | Items per page (max: 100) |
search | string | No | Search across form names |
filters | object | Yes | Filter criteria object |
filters.name | object | No | Filter by form name |
filters.active | object | No | Filter by active status |
filters.form_type | object | No | Filter by form type |
filters.created_at | object | No | Filter by creation date |
Filter Operations
Each filter field supports these operations:
eq: Equalsne: Not equalslike: Contains (for strings)gt,gte,lt,lte: Comparison operatorsin: Value in arraybetween: Between two values
Example Request
curl -X POST \
https://apis.app.stack9.co/api/forms/list \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"page": 1,
"limit": 20,
"search": "newsletter",
"filters": {
"active": {
"operation": "eq",
"value": true
},
"form_type": {
"operation": "eq",
"value": "embedded_form"
},
"created_at": {
"operation": "gte",
"value": "2024-01-01T00:00:00.000Z"
}
}
}'
Example Response
{
"results": [
{
"version": 2,
"created_at": "2024-01-15T10:30:00.123Z",
"updated_at": "2024-03-20T14:45:30.456Z",
"code": "form_Xk9mNp2Q",
"public_code": "pub_form_Abc123",
"name": "Newsletter Signup",
"allowed_origins": ["https://example.com"],
"active": true,
"form_type": "embedded_form",
"business_unit": "marketing",
"surveyJsOptions": {
"title": "Join Our Newsletter",
"pages": [...]
},
"submission_count": 1523,
"conversion_rate": 68.5
}
],
"total": 15,
"totalPages": 1
}
Get Form by Code
Retrieve a specific form by its unique code.
GET /api/forms/{code}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Form code (path parameter) |
Example Request
curl -X GET \
https://apis.app.stack9.co/api/forms/form_Xk9mNp2Q \
-H 'X-API-Key: your-api-key-here'
Example Response
{
"version": 2,
"created_at": "2024-01-15T10:30:00.123Z",
"updated_at": "2024-03-20T14:45:30.456Z",
"code": "form_Xk9mNp2Q",
"public_code": "pub_form_Abc123",
"name": "Newsletter Signup",
"allowed_origins": ["https://example.com", "https://www.example.com"],
"active": true,
"form_type": "embedded_form",
"business_unit": "marketing",
"surveyJsOptions": {
"title": "Join Our Newsletter",
"description": "Get weekly updates and exclusive content",
"logo": "https://example.com/logo.png",
"logoWidth": "200px",
"logoHeight": "60px",
"pages": [
{
"name": "page1",
"title": "Contact Information",
"elements": [
{
"type": "text",
"name": "email",
"title": "Email Address",
"inputType": "email",
"isRequired": true
}
]
}
],
"completedHtml": "<h3>Thank you!</h3>"
}
}
Get Form Schema with Theme
Retrieve form configuration along with its associated theme for rendering.
GET /api/forms/{code}/schema
This endpoint returns the complete form definition including theme configuration, useful for embedding and rendering forms in external applications.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Form code (path parameter) |
Example Request
curl -X GET \
https://apis.app.stack9.co/api/forms/form_Xk9mNp2Q/schema \
-H 'X-API-Key: your-api-key-here'
Example Response
{
"form": {
"code": "form_Xk9mNp2Q",
"public_code": "pub_form_Abc123",
"name": "Newsletter Signup",
"surveyJsOptions": {
"title": "Join Our Newsletter",
"pages": [...]
}
},
"theme": {
"code": "theme_Def456",
"name": "Brand Theme",
"surveyJsThemeOptions": {
"themeName": "modern",
"colorPalette": "light",
"isPanelless": true,
"primaryColor": "#2563eb",
"backgroundImage": "https://example.com/bg.jpg",
"backgroundImageFit": "cover"
}
}
}
Update Form
Update an existing form's configuration.
PUT /api/forms/{code}
Parameters
Same as Create Form. All fields provided will update the existing values.
Example Request
curl -X PUT \
https://apis.app.stack9.co/api/forms/form_Xk9mNp2Q \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"name": "Updated Newsletter Form",
"allowed_origins": ["*"],
"active": true,
"form_type": "embedded_form",
"surveyJsOptions": {
"title": "Subscribe to Our Newsletter",
"description": "Updated description",
"pages": [...]
}
}'
Example Response
{
"success": true,
"code": "form_Xk9mNp2Q"
}
Form Themes
Create Form Theme
Create a custom theme for styling forms.
POST /api/form_themes
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Theme name |
surveyJsThemeOptions | object | Yes | SurveyJS theme configuration |
surveyJsThemeOptions.themeName | string | No | Base theme name |
surveyJsThemeOptions.colorPalette | string | No | Color palette ("light" or "dark") |
surveyJsThemeOptions.isPanelless | boolean | No | Remove panel borders |
surveyJsThemeOptions.backgroundImage | string | No | Background image URL |
surveyJsThemeOptions.backgroundImageFit | string | No | Image fit mode ("auto", "contain", "cover") |
surveyJsThemeOptions.backgroundOpacity | number | No | Background opacity (0-1) |
surveyJsThemeOptions.primaryColor | string | No | Primary brand color |
surveyJsThemeOptions.header | object | No | Header configuration |
Example Request
curl -X POST \
https://apis.app.stack9.co/api/form_themes \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"name": "Modern Blue Theme",
"surveyJsThemeOptions": {
"themeName": "modern",
"colorPalette": "light",
"isPanelless": true,
"primaryColor": "#2563eb",
"backgroundImage": "https://example.com/gradient-bg.jpg",
"backgroundImageFit": "cover",
"backgroundImageAttachment": "fixed",
"backgroundOpacity": 0.1,
"header": {
"height": 200,
"inheritWidthFrom": "container",
"textAreaWidth": 768,
"logoPositionX": "right",
"logoPositionY": "middle",
"titlePositionX": "left",
"titlePositionY": "middle",
"descriptionPositionX": "left",
"descriptionPositionY": "bottom",
"overlapEnabled": false,
"backgroundImageOpacity": 0.8
},
"cssVariables": {
"--primary-color": "#2563eb",
"--primary-light": "#60a5fa",
"--primary-dark": "#1e40af",
"--background": "#ffffff",
"--background-dim": "#f9fafb",
"--foreground": "#1f2937",
"--border": "#e5e7eb",
"--font-family": "Inter, system-ui, sans-serif",
"--base-unit": "8px",
"--corner-radius": "6px"
}
}
}'
Example Response
{
"code": "theme_Def456"
}
List Form Themes
Retrieve available form themes.
POST /api/form_themes/list
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | number | Yes | Page number (1-based) |
limit | number | Yes | Items per page (max: 100) |
filters | object | No | Filter criteria |
Example Request
curl -X POST \
https://apis.app.stack9.co/api/form_themes/list \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"page": 1,
"limit": 20,
"filters": {}
}'
Example Response
{
"results": [
{
"version": 1,
"created_at": "2024-01-15T10:30:00.123Z",
"updated_at": "2024-01-15T10:30:00.123Z",
"code": "theme_Def456",
"name": "Modern Blue Theme",
"surveyJsThemeOptions": {
"themeName": "modern",
"colorPalette": "light",
"primaryColor": "#2563eb"
}
},
{
"code": "theme_Default",
"name": "Default Theme",
"surveyJsThemeOptions": {
"themeName": "default"
}
}
],
"total": 5,
"totalPages": 1
}
Get Form Theme by Code
Retrieve a specific theme configuration.
GET /api/form_themes/{code}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Theme code (path parameter) |
Example Request
curl -X GET \
https://apis.app.stack9.co/api/form_themes/theme_Def456 \
-H 'X-API-Key: your-api-key-here'
Example Response
{
"version": 1,
"created_at": "2024-01-15T10:30:00.123Z",
"updated_at": "2024-01-15T10:30:00.123Z",
"code": "theme_Def456",
"name": "Modern Blue Theme",
"surveyJsThemeOptions": {
"themeName": "modern",
"colorPalette": "light",
"isPanelless": true,
"primaryColor": "#2563eb",
"backgroundImage": "https://example.com/gradient-bg.jpg",
"backgroundImageFit": "cover",
"header": {
"height": 200,
"logoPositionX": "right",
"titlePositionX": "left"
}
}
}
Update Form Theme
Update an existing theme configuration.
PUT /api/form_themes/{code}
Parameters
Same as Create Form Theme.
Example Request
curl -X PUT \
https://apis.app.stack9.co/api/form_themes/theme_Def456 \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"name": "Updated Blue Theme",
"surveyJsThemeOptions": {
"themeName": "modern",
"colorPalette": "dark",
"primaryColor": "#3b82f6"
}
}'
Form Submissions
Create Form Submission
Submit data to a form. This endpoint is typically called from embedded forms.
POST /api/form_submissions
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
form_code | string | Yes | The form code this submission is for |
email_address | string | Yes | Responder's email address |
form_data | object | Yes | Form response data as key-value pairs |
Example Request
curl -X POST \
https://apis.app.stack9.co/api/form_submissions \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"form_code": "form_Xk9mNp2Q",
"email_address": "john.doe@example.com",
"form_data": {
"email": "john.doe@example.com",
"firstName": "John",
"lastName": "Doe",
"interests": "Product Updates",
"frequency": "Weekly",
"consent": true,
"company": "Acme Corp",
"phone": "+1-555-0123"
}
}'
Example Response
{
"submission_id": "sub_9kL3mP5n"
}
Error Responses
400 Bad Request
{
"message": "Invalid submission data",
"code": "INVALID_SUBMISSION",
"issues": [
{
"field": "email_address",
"message": "Invalid email format"
}
]
}
404 Not Found
{
"message": "Form not found or inactive",
"code": "FORM_NOT_FOUND"
}
List Form Submissions
Retrieve form submissions with filtering options.
POST /api/form_submissions/list
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | number | Yes | Page number (1-based) |
limit | number | Yes | Items per page (max: 100) |
filters | object | Yes | Filter criteria |
filters.form_code | object | No | Filter by form |
filters.email_address | object | No | Filter by email |
filters.created_at | object | No | Filter by submission date |
Example Request
curl -X POST \
https://apis.app.stack9.co/api/form_submissions/list \
-H 'X-API-Key: your-api-key-here' \
-H 'Content-Type: application/json' \
-d '{
"page": 1,
"limit": 50,
"filters": {
"form_code": {
"operation": "eq",
"value": "form_Xk9mNp2Q"
},
"created_at": {
"operation": "between",
"value": ["2024-01-01T00:00:00.000Z", "2024-12-31T23:59:59.999Z"]
}
}
}'
Example Response
{
"results": [
{
"id": "sub_9kL3mP5n",
"created_at": "2024-03-20T14:30:15.234Z",
"form_code": "form_Xk9mNp2Q",
"form_name": "Newsletter Signup",
"email_address": "john.doe@example.com",
"form_data": {
"firstName": "John",
"lastName": "Doe",
"interests": "Product Updates",
"frequency": "Weekly"
},
"subscriber_created": true,
"journey_triggered": false,
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0..."
}
],
"total": 1523,
"totalPages": 31
}
Form Embedding
Embedding Forms in Websites
Forms can be embedded in external websites using the following methods:
Method 1: iFrame Embedding
<iframe
src="https://forms.stack9.io/embed/pub_form_Abc123"
width="100%"
height="600"
frameborder="0"
style="border: 0; max-width: 100%;">
</iframe>
Method 2: JavaScript SDK
<!-- Stack9 Forms SDK -->
<script src="https://cdn.stack9.io/forms/v1/sdk.js"></script>
<div id="stack9-form"></div>
<script>
Stack9Forms.render({
container: 'stack9-form',
formCode: 'pub_form_Abc123',
theme: 'theme_Def456',
onComplete: function(submission) {
console.log('Form submitted:', submission.id);
// Custom completion logic
},
onError: function(error) {
console.error('Form error:', error);
}
});
</script>
Method 3: React Component
import { Stack9Form } from '@stack9/forms-react';
function NewsletterSignup() {
const handleComplete = (submission) => {
console.log('Form submitted:', submission.id);
};
return (
<Stack9Form
formCode="pub_form_Abc123"
theme="theme_Def456"
onComplete={handleComplete}
customData={{
source: 'website',
campaign: 'spring-2024'
}}
/>
);
}
CORS Configuration
To embed forms on external domains, configure the allowed_origins field:
{
"allowed_origins": [
"https://example.com",
"https://www.example.com",
"https://blog.example.com"
]
}
Use ["*"] to allow embedding on any domain (not recommended for production).
Advanced Features
Conditional Logic
Implement dynamic form behavior based on user responses:
{
"pages": [
{
"elements": [
{
"type": "radiogroup",
"name": "customerType",
"title": "Are you a new or existing customer?",
"choices": ["New Customer", "Existing Customer"]
},
{
"type": "text",
"name": "accountNumber",
"title": "Account Number",
"visibleIf": "{customerType} = 'Existing Customer'",
"isRequired": true
},
{
"type": "dropdown",
"name": "howHeard",
"title": "How did you hear about us?",
"visibleIf": "{customerType} = 'New Customer'",
"choices": ["Google", "Social Media", "Friend", "Other"]
}
]
}
]
}
Custom Validation
Add custom validation rules to form fields:
{
"elements": [
{
"type": "text",
"name": "age",
"title": "Age",
"inputType": "number",
"validators": [
{
"type": "numeric",
"minValue": 18,
"maxValue": 120,
"text": "Age must be between 18 and 120"
}
]
},
{
"type": "text",
"name": "couponCode",
"title": "Coupon Code",
"validators": [
{
"type": "regex",
"regex": "^[A-Z]{3}-[0-9]{4}$",
"text": "Invalid coupon format (e.g., ABC-1234)"
}
]
}
]
}
Multi-Language Support
Configure forms for multiple languages:
{
"locale": "es",
"title": {
"default": "Newsletter Signup",
"es": "Suscripción al Boletín",
"fr": "Inscription à la Newsletter"
},
"pages": [
{
"elements": [
{
"type": "text",
"name": "email",
"title": {
"default": "Email Address",
"es": "Dirección de Correo",
"fr": "Adresse E-mail"
}
}
]
}
]
}
File Upload Support
Enable file uploads in forms:
{
"elements": [
{
"type": "file",
"name": "resume",
"title": "Upload Resume",
"acceptedTypes": ".pdf,.doc,.docx",
"maxSize": 5242880,
"storeDataAsText": false,
"waitForUpload": true
}
]
}
Integration with Marketing Automation
Automatic Subscriber Creation
Form submissions automatically create or update subscriber profiles:
- New Subscribers: Created with form data mapped to profile fields
- Existing Subscribers: Profile updated with latest form data
- Custom Field Mapping: Map form fields to subscriber custom fields
- Audience Assignment: Auto-assign to specified audiences
- Subscription Preferences: Set initial subscription preferences
Journey Triggers
Configure forms to trigger marketing journeys on submission:
{
"post_submit_actions": [
{
"type": "trigger_journey",
"journey_id": "journey_Welcome123",
"data_mapping": {
"firstName": "form.firstName",
"product_interest": "form.interests"
}
}
]
}
Lead Scoring
Automatically score leads based on form responses:
{
"scoring_rules": [
{
"field": "company_size",
"value": "Enterprise",
"score": 50
},
{
"field": "budget",
"value": "> $100,000",
"score": 30
},
{
"field": "timeline",
"value": "This Quarter",
"score": 20
}
]
}
Analytics and Reporting
Form Performance Metrics
Track key performance indicators:
- Views: Number of times form was loaded
- Starts: Users who began filling the form
- Completions: Successful submissions
- Conversion Rate: Completions / Views
- Abandonment Rate: (Starts - Completions) / Starts
- Average Time: Mean time to complete
- Drop-off Points: Questions where users abandon
Submission Analytics
Analyze submission patterns:
GET /api/forms/{code}/analytics?period=30d
{
"summary": {
"total_views": 5234,
"total_starts": 2156,
"total_completions": 1523,
"conversion_rate": 29.1,
"abandonment_rate": 29.4
},
"daily_metrics": [
{
"date": "2024-03-20",
"views": 187,
"starts": 76,
"completions": 52,
"conversion_rate": 27.8
}
],
"field_completion": {
"email": 100,
"firstName": 98.5,
"lastName": 76.3,
"phone": 45.2
}
}