Termine

Bundled React module for appointment types, weekly booking windows, internal bookings, a public booking embed, and appointments agent tools.

What it does

book-appointment ("Termine") is a bundled React module for appointment scheduling: it manages appointment types (duration, buffer, optional price), weekly availability windows, and the resulting free slots, and lets staff book appointments internally. It also powers a public, embeddable booking page so website visitors can request appointments; public requests arrive as pending and are confirmed from the module.

All data lives in the app's own appointments backend (/api/appointments/*), not in a module-local store, so the same types, windows, and bookings are shared with the agent tools and the public embed.

How to open it

  • Web: /modules/book-appointment (bundled module, slug book-appointment).
  • Manifest: bundled-modules/book-appointment/module.json (renderer: "react"); React UI: src/components/modules/book-appointment-module.tsx.
  • Public booking page: /embed/book-appointment (for iframe embedding on external websites), backed by /api/public/book-appointment/*.
  • The module is bundled; it starts uninstalled on new minimal-policy instances and remains installed on grandfathered legacy-policy instances. Admins can install or uninstall it from the module store. It does not require developer mode.

Key workflows

Define appointment types

  1. In the "types" panel, create a type with name, duration (minutes), buffer after (minutes), and an optional price. Types carry a color and active flag.
  2. Select a type to preview its free slots in the chosen date range.

Set weekly availability

  1. Add availability windows per weekday with a start and end time (for example Mon 09:00-17:00).
  2. A window can apply to all types or be restricted to one appointment type.
  3. Free slots are computed from the windows, the slot step, existing bookings, buffers, minimum notice, and the booking horizon.

Book internally

  1. Pick a free slot in the "internal booking" panel, enter the customer's name (email/phone/notes optional), and save. Internal bookings are created with status booked.
  2. The "upcoming" list shows non-cancelled appointments; per row you can confirm a pending request (sends the customer a confirmation email when email is configured), mark a booked appointment completed, or cancel.

Publish the public booking page

  1. In the embed panel, toggle the public page on/off and edit its public title and intro text.
  2. Copy the generated iframe snippet (<iframe src=".../embed/book-appointment" ...>) into any external website.
  3. Visitor bookings arrive with source public_embed and status pending, and the visitor receives a request-received email; staff confirm them from the module.

How the agent can drive it

The native runtime exposes first-class appointment tools (tool-catalog family "Termine"). All four are public-safe: they never reveal existing bookings or customer data, so they are also available to public embed specialists.

  • appointments_list_types — list active appointment types and durations.
  • appointments_list_free_days — per-day free-slot counts for one appointment_type_id over a from/to date range; use for "which days are free?" overviews.
  • appointments_list_free_slots — concrete free start/end times for one type; optional from, to (YYYY-MM-DD), limit (1-100).
  • appointments_book — book one chosen slot; required: appointment_type_id, start_at (from appointments_list_free_slots), customer_name, customer_email; optional customer_phone, notes. From an internal chat the booking is created directly as booked (source agent); from the public embed it becomes a pending request and triggers the request-received email.

On the module page and the public embed surface, the chat agent is instructed to use these tools instead of describing manual steps.

API reference

Internal (authenticated), base /api/appointments:

RoutePurpose
GET /overviewsettings, types, availability windows, and appointments for a date range
GET /settings, PATCH /settingsread/update scheduling settings
GET /types, POST /types, DELETE /types/:idmanage appointment types
GET /availability, POST /availability, DELETE /availability/:idmanage weekly windows
GET /slots, GET /daysfree slots / per-day availability for one type
GET /appointments, POST /appointmentslist/create bookings
PATCH /appointments/:id/status, DELETE /appointments/:idchange status / cancel

Public (unauthenticated, CORS-enabled), base /api/public/book-appointment: GET /config, GET /days, GET /slots, POST /appointments. The module's own module API (/api/modules/book-appointment/api) only serves GET /health and points everything else to /api/appointments.

Configuration & limits

Settings (stored via /api/appointments/settings):

  • timezone (default Europe/Berlin)
  • booking horizon in days (default 45, 1-365)
  • minimum notice in minutes (default 120)
  • slot step in minutes (default 15, 5-240)
  • public page enabled flag, public title, and public intro text

Appointment statuses are pending, booked, completed, cancelled; sources are internal, agent, public_embed, public_api. Schema migrations: db/migrations/156_book_appointment_module.sql, 159_appointment_type_prices.sql, 165_appointment_pending_confirmation_emails.sql.

Troubleshooting

  • No free slots shown: check that the selected type is active, at least one availability window covers the date range, and the range is within the booking horizon and minimum notice.
  • Public page shows nothing: the public toggle (public_enabled) is off; enable it in the embed panel.
  • Visitor never got a confirmation: pending requests must be confirmed in the module (status booked); the confirmation email is sent on that transition when email is configured.