Skip to content

@memberjunction/actions-bizapps-formbuilders

Form builder and survey platform integration actions for MemberJunction. This package provides a unified interface across four major form/survey platforms, enabling AI agents, workflows, and applications to programmatically retrieve responses, analyze submissions, and manage forms through the MemberJunction Actions framework.

This package is part of the BizApps Actions collection within the broader MemberJunction Actions Framework. For core action architecture, design philosophy, and when to use actions versus direct code, see the Actions CLAUDE.md.

The package follows a three-tier class hierarchy: a shared base class providing common form operations, provider-specific base classes handling API authentication and data normalization, and individual action classes implementing specific operations.

graph TD
    subgraph Framework["Actions Framework"]
        BA["BaseAction<br/>@memberjunction/actions"]
    end

    subgraph Base["Shared Base Layer"]
        BFBA["BaseFormBuilderAction<br/>Credential management, CSV export,<br/>statistics helpers, response normalization"]
    end

    subgraph Providers["Provider Base Classes"]
        TF["TypeformBaseAction<br/>Bearer token auth<br/>Axios + rate limiting"]
        JF["JotFormBaseAction<br/>API key (query param)<br/>Regional endpoints"]
        SM["SurveyMonkeyBaseAction<br/>OAuth 2.0 Bearer<br/>Paginated responses"]
        GF["GoogleFormsBaseAction<br/>OAuth 2.0 Bearer<br/>Read-only API"]
    end

    subgraph Actions["Action Classes (34 total)"]
        TFA["Typeform Actions (10)"]
        JFA["JotForm Actions (8)"]
        SMA["SurveyMonkey Actions (8)"]
        GFA["Google Forms Actions (4)"]
    end

    subgraph Shared["Shared Utilities"]
        FCP["FileContentProcessor<br/>PDF, Excel, Word,<br/>image extraction"]
    end

    BA --> BFBA
    BFBA --> TF
    BFBA --> JF
    BFBA --> SM
    BFBA --> GF
    TF --> TFA
    JF --> JFA
    SM --> SMA
    GF --> GFA
    TFA -.-> FCP

    style Framework fill:#64748b,stroke:#475569,color:#fff
    style Base fill:#2d6a9f,stroke:#1a4971,color:#fff
    style TF fill:#7c5295,stroke:#563a6b,color:#fff
    style JF fill:#7c5295,stroke:#563a6b,color:#fff
    style SM fill:#7c5295,stroke:#563a6b,color:#fff
    style GF fill:#7c5295,stroke:#563a6b,color:#fff
    style TFA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style JFA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style SMA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style GFA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style FCP fill:#b8762f,stroke:#8a5722,color:#fff
PlatformAuth MethodActionsCapabilities
TypeformBearer token (personal access token)10Full CRUD: responses, forms, file content
JotFormAPI key (query parameter)8Full CRUD: submissions, forms
SurveyMonkeyOAuth 2.0 Bearer token8Full CRUD: responses, surveys, collectors
Google FormsOAuth 2.0 Bearer token4Read-only: responses, form details
Terminal window
npm install @memberjunction/actions-bizapps-formbuilders

This package is part of the MemberJunction monorepo. When working within the monorepo, add the dependency to your package’s package.json and run npm install at the repository root.

