Request forms · 8 fields
Booking request form template
A request, not a calendar. Visitors pick a preferred date, a time of day and an alternative, and you confirm the slot by email or phone. It suits businesses that fit appointments around other work.
Booking request
Live demo: try the fields. Submitting sends nothing.
02 / Field guide
Why these fields
Name
text · requiredRequired for the booking.
Email
email · requiredRequired. It is where the confirmation goes.
Phone
tel · optionalOptional. Keep it if you confirm or remind by phone, and say so.
What would you like to book?
text · requiredRequired, so you know how long to block.
Preferred date
date · requiredRequired. The browser's date picker avoids ambiguous formats such as 03/04.
Preferred time of day
select · requiredBands are easier to fit than an exact time and save a round of messages about minutes.
Alternative date
date · optionalOptional, but it often turns a refusal into a booking.
Anything we should know in advance?
textarea · optionalOptional. For a clinic or a therapist, ask only what you need to prepare, and nothing about health unless you must.
When to use it
Use it for consultations, repairs, studio sessions and viewings, where someone checks the diary before saying yes. If customers should pick and confirm a live slot themselves, you need a booking system; this form does not check availability.
Say on the page that the booking is confirmed only when you reply, and how soon you usually do.
Privacy and GDPR
- Booking details are needed to arrange what the person asked for, so no consent box is needed for that.
- Some bookings say more than a time. An appointment at a clinic or a counsellor reveals something about health, so keep those forms short and the retention brief.
- Delete requests that never became appointments after a short period.
03 / Make it yours
Choose your stack. Copy your form.
Replace the example endpoint with your Formward endpoint, then adapt the fields to your needs.
<form action="https://forms.formward.eu/f/your-form-id" 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="phone">Phone</label>
<input type="tel" name="phone" id="phone" />
<label for="service">What would you like to book?</label>
<input type="text" name="service" id="service" required />
<label for="preferred_date">Preferred date</label>
<input type="date" name="preferred_date" id="preferred_date" required />
<label for="preferred_time">Preferred time of day</label>
<select name="preferred_time" id="preferred_time" required>
<option value="Morning">Morning</option>
<option value="Afternoon">Afternoon</option>
<option value="Evening">Evening</option>
<option value="Any time">Any time</option>
</select>
<label for="alternative_date">Alternative date</label>
<input type="date" name="alternative_date" id="alternative_date" />
<label for="notes">Anything we should know in advance?</label>
<textarea name="notes" id="notes"></textarea>
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px" aria-hidden="true" />
<button type="submit">Send</button>
</form>Accessibility
Accessible by default, and how to keep it that way
- Every field in the code has a visible label tied to it with for and id, so screen readers announce what to enter and a click on the label focuses the field.
- Required fields carry the required attribute, so the browser explains a missing answer before anything is sent. Say “required” in words as well; an asterisk or a colour alone is easy to miss.
- The spam trap field (_gotcha) is hidden from screen readers with aria-hidden and skipped by the Tab key, so people never meet it.
- In the JavaScript versions, show the confirmation or error in an element with role="status" so the result is announced, and keep the entered answers when sending fails.
Changed the fields? Paste your version into the HTML form tester to see exactly what it sends, or run it through the GDPR form checker.
04 / Implementation
How the code talks to Formward
Each form you create gets its own endpoint in the form https://forms.formward.eu/f/your-form-id. The HTML version posts to it directly and the browser is redirected to a thank-you page, so it works without JavaScript.
The Next.js version below sends the same fields with fetch and an Accept: application/json header. Formward then answers with { ok: true, id }, or an error body with 402 when the plan limit is reached and 429 when the rate limit kicks in. See responses and status codes.
Next.js client component
"use client";
import { useState } from "react";
export function BookingRequestForm() {
const [sent, setSent] = useState(false);
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const form = e.currentTarget;
const res = await fetch("https://forms.formward.eu/f/your-form-id", {
method: "POST",
headers: { Accept: "application/json" },
body: new FormData(form),
});
if (res.ok) {
setSent(true);
form.reset();
}
}
if (sent) return <p>Thanks! Your message has been sent.</p>;
return (
<form onSubmit={onSubmit}>
<label htmlFor="name">Name</label>
<input type="text" name="name" id="name" required />
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" required />
<label htmlFor="phone">Phone</label>
<input type="tel" name="phone" id="phone" />
<label htmlFor="service">What would you like to book?</label>
<input type="text" name="service" id="service" required />
<label htmlFor="preferred_date">Preferred date</label>
<input type="date" name="preferred_date" id="preferred_date" required />
<label htmlFor="preferred_time">Preferred time of day</label>
<select name="preferred_time" id="preferred_time" required>
<option value="Morning">Morning</option>
<option value="Afternoon">Afternoon</option>
<option value="Evening">Evening</option>
<option value="Any time">Any time</option>
</select>
<label htmlFor="alternative_date">Alternative date</label>
<input type="date" name="alternative_date" id="alternative_date" />
<label htmlFor="notes">Anything we should know in advance?</label>
<textarea name="notes" id="notes" />
<input
type="text"
name="_gotcha"
tabIndex={-1}
autoComplete="off"
style={{ position: "absolute", left: "-9999px" }}
aria-hidden="true"
/>
<button type="submit">Send</button>
</form>
);
}
Spam protection
- The generated code already includes the hidden _gotcha honeypot. Leave it in: a bot that fills it gets a normal success response, the submission is filed as spam and no email is sent.
- Every form has a per-IP rate limit, and you can restrict it to your own domains with the allowed-origins list in the form settings.
- Cloudflare Turnstile is optional and works on every plan, including Free. Turn it on in the form settings, add the widget to your markup and Formward checks the token server-side.
- The form settings can also reject disposable email addresses, which is worth turning on when a fake address would waste your time.
What happens after submit
- Each request is emailed to you and stored in the EU on every plan. Formward does not hold a calendar or block slots, so add confirmed bookings to your own diary.
- From Professional, the autoresponder can acknowledge the request and say it is not yet confirmed. From Professional, a webhook can pass requests to a scheduling tool.
Questions
- Does this form check availability?
- No. It collects a preferred time and you confirm it. That keeps it simple and works with any diary, but two people can ask for the same slot, so answer in the order requests arrive.
- Can I stop requests when I am fully booked?
- Yes. The form's response settings take a submission limit and a closing date. Once either is reached, the form stops accepting requests and shows your closed message.
Related
- Request templates
Support, maintenance, refund and other requests.
- Online forms without a website
Share the booking form as a link.
- Form data retention
Clearing out old requests automatically.
- React forms
The form as a component with inline confirmation.
Customize before publishing
- Remove fields you do not need and mark only essential answers as required.
- Replace placeholder wording with terms your audience already understands.
- Add your privacy notice, retention details and expected response time.
- Test keyboard focus, validation errors and the confirmation state on mobile.
Use this template
Create a free account and the form is set up from this template. Copy your endpoint and replace https://forms.formward.eu/f/your-form-id in the code above.
No website? Use a hosted form
- Appointment request hosted template Hosted page with contact method, preferred date, time of day and an alternative date.
- Table reservation hosted template For restaurants: date, arrival time, party size and seating.