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
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey | string | Yes | — | 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. |
containerId | string | For inline | — | DOM id of the element the widget mounts into. Ignored in modal mode. |
Booking scope
| Option | Type | Default | Description |
|---|---|---|---|
externalMemberId | string | — | Lock the widget to one doctor by their external member id. The picker is skipped. See Lock to a single doctor. |
calendarOnly | boolean | false | Strip back to the calendar: no profile panel, picker, filters, or headers. See Calendar-only and compact. |
compact | boolean | false | Hide only the doctor profile panel; picker and headers stay. See Calendar-only and compact. |
doctorInfo | DoctorOverrideInfo | — | Override the fetched doctor's profile fields. |
doctorInfoByDoctorId | Record<string, DoctorOverrideInfo> | — | Per-doctor profile overrides, keyed by doctor id. |
Layout
| Option | Type | Default | Description |
|---|---|---|---|
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
| Option | Type | Default | Description |
|---|---|---|---|
otpChannels | ("phone" | "email")[] | ["phone", "email"] | Which channels the verification step offers the patient. See Patient verification. |
Appearance
| Option | Type | Default | Description |
|---|---|---|---|
theme | "default" | "modern" | MedosTheme | PartialTheme | "default" | Built-in theme name, a full theme object, or a partial override. See Theming. |
primaryColor | string | From theme | Brand colour shortcut. Hover and active shades are derived automatically. |
secondaryColor | string | From theme | Secondary brand colour. Hover shade derived automatically. |
borderRadius | string | number | From theme | Corner radius for the widget's surfaces. A number is treated as px. |
fontFamily | string | From theme | CSS font stack applied across the widget. |
fontUrl | string | — | 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
| Option | Type | Default | Description |
|---|---|---|---|
maxWidth | number | string | 600px in modal mode | Cap the widget width. A number is treated as px. |
maxHeight | number | string | 90vh in modal mode | Cap the widget height; inner content scrolls. A number is treated as px. |
See Sizing for guidance on picking values.
Callbacks
| Option | Type | Description |
|---|---|---|
onSuccess | (data?: BookingResult) => void | Fired once per completed booking, on the confirmation screen. See onSuccess for the payload. |
onError | (error: Error) => void | Fired when the widget can't start — the workspace load failed. In-flow errors don't reach it — see onError. |
onClose | () => void | Fired 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:
apiKeyis 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.