splitforms.com
BOOKINGS · CONTACT FORM TEMPLATE

Restaurant Reservation Request Form

OpenTable charges $1 per cover and $249/month base. For a small restaurant or one without table-management complexity, a reservation request form does the job for free.

1,000/mo free·no card·works on any host
form.htmlhtml46 lines
01<form action="https://splitforms.com/api/submit" method="POST">
02 <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
03 <input type="hidden" name="subject" value="New reservation request">
04
05 <label for="name">Full name *</label>
06 <input id="name" type="text" name="name" placeholder="Sasha Vorona" required>
07 <label for="email">Email *</label>
08 <input id="email" type="email" name="email" placeholder="sasha@example.com" required>
09 <label for="phone">Phone *</label>
10 <input id="phone" type="tel" name="phone" placeholder="+1 415 555 0142" required>
11 <label for="party_size">Party size *</label>
12 <select id="party_size" name="party_size" required>
13 <option value="">Choose…</option>
14 <option>2</option>
15 <option>3</option>
16 <option>4</option>
17 <option>5–6</option>
18 <option>7–10</option>
19 <option>10+</option>
20 </select>
21 <label for="date">Date *</label>
22 <input id="date" type="date" name="date" required>
23 <label for="time">Time *</label>
24 <select id="time" name="time" required>
25 <option value="">Choose…</option>
26 <option>5:30 PM</option>
27 <option>6:00 PM</option>
28 <option>6:30 PM</option>
29 <option>7:00 PM</option>
30 <option>7:30 PM</option>
31 <option>8:00 PM</option>
32 <option>8:30 PM</option>
33 <option>9:00 PM</option>
34 </select>
35 <label for="occasion">Occasion (optional)</label>
36 <input id="occasion" type="text" name="occasion" placeholder="Birthday, anniversary, etc.">
37
38 <!-- honeypot — bots fill every field -->
39 <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off">
40
41 <button type="submit">Send</button>
42</form>
43
44<p style="margin-top:12px;font-size:11px;color:#888;text-align:right">
45 Powered by <a href="https://splitforms.com" style="color:#888;text-decoration:none" target="_blank" rel="noopener">splitforms</a>
46</p>
1,000
submissions / mo, free
7
fields, ready to ship
5
code outputs
60s
from copy to inbox
Restaurant Reservation Request Form — example splitforms template with submissions inbox
§ 01Why it mattersthe qualifying-fields argument

OpenTable's $1-per-cover pricing taxes a restaurant's reservation volume — a 60-cover Saturday costs $60 in OT fees. For small restaurants and casual concepts, a reservation request form (date, time, party size, name, phone, special requests) handles 80% of bookings for $0. The host confirms via SMS or email within the hour. The form also handles private dining inquiries, large parties, and special-occasion notes — none of which OpenTable's standard flow surfaces well anyway.

OpenTable / Resy alternative for small restaurants — confirm via Twilio SMS.
✦ at a glance
  • Restaurant reservation · 7 fields
  • HTML, JS, React, PHP, cURL outputs
  • One POST endpoint, no SDK
  • Honeypot + classifier, no CAPTCHA
§ 02Live previewinteractive · sandboxed · no key required

See exactly what your visitors see — and you’ll receive.

Left: the rendered form, fully interactive in a sandboxed iframe. Right: the email and dashboard view that lands the moment a visitor submits.

preview · restaurant-reservation-formlocalhost:3000
✦ what you’ll see in your inbox

Every submission becomes an email plus a dashboard row. The fields below are the exact payload your form will send. Reply-to is wired to the visitor’s email so hitting reply goes back to them.

dashboard · new submission14ms · 200 OK
SUBJECT · New reservation request
Full name
Maya Iyer
Email
maya@studio71.co
Phone
+1 415 555 0142
Party size
2
Date
2026-05-15
Time
5:30 PM
Occasion (optional)

Iframe is sandboxed — submit doesn’t actually fire. Get your access key to wire it up live.

§ 03Three steps3 steps · ~60 seconds

Generate, embed, receive.

Three actions stand between you and your first lead. None of them require a backend, a database, or a CAPTCHA library.

STEP 01GENERATE

Capture date, time, party size

Required: date, time window (e.g. 7:00 PM but flexible 6:30-8:00), party size, name, phone. Optional: special occasion, dietary restrictions, seating preference.

Create your form
key=sk_live_••••••••
STEP 02EMBED

Confirm via SMS within an hour

Webhook to Twilio — the host gets a request, replies with confirmation or alternate time. Customer gets the reply via SMS too. Closes the loop without a phone call either direction.

snippethtml
<form action="https://splitforms.com/api/submit" method="POST">
  …
</form>
STEP 03RECEIVE

Route private dining separately

