Introduction
Formserve is a simple way to save information from your website via forms or front-end JavaScript. That is, you can save data from your website without a serverβFormserve is your server.
Formserve works great when you want the simplicity of a static website, but don't want to setup a server for a form or two. Capture leads on landing pages, use for contact forms, collecting emails for a newsletter, polls, surveys, etc.
Formserve works anywhere you can put an HTML form. It works with any static site generator e.g. Jekyll, Hugo, Hexo, GitBook, Gatsby and all others. Formserve also works on any hosting provider, from blog hosting providers like WordPress, to static hosting providers like GitHub Pages or S3, to Platform-as-a-Service providers like Heroku and Docker, and any other method of hosting you have up your sleeve.
π Quick Start Guide
Get your first form submission in under 5 minutes! This guide walks you through everything from signup to receiving your first submission.
What You'll Accomplish
- Create a free Formserve account
- Set up your first form endpoint
- Test your form locally
- Receive your first email notification
Create Your Account
Sign up for a free Formserve account. No credit card required!
π What you'll need:
- β’ A valid email address
- β’ A password (8+ characters)
Create Your First Endpoint
An endpoint is where your forms send their data. Creating one takes just seconds!
Quick Setup - Just 2 Fields:
Give it a descriptive name so you can identify it later
Start with localhost for testing, add your domain later
β¨ Smart Defaults: Email notifications, spam protection, and localhost testing are automatically configured!
Sign in first to create an endpoint
Copy Your Access Key
After creating your endpoint, you'll see the Setup tab with your unique access key.
You'll also find ready-to-use code snippets in:
- HTML - Plain form markup
- JavaScript - AJAX form handling
- React - React component example
Create a Test HTML File
Create a simple HTML file to test your form. Copy this code and save it as test-form.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test Form</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 500px;
margin: 50px auto;
padding: 20px;
}
input, textarea {
width: 100%;
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
background: #2563eb;
color: white;
padding: 12px 24px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover { background: #1d4ed8; }
</style>
</head>
<body>
<h1>Test Contact Form</h1>
<form action="https://formserve.io/f/YOUR_ACCESS_KEY" method="POST">
<label>Name</label>
<input type="text" name="name" required>
<label>Email</label>
<input type="email" name="email" required>
<label>Message</label>
<textarea name="message" rows="4" required></textarea>
<button type="submit">Send Message</button>
</form>
</body>
</html>
β οΈ Don't forget: Replace YOUR_ACCESS_KEY with your actual access key!
Test Your Form
Open your test-form.html file in your browser and submit the form!
Testing Checklist:
π§ What to expect: Within seconds, you'll receive an email notification with the form data at the email address you signed up with!
View Your Submission
Go to the Submissions tab to see your form data:
- View all form fields and values
- Filter by spam, unread, or search
- Export submissions as CSV, JSON, or XLSX
π Congratulations! What's Next?
Customize Settings
Visit the Settings tab to configure:
- β’ Add production domains
- β’ Adjust spam protection
- β’ Customize email notifications
- β’ Set up redirect URLs
Add Integrations
Connect your favorite tools:
- β’ Slack - Team notifications
- β’ Webhooks - Custom workflows
- β’ Mailchimp - Email marketing
Deploy to Production
Ready to go live?
- β’ Add your production domain
- β’ Update your website's form
- β’ Test from production
- β’ Monitor submissions
Learn Advanced Features
Explore more capabilities:
- β’ Formserve.js library
- β’ REST API
- β’ Advanced integration
Need Help?
We're here to help you succeed!
Setup
Getting started with Formserve is quick and easy - you'll be up and running in less than 5 minutes!
Step 1: Create Your Account
Sign up for a free Formserve account. No credit card required to get started.
Step 2: Create Your First Endpoint
An endpoint is ready to use in just two simple fields:
- Name - A descriptive name for your form (e.g., "Contact Form")
- Allowed Domains - Your website domain (pre-filled with "localhost:3000" for local testing)
β¨ Smart Defaults: Formserve automatically configures email notifications to your account email, enables spam protection, and allows localhost testing. You can customize everything later!
Step 3: Get Your Access Key
After creating your endpoint, you'll see the Setup tab with:
- Your unique access key
- Ready-to-use code snippets (HTML, JavaScript, React)
- Instructions for integration
Understanding Endpoints
An endpoint is a unique URL where your HTML forms submit data. Each endpoint acts as a secure receiver for your form submissions.
Endpoint Management Tabs
After creating an endpoint, you'll have access to four organized tabs:
- Setup - Your access key, code snippets (HTML/JavaScript/React), and integration instructions
- Settings - Configure domains, spam protection, notifications, redirects, and file uploads
- Submissions - View, search, filter, and export all form submissions
- Integrations - Connect Webhooks, Slack, Mailchimp, and other services
β οΈ Security Notice: Allowed domains are required for all endpoints. This security measure prevents unauthorized access, protects your submission quota, and blocks spam attacks. Only forms on your specified domains can submit to your endpoint.
Allowed Domains Configuration
Allowed domains determine which websites can submit to your endpoint. This is your primary security control.
Domain Format Examples:
example.com- Allows example.com and www.example.com*.example.com- Allows all subdomains (app.example.com, blog.example.com, etc.)localhost:3000- For local development (include the port number)example.com, *.myapp.com, localhost:3000- Multiple domains (comma-separated)
Important: Forms from domains not in your allowed list will be rejected, and the attempt will be logged as spam in your endpoint's spam log.
π‘ Pro Tip: Start with localhost:3000 to test locally, then add your production domain before going live. You can update allowed domains anytime in the Settings tab.
Working with Multiple Forms
Each endpoint can receive submissions from multiple forms on your website. You can organize submissions by using different field names or by creating separate endpoints.
Option 1: Multiple Forms, One Endpoint
Use the same endpoint for different forms and identify them with a hidden field:
<!-- Contact Form -->
<form action="https://formserve.io/f/YOUR_ACCESS_KEY" method="POST">
<input type="hidden" name="form_type" value="contact">
<!-- Your fields -->
</form>
<!-- Newsletter Form -->
<form action="https://formserve.io/f/YOUR_ACCESS_KEY" method="POST">
<input type="hidden" name="form_type" value="newsletter">
<!-- Your fields -->
</form>
Option 2: Separate Endpoints (Recommended)
Create individual endpoints for different purposes:
- "Contact Form" endpoint - for general inquiries
- "Newsletter Signup" endpoint - for email collection
- "Support Request" endpoint - for customer support
This approach provides better organization, separate spam protection settings, and dedicated integrations for each form type.
Website Integration
Integrating Formserve with your website is simple. You have two options: use plain HTML forms or enhance them with our JavaScript library for AJAX submissions.
Option 1: Plain HTML Form (Simplest)
A basic HTML form that redirects to a thank you page after submission:
<form action="https://formserve.io/f/YOUR_ACCESS_KEY" method="POST">
<label for="name">Name</label>
<input type="text" name="name" id="name" required>
<label for="email">Email</label>
<input type="email" name="email" id="email" required>
<label for="message">Message</label>
<textarea name="message" id="message" required></textarea>
<button type="submit">Send Message</button>
</form>
π‘ Important: Replace YOUR_ACCESS_KEY with the actual access key from your endpoint's Setup tab. Only fields with a name attribute will be saved.
Option 2: AJAX Form with Formserve.js (Enhanced)
For a better user experience with no page reload, use our JavaScript library:
Step 1: Include the Script
Add this script before the closing </body> tag:
<script src="https://formserve.io/v1/formserve.js?v=1.3"></script>
Step 2: Add the Class
Add class="formserve" to your form:
<form action="https://formserve.io/f/YOUR_ACCESS_KEY"
class="formserve"
method="POST">
<label for="name">Name</label>
<input type="text" name="name" id="name" required>
<label for="email">Email</label>
<input type="email" name="email" id="email" required>
<label for="message">Message</label>
<textarea name="message" id="message" required></textarea>
<button type="submit" class="formserve-form__submit">
<span>Send Message</span>
</button>
</form>
The form will now submit asynchronously (no page reload) and show a success message to the user.
β¨ Features with Formserve.js: Automatic AJAX submission, loading spinner support, success/error messages, and custom validation hooks. See the Formserve.js Integration Guide for advanced usage.
Formserve.js Integration Guide
Formserve.js is a lightweight JavaScript library that makes it easy to integrate form submissions with Formserve. It handles AJAX submissions, loading states, success/error messages, and provides hooks for custom behavior.
What is Formserve.js?
Formserve.js is a client-side library that:
- Automatically handles form submissions via AJAX (no page reloads)
- Provides built-in loading spinner support
- Shows success messages after submission
- Handles errors gracefully
- Offers callback hooks for custom validation and response handling
- Works with any HTML form (vanilla HTML, React, Vue, etc.)
Step 1: Installation
Add the Formserve.js script tag before the closing </body> tag in your HTML:
<script src="https://formserve.io/v1/formserve.js?v=1.3" charset="utf-8"></script>
Note: The script is loaded from Formserve's CDN and is always up-to-date. No npm installation or build step required!
Step 2: Create Your Form
Once the script is loaded, any form with the class formserve will be automatically handled by Formserve.js:
<form action="https://formserve.io/f/YOUR_ENDPOINT_KEY"
class="formserve"
method="POST">
<label for="name">Name</label>
<input type="text" name="name" id="name" required>
<label for="email">Email</label>
<input type="email" name="email" id="email" required>
<label for="message">Message</label>
<textarea name="message" id="message" required></textarea>
<button type="submit" class="formserve-form__submit">
<span>Submit</span>
</button>
</form>
That's it! The form will now submit asynchronously and show a success message when complete.
Key Components
action="https://formserve.io/f/YOUR_ENDPOINT_KEY"- Your unique endpoint URL from the dashboardclass="formserve"- Tells Formserve.js to handle this formmethod="POST"- Required for form submissionnameattributes - Only fields with a name will be saved
Loading Spinner (Optional)
Formserve.js can automatically show a loading spinner on your submit button during form submission. To enable this:
- Add the class
formserve-form__submitto your submit button - Wrap your button text in a
<span>tag
<button type="submit" class="formserve-form__submit">
<span>Submit</span>
</button>
Styling the Spinner
The spinner is white by default. To change the color, add CSS:
/* Custom spinner color */
.formserve-form__submit::after {
border-color: rgba(0, 123, 255, 0.3);
border-left-color: #007bff;
}
/* Or use the built-in dark loader */
<button class="formserve-form__submit formserve-form__submit--dark-loader">
<span>Submit</span>
</button>
Advanced Usage
Manual Initialization with Options
For more control, you can manually initialize forms with custom options:
const form = document.querySelector('#myForm');
Formserve.form(form, {
// Called before submission - return false to prevent submission
onSubmit: function(event) {
console.log('Form is about to submit');
// Custom validation
const email = form.querySelector('[name="email"]').value;
if (!email.includes('@')) {
alert('Please enter a valid email');
return false; // Prevents submission
}
return true; // Allow submission
},
// Called when response is received
onResponse: function(error, response) {
if (error) {
console.error('Submission failed:', error);
alert('Error: ' + error.message);
return false; // Prevents default success message
}
console.log('Submission successful:', response);
// Custom success handling
if (response.redirect_url) {
window.location.href = response.redirect_url;
} else {
alert('Thank you for your submission!');
}
return false; // Prevents default success message
},
// Custom success message template (HTML)
successTemplate: '<div class="success-message">Thank you! We\'ll be in touch soon.</div>'
});
Sending Data Without a Form
You can send data programmatically using Formserve.send():
// Prepare your data
const data = {
name: 'John Smith',
email: 'john@example.com',
message: 'Hello from JavaScript!'
};
// Send to Formserve
Formserve.send(
'YOUR_ENDPOINT_KEY', // Your endpoint key
data, // Data object
function(error, response) {
if (error) {
console.error('Submission failed:', error.message);
} else {
console.log('Submission successful:', response);
}
}
);
Complete Examples
Example 1: Contact Form with Custom Validation
<!DOCTYPE html>
<html>
<head>
<style>
.form-group { margin-bottom: 1rem; }
label { display: block; margin-bottom: 0.5rem; }
input, textarea { width: 100%; padding: 0.5rem; }
.error { color: red; font-size: 0.875rem; }
.success-message {
padding: 1rem;
background: #d4edda;
color: #155724;
border-radius: 4px;
margin-bottom: 1rem;
}
</style>
</head>
<body>
<form id="contactForm"
action="https://formserve.io/f/YOUR_ENDPOINT_KEY"
class="formserve"
method="POST">
<div class="form-group">
<label for="name">Name *</label>
<input type="text" name="name" id="name" required>
<span class="error" id="name-error"></span>
</div>
<div class="form-group">
<label for="email">Email *</label>
<input type="email" name="email" id="email" required>
<span class="error" id="email-error"></span>
</div>
<div class="form-group">
<label for="phone">Phone</label>
<input type="tel" name="phone" id="phone">
</div>
<div class="form-group">
<label for="message">Message *</label>
<textarea name="message" id="message" rows="5" required></textarea>
</div>
<button type="submit" class="formserve-form__submit">
<span>Send Message</span>
</button>
</form>
<script src="https://formserve.io/v1/formserve.js?v=1.3"></script>
<script>
const form = document.getElementById('contactForm');
Formserve.form(form, {
onSubmit: function(event) {
// Clear previous errors
document.querySelectorAll('.error').forEach(el => el.textContent = '');
// Custom validation
const name = form.querySelector('[name="name"]').value.trim();
const message = form.querySelector('[name="message"]').value.trim();
if (name.length < 2) {
document.getElementById('name-error').textContent = 'Name must be at least 2 characters';
return false;
}
if (message.length < 10) {
document.getElementById('message-error').textContent = 'Message must be at least 10 characters';
return false;
}
return true;
},
onResponse: function(error, response) {
if (error) {
alert('Failed to send message: ' + error.message);
return false;
}
// Show success message and reset form
form.reset();
return true; // Shows default success message
},
successTemplate: '<div class="success-message">β Thank you! We\'ve received your message and will respond soon.</div>'
});
</script>
</body>
</html>
Example 2: Newsletter Signup with Analytics
<form id="newsletter"
action="https://formserve.io/f/YOUR_ENDPOINT_KEY"
class="formserve"
method="POST">
<input type="email"
name="email"
placeholder="Enter your email"
required>
<button type="submit" class="formserve-form__submit">
<span>Subscribe</span>
</button>
</form>
<script>
const newsletterForm = document.getElementById('newsletter');
Formserve.form(newsletterForm, {
onSubmit: function(event) {
// Track submission attempt
if (typeof gtag !== 'undefined') {
gtag('event', 'newsletter_submit_attempt');
}
return true;
},
onResponse: function(error, response) {
if (error) {
// Track error
if (typeof gtag !== 'undefined') {
gtag('event', 'newsletter_submit_failed', {
error_message: error.message
});
}
return false;
}
// Track success
if (typeof gtag !== 'undefined') {
gtag('event', 'newsletter_submit_success');
}
// Clear the form
newsletterForm.reset();
return true; // Show success message
},
successTemplate: '<p style="color: green;">β You\'re subscribed! Check your email for confirmation.</p>'
});
</script>
Example 3: Multi-Step Form
<div id="multiStepForm">
<!-- Step 1 -->
<div class="step" data-step="1">
<h2>Step 1: Personal Information</h2>
<input type="text" id="step1-name" placeholder="Name" required>
<input type="email" id="step1-email" placeholder="Email" required>
<button onclick="nextStep(2)">Next</button>
</div>
<!-- Step 2 -->
<div class="step" data-step="2" style="display:none;">
<h2>Step 2: Company Details</h2>
<input type="text" id="step2-company" placeholder="Company Name">
<input type="text" id="step2-role" placeholder="Your Role">
<button onclick="prevStep(1)">Back</button>
<button onclick="nextStep(3)">Next</button>
</div>
<!-- Step 3 -->
<div class="step" data-step="3" style="display:none;">
<h2>Step 3: Message</h2>
<textarea id="step3-message" placeholder="Your message" rows="5"></textarea>
<button onclick="prevStep(2)">Back</button>
<button onclick="submitMultiStepForm()">Submit</button>
</div>
</div>
<script src="https://formserve.io/v1/formserve.js?v=1.3"></script>
<script>
function nextStep(step) {
document.querySelectorAll('.step').forEach(el => el.style.display = 'none');
document.querySelector(`.step[data-step="${step}"]`).style.display = 'block';
}
function prevStep(step) {
nextStep(step);
}
function submitMultiStepForm() {
// Collect data from all steps
const data = {
name: document.getElementById('step1-name').value,
email: document.getElementById('step1-email').value,
company: document.getElementById('step2-company').value,
role: document.getElementById('step2-role').value,
message: document.getElementById('step3-message').value
};
// Submit using Formserve.send
Formserve.send(
'YOUR_ENDPOINT_KEY',
data,
function(error, response) {
if (error) {
alert('Submission failed: ' + error.message);
} else {
alert('Thank you! Your submission has been received.');
// Reset and go back to step 1
document.querySelectorAll('input, textarea').forEach(el => el.value = '');
nextStep(1);
}
}
);
}
</script>
API Reference
Formserve.form(formElement, options)
Wraps a form element and handles submission automatically.
Parameters:
formElement(HTMLFormElement) - The form element to wrapoptions(Object, optional) - Configuration options:onSubmit(event)- Called before submission. Return false to prevent submission.onResponse(error, response)- Called after receiving response. Return false to prevent default success message.successTemplate- HTML string for custom success message
Formserve.send(endpointKey, data, callback)
Sends data directly to a Formserve endpoint without a form.
Parameters:
endpointKey(String) - Your endpoint key from the dashboarddata(Object) - The data to send (will be JSON stringified)callback(error, response)- Function called after submission completeserror- Error object if submission failed, null otherwiseresponse- Response object from Formserve
Best Practices
β DO: Use HTML5 validation
Add required, type="email", etc. for instant client-side validation
β DO: Include name attributes
Only form fields with a name attribute will be submitted to Formserve
β DO: Handle errors gracefully
Use the onResponse callback to show user-friendly error messages
β DON'T: Submit sensitive data without HTTPS
Always use HTTPS in production to protect user data
β DON'T: Forget accessibility
Include proper labels and ARIA attributes for screen readers
Troubleshooting
Form not submitting?
- Check that the
actionURL is correct - Verify the form has
class="formserve" - Ensure formserve.js is loaded (check browser console)
- Check browser console for JavaScript errors
Loading spinner not showing?
- Button must have class
formserve-form__submit - Button text must be wrapped in a
<span> - Cannot use
<input type="submit">- use<button>
Custom validation not working?
- Make sure
onSubmitreturnsfalseto prevent submission - Initialize the form manually with
Formserve.form() - Don't add both
class="formserve"AND manual initialization
Next Steps
- β Learn about Form Validation
- β Explore Advanced Integration options
- β Check out the FAQ for handling API responses in custom JavaScript
- β Set up Third-Party Integrations (Slack, Webhooks)
Data Handling
What data is saved?
Any form <input>, <textarea>, or <select> element with a name attribute is saved into Formserve. Some notes:
- Naming inputs with square brackets (e.g.
someName[aChildKey]) will save the input under a child object. This is useful for groups of things like checkboxes. e.g.{someName: {aChildKey: true}} - Checkboxes (
<input type="checkbox">) are stored as booleans. When unchecked, the browser does not send the input in the request, so a checkbox value will either be true, or the key will not exist at all. - File inputs (
<input type="file">) are ignored, and multipart requests will be rejected.
An example form:
<form action="https://formserve.io/f/{yourEndpointID}"
class="formserve" data-formserve-endpoint="{yourEndpointID}"
method="post">
<!-- Add your inputs as you normally would -->
<label name="name" for="name">Name</label>
<input type="text" name="name" placeholder="Your name">
<label name="email" for="email">Email</label>
<input type="email" name="email" placeholder="Your email">
<label name="message" for="message">Message</label>
<input type="textarea" name="message" placeholder="Your message">
<button class="formserve__submit" type="submit">
<span>Submit</span>
</button>
</form>
Will save the following payload:
{
email: 'user@example.com',
heardFrom: 'ph',
animal: 'tarantula',
likes: {
pizza: true
},
version: 'v1'
}
Special fields
Formserve can send you an email for each form submission and there are two specially named fields that make those emails easier to use:
email- the user's email. This will be used in the reply-to field of the email that Formserve sends you. So all you have to do is hit 'Reply' in your email client to respond to the user.subject- This will set the subject of the email that Formserve sends you for each submission.
These fields are useful when you setup contact forms. An example contact form:
<form action="https://formserve.io/f/{yourEndpointID}"
class="formserve" data-formserve-endpoint="{yourEndpointID}"
method="post">
<!-- This will be used in the email's reply-to field. Must have name="email" -->
<input type="email" name="email" value="user@example.com"/>
<!-- This will be used in the email's subject. Must have name="subject" -->
<input type="text" name="subject" value="Email subject"/>
<textarea name="body">Email body</textarea>
<button class="formserve__submit" type="button">
<span>Submit</span>
</button>
</form>
Bare minimum integration
You do not need to use the default asynchronous submission behavior. The absolute minimum you need to do is have your form POST to your project URL:
<form action="https://formserve.io/f/{yourEndpointID}"
class="formserve" data-formserve-endpoint="{yourEndpointID}"
method="post">
<input type="text" name="name" value="John Smith"/>
<input type="text" name="email" value="john@example.com"/>
<input type="submit" value="Send">
</form>
With this form, Formserve will save the data, then redirect back to the originating page.
Form Validation
Formserve works with any form validation library or scheme. If you have a favorite, just use that!
We recommend using HTML5 validation that is built into the browser. HTML5 validation is very rich these days, and has good browser support.
A basic example enforcing required attributes:
<!-- Note the `required` attributes in inputs! -->
<form action="https://formserve.io/f/{yourEndpointID}"
class="formserve" data-formserve-endpoint="{yourEndpointID}"
method="post">
<input type="text" name="name" required />
<input type="text" name="email" required />
<input type="submit" value="Send">
</form>
Other HTML5 Form Validation Resources
Advanced Integration
Using the loading spinner
Formserve can overlay a loading spinner on your submit button with some special markup. You must have a <button> element with the .formserve__submit and a <span> child.
<form>...
<button class="button formserve__submit" type="submit">
<span>Submit</span>
</button>
</form>
Styling the spinner
By default the spinner is white. You can change it to black by adding the formserve__submit--dark-loader class to the button.
You can specify a custom color by styling the border:
.formserve__submit::after {
border-color: rgba(0, 255, 0, 0.8);
border-reft-color: blue;
}
Loading spinner details
When a form is submitted, the <button> will go through a few CSS class states. These classes provide CSS animations.
.formserve__submit--start-loading: fades the<span>text out, and pops the loader into view.formserve__submit--loading: spins the loader.formserve__submit--end-loading: hides the loader, and fades the<span>text back in.
Some notes:
- If the inner
<span>is not specified, it will just overlay the spinner on the text. - If an
<input type="submit" />is used, the loading spinner will not work. A button must be used as the loading spinner is rendered in the::afterpseudo element. - The start and animations can be removed from the button. If animations do not exist, the JS will detect it and only add the
.formserve__submit--loadingclass to the button.
Formserve.js
When https://formserve.io/v1/formserve.js?v=1.3 is included on the page, a window.Formserve object is created. With it, you can hook into form submission, or send data to Formserve without a form at all.
Formserve.form(form[, options])
Formserve.form(...) wraps a form, submits the data to Formserve asynchronously, and gives you a couple hooks into the lifecycle. You can use these for things like validation or displaying messages to the user. By default, any forms with class formserve will be automatically wrapped with Formserve.form(...).
form:HTMLFormElement- the<form />element to submit to Formserve. It must have an action pointing to your Formserve project.options:Object- (optional)onSubmit:Function- returning false from this will prevent submission to FormserveonResponse:Function- returning false from this will prevent showing the successTemplate to the usersuccessTemplate:String
var form = document.querySelector('.formserve')
Formserve.form(form, {
onSubmit: function (event) { },
onResponse: function (error, response) { },
successTemplate: '<span>Thank you!</span>'
})
Formserve.send(EndpointID, formName, data, callback)
Formserve.send(...) allows you to send arbitrary JSON data via XHR to a Formserve form.
EndpointID:String- Your public EndpointID; a unique token give to each project.formName:String- The name of the form to save to. If you wish to send to a default form, formName must be 'default'.data:Object- The actual data to save.JSON.stringify()will be called on this object before submission.callback:Function- Called when submission is finishederror:Error- null when the request succeeds; Object with .message on failure.response:Object-{"data":"ok"}
var data = {
name: 'John Smith',
email: 'john@example.com'
}
Formserve.send('...yourEndpointID...', 'contact', data, function (error, response) {
console.log('saved?', !!error, '; response:', error || response)
})
Third-Party Integrations
Auto-responder Emails
Send automatic confirmation emails to form submitters. This is perfect for letting users know you've received their submission and will respond soon.
Setting up Auto-responder
To enable auto-responder emails:
- Go to your endpoint's settings page
- Scroll to the "Notification Settings" section
- Enable "Auto-responder Email"
- Configure the email subject and body
- Optionally set a custom from name and reply-to address
Template Variables
You can use template variables in both the subject and body of your auto-responder emails. Variables are wrapped in double curly braces and will be replaced with actual values from the form submission.
Built-in variables:
{{name}}- The submitter's name{{email}}- The submitter's email address{{endpoint_name}}- The name of your form endpoint{{date}}- Submission date (e.g., "January 15, 2025"){{time}}- Submission time (e.g., "02:30 PM")
Custom form fields: You can also use any field name from your form as a variable.
Example Auto-responder
Subject:
Thank you for contacting us, {{name}}!
Body:
Hi {{name}},
Thank you for reaching out to us through our {{endpoint_name}} form.
We received your message on {{date}} at {{time}}, and our team will review it shortly. We typically respond within 24-48 hours.
If you have any urgent questions, please don't hesitate to reply to this email.
Best regards,
The Support Team
Requirements
- Your form must collect an email address in a field named
email,email_address, oruser_email - The email address must be valid
- Both subject and body must be configured
Webhook
You can set up Formserve to call a URL on your own server for each form submission. Formserve will make an HTTP POST request to the URL of your choice with JSON data about the new item. To be clear, a webhook will be called each time a user submits a form.
Go to the Integrations tab on your project's Formserve UI, and click Set Webhook
Webhook Token
In each POST request Formserve makes to your server, it will include a token in the request body. On your server, you can use this token to verify that the request is from Formserve.
You can copy this token in the Formserve UI once you have set your URL. We advise you keep this token in an environment variable on your server.
{
"action": "newItem",
"isTest": true,
"token": "99c59ojxCCFfwwsLtyZUppcHbIyGrfXd",
...,
}
On your server, you might do something like this:
server.handlePost('/formserve-webhook', (bodyJSON) => {
if (bodyJSON.token === process.env.FORMBRIDGE_TOKEN) {
// Do successful things
} else {
// Fail; probably sketchy!
}
})
Webhook Payload
Each webhook request will contain data about the organization, project, form, and of course, the new item. Some notes:
item.payloadis the actual data the user submitted.isTestwill be true if the request is from clicking the Test Webhook button in the UI
{
"action": "newItem",
"isTest": true,
"token": "99c59ojxCCFfwwsLtyZUppcHbIyGrfXd",
"organization": {
"organizationEid": "JyAmtMGNVAjWPg8RnyG5vJkSk4f9Ntf7",
"name": "Test Org",
"isPersonal": false,
"billingEmail": "john@example.com"
},
"project": {
"projectEid": "YD2jPJKGY1CedwKfvM5NcDCHm5bQMpZQ",
"name": "Test Project",
"slug": "test-project",
"domains": "localhost,example.com"
},
"form": {
"bucketEid": "HutBkLTizLfF7YFtOftpEWFjMCLxhR3j",
"name": "contact-form",
"displayName": "Contact Form"
},
"item": {
"itemEid": "Wt3tiXgvsimZ7sUjnivxZG2AJtvHQjGi",
"payload": {
"name": "John Smith",
"email": "john@example.com"
}
}
}
Mailchimp Integration
Automatically sync your form submissions to your Mailchimp audience lists. Perfect for building email newsletters, managing leads, and growing your subscriber base.
Overview
The Mailchimp integration allows you to:
- Automatically add form submitters to your Mailchimp lists
- Map form fields to Mailchimp merge fields
- Sync submissions in real-time via background jobs
- Track sync status and errors
- Enable/disable syncing per endpoint
Important: Email Field Required
Mailchimp requires an email address to add subscribers to lists. Your form must collect an email field for syncing to work.
If your form doesn't collect emails (e.g., contact forms that only collect names and messages), submissions will be saved to Formserve but will NOT sync to Mailchimp.
Setup Guide
Step 1: Connect Your Mailchimp Account
Formserve offers two ways to connect your Mailchimp account:
β¨ Recommended: OAuth 2.0 (One-Click)
- In Formserve, go to Mailchimp in the sidebar
- Click the yellow "Connect with Mailchimp" button
- Log in to your Mailchimp account (if not already)
- Click "Allow" to authorize Formserve
- You'll be redirected back and connected automatically!
Benefits: More secure, easier setup, automatic token refresh, can be revoked anytime from Mailchimp.
Alternative: API Key (Advanced)
If you prefer to use an API key instead:
- In Formserve, go to Mailchimp in the sidebar
- Click "Use API Key (Advanced)"
- Log in to your Mailchimp account
- Go to Account β Extras β API keys
- Click "Create A Key" and copy it
- Note the server prefix (the part after the last dash, e.g., "us19")
- Paste the API key and server prefix into Formserve
- Click "Connect Account"
Step 2: Map Endpoints to Lists
- Go to any of your endpoints
- Click "Mailchimp Sync" button
- Click "Add List Mapping"
- Select which Mailchimp list to sync to
- Map your form fields to Mailchimp merge fields (optional)
- Enable syncing and save
Field Mapping
Formserve automatically detects the email field in your form submissions. You can optionally map additional fields:
| Form Field | Mailchimp Merge Field | Description |
|---|---|---|
email |
EMAIL |
Required - subscriber's email address |
name or first_name |
FNAME |
First name |
last_name |
LNAME |
Last name |
phone |
PHONE |
Phone number |
company |
COMPANY |
Company name |
You can find your list's available merge fields in Mailchimp under Audience β Settings β Audience fields and *|MERGE|* tags.
Example Form
Here's an example HTML form that works perfectly with Mailchimp integration:
<form action="https://formserve.io/f/YOUR_ENDPOINT_KEY" method="POST">
<!-- Email is required for Mailchimp -->
<input type="email" name="email" placeholder="Your email" required>
<!-- Optional fields that can be mapped to Mailchimp -->
<input type="text" name="name" placeholder="First name">
<input type="text" name="company" placeholder="Company name">
<button type="submit">Subscribe</button>
</form>
How It Works
- Form Submission: When someone submits your form, Formserve saves the submission
- Background Sync: A background job automatically syncs the data to Mailchimp
- Subscriber Added: The email is added/updated in your Mailchimp list with status "subscribed"
- Merge Fields: Any mapped fields are added to the subscriber's profile
- Status Tracking: Sync status and errors are tracked in your Formserve dashboard
Managing Your Integration
View Sync Status
For each endpoint, you can view:
- Total successful syncs
- Error count
- Last sync time
- Last error message (if any)
Enable/Disable Syncing
You can temporarily disable syncing:
- Global: Disable all syncing in Mailchimp settings
- Per Endpoint: Toggle syncing for individual endpoint-list mappings
Disconnect Account
To disconnect your Mailchimp account:
- Go to Mailchimp in the sidebar
- Click "Disconnect"
- Confirm the action
Note: Disconnecting will disable all endpoint mappings but won't delete existing subscribers in Mailchimp.
Troubleshooting
Common Issues
Connection Failed
Check that your API key and server prefix are correct. The server prefix should match the end of your API key.
Email Not Found in Submission / Nothing Syncing
Make sure your form has an email field named "email", "Email", or "email_address". If your form doesn't collect emails, submissions will be saved to Formserve but cannot sync to Mailchimp (Mailchimp requires an email address for all subscribers). You can also map custom field names in the field mapping settings.
Subscribers Not Appearing
Check that syncing is enabled for both the integration and the specific endpoint mapping. Also check the error log for any sync failures.
Invalid Email Error
Mailchimp validates email addresses. Make sure your form includes proper email validation to prevent invalid submissions.
Best Practices
- Email Validation: Always use
type="email"on your email input fields - Required Fields: Make the email field required to ensure all submissions can be synced
- Field Naming: Use standard field names (email, name, company) for automatic detection
- Monitor Errors: Regularly check sync status and address any errors
- Test First: Create a test list in Mailchimp to test your integration
- GDPR Compliance: Ensure you have consent to add people to your mailing list
Frequently Asked Questions
Q: Can I sync one form to multiple Mailchimp lists?
A: Yes! You can create multiple list mappings for the same endpoint.
Q: What happens if someone is already subscribed?
A: Mailchimp will update the subscriber's information with the new data.
Q: Are there any limits on syncing?
A: Formserve doesn't limit syncing, but Mailchimp has their own API rate limits. Normal usage won't hit these limits.
Q: Is the sync instant?
A: Syncing happens via background jobs, typically within a few seconds of form submission.
Q: Can I map custom merge fields?
A: Yes! You can map any form field to any Mailchimp merge field when creating or editing a list mapping.
Q: What if my form doesn't collect email addresses?
A: Mailchimp requires an email address to add subscribers. If your form doesn't collect emails (e.g., feedback forms, contact forms without email), submissions will be saved to Formserve but will NOT sync to Mailchimp. You'll need to add an email field to your form for syncing to work.
Q: Will I be charged/lose submissions if they don't have emails?
A: No! Submissions are always saved to Formserve regardless of Mailchimp syncing. The Mailchimp integration simply skips submissions that don't have an email field. Your form data is safe and accessible in your Formserve dashboard.
Q: Should I use OAuth or API Key to connect?
A: We recommend OAuth (the yellow "Connect with Mailchimp" button) because it's more secure, easier to set up, and tokens refresh automatically. Use the API key method only if you need it for advanced use cases or automation.
Q: Can I switch from API Key to OAuth (or vice versa)?
A: Yes! Simply disconnect your current connection and reconnect using your preferred method. Your list mappings will be preserved.
Q: What happens when my OAuth token expires?
A: OAuth tokens are automatically refreshed by Formserve. You don't need to do anything - your integration will continue working seamlessly.
Need Help?
If you have questions about the Mailchimp integration, please contact us at support@formserve.io
RESTFul API
Overview
The Formserve API provides programmatic access to:
- Submit form data to your form endpoints
- Retrieve form submissions for your endpoints
This simplified API focuses on these core functionalities to enable integration with static websites and other applications.
Authentication
All requests to retrieve submissions require authentication using an API key.
API Keys
API keys can be created and managed in the Formserve dashboard. Each API key is associated with a specific user account and inherits the permissions of that user.
Authentication Methods
Include your API key in one of the following ways:
X-API-Key: your_api_key_here
OR
https://formserve.example.com/api/v1/endpoints/abc123/submissions?api_key=your_api_key_here
Example Request with Authentication
curl -X GET \
"https://formserve.example.com/api/v1/endpoints/{yourEndpointID}/submissions" \
-H "X-API-Key: your_api_key_here"
Response Format
All API responses are in JSON format. Successful responses include the requested data or a confirmation message. Error responses include an error message and appropriate HTTP status code.
Common HTTP Status Codes
200 OK- Success201 Created- Form submission created successfully400 Bad Request- Invalid parameters401 Unauthorized- Missing or invalid API key403 Forbidden- API key valid but not authorized for this action404 Not Found- Endpoint not found422 Unprocessable Entity- Validation errors429 Too Many Requests- Rate limit exceeded500 Internal Server Error- Server error
Rate Limiting
API requests are limited to 100 requests per minute per API key. If you exceed this limit, you'll receive a 429 Too Many Requests response.
API Endpoints
1. Submit Form
Submits data to a form endpoint. This endpoint does not require authentication.
1.1 Request
POST /api/v1/f/:yourEndpointID
1.2 Parameters
Any form fields can be included in the request body. Special fields:
| Name | Description |
|---|---|
| _gotcha | Honeypot field. Should be left empty |
| _redirect | Custom redirect URL (overrides endpoint setting) |
| _referrer | Custom referrer (if not automatically detected) |
1.3 Example Request
{
"name": "John Doe",
"email": "john@example.com",
"message": "Hello, I'm interested in your services.",
"_gotcha": ""
}
1.4 Response
For AJAX/XHR requests:
{
"success": true,
"message": "Form submitted successfully"
}
For regular form submissions:
- Redirects to the redirect_url if specified
- Otherwise, returns a success message
1.5 Error Response
{
"success": false,
"errors": ["Email is required"]
}
2. List Submissions
Retrieves a paginated list of submissions for a specific endpoint.
2.1 Request
GET /api/v1/endpoints/:endpoint_key/submissions
2.2 Query Parameters
| Name | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| per_page | integer | Items per page (default: 20, max: 100) |
| filter | string | Filter submissions by: "spam", "not_spam" |
| unread | boolean | Filter by read status (true/false) |
2.3 Response
{
"submissions": [
{
"id": 1,
"endpoint_id": 1,
"data": {
"name": "John Doe",
"email": "john@example.com",
"message": "Hello, I'm interested in your services."
},
"created_at": "2025-05-10T16:30:00Z",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"referrer": "https://example.com/contact",
"spam": false,
"read": true
},
{
"id": 2,
"endpoint_id": 1,
"data": {
"name": "Jane Smith",
"email": "jane@example.com",
"message": "Please send me more information."
},
"created_at": "2025-05-10T15:45:00Z",
"ip_address": "192.168.1.2",
"user_agent": "Mozilla/5.0...",
"referrer": "https://example.com/products",
"spam": false,
"read": false
}
],
"meta": {
"total_count": 42,
"total_pages": 3,
"current_page": 1
}
}
3. Get Submission
Retrieves details for a specific submission.
3.1 Request
GET /api/v1/endpoints/:endpoint_key/submissions/:id
3.2 Response
{
"id": 1,
"endpoint_id": 1,
"data": {
"name": "John Doe",
"email": "john@example.com",
"message": "Hello, I'm interested in your services."
},
"created_at": "2025-05-10T16:30:00Z",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"referrer": "https://example.com/contact",
"spam": false,
"read": true
}
Error Codes and Troubleshooting
Common Error Codes
| Code | Description | Solution |
|---|---|---|
invalid_api_key |
API key is invalid or missing | Check your API key and ensure it's included in the request |
endpoint_not_found |
Endpoint does not exist | Verify the endpoint_key is correct |
quota_exceeded |
You've reached your plan's submission limit | Upgrade your plan or wait for the next billing cycle |
rate_limited |
Too many API requests | Reduce request frequency and implement exponential backoff |
invalid_origin |
Request origin not allowed | Add the domain to the endpoint's allowed_domains |
spam_blocked |
Submission blocked due to spam detection | Review and adjust spam protection settings |
Support
If you encounter issues not covered in this documentation, please contact Formserve support at support@formserve.io.