Originally published on the Form Backend Tool blog. This tutorial uses Form Backend Tool as the hosted form endpoint; the same steps work with any hosted form backend that gives you an endpoint URL.

A static HTML page can display a beautiful contact form, and then do absolutely nothing useful with it. There is no server behind a static page, so when a visitor presses Send, the submission has nowhere to go.

The fix is to give the form somewhere to send things: a hosted form endpoint. You create a form with a hosted service, point your HTML form at the endpoint it gives you, and every submission is stored in a dashboard and emailed to you. No server to run, no backend code, and no JavaScript required for the basic version.

The flow looks like this:

HTML form -> hosted endpoint -> validation and spam checks -> submission stored -> dashboard + email notification 

What you need

  • A static HTML page you can edit (your contact page, or whichever page the form belongs on).
  • A free account with a hosted form backend. This tutorial uses Form Backend Tool, whose Free plan needs no credit card.
  • An email address you control. Submissions are delivered there, and the address has to be verified before notifications are sent to it.

Step 1: Create the form and get your endpoint

  1. Sign up and create a form. In the dashboard, create a form and give it a name you will recognise, for example "Website contact form".
  2. Set the notification email. This is the address that receives each submission. If the dashboard shows it as unverified, use the verify action and click the link in the email it sends. The service only delivers to verified addresses, which is a detail that matters in the troubleshooting section below.
  3. Copy the endpoint. The form's page in the dashboard shows its endpoint URL, which looks like this:
https://form-backend-tool.vercel.app/api/forms/YOUR_FORM_KEY 

Every form has its own key, which is how the service knows which form a submission belongs to. The key is safe to put in public HTML: it can only submit to that form, it cannot read submissions or change settings.

Step 2: Connect the HTML form

Paste this form where the contact form belongs on your page, and replace YOUR_FORM_KEY in the action with the key from your dashboard:

<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> <!-- Optional: after a successful submit, send the visitor to your own page. Must be an absolute http:// or https:// URL. --> <input type="hidden" name="_redirect" value="https://your-site.example/thanks"> <!-- Honeypot: leave this empty and hidden. People never see it; simple bots fill it in, and those submissions are flagged as spam. --> <input type="text" name="_honey" style="display:none" tabindex="-1" autocomplete="off"> <button type="submit">Send</button> </form> 

The parts that matter:

  • action is the endpoint. It is the whole mechanism: when the form is submitted, the browser sends the fields to this URL. Leave it off or mistype the key and submissions go nowhere (a wrong key answers 404, see Troubleshooting).
  • method="POST" is required. The endpoint only accepts POST; any other method is refused with 405.
  • Each field's name becomes its label. A field named email shows up as "email" in your dashboard and in the notification email. Name fields for the reader who receives them, not for the page.
  • required is the browser's check. It stops an empty form before anything is sent. The endpoint also rejects a submission whose fields are all empty.

Already have a form on the page? You do not need this exact markup. Set your existing form's action to the endpoint and its method to POST, keep your name attributes, and add the two hidden fields.

Step 3: Test the form before you announce it

  1. Submit it like a visitor. Open the live page, fill the form with a message you will recognise, and press send. You should land on your _redirect page, or on the built-in thank-you page.
  2. Check the dashboard. The test submission should be listed under Submissions, unread, with every field you sent. This proves the storage half of the flow.
  3. Check your inbox. The same submission should arrive as an email at your notification address. If the dashboard has it but the inbox does not, the address is almost certainly not verified yet.

Add a redirect (optional)

The _redirect hidden field chooses the thank-you page. After a successful submit, the visitor is sent to that URL, which must be absolute (starting with http:// or https://), ideally a thanks page on your own site. Leave the field out and the visitor instead sees a simple built-in "Thank you" page from the service. Note that _redirect works with the classic form post above; if you submit with fetch and JSON instead, your own code decides what happens after the response.

Add basic spam protection

The _honey field in the example is a honeypot: a field real visitors never see and never fill in. Simple bots that complete every field on the page give themselves away, and their submissions are flagged as spam in the dashboard instead of being emailed to you. It filters some automated submissions; it does not eliminate spam, and no honest tool will promise that.

Behind the endpoint there is also a rate limit (10 submissions per 60 seconds per form per visitor) and payload limits (25 KB per submission), so a single form cannot be flooded cheaply. If you want the full picture of what each layer does and does not do, the longer explainer is Form Spam Protection: Honeypots, Rate Limiting, and CAPTCHA Explained.

Troubleshooting

The form answers "Form not found" (404).
The key in the action URL is wrong. Copy the endpoint again from the form's dashboard page instead of typing it.

"This form is not accepting submissions" (403).
The form is paused or disabled in the dashboard. Re-enable it there.

Method not allowed (405).
The form is not sending POST. Check that method="POST" is on the form tag; some site builders strip it.

Submissions reach the dashboard but no email arrives.
Two usual causes: the notification address is not verified yet, or the submission was flagged as spam (it is then kept in the dashboard, marked as spam, and not emailed). Verify the address from Step 1, and check the spam view in the dashboard before assuming messages are lost.

You hit a rate limit while testing (429).
The endpoint allows 10 submissions per 60 seconds per form per visitor. Enthusiastic testing trips it. Wait a minute and continue.

The redirect does not work.
_redirect must be an absolute URL. A relative path like /thanks is ignored, and the visitor sees the built-in thank-you page instead.

The full error reference is in the documentation.

When this approach is a good fit

  • Portfolio and marketing sites where the contact form is the only dynamic element.
  • Small business inquiry and quote forms, where a person reads and answers each submission.
  • Freelancer and client websites, where you do not want to run a server per client.
  • Lead capture and simple signups: name, email, a message, stored and notified.

When you should build your own backend

A hosted endpoint receives and stores submissions. It is the wrong tool when the form is really an application: file uploads that must be stored, payments or bookings, logged-in users, multi-step workflows, or business logic that has to run on every submission. Form Backend Tool, for example, does not store uploaded files and does not send webhooks, and this tutorial will not pretend otherwise. The decision guide Form Backend vs Building Your Own Backend works through that choice in full.

Conclusion

A static site does not need a server of its own just to have a working contact form. It needs an endpoint, a verified inbox, and about ten lines of form markup pointed at the right place. The original version of this tutorial, with the live demo and the complete documentation, lives at form-backend-tool.vercel.app, and if you get stuck, the support page reaches the founder directly.