HTML Form Integration with Form Backend Tool
This page is the reference version of the integration: the pattern, the field rules, what the endpoint answers, and the limits, in one place for developers who already have a form. If you are setting up your first form and want the guided version, follow the step by step tutorial instead; the concept behind it is in What Is a Form Backend?
The integration pattern
Integrating an HTML form with Form Backend Tool is a form backend pattern with exactly three requirements:
- The form's
actionis the form's endpoint URL,https://form-backend-tool.vercel.app/api/forms/YOUR_FORM_KEY, with your form's key in place ofYOUR_FORM_KEY. - The form's
methodis POST. No other method is accepted. - Every input that should be delivered carries a
name. The name becomes the field's label in the dashboard and the notification email.
The minimal working form is only this:
<form action="https://form-backend-tool.vercel.app/api/forms/YOUR_FORM_KEY" method="POST">
<label>Your name <input type="text" name="name" required></label>
<label>Your email <input type="email" name="email" required></label>
<label>Message <textarea name="message" required></textarea></label>
<button type="submit">Send</button>
</form>There is no script to install, no API key in the page, and no server of yours involved. The public key in the endpoint URL identifies the form; the endpoint sends CORS headers (Access-Control-Allow-Origin: *), so a form on any domain can post to it, as the docs describe.
Adding it to an existing form
Most integrations start from a form that already exists and either posts nowhere or posts to a script you are retiring. The change is a checklist, not a rewrite:
- Set
actionto the endpoint andmethodto POST. - Keep your markup, styling and field
nameattributes as they are. Rename a field only if you want a different label in the dashboard and email. - Add the two reserved fields below,
_redirectand_honey, if you want a custom thank-you page and the spam trap. - Remove the old handler (a
mailto:action, a form-handler script, a plugin endpoint) so submissions go to exactly one place. - Submit one test and confirm it in the dashboard and your inbox, as the tutorial walks through.
Field reference
Regular fields
Any named text input, textarea, select, checkbox or radio group is stored as a name and value pair. The endpoint accepts three content types: application/x-www-form-urlencoded and multipart/form-data, which is what browsers send for plain forms, and application/json for fetch calls. A form may carry at most 50 fields; field names up to 100 characters and values up to 5,000 characters are accepted.
_redirect
A hidden field whose value is the absolute http:// or https:// URL the visitor is sent to after a successful browser submission. Without it, the visitor sees a simple built-in thank-you page. Relative paths are not followed. See Redirects and success behaviour in the docs.
_honey
The honeypot. A hidden text field that people never fill in and bots do. A submission with a filled _honey is accepted quietly, stored, and flagged as spam in the dashboard; it is not emailed to you. Keep it hidden and never auto-fill it.
File inputs
A file input does not break the form, but the file itself is not stored: file parts of a multipart submission are ignored, and only text values are kept. Treat any form that must receive a file as out of scope for this integration, as the not supported list states.
Response behaviour
What the endpoint answers depends on how the request was made:
- Plain browser form: on success, the visitor is redirected to your
_redirectURL, or shown the built-in thank-you page (HTTP 200, HTML). - Fetch with
Accept: application/json: on success, HTTP 200 with{"ok": true, "message": "Submission received."}. - Errors, both styles: a status code and a short message. The ones an integration can realistically meet are 400 (empty or unparsable submission), 403 (form paused or disabled), 404 (wrong key in the URL), 405 (not POST), 413 (over the 25 KB cap), 415 (unsupported content type) and 429 (rate limit). The error reference is the full table, and the tutorial's troubleshooting section turns each one into a fix. A submission caught by the honeypot is the exception: it answers like a success, on purpose, and is flagged on your side only.
Integration examples
The pattern does not change with the form's purpose; only the fields do. Each of these was posted to a live endpoint in exactly this shape while this page was written.
Newsletter or lead form
One field is a complete integration. The submission is stored and emailed like any other, and the redirect takes the visitor to your confirmation page:
<form action="https://form-backend-tool.vercel.app/api/forms/YOUR_FORM_KEY" method="POST">
<label>Email address <input type="email" name="email" required></label>
<input type="hidden" name="_redirect" value="https://your-site.example/subscribed">
<input type="text" name="_honey" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Subscribe</button>
</form>Quote or request form
More fields, including a select, whose chosen option arrives as a normal text value. This is the shape most service business forms take:
<form action="https://form-backend-tool.vercel.app/api/forms/YOUR_FORM_KEY" method="POST">
<label>Name <input type="text" name="name" required></label>
<label>Phone <input type="tel" name="phone"></label>
<label>Service
<select name="service">
<option>Cleaning</option>
<option>Repair</option>
<option>Other</option>
</select>
</label>
<label>Details <textarea name="details"></textarea></label>
<input type="hidden" name="_redirect" value="https://your-site.example/thanks">
<input type="text" name="_honey" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Request quote</button>
</form>Contact and business website forms
A contact form is the minimal example at the top of this page, and a simple business website form is usually the quote shape with different labels. If your site has several forms (a contact form and a quote form, say), create a separate form per purpose in the dashboard: separate endpoints, separate submission lists, and each can notify a different address. The static websites guide covers that per-site setup.
JSON and fetch integration
When the form is handled by JavaScript, post JSON to the same endpoint and read the JSON answer:
await fetch("https://form-backend-tool.vercel.app/api/forms/YOUR_FORM_KEY", {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify({
name: "Ada",
email: "ada@example.com",
message: "Hello from my site",
}),
});Two details decide whether this works smoothly. Send Accept: application/json, otherwise the endpoint treats the request as a browser form and answers with the redirect or thank-you page instead of JSON. And keep the _honey rule in mind for any custom client: never include a filled honeypot field in the payload. Field names in JSON behave exactly like form field names, including the same limits.
Limits that shape an integration
- At most 25 KB per submission, 50 fields, names up to 100 characters, values up to 5,000 characters.
- Rate limit: 10 submissions per 60 seconds per form per visitor.
- Monthly quotas per form: 250 on Free (up to 3 forms), 2,500 on Pro ($12/month), 10,000 on Agency ($35/month).
- File uploads are not stored. No outgoing webhooks. No autoresponder email to the visitor.
The authoritative versions are the docs limits section and the not supported list; they win over any summary, including this one. Questions the reference does not answer go to the support page.