Airtable doesn't have a booking feature. No availability engine, no "find a time" widget, no invitee time-zone magic. And yet an airtable booking system is one of the most-requested builds we do as an Airtable consulting agency — because once your bookings live in the same base as your clients, invoices, and delivery workflow, everything downstream gets simpler.
This guide is the complete build: a slot-based schema, a booking form that can't double-book, confirmation and reminder emails, calendar sync, staff views, and a client-facing booking page. No Calendly, no Acuity — though we'll tell you honestly when those tools are the better call.
When Airtable Wins for Scheduling (and When Calendly Does)
Be honest about the fit before you build.
Airtable wins when:
- Bookings are part of a bigger workflow — the appointment kicks off onboarding, fulfillment, invoicing, or follow-up that already lives in Airtable.
- You book finite, defined slots: consultations, equipment rental, room hire, demo days, classes, clinic appointments.
- You need custom data at booking time — intake questions, service selection, file uploads — not just a name and email.
- You want one source of truth instead of a Calendly export gathering dust.
Calendly or Acuity wins when:
- You need real-time availability from your calendar — Calendly checks your Google/Outlook calendar live and only offers genuinely free times. Airtable cannot do this natively; you'd be maintaining a Slots table by hand or by automation.
- Invitees span many time zones and you want automatic local-time display. Airtable forms show slot times as you stored them, full stop.
- You're solo, scheduling is the only problem, and $10/month solves it. Don't build a system to save $120 a year.
The cost math matters too. Calendly runs $10/seat/month (Standard) to $16/seat/month (Teams); Acuity is $20–$61/month per account. A 10-person team on Calendly Teams is ~$160/month forever. If that team already runs on Airtable, the booking system below costs $0 extra — and the data lands where your operations live.
Step 1: The Schema — Slots, Bookings, Services, Clients
Every working airtable scheduling build we've shipped uses the same core pattern: a table of availability (Slots) and a table of demand (Bookings), linked. The link is what makes double-booking prevention possible.
Core tables
| Table | Purpose |
|---|---|
| Slots | Every bookable time window you offer |
| Bookings | One record per client booking |
| Services | What can be booked (duration, price, staff) |
| Clients | Who books (dedupe repeat bookers here) |
| Staff | Optional — who delivers each slot |
Slots fields
| Field | Type | Purpose |
|---|---|---|
| Slot Name | Formula | DATETIME_FORMAT(SET_TIMEZONE({Start Time}, 'America/New_York'), 'ddd D MMM, h:mm a') — human-readable label shown in the form |
| Start Time | Date with time | Toggle "Use the same time zone for all collaborators" ON |
| End Time | Date with time | Same time-zone setting |
| Service | Linked record (Services) | What this slot is for |
| Staff | Linked record (Staff) | Who delivers it |
| Bookings | Linked record (Bookings) | Filled when booked |
| Booking Count | Count (Bookings) | Drives the availability filter |
| Capacity | Number | 1 for appointments; higher for classes |
| Status | Formula | IF({Booking Count} >= {Capacity}, 'Booked', 'Open') |
Two details here do all the heavy lifting. First, the Slot Name formula — this is the text clients see in the form's dropdown, so make it unambiguous, with the day of week and an explicit time. Second, the time-zone toggle: Airtable stores all datetimes in GMT under the hood, and if you leave fields on "local time for each collaborator," your formulas, automations, and emails will disagree about what time a slot starts. Lock every booking-related date field to one named time zone. (More date-formula patterns in our Airtable date formulas guide.)
Bookings fields
| Field | Type | Purpose |
|---|---|---|
| Booking ID | Autonumber or formula | Primary field |
| Slot | Linked record (Slots, single) | The reserved time |
| Client Name | Single line text | From the form |
| Client Email | For confirmations | |
| Phone | Phone | For SMS reminders (optional) |
| Service | Lookup (via Slot) | Auto-derived — don't ask twice |
| Notes | Long text | Intake questions |
| Status | Single select | Confirmed / Rescheduled / Cancelled / No-Show / Completed |
| Confirmation Sent | Checkbox | Set by automation |
| Created | Created time | Audit trail |
Keep the form short. Every field you ask for costs conversions; everything derivable from the Slot (service, staff, price) should be a lookup, not a question.
Step 2: Preventing Double-Booking
This is the heart of the system, and it's a view filter, not code.
- On the Slots table, create a grid view called Open Slots.
- Filter:
Booking Countis less thanCapacity(or simply= 0for one-on-one appointments), ANDStart Timeis after today, AND optionallyStart Timeis at least 24 hours from now to stop last-minute bookings. - Sort by Start Time ascending.
Then, on the Bookings form (next step), open the Slot linked-record field settings and enable "Limit record selection to a view", pointing at Open Slots. The moment a booking is submitted, the slot's Booking Count goes to 1, it falls out of the Open Slots view, and no other client can select it. New slots you add appear in the form automatically. This filtered-view pattern is the standard approach to availability in Airtable — every serious booking build we've seen uses it.
The honest caveat: there's a small race-condition window. If two people have the form open simultaneously and both select the same slot, both submissions succeed — the view filter is evaluated when the form loads, not when it submits. In practice this is rare for low-volume booking, but don't ship without a backstop:
- Trigger: When a record matches conditions — Slots where
Booking Countis greater thanCapacity. - Action: Send a Slack/email alert to staff, who contact the second booker with alternatives.
For high-volume booking where collisions are likely, put a Make scenario or an Airtable script between the form and the table to re-check availability at submission time — or accept that this is the point where Calendly earns its fee.
Step 3: The Booking Form
Build the form on the Bookings table — clients create Booking records, never touch Slots.
- Include: Slot (limited to Open Slots view, required), Client Name, Client Email, Phone, Notes.
- Hide internal fields: Status, Confirmation Sent, lookups.
- In form settings, set a custom submission message ("You're booked — confirmation email on its way") and enable redirect URL if you want to send bookers to a thank-you page.
Native Airtable forms are deliberately simple. Two limitations matter for booking:
- Conditional show/hide logic for individual fields exists on every plan, but conditional groups — showing or hiding whole sections of fields, the building block of real form branching — sit on Business/Enterprise plans.
- No calendar-style picker. Clients choose from a dropdown list of slot records, not a visual calendar. For under ~30 open slots this is fine; beyond that the dropdown gets unwieldy.
If you hit those walls, Fillout (whose Airtable-native scheduling product is free) gives you a Calendly-style time picker writing straight into your base, and Filla/Typeform-class tools add multi-page logic. Full form patterns are in our Airtable forms guide, and if you need clients to modify a booking later, see updating existing records via forms.
Step 4: Confirmation Emails and Reminders
A booking system without confirmations is a no-show machine. Three automations cover it — well within the 50-automation-per-base cap and the 25,000 monthly runs on Airtable Team.
Automation 1: Instant confirmation
- Trigger: When record created in Bookings.
- Action: Send email (or the Gmail/Outlook action — strongly preferred, since native "Send email" comes from an Airtable address and lands in spam more often) to
Client Email. - Body: pull in the Slot Name lookup, service, location/meeting link, and a cancellation instruction.
- Action: Update record — check
Confirmation Sent.
Critical detail: automations run on GMT servers. If you insert a raw datetime field into the email, the client may see the wrong time. Always insert a formula field like:
DATETIME_FORMAT(SET_TIMEZONE({Start Time}, 'America/New_York'), 'dddd, MMMM D [at] h:mm a [ET]')
This single formula prevents the most common complaint we see in booking-system rescue projects. Deliverability, templates, and HTML email patterns are covered in our Airtable email automation guide.
Automation 2: 24-hour reminder
- Trigger: When record matches conditions — Bookings where a formula field
Hours Until Start(usingDATETIME_DIFF({Start Time lookup}, NOW(), 'hours')) drops below 24 AND Status = Confirmed. - Action: Send reminder email. For SMS, add a Twilio step via Make.
Note that NOW() in formulas refreshes only periodically — roughly every 15 minutes while the base is open, and around hourly when it's idle — so treat the reminder window as approximate — fire at "under 24 hours," not "exactly 24.0 hours."
Automation 3: Internal notification
- Trigger: When record created in Bookings.
- Action: Slack message to the staff channel or assigned staff member with booking details.
Cancellations
Give clients a cancellation path in the confirmation email — a prefilled form link or a "reply CANCEL" instruction processed by staff. When Status changes to Cancelled, an automation should clear the Slot link so the slot re-enters the Open Slots view and becomes bookable again. Forgetting this leaks inventory; it's mistake number one in DIY builds. More automation patterns in our Airtable automation guide.
Step 5: Views and an Interface for Managing the Schedule
The same two tables serve every internal role through views.
Calendar view (Slots table)
- Date field: Start Time (with End Time for duration display).
- Color by Status formula: Open vs Booked.
This is your at-a-glance week. Airtable's calendar view supports drag-to-reschedule, which updates Start Time directly — and your automations follow.
Today's Bookings (Grid, Bookings table)
- Filter: Slot's Start Time is today AND Status = Confirmed.
- Sort by Start Time ascending. The front-desk view.
No-Show and Cancellation Log
- Filter: Status is Cancelled or No-Show.
- Group by Client. Three no-shows from the same client is a policy conversation, and now you have the data.
Staff schedules
- One calendar view per staff member, filtered by the Staff link — or better, an Interface page with a calendar element and a "current user" filter.
For a polished internal app — today's schedule, a check-in button that flips Status to Completed, a slot-creation form — build an Interface on top. Our Interface Designer guide covers the patterns.
Step 6: Generating Slots Without Losing Your Mind
Nobody wants to hand-type 40 slot records a week. Options, in ascending order of effort:
- CSV import. Build a month of slots in a spreadsheet (a fill-down series of datetimes), import into Slots. Crude, effective, fine for many businesses.
- Repeating automation. A scheduled automation that runs weekly and creates next week's standard slots via repeating "Create record" actions or a script.
- Script. A 20-line scripting-block script that takes a date range, working hours, and slot duration, and generates records. Run it monthly. See our Airtable scripting guide.
- Make scenario. Same generation logic, plus it can check the staff member's Google Calendar and skip slots that collide with existing events — the closest you'll get to Calendly's live availability. Patterns in our Make + Airtable guide.
Step 7: Google Calendar Sync
Know the constraint up front: Airtable's native Google Calendar sync is one-way, into Airtable — it pulls events from a calendar into a synced table (refreshing roughly every 5 minutes, up to 10,000 events per sync) but cannot push Airtable records out to the calendar.
So the working setup is:
- Outbound (bookings → calendar): an Airtable automation with the Google Calendar "Create event" action, triggered when a Booking is created. Map Start/End from the Slot, put the client's email in attendees (Google then sends them a proper calendar invite — a free upgrade to your confirmation flow), and store the returned Event ID in a field on the Booking.
- Updates and cancellations: a second automation triggered when Status changes to Cancelled. Airtable does have a native "Update event" action — it works if you stored the Event ID at creation — so reschedules can stay native. There is no native delete action, though, so true cancellations (removing the event rather than editing it) go through Make or a script, matched on the stored Event ID.
- Inbound (calendar → Airtable): the native sync, used as a read-only conflict checker so staff see their non-booking commitments next to the schedule.
The full setup, including the two-way pattern, is in our Airtable + Google Calendar sync guide.
Step 8: A Client-Facing Booking Page with Softr
The embedded Airtable form is the fast path: paste the embed code on your site and you're live, and visitors never see your base. But if clients should log in, see their upcoming bookings, cancel or reschedule, and browse services, you've outgrown a form — you need a portal.
Softr is the standard front end for this. Plans run $49/month (Basic) to $139 (Professional) and $269 (Business) on annual billing — each plan caps logged-in app users (20 on Basic, 100 on Professional, 500 on Business), but crucially those users don't consume Airtable editor seats at $24+ each. Softr reads and writes your base via API, so the architecture stays identical:
- A list block on the Slots table, filtered to the Open Slots logic (Booking Count below Capacity, future dates), displayed as cards or a calendar-style list.
- A form or action button that creates a Booking record linked to the chosen slot — all your automations fire exactly as they do from the native form.
- A logged-in "My Bookings" page filtered to the current user's email, with a "Request cancellation" action that flips Status and triggers the slot-release automation.
We walk through the full portal architecture — auth, record-level permissions, page structure — in our client portal with Airtable and Softr guide. And if you want bookings taken by phone, the same base can sit behind a voice agent: see building a voice AI booking agent with ElevenLabs and Airtable.
Cost Comparison: Airtable vs Calendly vs Acuity
| Factor | Airtable booking system | Calendly | Acuity |
|---|---|---|---|
| Price | $0 extra on existing plan; else $24/editor/mo (Team) | $10–$16/seat/mo | $20–$61/mo per account |
| Live calendar availability | No (workaround via Make) | Native | Native |
| Invitee time-zone handling | Manual (formula-formatted labels) | Automatic | Automatic |
| Custom intake data | Unlimited fields | Limited custom questions | Intake forms (good) |
| Connects to ops/CRM/invoicing | Same base | Via integrations/export | Via integrations |
| Group/class capacity booking | Yes (Capacity field) | Limited | Native |
| Client portal | Via Softr ($49+/mo) | No | Client accounts |
| Setup time | Hours | Minutes | Under an hour |
The pattern: dedicated tools win on availability intelligence and setup speed; Airtable wins on data ownership, custom intake, capacity-based booking, and everything that happens after the booking.
Common Mistakes
Mistake 1: Date fields on local time. Every datetime in the booking flow should have "use the same time zone for all collaborators" enabled with an explicit zone. Mixed settings produce slots that shift by hours between the form, the base, and the email.
Mistake 2: No slot release on cancellation. Cancelled bookings that keep their Slot link silently destroy availability. Automate the unlink.
Mistake 3: Raw date fields in emails. Automation servers run GMT. Always insert a SET_TIMEZONE + DATETIME_FORMAT formula field, never the raw field.
Mistake 4: Asking for data you can derive. Service, price, staff, and duration all flow from the Slot via lookups. A five-field form converts; a fifteen-field form doesn't.
Mistake 5: Ignoring the race condition. Low volume, fine. High volume, add the over-capacity alert automation or move submission through Make with a re-check step.
Mistake 6: Building this when Calendly was the answer. If you're solo, booking simple calls, and nothing downstream depends on the data — buy the $10 tool.
Troubleshooting
Slots aren't appearing in the form. They're not in the Open Slots view — check Booking Count, the future-date filter, and whether the form's linked field is limited to the right view.
A booked slot still shows in the form. The client loaded the form before the slot was taken; the dropdown doesn't live-refresh. This is the race window — rely on the over-capacity alert.
Confirmation emails show the wrong time. Raw date field in the email body. Swap in the SET_TIMEZONE formula field.
Calendar events not created. The Google Calendar automation action lost its account connection (token expiry is the usual culprit) — reauthorize and check the automation run history.
Reminders firing late or twice. NOW()-based triggers are approximate; widen the condition window and add a "Reminder Sent" checkbox condition so it can't fire twice.
Next Steps
The booking system is rarely the end state — it's the front door. Once it's live, the natural extensions:
- Payments at booking — Stripe checkout links generated per booking (see our dynamic Stripe checkout guide).
- Post-appointment follow-up — an automation that fires when Status flips to Completed: feedback request, rebooking link, internal notes task.
- Reporting — utilization rate (booked vs open slots), no-show rate by client, revenue per staff member, all from rollups on the tables you already have.
If you'd rather have this built, hardened against the edge cases, and connected to your invoicing and CRM in a week instead of a quarter, get in touch — booking systems are one of the most common builds we scope.