Skip to content

forms-expert/sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Forms Expert SDK

Embeddable forms SDK for submitting forms via the Forms Expert API.

Installation

npm install @forms.expert/sdk

Quick Start

Vanilla JavaScript (CDN)

<!-- Include the SDK -->
<script src="https://unpkg.com/@forms.expert/sdk@latest/dist/vanilla/index.global.js"></script>

<!-- Create a container with data attributes -->
<div
  data-forms-expert="contact"
  data-api-key="pk_live_xxxxxxxxxxxx"
  data-resource-id="your-resource-id"
  data-lang="en"
></div>

<!-- Forms will auto-initialize on page load -->

Vanilla JavaScript (Module)

import { FormWidget } from '@forms.expert/sdk/vanilla';

const widget = new FormWidget(
  {
    apiKey: 'pk_live_xxxxxxxxxxxx',
    resourceId: 'your-resource-id',
  },
  {
    target: '#my-form',
    slug: 'contact',
    lang: 'en',
    onSuccess: (response) => {
      console.log('Form submitted:', response.submissionId);
    },
    onError: (error) => {
      console.error('Submission failed:', error);
    },
  }
);

widget.init();

React

import { FormsExpertForm } from '@forms.expert/sdk/react';

function ContactPage() {
  return (
    <FormsExpertForm
      config={{
        apiKey: 'pk_live_xxxxxxxxxxxx',
        resourceId: 'your-resource-id',
      }}
      slug="contact"
      lang="en"
      submitText="Send Message"
      onSuccess={(response) => {
        console.log('Submitted:', response.submissionId);
      }}
    />
  );
}

React Hook

import { useForm, FormsProvider } from '@forms.expert/sdk/react';

// With provider
function App() {
  return (
    <FormsProvider
      config={{
        apiKey: 'pk_live_xxxxxxxxxxxx',
        resourceId: 'your-resource-id',
      }}
    >
      <ContactForm />
    </FormsProvider>
  );
}

function ContactForm() {
  const form = useForm({
    slug: 'contact',
    lang: 'en',
    onSuccess: (response) => alert('Thanks!'),
  });

  const handleSubmit = async (e) => {
    e.preventDefault();
    await form.submit();
  };

  if (form.isSubmitted) {
    return <p>Thank you for your submission!</p>;
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={form.values.email || ''}
        onChange={(e) => form.setValue('email', e.target.value)}
      />
      {form.errors.email && <span>{form.errors.email}</span>}

      <textarea
        value={form.values.message || ''}
        onChange={(e) => form.setValue('message', e.target.value)}
      />
      {form.errors.message && <span>{form.errors.message}</span>}

      <button type="submit" disabled={form.isLoading}>
        {form.isLoading ? 'Sending...' : 'Submit'}
      </button>
    </form>
  );
}

Vue 3

<script setup>
import { useForm } from '@forms.expert/sdk/vue';

const form = useForm({
  slug: 'contact',
  lang: 'en',
  config: {
    apiKey: 'pk_live_xxxxxxxxxxxx',
    resourceId: 'your-resource-id',
  },
  onSuccess: (response) => {
    alert('Form submitted!');
  },
});

const handleSubmit = async () => {
  await form.submit();
};
</script>

<template>
  <form @submit.prevent="handleSubmit">
    <div v-if="form.isSubmitted.value">
      Thank you for your submission!
    </div>
    
    <template v-else>
      <input
        type="email"
        :value="form.values.value.email"
        @input="form.setValue('email', $event.target.value)"
      />
      <span v-if="form.errors.value.email">{{ form.errors.value.email }}</span>

      <button type="submit" :disabled="form.isLoading.value">
        {{ form.isLoading.value ? 'Sending...' : 'Submit' }}
      </button>
    </template>
  </form>
</template>

Core SDK

For programmatic form submission without UI:

import { FormsSDK } from '@forms.expert/sdk';

const sdk = new FormsSDK({
  apiKey: 'pk_live_xxxxxxxxxxxx',
  resourceId: 'your-resource-id',
});

// Check if form is active (optionally pass language code)
const status = await sdk.isActive('contact', 'en');
if (!status.active) {
  console.error('Form not available');
}

// Validate data
const validation = await sdk.validate('contact', {
  email: 'user@example.com',
  message: 'Hello!',
});

if (!validation.valid) {
  console.error('Validation errors:', validation.errors);
}

// Submit form
const response = await sdk.submit('contact', {
  email: 'user@example.com',
  message: 'Hello!',
});

console.log('Submission ID:', response.submissionId);

Form Handler

For more control, use the FormHandler:

const handler = sdk.form('contact', {
  onSubmitStart: () => console.log('Submitting...'),
  onSubmitSuccess: (response) => console.log('Success!', response),
  onSubmitError: (error) => console.error('Error:', error),
  onValidationError: (errors) => console.error('Validation:', errors),
});

// Initialize to get form config
await handler.initialize();

// Check captcha requirement
if (handler.requiresCaptcha()) {
  const provider = handler.getCaptchaProvider(); // 'turnstile' | 'recaptcha' | 'hcaptcha'
  // Initialize captcha widget...
}

// Submit with validation
await handler.submit({ email: 'user@example.com' });

Configuration

SDK Config

