Book Appointments
Drop a self-service slot picker on any page. Visitors see your live availability, pick a time, fill in name + email (plus any custom fields), and walk away with a confirmation email and an .ics calendar invite. You see every booking in your dashboard.
How It Works
- Visitor opens your page; the embed renders the booking widget inside Shadow DOM.
- The widget fetches free slots for the next N days from
/api/embed/availability, scoped to your account + the message's settings. - Visitor picks a date, then a time slot. The UI greys out slots that are already taken.
- Visitor fills in name, email, and any custom fields you configured, then submits.
- Server validates the slot is still free, persists the booking, sends the confirmation email, and fires any configured webhook.
Owner Configuration
Open Dashboard -> Messages -> New -> Book Appointment, or edit an existing booking message. The settings panel covers:
| Setting | Purpose |
|---|---|
weeklyHours | Per-weekday open / close (e.g., Mon-Fri 9-17, Sat 10-13, Sun closed). |
slotLength | 15, 30, 45, 60, 90, or 120 minutes. |
buffer | Gap inserted between back-to-back meetings (default 0). |
leadTime | Minimum hours before now that visitors can book (default 1). |
bookingHorizon | How many days ahead visitors can book (default 60). |
timezone | Owner timezone. Slots stored in UTC; visitor sees their local time via Intl.DateTimeFormat. |
blockedDates | One-off blackouts (holidays, conferences) without changing recurring hours. |
customFields | Extra inputs beyond name + email (e.g., "What would you like to discuss?"). |
appointmentWebhookUrl | POSTed JSON for every successful booking (Slack, Zapier, your CRM). |
Race-Resolved Booking
Two visitors can hit Submit on the same slot at almost the same time. The server validates the slot is still free at the moment of write; the loser gets a 409 Conflict response and the calendar UI refreshes to hide the now-taken slot. The winner is the oldest write that lands.
Endpoint: POST /api/embed/appointments/submit. Body includes messageId, slotStartISO, name, email, plus any custom field values keyed by their configured name.
Confirmation Email + .ics + Provider Deep Links
On a successful booking the visitor receives an email with:
- A universal
.icsfile attachment (works on every calendar app on every OS). - An Add to Google Calendar deep link.
- An Add to Outlook / Office 365 deep link.
- The booking summary (date, time, owner timezone, custom field values).
Email is sent via Resend from info@floatmessage.com. The visitor sees the date in their own timezone; the owner sees it in the timezone configured on the message.
Webhook Payload
Set appointmentWebhookUrl on the booking message and FloatMessage POSTs JSON to that URL on every successful booking:
{
"type": "appointment_booked",
"messageId": "msg_abc123",
"bookingId": "apt_xyz789",
"name": "Jane Doe",
"email": "jane@example.com",
"slotStartUTC": "2026-05-14T15:00:00.000Z",
"slotEndUTC": "2026-05-14T15:30:00.000Z",
"ownerTimezone": "America/Los_Angeles",
"visitorTimezone": "Europe/Paris",
"pageUrl": "https://example.com/pricing",
"country": "FR",
"customFields": {
"topic": "Pricing question"
},
"submittedAt": "2026-05-13T10:42:09.501Z"
}Plug into Slack via the Incoming Webhook integration, or into Zapier / Make / n8n / your own backend.
Owner Dashboard
Open Dashboard -> Appointments for a month-grid calendar with daily booking counts. Click any day for the detailed list - visitor name, email, time, custom fields. From there you can:
- Copy the visitor email or open a
mailto:draft. - Cancel a booking (frees the slot for someone else, sends a cancellation email if configured).
- Filter by message (if you run several different booking offers).
Targeting + Smart Triggers
Booking messages support every targeting rule the rest of FloatMessage supports - URL pattern, country, device class, schedule windows, exit intent, dismiss behaviors. A common setup is to show the booking widget only on the pricing page for desktop visitors during business hours, with a session-only dismiss so it reappears on the next visit.
See Scheduling & Triggers and Geo Targeting for the full rule list.
Related
- All 18 templates
- Contact forms (similar submission inbox + webhook flow)
- Guide: Book appointments with FloatMessage
- Feature overview →