WidgetsBooking widgetConfigure

init() options

The full reference for MedosBooking.init(), open(), and close().

This page is the booking widget's reference

The options below belong to window.MedosBooking. The patient portal takes the same object minus the booking-specific keys; the enquiry and package widgets have much smaller surfaces of their own. See Widgets.

MedosBooking.init(config) bootstraps the widget. MedosBooking.open(config?) opens it as a modal (and accepts a partial config that merges with the last init call). MedosBooking.close() closes the modal.

Want to try these before writing any code? Use the booking playground — it generates the exact snippet as you change options.

Core

OptionTypeRequiredDefaultDescription
apiKeystringYes—Your Medos publishable API key. See API keys.
mode"modal" | "inline"No"inline"Modal opens over the page; inline mounts into containerId. Anything other than "modal" — including omitting it — is treated as inline. See Modal vs inline.
containerIdstringFor inline—DOM id of the element the widget mounts into. Ignored in modal mode.

Booking scope

OptionTypeDefaultDescription
externalMemberIdstring—Lock the widget to one doctor by their external member id. The picker is skipped. See Lock to a single doctor.
calendarOnlybooleanfalseStrip back to the calendar: no profile panel, picker, filters, or headers. See Calendar-only and compact.
compactbooleanfalseHide only the doctor profile panel; picker and headers stay. See Calendar-only and compact.
doctorInfoDoctorOverrideInfo—Override the fetched doctor's profile fields.
doctorInfoByDoctorIdRecord<string, DoctorOverrideInfo>—Per-doctor profile overrides, keyed by doctor id.

Layout

OptionTypeDefaultDescription
layout"vertical" | "horizontal""vertical"Where the doctor list sits relative to the calendar. "vertical" puts it on top as a horizontal strip; "horizontal" puts it in a left column beside the calendar.

"vertical" renders exactly as the widget did before this option existed, so leaving it unset changes nothing.

"horizontal" needs desktop width and a list worth showing. It falls back to "vertical" below the md breakpoint, and whenever there is no list at all — calendarOnly, a single visible doctor, or compact, which pins the body to a single calendar column.

Unknown values degrade, they don't break

layout, fontSize, and otpChannels all arrive as untyped JavaScript from your script tag, so each is validated once when the widget mounts. An unrecognised value logs a [Medos] console warning and falls back to the default rather than failing the render.

Verification

OptionTypeDefaultDescription
otpChannels("phone" | "email")[]["phone", "email"]Which channels the verification step offers the patient. See Patient verification.

Appearance

OptionTypeDefaultDescription
theme"default" | "modern" | MedosTheme | PartialTheme"default"Built-in theme name, a full theme object, or a partial override. See Theming.
primaryColorstringFrom themeBrand colour shortcut. Hover and active shades are derived automatically.
secondaryColorstringFrom themeSecondary brand colour. Hover shade derived automatically.
borderRadiusstring | numberFrom themeCorner radius for the widget's surfaces. A number is treated as px.
fontFamilystringFrom themeCSS font stack applied across the widget.
fontUrlstring—Stylesheet URL (e.g. Google Fonts) loaded so fontFamily resolves.
fontSize"small" | "medium" | "large""medium"Scales every font size in the widget proportionally — small is 0.875×, large is 1.125×. "medium" is the baseline and a no-op.

Brand shortcuts win over `theme`

primaryColor, secondaryColor, borderRadius, and fontFamily are top-level shortcuts that layer on top of whatever theme you pass. You can start from "modern" and just override the primary colour. See Brand colours.

Sizing

OptionTypeDefaultDescription
maxWidthnumber | string600px in modal modeCap the widget width. A number is treated as px.
maxHeightnumber | string90vh in modal modeCap the widget height; inner content scrolls. A number is treated as px.

See Sizing for guidance on picking values.

Callbacks

OptionTypeDescription
onSuccess(data?: BookingResult) => voidFired once per completed booking, on the confirmation screen. See onSuccess for the payload.
onError(error: Error) => voidFired when the widget can't start — the workspace load failed. In-flow errors don't reach it — see onError.
onClose() => voidFired when the modal closes — including the automatic close 3 seconds after a booking completes. Modal mode only.

There is no `baseUrl` option

