WebForm.dev API Documentation

Complete reference for all embed.js features, configuration options, and JavaScript events.

Quick Start Guide

Basic setup and simple examples to get you running in minutes.

View Quick Start

Full API Reference

Complete documentation for advanced features and customization.

You're here! Continue reading below.

HTTP API Reference

Get Form

GET
/form/{form_key}

Retrieves a form by its key and displays the form template.

URL Parameters:

  • form_key - The unique identifier for the form

Response:

Returns an HTML form template that users can fill out and submit.

Submit Form

POST
/send/{form_key}

Submits data to a form and sends an email notification.

URL Parameters:

  • form_key - The unique identifier for the form

Core Form Fields:

  • name - Sender's name (optional)
  • email (or replyto, _replyto) - Sender's email address
  • subject (or title, _subject) - Email subject (optional)
  • message - Form message content

Configuration Fields:

  • webform_key - Form key (can also be in URL path)
  • webform_next - Redirect URL after successful submission (optional)
  • webform_gotcha - Honeypot field for spam protection (leave empty)
  • webform_test - Set to true for testing mode (no email sent)
  • webform_recaptcha - reCAPTCHA response token
  • webform_field_order - Comma-separated list of field names to control display order in emails

Custom Fields:

Any additional form fields not listed above will be automatically included in email notifications. These fields will appear in an "Additional Information" section in the email.

📧 Email Formatting: Field names with underscores (e.g., first_name) will be displayed as title case with spaces (e.g., "First Name") in email notifications for better readability.

Example HTML Form:

<form action="https://send.webform.dev/send/your-form-key" method="POST">
  <input name="name" type="text" placeholder="Your Name">
  <input name="email" type="email" placeholder="Your Email" required>
  <input name="subject" type="text" placeholder="Subject">
  <textarea name="text" placeholder="Your Message" required></textarea>
  <!-- Hidden honeypot field for spam protection -->
  <input name="_gotcha" type="text" style="display:none">
  <button type="submit">Send Message</button>
</form>

Configuration Options

Basic Configuration Attributes

Configure form behavior using data attributes on the form element:

Success Behavior:

  • data-success-behavior: "button" (default), "message", or "custom"
  • data-success-message: Custom success message
  • data-success-class: Custom CSS class for success elements
  • data-reset-form: "true" (default) or "false"

Error Handling:

  • data-error-position: "inline" (default), "top", or "bottom"
  • data-submit-text: Text to show while submitting
<form class="webform-embed"
      action="https://send.webform.dev/send/YOUR_FORM_KEY"
      method="POST"
      data-success-behavior="replace"
      data-success-message="Thank you! We'll be in touch soon."
      data-error-position="top"
      data-submit-text="Sending...">
  <!-- form fields -->
</form>

Enhanced User Feedback Features

Improve user experience with visual feedback:

  • data-loading-spinner: "true" or "false" - Show spinner during submission
  • data-disable-fields-on-submit: "true" or "false" - Disable all form fields during submission
  • data-loading-overlay: "true" or "false" - Show overlay to prevent interaction
<form class="webform-embed"
      action="https://send.webform.dev/send/YOUR_FORM_KEY"
      method="POST"
      data-loading-spinner="true"
      data-disable-fields-on-submit="true"
      data-loading-overlay="false">
  <!-- form fields -->
</form>

Network Resilience Features

Handle network issues gracefully:

  • data-max-retries: Number - Maximum retry attempts for network errors (default: 2)
  • data-fallback-on-error: "true" (default) or "false" - Fall back to regular form submission
<form class="webform-embed"
      action="https://send.webform.dev/send/YOUR_FORM_KEY"
      method="POST"
      data-max-retries="3"
      data-fallback-on-error="true">
  <!-- form fields -->
</form>

Success Enhancements

Enhance success feedback and user flow:

  • data-success-redirect: URL - Redirect after success
  • data-success-redirect-delay: Number - Delay before redirect in ms (default: 3000)
<form class="webform-embed"
      action="https://send.webform.dev/send/YOUR_FORM_KEY"
      method="POST"
      data-success-redirect="/thank-you"
      data-success-redirect-delay="5000">
  <!-- form fields -->
