Troubleshooting
Common issues and how to fix them.
Nine out of ten integration issues fit one of these patterns. Skim the headings — if one matches, follow the fix.
The widget doesn't render at all
Is the script loaded? In DevTools → Network, check that
unified.js returned 200. If it didn't, the CDN URL is wrong or
blocked by a CSP rule.
Is MedosBooking defined? In the Console tab, type MedosBooking
and press Enter. If it says "undefined", the script hasn't loaded or
threw a parse error.
Is init() being called? Search your bundle for MedosBooking.init.
If the call sits inside a <script type="module">, make sure the
bundle loads first.
Any errors in the console? onError might have fired with an API
error and you don't have a handler wired up.
Container with id "…" not found
Inline mode couldn't find the <div> you named in containerId. Fixes:
- Verify the id matches exactly, case-sensitive, no leading
#. - Make sure the
<div>exists in the DOM before you callinit(). If your React app renders the container conditionally, wait for it to mount before initializing.
"API key is required" or "Invalid API key"
- Check the key starts with
mk_. - Confirm you're not accidentally using an empty string (a common env-var typo). Log the value first if unsure.
- Confirm the key belongs to the workspace you expect — a key reaches exactly one workspace. See Going live.
- Check the key's allowed origin — see below.
The key works on one domain but not another
Browser keys can be bound to a single origin. A key bound to
https://yourclinic.com is rejected on any other origin, which usually shows
up as an authentication or forbidden error from onError.
Things that count as a different origin:
| Working | Also needs its own key |
|---|---|
https://yourclinic.com | https://www.yourclinic.com |
https://yourclinic.com | https://staging.yourclinic.com |
https://yourclinic.com | http://localhost:3000 |
The allowed origin is configured on the Medos side, not in your dashboard — ask your Medos contact to bind the key to the domain you're serving from, or to issue a separate key per domain. See Origin-bound keys.
This is also why a production key won't render in the Playground — the docs site isn't your bound origin.
Blank screen inside the widget
Usually a Content Security Policy issue. The widget needs to reach the
Medos API — check your CSP for connect-src and add the API hostname.
If your site uses a strict CSP, you'll also need script-src to allow
the CDN URL.
The theme doesn't apply
- Confirm the
themevalue spells the built-in name correctly ("default"or"modern"— lowercase). - Check the console for an ignored-keys warning. Brand shortcuts like
primaryColormust sit at the top level of your config, not insidetheme. Nested there, they're ignored and the widget logs which keys it skipped. See Brand colours. - Remember the widget won't pick up a theme from anywhere else — with no
themein your config you getdefault, regardless of dashboard settings.
The custom font isn't applied
- If the font isn't already loaded by your site, pass
fontUrlalongsidefontFamilyso the widget can load the stylesheet. - Make sure
fontFamilymatches the family name the stylesheet defines, quoted if it contains spaces:"'DM Sans', sans-serif". - A strict CSP needs
font-srcandstyle-srcto allow your font host.
Nothing happens after the patient confirms
If your workspace collects payment online, confirming opens a hosted checkout in a new window — and browsers sometimes block that popup. The patient stays on the waiting screen, which has a Reopen checkout action that isn't blocked because it responds to their click.
See Online payment for the full set of outcomes the waiting screen handles.
OTP never arrives
- The patient's phone number's country code must be included
(e.g.
+1,+91). - SMS delivery goes through the platform's provider — if delivery is systematically failing for a region, contact support.
- You may have hit the send limit. By default a number can be sent at most 50 OTPs per hour. If you've been testing repeatedly with the same number and delivery stops, that's the usual cause — wait it out or use another number.
OTP defaults
A code expires after 5 minutes, and a patient gets 3 verification attempts before they need a new one. These are platform defaults, so a deployment can be configured differently — check with your Medos admin if the behaviour you see doesn't match.
Slots look wrong / empty
- Check that the doctor has availability configured for the date range.
- Consultation types matter — a doctor with only "online" availability won't show slots when the widget is filtered to "offline".
- If the whole calendar is empty, the doctor might be inactive or missing a public profile — see Doctor visibility.
Modal auto-closes too fast (or too slow)
The success auto-close is 3 seconds. This is not currently configurable. If you need to control the timing (e.g. suppress the auto-close and keep the confirmation on screen), use inline mode instead — inline never auto-closes.
Still stuck
If none of the above matches, capture the following before reaching out:
- The exact
MedosBooking.init(...)call you're making. - The output of
MedosBookingin the browser console. - Any
onErrormessage you see. - Browser + version, framework + version.
That's usually enough for support to diagnose in one round-trip.