The API endpoint is compiled into the widget bundle, so there's nothing to point anywhere. If you're carrying a baseUrl over from older config, delete it.

Minimal example

MedosBooking.init({
  apiKey: "mk_your_publishable_key",
  mode: "modal",
});

Full example

MedosBooking.init({
  apiKey: "mk_your_publishable_key",
  mode: "inline",
  containerId: "medos-booking",

  // appearance
  theme: "modern",
  primaryColor: "#4f46e5",
  secondaryColor: "#6366f1",
  borderRadius: 12,
  fontFamily: "'Inter', sans-serif",
  fontUrl:
    "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap",
  fontSize: "medium",

  // layout
  layout: "horizontal",

  // verification
  otpChannels: ["phone", "email"],

  // sizing
  maxWidth: 900,
  maxHeight: 720,

  // booking scope
  externalMemberId: "your-doctor-external-id",
  calendarOnly: false,
  compact: false,

  // callbacks
  onSuccess: (result) => {
    console.log("Booked", result);
    window.location.href = "/booking-confirmed";
  },
  onError: (err) => console.error("Booking error", err),
  onClose: () => console.log("Modal closed"),
});

Methods

init(config)

Initializes the widget. Call once per page (or per iframe).

  • Modal mode: opens the modal immediately.
  • Inline mode: mounts into containerId.

Throws if:

  • apiKey is missing → "API key is required"
  • Inline mode without containerId → "containerId is required for inline mode"
  • Inline mode with an unknown containerId → "Container with id ... not found"

Call init() only once

Calling init() a second time mounts a second widget instance in the same container, which can double-render the booking UI. To re-open in modal mode use open(). To re-render inline, clear the container's HTML first, then call init() again — or mount each instance in its own iframe (see Multiple instances).

open(config?)

Opens the widget as a modal again after init(). The optional config merges into the last-known config, so a later click can reopen it with just tweaks:

// First click: init() starts the widget and, in modal mode, opens it.
MedosBooking.init({ apiKey: "mk_...", mode: "modal" });

// A later click, after the patient closed it:
MedosBooking.open({ externalMemberId: "your-doctor-external-id" });

Throws if no apiKey has ever been set. Call init() first: open() on its own skips the step that exchanges your key for a session.

close()

Closes the currently open modal. No-op if the widget is inline or the modal isn't open. Fires onClose if it was provided.

MedosBookingConfig type

The whole config object, for TypeScript projects:

interface MedosBookingConfig {
  /** Required. Your publishable key. */
  apiKey: string;

  // mounting
  mode?: "modal" | "inline";
  containerId?: string;
  maxWidth?: number | string;
  maxHeight?: number | string;

  // booking scope
  externalMemberId?: string;
  calendarOnly?: boolean;
  compact?: boolean;
  layout?: "vertical" | "horizontal";
  doctorInfo?: DoctorOverrideInfo;
  doctorInfoByDoctorId?: Record<string, DoctorOverrideInfo>;

  // verification
  otpChannels?: ("phone" | "email")[];

  // appearance
  theme?: "default" | "modern" | MedosTheme | PartialTheme;
  primaryColor?: string;
  secondaryColor?: string;
  borderRadius?: string | number;
  fontFamily?: string;
  fontUrl?: string;
  fontSize?: "small" | "medium" | "large";

  // callbacks
  onSuccess?: (result: BookingResult) => void;
  onError?: (error: Error) => void;
  onClose?: () => void;
}

DoctorOverrideInfo shape

Used by doctorInfo and doctorInfoByDoctorId to override profile fields the API returns.

interface DoctorOverrideInfo {
  fullName?: string;
  intro?: string;
  qualifications?: Array<{
    degree: string;
    institution?: string;
    year?: number;
  }>;
  awards?: string[];
  availableDays?: string;
  designation?: string;
  experience?: string;
  languages?: string[];
  registrationNumber?: string;
  registrationAuthority?: string;
  specialization?: string[];
  services?: string[];
  expertise?: string[];
  mode?: string[];
  gender?: string;
  profileImageUrl?: string;
  email?: string;
  phoneNumber?: string;
}

Any field you omit falls back to the API value. See Override doctor info for common patterns.

On this page