</form>

Spam Protection

WebForm.dev includes built-in spam protection features:

  • reCAPTCHA Integration - Automatic bot detection
  • Rate Limiting - Prevent form abuse
  • Honeypot Fields - Hidden fields to catch bots
  • IP Blocking - Block specific IP addresses
<form action="https://send.webform.dev/send/YOUR_FORM_KEY" method="POST">
  <!-- Regular form fields -->
  <input name="name" type="text" placeholder="Your Name">
  <input name="email" type="email" placeholder="Your Email" required>
  <textarea name="message" placeholder="Your Message" required></textarea>

  <!-- Honeypot field for spam protection -->
  <input name="webform_gotcha" type="text" style="display:none">

  <!-- Custom redirect after submission -->
  <input name="webform_next" type="hidden" value="https://yoursite.com/thanks">

  <button type="submit">Send Message</button>
</form>

JavaScript Events

Event Lifecycle

The embed.js script fires custom events throughout the form submission process, allowing for advanced integrations and custom processing.

Event Order:

  1. webform:beforesubmit - Pre-submission processing (cancelable)
  2. webform:submit - Form submission begins
  3. webform:success - Successful submission
  4. webform:error - Submission error
  5. webform:fallback - Fallback to regular submission

webform:beforesubmit Event

Fired before form submission, allowing you to modify form data or cancel the submission:

// Get the form element
const contactForm = document.querySelector('.webform-embed');

contactForm.addEventListener('webform:beforesubmit', function(e) {
  const { formData, form, config } = e.detail;

  // Add metadata to form submission
  formData.set('timestamp', new Date().toISOString());
  formData.set('page_url', window.location.href);
  formData.set('referrer', document.referrer || 'direct');

  // Validate form fields
  const name = formData.get('name');
  const email = formData.get('email');
  const message = formData.get('message');

  // Check required fields
  if (!name || name.trim() === '') {
    e.preventDefault();
    displayValidationError(form, 'Name is required');
    return;
  }

  if (!email || !validateEmail(email)) {
    e.preventDefault();
    displayValidationError(form, 'Please enter a valid email address');
    return;
  }

  if (!message || message.trim().length < 10) {
    e.preventDefault();
    displayValidationError(form, 'Message must be at least 10 characters long');
    return;
  }

  // Optional: Clean up the message text
  const cleanedMessage = message.trim().replace(/\s+/g, ' ');
  formData.set('message', cleanedMessage);
});

// Email validation function
function validateEmail(email) {
  const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailPattern.test(email);
}

