Integration Marketplace

The GudForm marketplace lets you install pre-built integrations or build and sell your own. Integrations receive form submission data via webhooks and can send data to third-party services.

Available on all plans. Install integrations from the marketplace on any plan including Free and Starter. Building and publishing integrations requires a Pro or Business plan.


How Integrations Work

GudForm integrations follow a simple event-driven model:

  1. Install: Users browse the marketplace and install an integration on their account.
  2. Configure: Users authenticate with the third-party service (OAuth) and map form fields to the integration.
  3. Activate: Users enable the integration on specific forms.
  4. Trigger: When a form response is submitted, GudForm sends the data to all active integrations via webhook.

Event Flow

Form Submission → GudForm Webhook → Integration Endpoint → Third-Party Service (e.g. Google Sheets, Slack, Mailchimp)


Building an Integration

1. Integration Manifest

Every integration starts with a manifest that describes it to the marketplace. Create a gudform-integration.json file:

gudform-integration.jsonJSON
{
  "name": "Google Sheets",
  "slug": "google-sheets",
  "version": "1.0.0",
  "description": "Automatically add form responses as rows in Google Sheets",
  "author": {
    "name": "Your Company",
    "email": "dev@yourcompany.com",
    "url": "https://yourcompany.com"
  },
  "icon": "https://yourcdn.com/icons/google-sheets.svg",
  "category": "PRODUCTIVITY",
  "pricing": {
    "type": "free"
  },
  "auth": {
    "type": "oauth2",
    "authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth",
    "tokenUrl": "https://oauth2.googleapis.com/token",
    "scopes": ["https://www.googleapis.com/auth/spreadsheets"]
  },
  "webhookUrl": "https://your-server.com/webhooks/gudform",
  "configFields": [
    {
      "key": "spreadsheetId",
      "label": "Spreadsheet",
      "type": "text",
      "required": true,
      "helpText": "The ID of the Google Sheet to write to"
    },
    {
      "key": "sheetName",
      "label": "Sheet Name",
      "type": "text",
      "required": false,
      "default": "Sheet1"
    }
  ],
  "events": ["form.response.completed", "form.moved"]
}

2. Webhook Endpoint

Your integration receives form data via HTTP POST at the webhookUrl defined in your manifest. The payload follows the same format as GudForm webhooks:

Incoming payloadJSON
{
  "event": "form.response.completed",
  "formId": "clx1234abcd",
  "formTitle": "Customer Feedback",
  "collectionId": "col_abc123",
  "collectionName": "Surveys",
  "responseId": "resp_abc123",
  "answers": [
    {
      "questionId": "q_001",
      "question": "What is your name?",
      "type": "SHORT_TEXT",
      "answer": "Jane Smith"
    },
    {
      "questionId": "q_002",
      "question": "Email",
      "type": "EMAIL",
      "answer": "jane@example.com"
    }
  ],
  "integration": {
    "installationId": "inst_xyz789",
    "config": {
      "spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
      "sheetName": "Responses"
    },
    "credentials": {
      "access_token": "ya29.a0...",
      "refresh_token": "1//0..."
    }
  },
  "timestamp": "2025-01-20T14:32:15.000Z"
}

3. Process the Data

Your webhook handler should process the data and send it to the third-party service. Return a 200 status code on success.

handler.tsTypeScript
import { google } from "googleapis";

export async function POST(req: Request) {
  const payload = await req.json();
  const { answers, integration } = payload;
  const { config, credentials } = integration;

  // Initialize Google Sheets client
  const auth = new google.auth.OAuth2();
  auth.setCredentials(credentials);

  const sheets = google.sheets({ version: "v4", auth });

  // Map answers to a row
  const row = answers.map((a) => a.answer);

  // Append to spreadsheet
  await sheets.spreadsheets.values.append({
    spreadsheetId: config.spreadsheetId,
    range: `${config.sheetName}!A:Z`,
    valueInputOption: "USER_ENTERED",
    requestBody: { values: [row] },
  });

  return new Response(JSON.stringify({ success: true }), {
    status: 200,
  });
}

Manifest Reference

