Skip to content
Building Your Form

Your first HTML form

Create an HTML contact form with Qubeforms using a standard form action. Submit without JavaScript and configure redirects, email delivery, and spam protection.

1. Add the external form stylesheet

Save the CSS below as a separate file in your website. HTML examples load it from /static/assets/css/form-helper.css; React and Vue import ./form-helper.css beside the component. Adjust the path to match your site and confirm the file loads before publishing. The generic .form-helper class moves the text input off-screen without the hidden attribute or display: none. Keep tabindex="-1", autocomplete="off", and aria-hidden="true". New forms use fax_number; existing forms keep their saved name. Match Settings → Delivery & spam → Honeypot field in HTML, JSON, and drafts. To rename an existing trap, update both the setting and the website together. Never use a name that also collects a real visitor answer.

.form-helper {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
    pointer-events: none;
}

2. Create your form endpoint

Sign in, open Forms, enter a form name and the origin of your website, and select Create endpoint. Open Manage → General in the form settings and copy the submission endpoint. Keep the form Active. Use the public cf_pk_ key in your website; private read keys and your account password are never needed in an HTML form.

3. Add a labeled HTML form

Replace cf_pk_YOUR_KEY with your public key. Each submitted control needs a name, and each visible control needs a label. This example works without JavaScript when the form does not require CAPTCHA. Keep the honeypot empty and use your configured name if you changed it from fax_number. The message limit prevents the browser from sending more text than Qubeforms retains for one string field.

<link rel="stylesheet" href="/static/assets/css/form-helper.css">
<form action="https://api.qubeforms.io/v1/cf_pk_YOUR_KEY/submissions" method="post">
  <label for="contact-email">Email (required)</label>
  <input id="contact-email" name="email" type="email" autocomplete="email" required>

  <label for="contact-message">Message (required)</label>
  <textarea id="contact-message" name="message" maxlength="20000" required></textarea>

  <input class="form-helper" name="fax_number" type="text" tabindex="-1" autocomplete="off" aria-hidden="true">
  <button type="submit">Send</button>
</form>

4. Choose where visitors go after sending

Without a requested redirect, the browser displays the API response after submitting. To show your own thank-you page, allow its URL in Delivery & spam → Safe redirect allowlist and add a hidden _cf_redirect input with that URL. Merely saving the allowlist does not pick a destination. See Safe thank-you redirects for a complete example. Use AJAX and JSON submissions if you want to show feedback in the same page.

5. Connect notification email

Open Settings → Recipients, add the mailbox that should receive notifications, and complete verification. In Delivery & spam, keep Reply-To field set to email for this example. The recipient receives the notification; Reply-To identifies the visitor when you reply. Neither the visitor’s address nor your profile email automatically becomes a verified recipient.

6. Test from your actual website

Serve the page over HTTP or HTTPS and submit non-sensitive test data. The browser’s origin must be allowed for this form, including its scheme, host, and port. Check the stored fields in Submissions, look in Spam if needed, and inspect delivery status. A successful response confirms receipt, not that an email already reached the mailbox.

7. Extend the form

Add checkboxes and grouped fields using Field names, checkboxes, and multiple values. Add file inputs with enctype="multipart/form-data" on Starter or higher. If you enable CAPTCHA, integrate its widget and response token before publishing. Keep visitor input available when a request fails; native submission navigates away, so AJAX is useful when you need controlled error recovery in the page.

Keep private credentials private

Public form keys can appear in browser code. Read keys, management credentials, and webhook signing secrets must stay on the server.