// Display validation errors
function displayValidationError(form, message) {
  // Remove existing error
  const existingError = form.querySelector('.validation-error');
  if (existingError) {
    existingError.remove();
  }

  // Create error element
  const errorElement = document.createElement('div');
  errorElement.className = 'validation-error';
  errorElement.style.cssText = `
    background: #fee;
    border: 1px solid #fcc;
    border-radius: 4px;
    color: #c33;
    margin-bottom: 10px;
    padding: 10px;
    font-size: 14px;
  `;
  errorElement.textContent = message;

  // Insert at top of form
  form.insertBefore(errorElement, form.firstChild);

  // Scroll to error
  errorElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
💡 Use e.preventDefault() to cancel submission. The FormData object can be modified directly.

Event Details Reference

webform:beforesubmit

  • Cancelable: Yes (use event.preventDefault())
  • formData: Mutable FormData object for the submission
  • form: The HTML form element
  • config: Form configuration from data attributes

webform:success

  • form: The HTML form element
  • data: Server response data
  • message: Success message text
  • config: Form configuration

webform:error

  • form: The HTML form element
  • message: Error message text
  • config: Form configuration
  • category: Error category ('network', 'server')
  • error: The original Error object

webform:fallback

  • form: The HTML form element
  • reason: Reason for fallback ('max_retries', 'network_error', etc.)
  • error: The final error that triggered fallback

Advanced Features

Real-World Integration Example

Address autocomplete integration that combines street, city, and zip for submission:

// Store address components from autocomplete
let addressComponents = { street: '', city: '', zip: '' };

// Listen for address selection
addressInput.addEventListener('address-selected', (e) => {
  addressComponents = e.detail;
});

// Process address before form submission
form.addEventListener('webform:beforesubmit', (e) => {
  const { formData } = e.detail;

  // Combine address components for submission
  const fullAddress = [
    addressComponents.street,
    addressComponents.city,
    addressComponents.zip
  ].filter(Boolean).join(', ');

  if (fullAddress) {
    formData.set('address', fullAddress);
  }

  // Update subject line with street address
  const subject = addressComponents.street ?
    `Contact - ${addressComponents.street}` :
    'Contact Form';
  formData.set('subject', subject);
});

CSP Compatibility

The embed script is fully compatible with strict Content Security Policies:

  • ✅ No inline styles or unsafe-eval
  • ✅ Uses CSS classes and CustomEvents
  • ✅ Works with script-src 'self' and style-src 'self'

CSS Classes Used:

  • .webform-error - Error messages
  • .webform-success - Success message styling
  • .webform-success-replace - Full form replacement view
  • .webform-loading - Button loading state
  • .webform-spinner - Loading spinner
  • .webform-submitting - Form during submission

Custom Fields

Automatic Field Detection

WebForm.dev automatically includes all form fields in email notifications, except for configuration fields (those starting with webform_).

How it works:

  • Core fields (name, email, subject, message) appear in the main email body
  • All other fields appear in an "Additional Information" section
  • Configuration fields starting with webform_ are used for form behavior but not displayed in emails
  • Field names with underscores are automatically formatted (e.g., phone_number becomes "Phone Number")
  • Fields can be reordered using the webform_field_order parameter
<form action="https://send.webform.dev/send/YOUR_FORM_KEY" method="POST">
  <!-- Core fields -->
  <input name="name" type="text" placeholder="Your Name" required>
  <input name="email" type="email" placeholder="Your Email" required>
  <input name="subject" type="text" placeholder="Subject">
  <textarea name="message" placeholder="Your Message" required></textarea>

  <!-- Custom fields (automatically included in email) -->
  <input name="company" type="text" placeholder="Company Name">
  <input name="phone" type="tel" placeholder="Phone Number">
  <select name="department">
    <option value="sales">Sales</option>
    <option value="support">Support</option>
    <option value="billing">Billing</option>
  </select>

  <!-- Configuration fields (not included in email) -->
  <input name="webform_gotcha" type="text" style="display:none">
  <input name="webform_next" type="hidden" value="/thanks">

  <button type="submit">Send Message</button>
</form>

Field Ordering

Control the order of custom fields in email notifications using the webform_field_order parameter:

<form action="https://send.webform.dev/send/YOUR_FORM_KEY" method="POST">
  <input name="name" type="text" placeholder="Your Name" required>
  <input name="email" type="email" placeholder="Your Email" required>
  <textarea name="message" placeholder="Your Message" required></textarea>

  <input name="company" type="text" placeholder="Company">
  <input name="phone" type="tel" placeholder="Phone">
  <input name="budget" type="text" placeholder="Budget Range">
  <input name="timeline" type="text" placeholder="Timeline">

  <!-- Order: phone, company, timeline (budget will appear last) -->
  <input name="webform_field_order" type="hidden" value="phone,company,timeline">

  <button type="submit">Send Message</button>
</form>
💡 Fields not listed in webform_field_order will appear after the ordered fields in the email.

Supported Field Types

WebForm.dev automatically handles various HTML form field types:

  • Text inputs - <input type="text">, <input type="email">, etc.
  • Textareas - <textarea> fields for longer text
  • Select dropdowns - <select> with single or multiple options
  • Radio buttons - Selected value will be included
  • Checkboxes - Multiple selected values will be listed as comma-separated

Security Features

🔒 Data Encryption

All data is encrypted in transit using TLS 1.3 and at rest using AES-256.

🛡️ GDPR Compliant

Built with privacy by design. Minimal data collection and transparent handling.

Rate Limiting

Automatic protection against abuse with configurable rate limits.

🔍 Audit Logs

Complete audit trail of all form submissions and API calls.

Advanced Examples

Business Inquiry Form with Custom Fields

<form action="https://send.webform.dev/send/business_inquiry_form" method="POST">
  <!-- Core fields -->
  <input type="text" name="name" placeholder="Full Name" required>
  <input type="email" name="email" placeholder="Email Address" required>
  <input type="text" name="subject" value="Business Inquiry">
  <textarea name="message" placeholder="Tell us about your project" required></textarea>

  <!-- Custom fields (automatically included in email) -->
  <input type="text" name="company" placeholder="Company Name">
  <input type="tel" name="phone" placeholder="Phone Number">
  <select name="budget">
    <option value="">Select Budget Range</option>
    <option value="under-5k">Under $5,000</option>
    <option value="5k-15k">$5,000 - $15,000</option>
    <option value="15k-50k">$15,000 - $50,000</option>
    <option value="over-50k">Over $50,000</option>
  </select>
  <select name="services">
    <option value="">Services Needed</option>
    <option value="web-design">Web Design</option>
    <option value="development">Development</option>
    <option value="consulting">Consulting</option>
    <option value="maintenance">Maintenance</option>
  </select>
  <input type="text" name="timeline" placeholder="Desired Timeline">

  <!-- Control field order in email -->
  <input type="hidden" name="webform_field_order" value="company,phone,services,budget,timeline">

  <!-- Configuration fields -->
  <input name="webform_gotcha" type="text" style="display:none">
  <input name="webform_next" type="hidden" value="/thanks">

  <button type="submit">Submit Inquiry</button>
</form>
💡 This form will display company, phone, services, budget, and timeline in that order in the email's "Additional Information" section.

Enhanced Contact Form with All Features

A form using all the enhanced user feedback features for the best user experience:

<form action="https://send.webform.dev/send/enhanced_contact_form" method="POST" class="webform-embed"
      data-success-message="Thank you! We'll get back to you within 24 hours."
      data-submit-text="Sending your message..."
      data-error-position="top"

      <!-- Enhanced user feedback features -->
      data-loading-spinner="true"
      data-disable-fields-on-submit="true"
      data-loading-overlay="false"

      <!-- Network resilience features -->
      data-max-retries="3"
      data-retry-delay="1500"
      data-show-retry-message="true"
      data-fallback-on-error="true"
      data-error-details="false"

      <!-- Success enhancements -->
      data-success-animation="fade"
      data-success-redirect="/thank-you"
      data-success-redirect-delay="5000">

  <!-- Form fields -->
  <input type="text" name="name" placeholder="Your Name" required>
  <input type="email" name="email" placeholder="Your Email" required>
  <input type="tel" name="phone" placeholder="Phone Number">
  <textarea name="message" placeholder="How can we help you?" required></textarea>

  <!-- Configuration -->
  <input name="webform_gotcha" type="text" style="display:none">
  <button type="submit">Send Message</button>
</form>

<script>
// Enhanced event handling for better user experience
const form = document.querySelector('.webform-embed');

// Handle fallback gracefully
form.addEventListener('webform:fallback', (e) => {
  console.log('Switching to backup submission method');

  // Optional: Show user-friendly message
  const notice = document.createElement('div');
  notice.textContent = 'Using backup submission method...';
  notice.style.cssText = 'color: orange; font-size: 14px; margin: 10px 0;';
  form.insertBefore(notice, form.firstChild);
});

// Enhanced error handling with categories
form.addEventListener('webform:error', (e) => {
  const { category, message } = e.detail;

  // Track errors in analytics
  if (window.gtag) {
    gtag('event', 'form_error', {
      error_category: category,
      error_message: message
    });
  }

  // Custom handling based on error type
  if (category === 'network') {
    console.log('Network issue detected - user may be offline');
  }
});

// Track successful submissions
form.addEventListener('webform:success', (e) => {
  console.log('Form submitted successfully!');

  if (window.gtag) {
    gtag('event', 'form_submit_success', {
      form_type: 'contact'
    });
  }
});
</script>
✨ This form includes spinner animation, retry logic, graceful fallback, and redirects users to a thank-you page after 5 seconds.