Skip to content
← All use cases
Use case · HTML form endpoint

An HTML form endpoint: one URL in the action attribute

A form endpoint is the address a form sends its data to. In HTML that address lives in the action attribute. Point it at a Formward endpoint and the browser does the rest: it collects every named field, sends them as a POST, and follows the redirect that comes back. No JavaScript, no server of your own.

<form action="https://forms.formward.eu/f/YOUR_FORM_ID" method="POST">
  <label for="email">Email</label>
  <input id="email" type="email" name="email" required>

  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <input type="hidden" name="_redirect" value="/thanks">
  <button type="submit">Send</button>
</form>

Replace YOUR_FORM_ID with the ID from your dashboard. That is the whole integration on every plan, including Free with 50 submissions a month.

The three attributes that matter

  • action is the endpoint URL. The browser sends the form there instead of to the page it came from.
  • method="POST" puts the answers in the request body. Without it the browser uses GET and writes them into the URL.
  • name on every input. A field without a name is not sent at all, which is the most common reason a submission arrives with a field missing. The name becomes the column in your dashboard and the key in exports and webhooks.

Labels, required and type="email" are not sent anywhere, but they matter: the browser checks them before it submits, and screen readers rely on the labels.

What the browser actually sends

When the visitor presses submit, the browser builds a request like this one. Field names and values are URL-encoded and joined with &:

POST /f/YOUR_FORM_ID HTTP/1.1
Host: forms.formward.eu
Origin: https://www.example.com
Content-Type: application/x-www-form-urlencoded

email=ada%40example.com&message=Hello&_redirect=%2Fthanks

The Origin header names the site the form was on. If you fill in the allowed-origins list in the form settings, Formward refuses posts from any other site with a 403. Leave it empty while testing, and fill it in before you go live.

What happens after the POST

Formward runs the checks in a fixed order before anything is stored:

  1. The form exists and is active, otherwise 404.
  2. The origin is allowed, otherwise 403.
  3. The sender is under the rate limit, otherwise 429 with a Retry-After header.
  4. If you switched on Cloudflare Turnstile, the challenge token is valid, otherwise 403.
  5. The honeypot _gotcha is empty. If a bot filled it, the response looks like success but the submission is filed as spam and no email is sent.
  6. Required consent is given, and the submission stays within the limits on field count and value length, otherwise 422.
  7. The monthly quota has room, otherwise 402.

Then the submission is stored on servers in Sweden and queued for the notification email, and the browser is redirected to your thank-you page, or to Formward's default confirmation if you have not set one. Errors in a plain HTML post come back as a short readable page rather than JSON, so a visitor never sees raw code.

Files and encodings

A plain form sends application/x-www-form-urlencoded. To send files, add enctype="multipart/form-data" and a file input. Uploads need the Professional plan or above; on lower plans a submission carrying files is refused.

<form action="https://forms.formward.eu/f/YOUR_FORM_ID"
      method="POST" enctype="multipart/form-data">
  <input type="email" name="email" required>
  <input type="file" name="attachment" accept=".pdf,.jpg,.png">
  <button type="submit">Send</button>
</form>

Types, sizes and storage are covered in forms with file uploads.

When to add JavaScript

The plain form is the most robust version: it works with scripts blocked, on old browsers and while your bundle is still loading. Add JavaScript when you want the visitor to stay on the page and see an inline message instead of a redirect. Keep the action attribute in place when you do, so the form still submits if the script fails. The contact form API page shows the fetch() version and the JSON it gets back.

Where the data lives

Formward stores submissions, file attachments and backups in Sweden, on servers run by Hostup AB. Notification email goes out through Mailjet from an EU data centre. Submitter IP addresses are replaced with a keyed HMAC-SHA-256 hash on receipt, so the raw address is never written to disk. On Professional and Business, AI features run on Mistral AI in France and can be switched off per form.

Data leaves the EU only where you send it: a notification inbox hosted outside the EU, a webhook URL, a Slack channel or a Google Sheet. Cloudflare Turnstile is a US service, and it is off unless you switch it on for a form. The details are in the sub-processor register, the data residency page and the published DPA. For the wider picture, see GDPR form backend.

Questions

What is a form endpoint?
A URL that accepts a form submission. The browser sends the fields there when the visitor presses submit, and the service behind the URL decides what to do with them: store them, email them, forward them. With Formward the endpoint is https://forms.formward.eu/f/ followed by your form ID.
Is the form ID a secret?
No. It sits in your page source, so anyone can read it. That is why each form has an allowed-origins list, a per-IP rate limit and a honeypot field. API keys are a separate thing, used only for the management REST API.
What happens if someone opens the endpoint URL in a browser?
They get a short page explaining that the endpoint only accepts POST. A GET never creates a submission.
Can I use method="GET"?
No. GET would put the answers in the URL, where they end up in browser history and server logs. The endpoint only accepts POST.
Where does the visitor land after submitting?
On the page named in a hidden _redirect field, else on the redirect URL set in the form settings, else on Formward's default confirmation. Set your own so visitors stay on your site. A _redirect must be a relative path or a URL on one of your allowed origins.

Get an endpoint for your form

Create a form, copy its URL into the action attribute and send a test. It takes about two minutes.

HTML form endpoint: a URL for your form action | Formward