A 'party of 12+' or 'private event' checkbox routes to the events manager, not the host stand. Different sales process, different lead time.

inbox · 1 newjust now
FROM contact@yoursite.com
New reservation request
Maya Iyer maya@studio71.co
Loved your last open house in Hayes — looking for similar with parking. Pre-approved through Wells Fargo.
§ 04Copy & ship5 languages · same endpoint

Five outputs. One backend.

HTML by default. Click open the language you ship in — every variant POSTs to the same /api/submit endpoint.

01HTMLform.html46 lines
<form action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
  <input type="hidden" name="subject" value="New reservation request">

  <label for="name">Full name *</label>
  <input id="name" type="text" name="name" placeholder="Sasha Vorona" required>
  <label for="email">Email *</label>
  <input id="email" type="email" name="email" placeholder="sasha@example.com" required>
  <label for="phone">Phone *</label>
  <input id="phone" type="tel" name="phone" placeholder="+1 415 555 0142" required>
  <label for="party_size">Party size *</label>
  <select id="party_size" name="party_size" required>
    <option value="">Choose…</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
    <option>5–6</option>
    <option>7–10</option>
    <option>10+</option>
  </select>
  <label for="date">Date *</label>
  <input id="date" type="date" name="date" required>
  <label for="time">Time *</label>
  <select id="time" name="time" required>
    <option value="">Choose…</option>
    <option>5:30 PM</option>
    <option>6:00 PM</option>
    <option>6:30 PM</option>
    <option>7:00 PM</option>
    <option>7:30 PM</option>
    <option>8:00 PM</option>
    <option>8:30 PM</option>
    <option>9:00 PM</option>
  </select>
  <label for="occasion">Occasion (optional)</label>
  <input id="occasion" type="text" name="occasion" placeholder="Birthday, anniversary, etc.">

  <!-- honeypot — bots fill every field -->
  <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off">

  <button type="submit">Send</button>
</form>

<p style="margin-top:12px;font-size:11px;color:#888;text-align:right">
  Powered by <a href="https://splitforms.com" style="color:#888;text-decoration:none" target="_blank" rel="noopener">splitforms</a>
</p>
02JavaScriptform.js62 lines
<form id="lf-form">
  <label for="name">Full name *</label>
  <input id="name" type="text" name="name" placeholder="Sasha Vorona" required>
  <label for="email">Email *</label>
  <input id="email" type="email" name="email" placeholder="sasha@example.com" required>
  <label for="phone">Phone *</label>
  <input id="phone" type="tel" name="phone" placeholder="+1 415 555 0142" required>
  <label for="party_size">Party size *</label>
  <select id="party_size" name="party_size" required>
    <option value="">Choose…</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
    <option>5–6</option>
    <option>7–10</option>
    <option>10+</option>
  </select>
  <label for="date">Date *</label>
  <input id="date" type="date" name="date" required>
  <label for="time">Time *</label>
  <select id="time" name="time" required>
    <option value="">Choose…</option>
    <option>5:30 PM</option>
    <option>6:00 PM</option>
    <option>6:30 PM</option>
    <option>7:00 PM</option>
    <option>7:30 PM</option>
    <option>8:00 PM</option>
    <option>8:30 PM</option>
    <option>9:00 PM</option>
  </select>
  <label for="occasion">Occasion (optional)</label>
  <input id="occasion" type="text" name="occasion" placeholder="Birthday, anniversary, etc.">
  <button type="submit">Send</button>
</form>

<p style="margin-top:12px;font-size:11px;color:#888;text-align:right">
  Powered by <a href="https://splitforms.com" style="color:#888;text-decoration:none" target="_blank" rel="noopener">splitforms</a>
</p>

<script>
  document.getElementById('lf-form').addEventListener('submit', async (e) => {
    e.preventDefault();
    const data = new FormData(e.target);
    data.set('access_key', 'YOUR_ACCESS_KEY');
    data.set('subject', 'New reservation request');

    const res = await fetch('https://splitforms.com/api/submit', {
      method: 'POST',
      body: data,
      headers: { Accept: 'application/json' },
    });

    const json = await res.json();
    if (json.success) {
      e.target.reset();
      alert('Sent!');
    } else {
      alert('Error: ' + (json.message || 'Try again'));
    }
  });
</script>
03React / Next.jsForm.tsx77 lines
'use client';

import { useState, type FormEvent } from 'react';

