medos-sdk
v1.2.1
Published
Medos SDK for managing appointments, meetings, and calendars in apps
Readme
Medos SDK
A JavaScript/TypeScript SDK for integrating healthcare appointment booking into your applications. Built for clinics, hospitals, and healthcare platforms.
✨ Features
- 🎨 Powerful Theming System - Customize appearance with built-in themes or create your own
- ⚛️ React & Vanilla JS - Works with React or pure JavaScript
- 🔒 Secure Authentication - API key and session token support
- 📱 Responsive Design - Mobile-first, works on all screen sizes
- 🎯 TypeScript-First - Full type safety and IntelliSense support
- ♿ Accessible - WCAG compliant components
Installation
npm install medos-sdkTable of Contents
- Quick Start
- Getting Started
- Usage
- React Integration
- Vanilla JavaScript
- TypeScript
- API Reference
- Error Handling
- Examples and Documentation
- Requirements
Quick Start
React
import { MedosThemeProvider, AppointmentCalender } from "medos-sdk/react";
function App() {
return (
<MedosThemeProvider theme="modern">
<AppointmentCalender onError={(err) => console.error(err)} />
</MedosThemeProvider>
);
}Vanilla JavaScript
import { initAppointmentCalendar } from "medos-sdk/vanilla";
initAppointmentCalendar({
containerId: "appointment-widget",
apiKey: "your-api-key",
theme: "modern", // or 'default'
});HTML/CSS/JS
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="path/to/widget.css" />
</head>
<body>
<div id="appointment-calendar"></div>
<script src="path/to/widget.js"></script>
<script>
window.MedosAppointmentCalendar.init({
containerId: "appointment-calendar",
apiKey: "your-api-key",
});
</script>
</body>
</html>Getting Started
Authentication
The SDK supports two authentication methods:
Server-Side (API Key)
Use this method for backend services and server-side rendering.
import { MedosClient } from "medos-sdk";
await MedosClient.init({
apiKey: "your-api-key",
});Client-Side (Session Token)
Use this method for frontend applications. Obtain the session token from your backend.
import { MedosClient } from "medos-sdk";
await MedosClient.initWithSession({
sessionToken: "user-session-token",
});Usage
Fetch Clinic Addresses and Doctors
Retrieve all available clinic locations with their associated doctors.
const result = await MedosClient.fetchAllAddressesAndDoctors();Response:
{
totalAddresses: 5,
totalDoctors: 12,
workspaceId: "workspace-123",
addresses: [
{
id: "addr-1",
completeAddress: "123 Medical Center, New York, NY 10001",
addressLine1: "123 Medical Center",
city: "New York",
state: "NY",
country: "USA",
zipcode: "10001",
doctors: [
{
id: "doc-1",
name: "Dr. John Smith",
email: "[email protected]",
specialty: "Cardiology"
}
]
}
]
}Fetch Available Slots
Get available appointment time slots for a specific doctor.
const slots = await MedosClient.fetchAppointments(
"workspace-123", // workspaceId
"addr-1", // addressId
"doc-1", // doctorId
"2025-11-16" // appointmentDate (YYYY-MM-DD)
);Response:
[
{
start: "2025-11-16T10:00:00",
end: "2025-11-16T10:30:00",
id: "slot-1",
},
{
start: "2025-11-16T11:00:00",
end: "2025-11-16T11:30:00",
id: "slot-2",
},
];Book an Appointment
Create a new appointment booking.
import { AppointmentService } from "medos-sdk";
const appointment = await AppointmentService.createAppointment({
workspaceAddressId: "addr-1",
doctorId: "doc-1",
mode: "OFFLINE",
appointmentDate: "2025-11-16",
fromDateTimeTs: "10:00",
toDateTimeTs: "10:30",
consultationCharge: "100",
type: "CONSULTATION",
source: "SDK_POWERED_WEBSITE",
patientPayload: {
firstName: "Jane",
lastName: "Doe",
email: "[email protected]",
countryCode: "+1",
phoneNumber: "5551234567",
age: 30,
gender: "FEMALE",
},
patientAddress: {
addressLine1: "456 Patient Street",
city: "New York",
state: "NY",
country: "USA",
zipcode: "10001",
landmark: "Near Central Park",
},
});Optional Fields:
| Field | Default Value | Description |
| -------------------- | ----------------------- | -------------------------------------------- |
| mode | "OFFLINE" | Consultation mode: "OFFLINE" or "ONLINE" |
| consultationCharge | "0" | Consultation fee as string |
| type | "CONSULTATION" | Appointment type |
| source | "SDK_POWERED_WEBSITE" | Source identifier |
Phone Verification
Implement OTP-based phone number verification for patients.
Send OTP
await MedosClient.sendPhoneVerificationOtp({
countryCode: "+1",
phoneNumber: "5551234567",
});Verify OTP
const result = await MedosClient.verifyPhoneVerificationOtp({
countryCode: "+1",
phoneNumber: "5551234567",
otp: "123456",
});TypeScript
The SDK is written in TypeScript and provides comprehensive type definitions.
import {
MedosClient,
AppointmentService,
BookAppointmentPayload,
AddressesResponse,
PatientPayload,
PatientAddressPayload,
} from "medos-sdk";
const payload: BookAppointmentPayload = {
workspaceAddressId: "addr-1",
doctorId: "doc-1",
appointmentDate: "2025-11-16",
fromDateTimeTs: "10:00",
toDateTimeTs: "10:30",
patientPayload: {
firstName: "John",
lastName: "Doe",
countryCode: "+1",
phoneNumber: "5551234567",
},
patientAddress: {
addressLine1: "123 Main Street",
city: "New York",
state: "NY",
country: "USA",
zipcode: "10001",
},
};
const appointment = await AppointmentService.createAppointment(payload);Type Definitions
BookAppointmentPayload
{
workspaceAddressId: string | number;
doctorId: string | number;
appointmentDate: string; // Format: "YYYY-MM-DD"
fromDateTimeTs: string; // Format: "HH:MM"
toDateTimeTs: string; // Format: "HH:MM"
mode?: "OFFLINE" | "ONLINE"; // Default: "OFFLINE"
consultationCharge?: string; // Default: "0"
type?: "CONSULTATION" | string; // Default: "CONSULTATION"
source?: string; // Default: "SDK_POWERED_WEBSITE"
patientPayload: PatientPayload;
patientAddress: PatientAddressPayload; // Required
}PatientPayload
{
firstName: string;
lastName: string;
countryCode: string;
phoneNumber: string;
email?: string;
age?: number;
gender?: "MALE" | "FEMALE" | "OTHER";
}PatientAddressPayload
{
addressLine1?: string;
city?: string;
state?: string;
country?: string;
zipcode?: string;
landmark?: string;
}React Integration
Pre-built appointment calendar component for React applications.
import { AppointmentCalender } from "medos-sdk";
function BookingPage() {
return <AppointmentCalender />;
}The component automatically uses the initialized MedosClient instance.
Using React-specific exports
For better tree-shaking and to avoid React dependency conflicts:
import { AppointmentCalender } from "medos-sdk/react";Vanilla JavaScript / HTML Integration
For websites using plain HTML, CSS, and JavaScript (no React), use the vanilla widget. The SDK provides two widgets: Appointment Booking and Enquiry Form.
Installation Options
Option 1: NPM Package (Recommended)
npm install medos-sdkAfter building, you'll find the widget files in:
dist/vanilla/widget.js- JavaScript bundle (UMD format)dist/vanilla/widget.css- Base stylesheetdist/vanilla/widget-themed.css- Advanced theming stylesheet
Option 2: CDN Integration
Load directly from CDN (replace with actual CDN URL when available):
<!-- CSS -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.css"
/>
<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.js"></script>Appointment Booking Widget
Basic Usage
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="path/to/widget.css" />
</head>
<body>
<div id="appointment-calendar"></div>
<script src="path/to/widget.js"></script>
<script>
// Method 1: Global API (Recommended)
window.MedosAppointmentCalendar.init({
containerId: "appointment-calendar",
apiKey: "your-api-key",
onError: (err) => {
console.error("Error:", err);
alert("An error occurred. Please try again.");
},
onSuccess: () => {
console.log("Appointment booked successfully!");
},
});
// Method 2: Class-based API (Alternative)
// const widget = new window.MedosAppointmentWidget('appointment-calendar', {
// apiKey: 'your-api-key'
// });
</script>
</body>
</html>CDN Integration Example
<!DOCTYPE html>
<html>
<head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.css"
/>
</head>
<body>
<div id="appointment-widget"></div>
<script src="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.js"></script>
<script>
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
sessionToken: "your-session-token", // Obtained from your server
baseURL: "https://api.medos.one/v1",
onError: (err) => console.error(err),
onSuccess: () => console.log("Success!"),
});
</script>
</body>
</html>Enquiry Form Widget
Basic Usage
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="path/to/widget.css" />
</head>
<body>
<div id="enquiry-form"></div>
<script src="path/to/widget.js"></script>
<script>
// Method 1: Global API (Recommended)
window.MedosEnquiryForm.init({
containerId: "enquiry-form",
apiKey: "your-api-key",
onError: (err) => console.error(err),
onSuccess: (enquiry) => {
console.log("Enquiry submitted:", enquiry);
alert("Thank you! Your enquiry has been submitted.");
},
});
// Method 2: Class-based API (Alternative)
// const widget = new window.MedosEnquiryWidget('enquiry-form', {
// apiKey: 'your-api-key'
// });
</script>
</body>
</html>Widget Step Flow
Appointment Booking Steps
The appointment widget follows this exact step sequence (matching React component):
- Step 0: Phone Verification - Country code selection, phone input, OTP verification
- Step 1: Booking Option Selection - Session packs vs. new appointment (auto-skipped if no packages)
- Step 2: Location & Doctor Selection - Address and doctor selection with chief complaint
- Step 3: Date & Time Selection - Calendar, consultation mode, and time slot selection
- Step 4: Patient Selection - Choose existing patient or create new
- Step 5: Patient Details Form - Patient information and address (for new patients)
- Step 6: Appointment Summary - Review all details and cost breakdown
- Step 7: Success Confirmation - Confirmation with appointment details
Enquiry Form Steps
- Step 1: Contact Information - Name, email, phone number
- Step 2: Inquiry Details - Subject and detailed message
- Step 3: Contact Preference - Preferred contact method (email, phone, both)
- Step 4: Success Confirmation - Submission confirmation
Configuration Options
Complete API reference for widget initialization:
interface WidgetOptions {
containerId: string; // Required: ID of container element
apiKey?: string; // Optional: API key for authentication
sessionToken?: string; // Optional: Session token (alternative to apiKey)
baseURL?: string; // Optional: API base URL (default: https://api.medos.one/v1)
onError?: (error: Error) => void; // Optional: Error callback
onSuccess?: (data?: any) => void; // Optional: Success callback
onStepChange?: (step: number) => void; // Optional: Step change callback
theme?: "default" | "modern" | string; // Optional: Theme selection
}Configuration Examples
Basic Configuration:
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
apiKey: "your-api-key",
});Advanced Configuration with Callbacks:
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
sessionToken: "user-session-token",
baseURL: "https://api.medos.one/v1",
theme: "modern",
onError: (error) => {
console.error("Widget error:", error);
// Show user-friendly error message
document.getElementById("error-message").textContent =
"Unable to load appointment booking. Please try again.";
document.getElementById("error-message").style.display = "block";
},
onSuccess: (appointment) => {
console.log("Appointment booked successfully", appointment);
// Redirect or show success message
window.location.href = "/appointment-confirmation";
},
onStepChange: (step) => {
console.log("Current step:", step);
// Track user progress for analytics
if (typeof analytics !== "undefined") {
analytics.track("appointment_step_change", { step });
}
},
});Environment-Specific Configuration:
const isProduction = window.location.hostname !== "localhost";
const config = {
containerId: "appointment-widget",
baseURL: isProduction
? "https://api.medos.one/v1"
: "https://dev-api.medos.one/v1",
sessionToken: await getSessionToken(), // Fetch from your backend
onError: (error) => handleWidgetError(error),
};
window.MedosAppointmentCalendar.init(config);Authentication Methods
Using Session Token (Recommended for Production)
For better security, obtain the session token server-side:
// Fetch session token from your backend
async function initializeWidget() {
try {
const response = await fetch("/api/get-session-token");
const { sessionToken } = await response.json();
window.MedosAppointmentCalendar.init({
containerId: "appointment-calendar",
sessionToken: sessionToken,
baseURL: "https://api.medos.one/v1",
onError: (err) => console.error(err),
});
} catch (error) {
console.error("Failed to get session token:", error);
}
}
initializeWidget();Using API Key (Development Only)
window.MedosAppointmentCalendar.init({
containerId: "appointment-calendar",
apiKey: "your-api-key", // Only for development/testing
onError: (err) => console.error(err),
});Server-Side Integration Examples
PHP Integration
<?php
// Get session token from your backend
function getSessionTokenFromBackend() {
// Your implementation to get session token
// This should call your backend API that exchanges API key for session token
$apiKey = 'your-api-key';
$response = file_get_contents('https://api.medos.one/v1/auth/session', false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $apiKey\r\nContent-Type: application/json\r\n",
'content' => json_encode(['apiKey' => $apiKey])
]
]));
$data = json_decode($response, true);
return $data['sessionToken'];
}
$sessionToken = getSessionTokenFromBackend();
?>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="path/to/widget.css">
</head>
<body>
<div id="appointment-calendar"></div>
<script src="path/to/widget.js"></script>
<script>
window.MedosAppointmentCalendar.init({
containerId: 'appointment-calendar',
sessionToken: '<?php echo htmlspecialchars($sessionToken); ?>',
onError: function(err) {
console.error('Error:', err);
alert('An error occurred. Please try again.');
},
onSuccess: function() {
console.log('Appointment booked successfully!');
// Redirect to confirmation page
window.location.href = '/appointment-confirmation.php';
}
});
</script>
</body>
</html>Node.js/Express Integration
// Backend route to get session token
app.get("/api/session-token", async (req, res) => {
try {
const response = await axios.post("https://api.medos.one/v1/auth/session", {
apiKey: process.env.MEDOS_API_KEY,
});
res.json({ sessionToken: response.data.sessionToken });
} catch (error) {
res.status(500).json({ error: "Failed to get session token" });
}
});<!-- Frontend HTML -->
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/dist/vanilla/widget.css" />
</head>
<body>
<div id="appointment-widget"></div>
<script src="/dist/vanilla/widget.js"></script>
<script>
fetch("/api/session-token")
.then((response) => response.json())
.then((data) => {
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
sessionToken: data.sessionToken,
onError: (err) => console.error(err),
onSuccess: () => console.log("Success!"),
});
})
.catch((error) => console.error("Failed to initialize widget:", error));
</script>
</body>
</html>Multiple Widgets on Same Page
You can use multiple widgets independently on the same page:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="path/to/widget.css" />
</head>
<body>
<!-- Appointment Widget -->
<div id="appointment-widget"></div>
<!-- Enquiry Widget -->
<div id="enquiry-widget"></div>
<script src="path/to/widget.js"></script>
<script>
// Initialize appointment widget
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
apiKey: "your-api-key",
onSuccess: () => console.log("Appointment booked!"),
});
// Initialize enquiry widget
window.MedosEnquiryForm.init({
containerId: "enquiry-widget",
apiKey: "your-api-key",
onSuccess: (enquiry) => console.log("Enquiry submitted:", enquiry),
});
</script>
</body>
</html>Global API Reference
After loading the widget script, these global objects are available:
// Global initialization functions
window.MedosAppointmentCalendar.init(options); // Appointment widget
window.MedosEnquiryForm.init(options); // Enquiry form widget
// Widget classes for advanced usage
window.MedosAppointmentWidget; // Appointment widget class
window.MedosEnquiryWidget; // Enquiry widget classWidget Lifecycle Management
Destroying Widgets
// For class-based initialization
const widget = new window.MedosAppointmentWidget("container", options);
// Later...
widget.destroy(); // Clean up event listeners and DOM
// For global API initialization
// Widgets are automatically cleaned up when container is removed from DOMReinitializing Widgets
// Clear container and reinitialize
const container = document.getElementById("appointment-widget");
container.innerHTML = ""; // Clear existing widget
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
apiKey: "your-api-key",
});Theme Customization
The SDK provides comprehensive theming capabilities through CSS variables. Choose between two CSS files based on your customization needs:
Basic Theming (widget.css)
For simple customization with minimal variables:
<link rel="stylesheet" href="dist/vanilla/widget.css" />
<style>
.my-theme {
--medos-primary-color: #7c3aed;
--medos-primary-color-hover: #6d28d9;
--medos-bg-color: #ffffff;
--medos-text-color: #1f2937;
}
</style>
<div id="widget" class="my-theme"></div>Advanced Theming (widget-themed.css)
For comprehensive design system customization:
<link rel="stylesheet" href="dist/vanilla/widget-themed.css" />
<style>
.my-advanced-theme {
/* Colors */
--medos-color-primary: #7c3aed;
--medos-color-background: #ffffff;
--medos-color-text: #1f2937;
/* Typography */
--medos-typography-font-family: "Georgia", serif;
--medos-typography-font-size-md: 18px;
/* Spacing & Layout */
--medos-spacing-md: 16px;
--medos-radius-md: 20px;
--medos-shadow-lg: 0 20px 40px rgba(124, 58, 237, 0.15);
}
</style>
<div id="widget" class="my-advanced-theme"></div>Dynamic Theme Switching
// Apply theme programmatically
const container = document.getElementById("widget-container");
// Method 1: CSS classes
container.classList.add("dark-theme");
// Method 2: Direct CSS variables
container.style.setProperty("--medos-color-primary", "#7c3aed");
container.style.setProperty("--medos-color-background", "#1f2937");
// Method 3: Theme objects
const themes = {
purple: {
"--medos-color-primary": "#7c3aed",
"--medos-color-secondary": "#a855f7",
},
green: {
"--medos-color-primary": "#10b981",
"--medos-color-secondary": "#34d399",
},
};
function applyTheme(themeName) {
const theme = themes[themeName];
Object.entries(theme).forEach(([property, value]) => {
container.style.setProperty(property, value);
});
}Theme Examples
Explore comprehensive theming examples in the examples/ directory:
theme-customization-basic.html- Basic CSS variable overridestheme-customization-advanced.html- Multiple theme comparisonstheme-customization-javascript.html- Dynamic theme switchingtheme-comparison.html- Side-by-side CSS file comparisonenquiry-form-theming.html- Enquiry form specific themes
Available CSS Variables
Basic Variables (widget.css):
--medos-primary-color,--medos-primary-color-hover--medos-bg-color,--medos-bg-color-secondary--medos-text-color,--medos-text-color-secondary--medos-border-color,--medos-border-radius
Complete Variables (widget-themed.css):
- Colors: 15+ color tokens for comprehensive theming
- Typography: Font family, sizes, weights
- Spacing: Consistent spacing scale (xs, sm, md, lg, xl)
- Layout: Border radius, shadows, transitions
See examples/README-THEME-CUSTOMIZATION.md for complete documentation.
Troubleshooting Guide
Common Issues and Solutions
1. Widget Not Loading
Problem: Widget container remains empty, no errors in console.
Solutions:
// Check if widget script loaded
if (typeof window.MedosAppointmentCalendar === "undefined") {
console.error("Widget script not loaded. Check script src path.");
}
// Ensure container exists
const container = document.getElementById("your-container-id");
if (!container) {
console.error("Container element not found. Check containerId.");
}
// Wait for DOM ready
document.addEventListener("DOMContentLoaded", function () {
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
apiKey: "your-api-key",
});
});2. Authentication Errors
Problem: "Invalid API key" or "Authentication failed" errors.
Solutions:
// Verify API key format
const apiKey = "your-api-key";
if (!apiKey || apiKey === "your-api-key") {
console.error("Please replace with your actual API key");
}
// Use session token for production
window.MedosAppointmentCalendar.init({
containerId: "widget",
sessionToken: "your-session-token", // More secure
baseURL: "https://api.medos.one/v1",
});
// Check API endpoint
fetch("https://api.medos.one/v1/health")
.then((response) => console.log("API accessible:", response.ok))
.catch((error) => console.error("API not accessible:", error));3. CSS Styling Issues
Problem: Widget appears unstyled or has layout issues.
Solutions:
<!-- Ensure CSS is loaded before JavaScript -->
<link rel="stylesheet" href="path/to/widget.css" />
<script src="path/to/widget.js"></script>
<!-- Check for CSS conflicts -->
<style>
/* Ensure widget container has proper styling */
#appointment-widget {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
/* Reset any conflicting styles */
.medos-appointment-container * {
box-sizing: border-box;
}
</style>4. Network/CORS Errors
Problem: "CORS policy" or network request failures.
Solutions:
// Check baseURL configuration
window.MedosAppointmentCalendar.init({
containerId: "widget",
apiKey: "your-api-key",
baseURL: "https://api.medos.one/v1", // Ensure correct URL
onError: (error) => {
if (error.message.includes("CORS")) {
console.error("CORS error: Ensure your domain is whitelisted");
}
if (error.message.includes("Network")) {
console.error("Network error: Check internet connection and API status");
}
},
});
// Test API connectivity
async function testAPIConnection() {
try {
const response = await fetch("https://api.medos.one/v1/health");
console.log("API Status:", response.status);
} catch (error) {
console.error("Cannot reach API:", error);
}
}5. Multiple Widget Conflicts
Problem: Multiple widgets interfering with each other.
Solutions:
// Use unique container IDs
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget-1", // Unique ID
apiKey: "your-api-key",
});
window.MedosEnquiryForm.init({
containerId: "enquiry-widget-1", // Different unique ID
apiKey: "your-api-key",
});
// Clean up widgets when needed
const widget = new window.MedosAppointmentWidget("container", options);
// Later...
widget.destroy(); // Prevents memory leaks6. Mobile/Responsive Issues
Problem: Widget doesn't display properly on mobile devices.
Solutions:
<!-- Ensure viewport meta tag -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
/* Responsive container */
.widget-container {
width: 100%;
max-width: 100vw;
padding: 10px;
box-sizing: border-box;
}
/* Mobile-specific adjustments */
@media (max-width: 768px) {
.widget-container {
padding: 5px;
}
}
</style>7. Theme Not Applying
Problem: Custom CSS variables not taking effect.
Solutions:
/* Ensure proper CSS specificity */
.my-theme .medos-appointment-container {
--medos-color-primary: #7c3aed !important;
}
/* Or apply to widget container directly */
#appointment-widget {
--medos-color-primary: #7c3aed;
--medos-color-background: #ffffff;
}// Apply theme programmatically
const container = document.getElementById("appointment-widget");
container.style.setProperty("--medos-color-primary", "#7c3aed");
// Verify theme variables are applied
const computedStyle = getComputedStyle(container);
const primaryColor = computedStyle.getPropertyValue("--medos-color-primary");
console.log("Applied primary color:", primaryColor);Debugging Tips
Enable Debug Mode:
// Add debug logging
window.MedosAppointmentCalendar.init({
containerId: "widget",
apiKey: "your-api-key",
debug: true, // Enable debug mode if available
onError: (error) => {
console.error("Widget Error Details:", {
message: error.message,
stack: error.stack,
timestamp: new Date().toISOString(),
});
},
onStepChange: (step) => {
console.log("Step changed to:", step);
},
});Check Widget State:
// Inspect widget instance
const container = document.getElementById("appointment-widget");
const widgetInstance = container._medosWidget; // Internal reference
if (widgetInstance) {
console.log("Widget state:", widgetInstance.getState());
}
// Check global objects
console.log("Available globals:", {
MedosAppointmentCalendar: typeof window.MedosAppointmentCalendar,
MedosEnquiryForm: typeof window.MedosEnquiryForm,
MedosAppointmentWidget: typeof window.MedosAppointmentWidget,
MedosEnquiryWidget: typeof window.MedosEnquiryWidget,
});Network Debugging:
// Monitor API calls
const originalFetch = window.fetch;
window.fetch = function (...args) {
console.log("API Request:", args[0]);
return originalFetch
.apply(this, args)
.then((response) => {
console.log("API Response:", response.status, response.url);
return response;
})
.catch((error) => {
console.error("API Error:", error);
throw error;
});
};Performance Optimization
Lazy Loading:
// Load widget only when needed
function loadWidget() {
if (!document.getElementById("widget-script")) {
const script = document.createElement("script");
script.id = "widget-script";
script.src = "path/to/widget.js";
script.onload = () => {
window.MedosAppointmentCalendar.init({
containerId: "appointment-widget",
apiKey: "your-api-key",
});
};
document.head.appendChild(script);
}
}
// Load on user interaction
document
.getElementById("book-appointment-btn")
.addEventListener("click", loadWidget);Resource Optimization:
<!-- Preload critical resources -->
<link rel="preload" href="path/to/widget.css" as="style" />
<link rel="preload" href="path/to/widget.js" as="script" />
<!-- Use appropriate CSS file for your needs -->
<!-- widget.css for basic theming (smaller file) -->
<link rel="stylesheet" href="dist/vanilla/widget.css" />
<!-- widget-themed.css for advanced theming (larger file) -->
<link rel="stylesheet" href="dist/vanilla/widget-themed.css" />Getting Help
If you encounter issues not covered in this guide:
- Check Browser Console: Look for error messages and warnings
- Verify Network Tab: Check if API requests are successful
- Test with Examples: Compare with working examples in
examples/directory - Check Version Compatibility: Ensure you're using compatible versions
- Review Documentation: Check
docs/VANILLA_WIDGET.mdfor additional details
Common Error Messages:
"Container element not found"→ CheckcontainerIdparameter"Invalid API key"→ Verify API key or use session token"Network request failed"→ Check internet connection and API status"Widget already initialized"→ Clear container before reinitializing"Theme variables not applied"→ Check CSS specificity and variable names
Package Exports
The SDK provides multiple entry points for different use cases:
medos-sdk- Default export (includes React components)medos-sdk/react- React-specific exportsmedos-sdk/vanilla- Vanilla JS exports (ES modules)medos-sdk/core- Core services only (no framework dependencies)medos-sdk/widget- Widget bundle with CSS
Examples and Documentation
Comprehensive examples and documentation are available:
HTML Examples (examples/ directory)
vanilla-appointment-booking.html- Basic appointment widget with local filescdn-appointment-booking.html- CDN integration example with fallback strategiesenquiry-form.html- Enquiry form widget with both local and CDN optionstheme-customization-basic.html- Basic CSS variable overrides and themingtheme-customization-advanced.html- Advanced theming with multiple theme comparisonstheme-customization-javascript.html- Dynamic theme switching and programmatic themingtheme-comparison.html- Side-by-side comparison of CSS filesenquiry-form-theming.html- Enquiry form specific theming examples
Documentation (docs/ directory)
VANILLA_WIDGET.md- Comprehensive vanilla widget documentationCDN_INTEGRATION.md- Complete CDN integration guide with best practicesBUILD.md- Build system and development setupIMPLEMENTATION_STATUS.md- Current implementation status and roadmap
Theme Documentation
examples/README-THEME-CUSTOMIZATION.md- Complete theming guide with examples- CSS variable reference for both
widget.cssandwidget-themed.css - Dynamic theme switching examples and best practices
API Reference
MedosClient
init(config)
Initialize the SDK with an API key (server-side).
Parameters:
config.apiKey(string, required) - Your Medos API keyconfig.baseURL(string, optional) - API base URL. Defaults to dev environment
Returns: Promise<void>
initWithSession(config)
Initialize the SDK with a session token (client-side).
Parameters:
config.sessionToken(string, required) - Session tokenconfig.baseURL(string, optional) - API base URL. Defaults to dev environment
Returns: Promise<void>
fetchAllAddressesAndDoctors()
Fetch all clinic addresses and their associated doctors.
Returns: Promise<AddressesResponse>
Response Type:
{
totalAddresses?: number;
totalDoctors?: number;
workspaceId?: number | string;
addresses: Array<{
id: string;
completeAddress?: string;
addressLine1?: string;
city?: string;
state?: string;
country?: string;
zipcode?: string;
doctors?: Array<{
id: string;
name: string;
email?: string;
specialty?: string;
}>;
}>;
}fetchAppointments(workspaceId, addressId, doctorId, appointmentDate)
Fetch available appointment slots for a specific doctor.
Parameters:
workspaceId(string | number) - Workspace identifieraddressId(string | number) - Address identifierdoctorId(string | number) - Doctor identifierappointmentDate(string) - Date in YYYY-MM-DD format
Returns: Promise<Slot[]>
Response Type:
Array<{
start: string; // ISO datetime format
end: string; // ISO datetime format
id?: string;
}>;sendPhoneVerificationOtp(payload)
Send OTP to a phone number for verification.
Parameters:
payload.countryCode(string) - Country code with + prefix (e.g., "+1")payload.phoneNumber(string) - Phone number without country code
Returns: Promise<any>
verifyPhoneVerificationOtp(payload)
Verify OTP for a phone number.
Parameters:
payload.countryCode(string) - Country code with + prefixpayload.phoneNumber(string) - Phone number without country codepayload.otp(string) - OTP code received
Returns: Promise<any>
AppointmentService
createAppointment(payload)
Create a new appointment booking.
Parameters:
payload(BookAppointmentPayload) - Appointment details
Returns: Promise<any>
Error Handling
All SDK methods return Promises and should be wrapped in try-catch blocks.
try {
await MedosClient.init({ apiKey: "your-api-key" });
const addresses = await MedosClient.fetchAllAddressesAndDoctors();
} catch (error) {
console.error("Failed to fetch addresses:", error.message);
}Requirements
- Node.js: v14 or higher
- Browsers: Modern browsers with ES6+ support
- React: v19 or higher (only required for React components, not for vanilla widget)
- TypeScript: v5 or higher (optional)
Support
For bug reports and feature requests, please visit our GitHub Issues.
License
UNLICENSED
Author
Pooranjoy Bhattacharya
Built for healthcare providers worldwide.