FieldTypeRequiredDescription
namestringYesDisplay name in the marketplace
slugstringYesUnique URL-safe identifier
versionstringYesSemver version string
descriptionstringYesShort description (max 200 chars)
authorobjectYesAuthor name, email, and website
iconstringYesURL to integration icon (SVG recommended, 64x64)
categoryenumYesPRODUCTIVITY, CRM, MARKETING, COMMUNICATION, ANALYTICS, STORAGE, AUTOMATION, OTHER
pricingobjectYesPricing model: free, one_time, or subscription
authobjectNoOAuth2 config or API key authentication
webhookUrlstringYesEndpoint to receive form events
configFieldsarrayNoUser-configurable settings for the integration
eventsstring[]YesWebhook events to subscribe to (e.g. form.response.completed, form.moved, collection.created)

Categories

PRODUCTIVITYProductivity

Google Sheets, Notion, Airtable

CRMCRM

HubSpot, Salesforce, Pipedrive

MARKETINGMarketing

Mailchimp, ConvertKit, ActiveCampaign

COMMUNICATIONCommunication

Slack, Discord, Teams

ANALYTICSAnalytics

Google Analytics, Mixpanel

STORAGEStorage

Google Drive, Dropbox, S3

AUTOMATIONAutomation

Zapier, Make, n8n

OTHEROther

Everything else


Pricing Models

Integrations can use one of three pricing models. GudForm takes a 20% platform fee on paid integrations.

Free integrationJSON
{
  "pricing": {
    "type": "free"
  }
}
One-time purchaseJSON
{
  "pricing": {
    "type": "one_time",
    "amount": 999,
    "currency": "usd"
  }
}
Monthly subscriptionJSON
{
  "pricing": {
    "type": "subscription",
    "amount": 499,
    "currency": "usd",
    "interval": "month"
  }
}

Publishing to the Marketplace

Submission Process

  1. Register as a developer in your account settings.
  2. Submit your integration via the developer dashboard with your manifest, icon, and a demo video or screenshots.
  3. Review: Our team reviews your integration for security, functionality, and marketplace guidelines.
  4. Publish: Once approved, your integration goes live on the marketplace.

Requirements

  • HTTPS webhook endpoint
  • Valid gudform-integration.json manifest
  • SVG or high-resolution icon (min 128x128px)
  • Description and setup instructions
  • Webhook must respond within 10 seconds and return 2xx status
  • Handle retry deliveries idempotently

OAuth Flow for Integrations

When users install an integration that requires OAuth, GudForm handles the OAuth flow:

  1. User clicks “Connect” on your integration.
  2. GudForm redirects to your auth.authorizationUrl with the required scopes.
  3. User authorizes on the third-party service.
  4. The service redirects back to GudForm with an authorization code.
  5. GudForm exchanges the code for tokens using your auth.tokenUrl.
  6. Tokens are stored securely and passed to your webhook in the integration.credentials field.
OAuth config in manifestJSON
{
  "auth": {
    "type": "oauth2",
    "authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth",
    "tokenUrl": "https://oauth2.googleapis.com/token",
    "scopes": [
      "https://www.googleapis.com/auth/spreadsheets"
    ],
    "clientIdEnvVar": "GOOGLE_CLIENT_ID",
    "clientSecretEnvVar": "GOOGLE_CLIENT_SECRET"
  }
}

Security note: OAuth credentials are encrypted at rest and only decrypted when delivering webhook events to your endpoint. GudForm never exposes raw tokens in the dashboard.


Testing Your Integration

  1. Local development: Use ngrok or a similar tool to expose your local webhook endpoint.
  2. Test events: Use the “Send test event” button in the developer dashboard to trigger a sample webhook delivery.
  3. Webhook logs: View delivery attempts, payloads, and response codes in the developer dashboard.
Test with curlbash
curl -X POST https://your-server.com/webhooks/gudform \
  -H "Content-Type: application/json" \
  -H "X-GudForm-Signature: sha256=test" \
  -d '{
    "event": "form.response.completed",
    "formId": "test_form_id",
    "formTitle": "Test Form",
    "collectionId": "test_collection_id",
    "collectionName": "Default",
    "responseId": "test_response_id",
    "answers": [
      {
        "questionId": "q1",
        "question": "Name",
        "type": "SHORT_TEXT",
        "answer": "Test User"
      }
    ],
    "integration": {
      "installationId": "test_install",
      "config": {},
      "credentials": {}
    },
    "timestamp": "2025-01-20T12:00:00.000Z"
  }'