Patient portal widget
window.MedosPatientPortal — a returning patient verifies once and manages their own appointments, family members, and session credits.
Where the booking widget ends at "you're booked", the patient portal starts there. A returning patient verifies a phone number or email address once, and sees everything the clinic already holds for that contact.
<script src="https://widgets.medos.one/v2/portal.js"></script>
<div id="medos-portal"></div>
<script>
MedosPatientPortal.init({
apiKey: "mk_your_publishable_key",
mode: "inline",
containerId: "medos-portal",
});
</script>The bundle is self-contained and exposes one global, window.MedosPatientPortal.
Install › CDN covers deferring the tag
and loading it on demand.
What the patient sees
Sign in — a phone number or an email address, then the code sent to it.
The same verification the booking widget uses; the
otpChannels option
controls which channels are offered.
Their appointments — upcoming and past, with a picker to switch between the family members registered on that contact.
Act on one — view the details, cancel it, reschedule it to another slot, or submit a payment claim if the clinic takes manual payments.
Session credits — a wallet card showing active session packs, how many sessions remain on each, and when they expire.
Family members — the patient records already registered on that contact, plus a dialog to add another.
Book again — opens the booking widget in place, skipping verification because this patient has already proved the contact.
Try it
Configure it below and copy the snippet. The preview runs against a demo workspace.
Patient portal
A returning patient verifies once, then manages their own appointments and credits.
window.MedosPatientPortal
Theme
Custom theme
View
Verification
Which channels the patient can receive their one-time code on. Narrow it when a workspace only supports one — an email option with no sending domain configured never delivers.
<div id="medos-portal" style="min-height: 600px"></div>
<script src="https://widgets.medos.one/v2/portal.js"></script>
<script>
MedosPatientPortal.init({
apiKey: "mk_your_publishable_key",
mode: "inline",
containerId: "medos-portal",
theme: "default",
onError: (err) => console.error(err),
});
</script>Open it from a "My appointments" link
init({ mode: "modal" }) opens the modal straight away, so call it from the
click handler rather than on page load. After the first click, open() shows
the same portal again.
<script defer src="https://widgets.medos.one/v2/portal.js"></script>
<button id="my-appointments">My appointments</button>
<script>
let started = false;
document.getElementById("my-appointments").onclick = () => {
if (started) return MedosPatientPortal.open();
started = true;
MedosPatientPortal.init({
apiKey: "mk_your_publishable_key",
mode: "modal",
onClose: () => console.log("Portal closed"),
});
};
</script>In this section
Configure
Methods, every option with its type and default, and the TypeScript type.
Callbacks
onError and onClose — and why onSuccess never fires.
Errors
What throws, what reaches onError, and what the portal handles itself.
Notes
- The portal is patient-scoped, not doctor-scoped. It shows the appointments on the verified contact across every doctor in the workspace. There is nothing to pre-select.
- Nothing is visible before verification. The first screen is the contact field; no patient data is fetched until a code has been confirmed.
- A portal and a booking widget can share a page. Each gets its own store and query client, so verifying in one does not sign the other in.
- Language and direction are per-instance. The portal has its own language selector, and applies right-to-left direction to its own root only — never to your page. See Internationalization.