Option Type Required Description
apiKey string Yes Publishable API key (pk_live_* or pk_test_*)
resourceId string Yes Resource ID containing the form
baseUrl string No API base URL (default: https://api.forms.expert/api/v1)

Widget Options

Option Type Default Description
target string | HTMLElement - Target element or selector
slug string - Form slug
submitText string 'Submit' Submit button text
showBranding boolean true Show "Powered by forms.expert" branding
resetOnSuccess boolean false Reset form after successful submission
lang string - Language code (e.g. 'en', 'uk') passed as ?lang=CODE to the backend
redirectUrl string - Redirect URL after success
onSuccess function - Success callback
onError function - Error callback
onValidationError function - Validation error callback

Data Attributes (Auto-init)

Attribute Required Description
data-forms-expert Yes Form slug
data-api-key Yes Publishable API key
data-resource-id Yes Resource ID
data-base-url No Custom API base URL
data-submit-text No Submit button text
data-branding No Set to 'false' to hide branding
data-lang No Language code (e.g. en, uk)
data-reset No Set to 'true' to reset after submission

Styling

The SDK automatically reads styling from the form configuration set in the builder. Styling is merged from two sources: schema.styling (basic) and the top-level styling object (full hosted config). Top-level values take precedence.

Styling Properties

Property Type Default Description
theme 'light' | 'dark' | 'system' 'light' Color theme
primaryColor string '#3b82f6' Primary accent color (button background)
buttonColor string '#ffffff' Button text color
backgroundColor string '#ffffff' Form background color
textColor string '#1f2937' Text color
errorColor string '#EF4444' Validation error color
successColor string '#22c55e' Success state color (badge, messages)
fontFamily string 'Inter, system-ui, sans-serif' Font family
fontSize 'sm' | 'md' | 'lg' 'md' Base font size
buttonText string 'Submit' Submit button label
buttonStyle 'filled' | 'outline' 'filled' Button fill style
labelPosition 'top' | 'left' | 'floating' 'top' Label placement
hideRequiredAsterisk boolean false Hide * on required fields
transparentBackground boolean false Transparent form background

Border Radius

Field border radius (borderRadius) — applied to inputs, selects, textareas:

Value Pixels Description
'none' 0 No rounding
'sm' 2px Subtle rounding
'md' 6px Medium rounding (default)
'lg' 8px Large rounding

Button border radius (buttonRadius) — applied to the submit button independently:

Value Pixels Description
'none' 0 Square corners
'small' 4px Subtle rounding
'medium' 8px Medium rounding (default)
'large' 12px Large rounding
'full' 9999px Fully rounded / pill shape

Layout & Spacing

Property Values Default Description
formWidth 'narrow' | 'medium' | 'wide' | 'full' 'full' Form container width
formPadding 'compact' | 'normal' | 'relaxed' | 'spacious' 'normal' Inner form padding
fieldLayout 'stacked' | 'inline' 'stacked' Field arrangement
fieldSpacing 'compact' | 'normal' | 'relaxed' | 'spacious' 'normal' Vertical gap between fields
labelSpacing 'compact' | 'normal' | 'relaxed' 'normal' Gap between label and input
buttonAlign 'left' | 'center' | 'right' 'left' Submit button alignment

Layout Fields (Heading & Paragraph)

Heading size (headingSize) — controls <h2> heading fields:

Value Font Size Description
'small' 18px Small heading
'medium' 22px Medium heading (default)
'large' 28px Large heading
'extra-large' 34px Extra-large heading

Paragraph size (paragraphSize) — controls paragraph layout fields:

Value Font Size Description
'small' 12px Small text
'medium' 14px Medium text (default)
'large' 16px Large text

Individual paragraph fields can override the global size via the paragraphFontSize field property (in pixels).

Form Name Display

The form name is rendered as an <h1> above the form fields. Visibility is controlled by hostedConfig.showFormName (defaults to true). This can be toggled in the form builder under Page Settings → "Show form name as title".

Logo & Background

Property Type Description
logoUrl string URL for a logo image above the form
logoPosition 'top-left' | 'top-center' | 'top-right' Logo alignment
coverImageUrl string Cover image URL
backgroundImageUrl string Background image URL
backgroundOverlay number Background overlay opacity (0–100)

Error Handling

import { FormsError, FormValidationError } from '@forms.expert/sdk';

try {
  await sdk.submit('contact', data);
} catch (error) {
  if (error instanceof FormValidationError) {
    // Handle validation errors
    error.errors.forEach(({ field, message }) => {
      console.log(`${field}: ${message}`);
    });
  } else if (error instanceof FormsError) {
    // Handle API errors
    console.error(`${error.code}: ${error.message}`);
    
    if (error.code === 'FORM_RATE_LIMIT_EXCEEDED') {
      // Retry after delay
      setTimeout(() => retry(), error.retryAfter * 1000);
    }
  }
}

Error Codes

Code Description
FORM_NOT_FOUND Form does not exist
FORM_NOT_PUBLISHED Form is not published
VALIDATION_ERROR Form data validation failed
CAPTCHA_REQUIRED CAPTCHA token missing
CAPTCHA_FAILED CAPTCHA verification failed
FORM_RATE_LIMIT_EXCEEDED Form-specific rate limit exceeded
GLOBAL_RATE_LIMIT_EXCEEDED IP rate limit exceeded
ORIGIN_NOT_ALLOWED Request origin not in whitelist

TypeScript

Full TypeScript support with exported types:

import type {
  FormField,
  FormSchema,
  FormStyling,
  FormStatusResponse,
  ValidationResponse,
  SubmissionResponse,
  FormsSDKConfig,
} from '@forms.expert/sdk';

License

MIT

Website: forms.expert

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published