Configuration
Every prop on every widget — the exhaustive reference. For the typical install, see Quick Start.
<BookingWidget /> (generic)
import { BookingWidget } from "@periscaleai/booking-widget";
<BookingWidget
apiBase="https://api.periscale.app/api/v1/business/website/booking"
apiKey="sb_live_xxx"
defaultTab="reserve"
labels={{ reserve: "Schedule", myBookings: "My sessions" }}
onBookingComplete={(apt) => console.log(apt.id)}
/>Required
| Prop | Type | Description |
|---|---|---|
apiBase | string | Base URL of the Periscale public booking API, e.g. https://api.periscale.app/api/v1/business/website/booking. |
Auth
| Prop | Type | Description |
|---|---|---|
apiKey | string | Your sb_live_* widget API key. Required on third-party sites — appended as ?api_key=… on every request. |
Behavior
| Prop | Type | Default | Description |
|---|---|---|---|
defaultTab | "reserve" | "my-bookings" | "reserve" | Which tab is active on first paint. |
onBookingComplete | (appointment: Appointment) => void | — | Fires after a successful create. Useful for analytics, redirects, GA4 events. |
className | string | — | Tailwind classes appended to the outer container. |
Vocabulary
The widget defaults to "Reserve" / "My Reservations" but it's just a label; pass labels to re-skin without forking.
| Key | Default | Use |
|---|---|---|
labels.reserve | "Book" | First tab label. |
labels.myBookings | "My Bookings" | Second tab label. |
labels.bookingsHelp | — | (Reserved.) |
labels.confirm | — | (Reserved.) |
<RestaurantBookingWidget />
See the Restaurant flavor page for the prop table and full flow.
Booking config (server-side)
Most appearance knobs (slot duration, advance booking window, cancellation policy, confirmation/reminder email toggles) live on the business in your Periscale dashboard — not on the widget. The widget reads them at first paint via GET {apiBase}/config/.
The fields you can configure server-side:
| Field | Default | Description |
|---|---|---|
is_enabled | false | Master toggle. Disabled config → widget shows "Online booking is currently unavailable". |
timezone | "Asia/Dhaka" | IANA timezone used for slot calculations. |
slot_duration_minutes | 30 | Default slot length when no service is selected. |
buffer_between_slots_minutes | 0 | Gap forced between consecutive slots. |
max_advance_booking_days | 30 | How far in advance customers can book. |
min_advance_booking_hours | 1 | Minimum lead time. |
max_bookings_per_slot | 1 | Concurrent bookings allowed per slot. |
cancellation_policy_hours | 24 | Free-cancellation window. |
allow_customer_cancellation | true | If false, the My-Bookings cancel button is hidden. |
confirmation_email_enabled | true | Send the auto-confirmation email on create. |
reminder_email_enabled | true | Send a reminder email before the appointment. |
reminder_hours_before | 24 | Reminder lead time. |
google_integration | — | Link a Google Calendar integration to two-way-sync appointments. |
Edit these in the Booking integration of your dashboard, or via PATCH /api/v1/business/{id}/bookings/config/.
Theming
The widget uses Tailwind utility classes scoped to its own DOM. To re-color it, target the host element with your own Tailwind layer or override:
/* Brand the primary buttons + accents. */
.bg-amber-500 { background-color: #20808D; }
.hover\:bg-amber-600:hover { background-color: #196872; }
.text-amber-600 { color: #20808D; }
.ring-amber-200 { --tw-ring-color: rgba(32, 128, 141, 0.25); }
.border-amber-500 { border-color: #20808D; }A first-class theme prop is on the roadmap. For now, override at the CSS layer.
TypeScript
Both widgets are fully typed. The package ships granular subpath exports if you only need types or the API client:
import type { Appointment, BookingConfig, TimeSlot } from "@periscaleai/booking-widget/types";
import type { Reservation, RestaurantTable } from "@periscaleai/booking-widget/restaurant/types";