export default function RestaurantForm() {
  const [status, setStatus] = useState<'idle' | 'sending' | 'sent' | 'error'>('idle');

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setStatus('sending');

    const data = new FormData(e.currentTarget);
    data.set('access_key', 'YOUR_ACCESS_KEY');
    data.set('subject', 'New reservation request');

    const res = await fetch('https://splitforms.com/api/submit', {
      method: 'POST',
      body: data,
      headers: { Accept: 'application/json' },
    });

    const json = await res.json();
    setStatus(json.success ? 'sent' : 'error');
    if (json.success) e.currentTarget.reset();
  }

  if (status === 'sent') return <p>Thanks — we&rsquo;ll be in touch.</p>;

  return (
    <>
    <form onSubmit={onSubmit}>
      <label htmlFor="name">Full name *</label>
      <input id="name" type="text" name="name" placeholder="Sasha Vorona" required />
      <label htmlFor="email">Email *</label>
      <input id="email" type="email" name="email" placeholder="sasha@example.com" required />
      <label htmlFor="phone">Phone *</label>
      <input id="phone" type="tel" name="phone" placeholder="+1 415 555 0142" required />
      <label htmlFor="party_size">Party size *</label>
      <select id="party_size" name="party_size" required>
        <option value="">Choose…</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5–6</option>
        <option>7–10</option>
        <option>10+</option>
      </select>
      <label htmlFor="date">Date *</label>
      <input id="date" type="date" name="date" required />
      <label htmlFor="time">Time *</label>
      <select id="time" name="time" required>
        <option value="">Choose…</option>
        <option>5:30 PM</option>
        <option>6:00 PM</option>
        <option>6:30 PM</option>
        <option>7:00 PM</option>
        <option>7:30 PM</option>
        <option>8:00 PM</option>
        <option>8:30 PM</option>
        <option>9:00 PM</option>
      </select>
      <label htmlFor="occasion">Occasion (optional)</label>
      <input id="occasion" type="text" name="occasion" placeholder="Birthday, anniversary, etc." />

      <button type="submit" disabled={status === 'sending'}>
        {status === 'sending' ? 'Sending…' : 'Send'}
      </button>

      {status === 'error' && <p>Something went wrong. Try again.</p>}
    </form>

      <p style={{ marginTop: 12, fontSize: 11, color: '#888', textAlign: 'right' }}>
        Powered by <a href="https://splitforms.com" target="_blank" rel="noopener" style={{ color: '#888', textDecoration: 'none' }}>splitforms</a>
      </p>
    </>
  );
}
04PHPsubmit.php28 lines
<?php
// Drop into a PHP page. Receives a form POST and proxies it to splitforms.com.
// Useful when you want to add server-side validation or rate limiting.

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $allowed = ['name', 'email', 'phone', 'party_size', 'date', 'time', 'occasion'];
    $payload = ['access_key' => 'YOUR_ACCESS_KEY'];
    $payload['subject'] = 'New reservation request';

    foreach ($allowed as $f) {
        if (isset($_POST[$f])) $payload[$f] = $_POST[$f];
    }

    $ch = curl_init('https://splitforms.com/api/submit');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']);
    $response = curl_exec($ch);
    $status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    header('Content-Type: application/json');
    http_response_code($status);
    echo $response;
    exit;
}
?>
05cURLtest.sh11 lines
curl -X POST https://splitforms.com/api/submit \
  -H "Accept: application/json" \
  -d "access_key=YOUR_ACCESS_KEY" \
  -d "subject=New reservation request" \
  -d "name=Jane Builder" \
  -d "email=jane@example.com" \
  -d "phone=+15555555555" \
  -d "party_size=2" \
  -d "date=2026-05-15" \
  -d "time=5:30 PM" \
  -d "occasion=Jane Builder" 

Replace YOUR_ACCESS_KEY with the key from your dashboard. That’s the only edit.

§ 06FAQ4 answered

Things people ask before they ship.

Direct answers, no marketing fluff. Missing one? Email hello@splitforms.com.

01Why not just use OpenTable or Resy?
If you're a high-volume restaurant with a long bar wait and complex floor management, use them. If you're a small bistro doing 30-60 covers a night, OpenTable's $200+ monthly base plus per-cover fees doesn't make sense. The form handles requests; the POS handles the actual table management.
02Can I integrate with my POS (Toast / Square / Resy)?
Yes — webhook the JSON. Toast and Square both accept inbound webhooks via Zapier. The reservation lands as a future-dated guest record.
03How do I handle no-shows?
The form captures phone — send an SMS reminder 4 hours before the reservation via Twilio. Reduces no-shows by ~30% in industry data. For high-demand reservations, optionally collect a credit card via a follow-up Stripe link as a no-show deposit.
04What about special occasions like birthdays and anniversaries?
Add a 'special occasion' field. The kitchen can prep a dessert plate; the server greets accordingly. Capturing this on the form (rather than at the table) gives the kitchen the heads-up they need.
✻ ✻ ✻

Ship your restaurant reservation request form in 60 seconds.

1,000 free submissions per month. No credit card. Copy the snippet, paste your access key, watch leads land in your inbox.

Get free access key →Browse all 60 templates →
v0.1 · founders pricing locked in · early access open