Action ClassRegistration NameDescription
GetTypeformResponsesActionGetTypeformResponsesActionRetrieve responses with filtering, pagination, and auto-paginate support
GetSingleTypeformResponseActionGetSingleTypeformResponseActionRetrieve a specific response by token
GetTypeformStatisticsActionGetTypeformStatisticsActionCalculate aggregate analytics (completion rates, distributions, top answers)
ExportTypeformCSVActionExportTypeformCSVActionExport responses to CSV format with optional metadata
WatchNewTypeformResponsesActionWatchNewTypeformResponsesActionPoll for new submissions since a given timestamp
GetTypeformActionGetTypeformActionRetrieve complete form configuration and field definitions
GetTypeformFormsActionGetTypeformFormsActionList all forms in a workspace
TypeformGetFileContentActionTypeformGetFileContentActionDownload and process file upload answers (PDF, Excel, Word, images)
CreateTypeformActionCreateTypeformActionCreate new forms programmatically with fields, settings, and logic
UpdateTypeformActionUpdateTypeformActionModify existing forms with safe merge mode
Action ClassRegistration NameDescription
GetJotFormSubmissionsActionGetJotFormSubmissionsActionRetrieve submissions with filtering and pagination
GetSingleJotFormSubmissionActionGetSingleJotFormSubmissionActionRetrieve a specific submission by ID
GetJotFormStatisticsActionGetJotFormStatisticsActionCalculate aggregate analytics from submissions
ExportJotFormCSVActionExportJotFormCSVActionExport submissions to CSV format
WatchNewJotFormSubmissionsActionWatchNewJotFormSubmissionsActionPoll for new submissions since a given timestamp
GetJotFormActionGetJotFormActionRetrieve form details and questions
CreateJotFormActionCreateJotFormActionCreate new forms with questions and properties
UpdateJotFormActionUpdateJotFormActionModify existing form configuration
Action ClassRegistration NameDescription
GetSurveyMonkeyResponsesActionGetSurveyMonkeyResponsesActionRetrieve responses with date range and status filtering
GetSingleSurveyMonkeyResponseActionGetSingleSurveyMonkeyResponseActionRetrieve a specific response by ID
GetSurveyMonkeyStatisticsActionGetSurveyMonkeyStatisticsActionCalculate aggregate analytics from responses
ExportSurveyMonkeyCSVActionExportSurveyMonkeyCSVActionExport responses to CSV format
WatchNewSurveyMonkeyResponsesActionWatchNewSurveyMonkeyResponsesActionPoll for new responses since a given timestamp
GetSurveyMonkeyActionGetSurveyMonkeyActionRetrieve survey details and configuration
CreateSurveyMonkeyActionCreateSurveyMonkeyActionCreate new surveys with pages and questions
UpdateSurveyMonkeyActionUpdateSurveyMonkeyActionModify existing survey properties
Action ClassRegistration NameDescription
GetSingleGoogleFormsResponseActionGetSingleGoogleFormsResponseActionRetrieve a specific response by ID
GetGoogleFormsStatisticsActionGetGoogleFormsStatisticsActionCalculate aggregate analytics from responses
ExportGoogleFormsCSVActionExportGoogleFormsCSVActionExport responses to CSV format
GetGoogleFormActionGetGoogleFormActionRetrieve form details, questions, and quiz settings

Note: Google Forms API is read-only. There are no endpoints for creating or updating forms programmatically.

All providers normalize their responses into a shared FormResponse interface, enabling provider-agnostic processing downstream.

classDiagram
    class FormResponse {
        +string responseId
        +string formId
        +Date submittedAt
        +boolean completed
        +FormAnswer[] answerDetails
        +Record answers
        +metadata
        +calculatedFields
        +hiddenFields
    }

    class FormAnswer {
        +string fieldId
        +string fieldType
        +string question
        +answer
        +string[] choices
    }

    class FormStatistics {
        +number totalResponses
        +number completedResponses
        +number partialResponses
        +number completionRate
        +number averageCompletionTime
        +Record responsesByDate
        +topAnswers
    }

    FormResponse --> FormAnswer : answerDetails

    style FormResponse fill:#2d6a9f,stroke:#1a4971,color:#fff
    style FormAnswer fill:#7c5295,stroke:#563a6b,color:#fff
    style FormStatistics fill:#2d8659,stroke:#1a5c3a,color:#fff

All form builder actions use a secure credential resolution chain. Credentials are never passed as direct action parameters; instead, they are resolved from environment variables or the MemberJunction Company Integrations entity.

  1. Environment variables (company-specific): BIZAPPS_{PROVIDER}_{COMPANY_ID}_{CREDENTIAL_TYPE}
  2. Environment variables (default): BIZAPPS_{PROVIDER}_{CREDENTIAL_TYPE}
  3. Database (Company Integrations entity): AccessToken, APIKey fields
Terminal window
# Typeform - Personal access token
export BIZAPPS_TYPEFORM_API_TOKEN=tfp_your_token_here
export BIZAPPS_TYPEFORM_12345_API_TOKEN=tfp_company_specific_token
# JotForm - API key
export BIZAPPS_JOTFORM_API_KEY=your_jotform_api_key
export BIZAPPS_JOTFORM_12345_API_KEY=company_specific_key
# SurveyMonkey - OAuth 2.0 access token
export BIZAPPS_SURVEYMONKEY_ACCESS_TOKEN=your_oauth_token
# Google Forms - OAuth 2.0 access token
export BIZAPPS_GOOGLE_FORMS_ACCESS_TOKEN=your_google_oauth_token
# OAuth2 client credentials (for token refresh)
export BIZAPPS_TYPEFORM_CLIENT_ID=your_client_id
export BIZAPPS_TYPEFORM_CLIENT_SECRET=your_client_secret

Store credentials in the Company Integrations entity linked to the appropriate Integration record:

