Widgets

Widgets

Four embeddable widgets ship from the Medos SDK — booking, patient portal, enquiry form, and package purchase. Each is its own script tag and its own global.

The Medos client SDK is a set of independent CDN bundles, one per widget. Each is a self-contained IIFE that mounts React into a container you provide, and each exposes exactly one global on window.

They share the same API key, the same theming system, and the same modal-or-inline mounting model — but they are separate scripts. Load only the ones the page needs; every bundle carries its own copy of React.

There is no npm package

medos-sdk on npm is deprecated and no longer published. Every integration loads a CDN bundle — no build step, no framework lock-in, no peer dependency to reconcile. If you have npm i medos-sdk in a project, remove it.

The four widgets

Each widget has an overview that explains what it is for and how it behaves, with a live playground, then pages for its configuration, callbacks, and errors — every config key, every callback payload, the TypeScript types, and the error model.

Bundles and globals

WidgetScriptGlobalMethodsOptions
Bookinghttps://widgets.medos.one/v2/unified.jswindow.MedosBookinginit, open, closeConfigure
Patient portalhttps://widgets.medos.one/v2/portal.jswindow.MedosPatientPortalinit, open, closeConfigure
Enquiry formhttps://widgets.medos.one/v2/enquiries.jswindow.MedosEnquiryinit, open, closeConfigure
Package purchasehttps://widgets.medos.one/v2/packages.jswindow.MedosPackagePurchaseinitConfigure

The URL is the same for every site and every environment — there is nothing to configure per deployment.

Most of these docs are about the booking widget

The booking widget section has the most depth — configuration, booking system types, callbacks, and advanced topics — and the framework guides under Install use it as their example. Theming applies to every widget. Each widget's overview says what it shares with the booking widget and where it differs.

What they share

  • One API key. The same mk_ key starts every widget — see API keys. Each widget identifies its own type when it exchanges the key for a session token, so the platform can scope and observe them separately.
  • Instance isolation. Every mounted widget gets its own React tree, its own TanStack Query client, and its own store. Two widgets on one page never share state. See Architecture at a glance.
  • mode: "modal" | "inline". Modal overlays the page; inline mounts into the element whose id you pass as containerId. The package widget is inline only.

What they don't share

  • Config surface. Every widget takes the same theming options — built-in theme names, the flat brand shortcuts, and fontSize. Beyond that the surfaces differ: only the booking widget and the patient portal take sizing and otpChannels, the enquiry form has no verification step, and the package widget mounts inline only. Each widget's Configure page has the exact list.
  • Globals. They are separate singletons. Loading all four gives you four independent widgets, not one widget with four modes.

A widget type has to be enabled for your workspace

Each widget presents a distinct type when it starts a session, and the platform gateway only mints sessions for types it has been told to allow. If a widget fails immediately with an authentication error while the booking widget works with the same key, ask your Medos contact to enable that widget type for your workspace.

Trying them

Each widget's page carries its own playground, pinned to that widget: configure it with the controls, watch the preview update, and copy the generated snippet. The preview runs against a demo workspace, so the doctors, locations and availability are sample data, and no key is needed to use it.

The controls on offer change with the widget, because the option surfaces genuinely differ:

WidgetThemefontSizelayoutotpChannelsCompact / CalendarmaxHeightModal
BookingName + shortcutsYesYesYesYesYesYes
Patient portalName + shortcutsYes—Yes—YesYes
Enquiry formPartialTheme object—————Yes
Package purchase———————

The enquiry form's colour and font controls are emitted as a nested theme object rather than as the flat primaryColor / fontFamily shortcuts; both forms work on that widget. The playground doesn't offer theming controls for the package widget, though the widget itself accepts the same theming options — see its Configure page.

What the controls map to

ControlConfig optionReference
Theme presetstheme, primaryColor, secondaryColor, borderRadiusTheming
Override brand coloursprimaryColor, secondaryColorBrand colours
borderRadius sliderborderRadiusBrand colours
Font pickerfontFamily + fontUrlBrand colours
fontSizefontSizeinit() options
Inline / Modalmode (+ containerId for inline)Modal vs inline
Full / Compact / Calendarcompact, calendarOnlyCalendar-only and compact
maxHeight slidermaxHeightSizing
layoutlayoutinit() options
VerificationotpChannelsinit() options
Device buttons— preview only, the widget is responsive by default—

The device buttons don't map to a config option. The widget adapts its own layout to the space it's given, so resizing the preview frame is the same as resizing a browser window.

Options that render identically to leaving them out — fontSize: "medium", layout: "vertical", both verification channels — are omitted from the generated snippet, so what you copy is the shortest config that reproduces what's on screen. The snippet also never carries a real key: it shows apiKey: "mk_your_publishable_key" as a placeholder, because you may be sharing your screen and the copied sample is meant to be pasted into a repo.

A preview that won't load isn't necessarily your fault

The preview loads each widget's bundle from widgets.medos.one. If something on your side blocks it — an ad blocker, a corporate network policy, an offline connection — the preview says so and the generated snippet stays correct.

Server-side

These bundles run in the browser and use a publishable key. To book, reschedule, or cancel from your own backend — with a secret key, an IP allowlist, and no UI — use the Server-side API instead.

On this page