-- 1. Create Integration record for the platform
INSERT INTO Integration (Name, Description, NavigationBaseURL, ClassName)
VALUES ('Typeform', 'Typeform form builder', 'https://api.typeform.com', 'TypeformIntegration');
-- 2. Link to Company with credentials
INSERT INTO CompanyIntegration (CompanyID, IntegrationID, AccessToken, IsActive)
VALUES (@CompanyID, @IntegrationID, 'tfp_your_token', 1);
import { ActionEngineServer } from '@memberjunction/actions';
const engine = ActionEngineServer.Instance;
// Get Typeform responses with date filtering
const result = await engine.RunAction({
Action: engine.Actions.find(a => a.Name === 'Get Typeform Responses'),
Params: [
{ Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
{ Name: 'FormID', Type: 'Input', Value: 'abc123' },
{ Name: 'Since', Type: 'Input', Value: '2024-01-01T00:00:00Z' },
{ Name: 'GetAllPages', Type: 'Input', Value: true }
],
ContextUser: currentUser
});
if (result.Success) {
const responses = result.Params.find(p => p.Name === 'Responses')?.Value;
console.log(`Retrieved ${responses.length} responses`);
}
const exportResult = await engine.RunAction({
Action: engine.Actions.find(a => a.Name === 'Export JotForm Responses to CSV'),
Params: [
{ Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
{ Name: 'FormID', Type: 'Input', Value: '240123456789' },
{ Name: 'IncludeMetadata', Type: 'Input', Value: true }
],
ContextUser: currentUser
});
const csvData = exportResult.Params.find(p => p.Name === 'CSVData')?.Value;
const createResult = await engine.RunAction({
Action: engine.Actions.find(a => a.Name === 'Create Typeform'),
Params: [
{ Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
{ Name: 'Title', Type: 'Input', Value: 'Customer Feedback Survey' },
{
Name: 'Fields', Type: 'Input', Value: [
{
type: 'short_text',
title: 'What is your name?',
ref: 'name'
},
{
type: 'rating',
title: 'How satisfied are you?',
ref: 'satisfaction',
properties: { steps: 5, shape: 'star' }
},
{
type: 'long_text',
title: 'Any additional feedback?',
ref: 'feedback'
}
]
}
],
ContextUser: currentUser
});
const formUrl = createResult.Params.find(p => p.Name === 'FormURL')?.Value;
// Poll for new SurveyMonkey responses
const watchResult = await engine.RunAction({
Action: engine.Actions.find(a => a.Name === 'Watch for New SurveyMonkey Responses'),
Params: [
{ Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
{ Name: 'SurveyID', Type: 'Input', Value: 'survey-456' },
{ Name: 'LastCheckedTimestamp', Type: 'Input', Value: '2024-06-01T00:00:00Z' },
{ Name: 'OnlyCompleted', Type: 'Input', Value: true }
],
ContextUser: currentUser
});
const hasNew = watchResult.Params.find(p => p.Name === 'HasNewResponses')?.Value;
const newResponses = watchResult.Params.find(p => p.Name === 'NewResponses')?.Value;

The package includes a FileContentProcessor utility used by the Typeform GetFileContentAction to intelligently extract content from file upload answers. It supports multiple file formats:

FormatProcessingOutput
PDFText extraction via pdf-parsePlain text
Excel (.xlsx, .xls)Sheet parsing via exceljsStructured JSON
Word (.docx, .doc)Text extraction via mammothPlain text
ImagesBase64 encodingBase64 string (for LLM vision)
Text/JSON/XML/CSVUTF-8 decodingPlain text
Other binaryBase64 encodingBase64 string

All actions return consistent error information through the ActionResultSimple interface:

Result CodeDescription
SUCCESSOperation completed successfully
MISSING_FORM_IDRequired FormID parameter was not provided
MISSING_API_TOKENNo API credentials could be resolved
MISSING_CONTEXT_USERContext user is required for credential lookup
ERRORGeneral error (check Message for details)

Each provider automatically handles platform-specific HTTP errors:

  • 401 - Invalid or expired API token
  • 403 - Insufficient permissions / scope
  • 404 - Form or response not found
  • 429 - Rate limit exceeded (automatic retry with exponential backoff)

All providers include built-in rate limit handling with automatic retry:

  • Respects Retry-After headers when provided
  • Falls back to 60-second wait when no header is present
  • Adds 100ms delays between pagination requests to avoid hitting limits
  • JotForm: Regional endpoints (US, EU, HIPAA) for data residency compliance
PackagePurpose
@memberjunction/actionsAction engine and BaseAction class
@memberjunction/actions-baseActionParam types and base interfaces
@memberjunction/coreRunView, Metadata, UserInfo, logging
@memberjunction/core-entitiesCompanyIntegrationEntity for credential lookup
@memberjunction/global@RegisterClass decorator
axiosHTTP client for all provider API calls
exceljsExcel file parsing in FileContentProcessor
mammothWord document text extraction
pdf-parsePDF text extraction

To integrate a new form/survey platform:

  1. Create provider directory: src/providers/{platform}/
  2. Implement a provider base class extending BaseFormBuilderAction with:
    • formPlatform and integrationName properties
    • Axios instance with authentication and rate limit interceptors
    • API client methods for the provider’s endpoints
    • Response normalization to the shared FormResponse interface
    • Provider-specific error handling
  3. Create individual action classes in src/providers/{platform}/actions/
  4. Export all classes from src/providers/{platform}/index.ts
  5. Add the provider export to src/index.ts