API Documentation
Getting Started
The SmartScanPro.ai API is a powerful medical device data extraction service that uses advanced AI to process images of medical devices and extract actionable data in JSON format.
Base URL
https://api.smartscanpro.ai
Quick Setup
- Register for an account at
register.html - Create a project in the dashboard
- Get your API key from the dashboard
- Start making API calls with your key
Minimum Requirements
- Image Format: JPEG, PNG, GIF, WebP
- Image Size: Maximum 10MB
- Authentication: API key required
- Content Type: multipart/form-data
Authentication
The SmartScanPro.ai API uses API key authentication for all requests.
API Key Authentication
Include your API key in the request headers:
X-API-Key: dk_your_api_key_here
Or as a query parameter:
https://api.smartscanpro.ai/v1/extract-medical-data?api_key=dk_your_api_key_here
Getting Your API Key
- Register at
register.html - Login to your dashboard at
dashboard.html - Navigate to "API Keys" section
- Generate a new API key
- Copy and securely store your key
API Endpoints
Medical Data Extraction
/api/v1/extract-medical-data
Extract medical device data from images using advanced AI.
Headers:
X-API-Key: dk_your_api_key_here
Content-Type: multipart/form-data
Parameters:
image(file, required): Medical device imagedevice_type(string, optional): Device type hintconfidence_threshold(number, optional): Minimum confidence (0.0-1.0)
Device Information
/api/device-types
Get list of supported device types.
Health Check
/api/health
Check API health status.
Dashboard API Endpoints
User Management
- GET
/api/auth/profile - PUT
/api/auth/profile
Projects
- GET
/api/projects - POST
/api/projects - GET
/api/projects/:id
Usage Analytics
- GET
/api/dashboard/stats - GET
/api/usage/analytics - GET
/api/usage/logs
API Keys
- GET
/api/api-keys - POST
/api/api-keys/generate
Supported Devices & Documents
The SmartScanPro.ai API supports 15 different types of medical devices and documents:
Medical Devices (12 Types)
Blood Pressure Monitors
Device Type: blood-pressure
Extracted Data:
- Systolic pressure (top number, mmHg)
- Diastolic pressure (bottom number, mmHg)
- Pulse rate (PR/PULSE, BPM)
- Mean arterial pressure (if calculated)
- Pulse pressure (if calculated)
- Measurement timestamp
- Battery status/indicators
- Memory readings (if displayed)
- User profile (if multi-user device)
- Irregular heartbeat indicators
- Cuff pressure indicators
- Error codes or warnings
Supported Brands: Omron, Withings, A&D Medical, Beurer, Generic monitors
Digital Scales
Device Type: scale
Extracted Data:
- Weight measurement (kg, lb, lbs, st, oz)
- BMI calculation (if height programmed)
- Body fat percentage (%)
- Muscle mass (kg, lbs)
- Bone mass (kg, lbs)
- Water percentage (%)
- Visceral fat rating
- Metabolic age
- Protein percentage
- Basal metabolic rate (BMR)
- User profile/memory slot
- Measurement timestamp
- Battery indicators
- Trend indicators (up/down arrows)
Supported Brands: Withings, Fitbit Aria, Tanita, Renpho, Eufy, Generic smart scales
Glucose Meters
Device Type: glucose-meter
Extracted Data:
- Blood glucose level (main reading)
- Unit (mg/dL, mmol/L)
- Measurement date and time
- Test strip lot number
- Control solution results (if visible)
- Memory readings/averages (7-day, 14-day, 30-day)
- Before/after meal indicators
- High/low glucose alerts
- Ketone readings (if meter supports)
- Temperature compensation
- Battery level indicators
- Error codes or messages
- User ID (if multi-user)
- Alternate site testing indicators
Supported Brands: Accu-Chek, OneTouch, FreeStyle, Contour, Bayer, Generic meters
Pulse Oximeters
Device Type: pulse-oximeter
Extracted Data:
- Oxygen saturation (SpO2 percentage)
- Pulse rate (PR/pulse, BPM)
- Perfusion index (PI)
- Plethysmographic waveform quality
- Signal strength indicators
- Low perfusion alerts
- Motion artifact detection
- Pulse amplitude
- Measurement timestamp
- Battery level indicators
- Sensor off/probe off alerts
- Adult/pediatric/neonatal mode
- Alarm limits (high/low SpO2, pulse)
- Trend data (if displayed)
Supported Brands: Masimo, Nonin, Contec, Zacurate, Innovo, Generic oximeters
Digital Thermometers
Device Type: thermometer
Extracted Data:
- Body temperature value
- Unit (°C, °F)
- Measurement location (oral, rectal, axillary, forehead, ear)
- Fever indicators/alerts
- Normal temperature range indicators
- Age-specific fever thresholds
- Memory readings (last measurement)
- Measurement timestamp
- Battery level indicators
- Probe cover detection
- Environmental temperature compensation
- Error codes (probe error, ambient temp, etc.)
- Calibration status
- Auto-shutoff indicators
Supported Brands: Braun, Omron, iHealth, Kinsa, Vicks, Generic digital thermometers
Peak Flow Meters
Device Type: peak-flow-meter
Extracted Data:
- Peak expiratory flow rate (PEFR in L/min)
- Personal best percentage (if displayed)
- Zone indicators (green/yellow/red traffic light)
- Age/height predicted values
- Previous reading comparisons
- Average readings (daily, weekly)
- Measurement timestamp
- Patient age/height settings
- Medication timing indicators
- Asthma action plan zone
- Memory storage indicators
- Low flow alerts
- Calibration status
- Unit settings (L/min, L/sec)
Supported Brands: Clement Clarke, Respironics, Omron, Vitalograph, Microlife
ECG Monitors
Device Type: ecg-monitor
Extracted Data:
- Heart rate (HR or BPM)
- Rhythm classification (normal sinus, atrial fibrillation, etc.)
- QT/QTc intervals (if displayed)
- Lead configuration (Lead I, II, III, aVR, aVL, aVF)
- P-wave analysis
- QRS complex duration
- ST segment analysis
- T-wave morphology
- Arrhythmia detection
- Heart rate variability (HRV)
- Measurement timestamp
- Recording duration
- Signal quality indicators
- Battery status
- Electrode contact status
- Artifact detection
Supported Brands: AliveCor, Omron HeartScan, EMAY, CheckMe, Wellue, Generic portable ECGs
Vaccine Certificates
Device Type: vaccine-certificate
Extracted Data:
- Patient name and demographics
- Date of birth or age
- Vaccine name/type (specific vaccine identification)
- Vaccine manufacturer (Pfizer, Moderna, etc.)
- Vaccination date(s)
- Lot number/batch number
- Healthcare provider/clinic name
- Administrator name (who gave vaccine)
- Next due date (if applicable)
- Dose number (1st, 2nd, 3rd, booster, annual)
- Route of administration (IM, oral, nasal)
- Site of injection (left/right arm, thigh)
- Expiration date of vaccine
- VIS (Vaccine Information Statement) date
- Patient consent indicators
Supported Types: COVID-19, Influenza, Hepatitis, MMR, Travel vaccines, Childhood immunizations, ALL vaccine types
Dialysis Machines
Device Type: dialysis-machine
Extracted Data:
- Treatment time (hours:minutes)
- Ultrafiltration rate (UF rate in mL/hr or L/hr)
- Blood flow rate (QB in mL/min)
- Dialysate flow rate (QD in mL/min)
- Transmembrane pressure (TMP in mmHg)
- Venous pressure (VP in mmHg)
- Arterial pressure (AP in mmHg)
- Fluid removal goal (in L or mL)
- Kt/V ratio (dialysis adequacy)
- Treatment status (running, paused, complete)
- Total fluid removed
- Conductivity readings
- Temperature settings
- Heparin dosing (if displayed)
- Access pressure monitoring
- Alarm status and alerts
- Patient dry weight
- Session start/end times
Supported Brands: Fresenius, Baxter, B. Braun, Nipro, Gambro, Generic dialysis equipment
Pregnancy Test Kits
Device Type: pregnancy-kit
Extracted Data:
- Test result (positive, negative, invalid)
- Test type (digital, strip, cassette)
- Control line status (visible, not visible, faint)
- Test line intensity/visibility (faint, strong, clear)
- Test date/time (if visible on device)
- Brand name and model
- Weeks indicator (if digital test shows weeks since conception)
- Error codes or messages
- Test validity indicators
- Lot number/batch information
- Expiration date
- Test timing (minutes to read)
- Sample type indicators
- Sensitivity level (mIU/mL)
Supported Types: Digital tests, strip tests, cassette tests, early detection tests, all major brands
5-Parameter Monitors
Device Type: 5para-monitor
Extracted Data:
- Heart rate (HR in bpm)
- Blood pressure (systolic/diastolic in mmHg)
- Oxygen saturation (SpO2 in %)
- Respiratory rate (RR in breaths/min)
- Body temperature (TEMP in °C or °F)
- Mean arterial pressure (MAP in mmHg)
- Pulse pressure (calculated)
- Alarm indicators and alerts
- Lead configuration (for ECG component)
- Waveform quality indicators
- NIBP (non-invasive blood pressure) cycle time
- SpO2 sensor status
- Temperature probe type
- Patient information display
- Trend data (if available)
- Timestamp information
- Device status and connectivity
Supported Brands: Philips, GE Healthcare, Mindray, Nihon Kohden, Masimo, Generic patient monitors
COVID Test Strips
Device Type: covid-test-strip
Extracted Data:
- Test result (positive, negative, invalid, inconclusive)
- Test type (rapid antigen, lateral flow, PCR, etc.)
- Brand/manufacturer (Abbott, Quidel, BD, iHealth, etc.)
- Control line status (visible, not visible, faint)
- Test line status (visible, not visible, faint, strong)
- Test date/time (if visible on device or packaging)
- Lot number/batch number (if visible)
- Expiration date (if visible)
- Test window timing (e.g., "15 minutes")
- Error codes or invalid result indicators
- Sample type (nasal swab, saliva, etc.)
- Sensitivity/specificity information (if visible)
- Test kit serial number
- Storage temperature indicators
- QR codes or digital verification
Supported Types: Rapid antigen (BinaxNOW, FlowFlex, QuickVue), lateral flow, home test kits, professional tests
Medical Documents (3 Types)
Prescription Documents
Document Type: prescription
Extracted Data:
- Patient information (name, DOB, address, phone)
- Prescriber information (name, NPI, DEA number, address)
- Pharmacy information (if pre-filled)
- Date prescribed/written
- Drug name (generic and brand names)
- Strength/dosage (mg, ml, units, etc.)
- Quantity prescribed
- Directions for use/Sig (frequency, timing)
- Number of refills allowed
- Days supply
- NDC number (if visible)
- Diagnosis/indication (if mentioned)
- Special instructions or notes
- Controlled substance information
- Generic substitution allowance (DAW codes)
Discharge Summaries
Document Type: discharge-summary
Extracted Data:
- Patient demographics (name, DOB, MRN)
- Admission/discharge dates
- Admitting diagnosis and primary diagnosis
- Secondary diagnoses and comorbidities
- Procedures performed during stay
- Hospital course summary
- Discharge medications with instructions
- New vs. continued medications
- Follow-up appointments and instructions
- Activity restrictions or recommendations
- Diet instructions
- Discharge disposition (home, rehab, SNF)
- Attending physician and consultants
- Vital signs at discharge
- Lab values at discharge
- Wound care instructions
- Signs/symptoms to watch for
Clinical Notes
Document Type: clinical-notes
Extracted Data:
- Patient information (name, DOB, MRN)
- Date and time of visit/note
- Provider information (physician, nurse, etc.)
- Visit type (office visit, hospital round, consultation)
- Chief complaint or reason for visit
- History of Present Illness (HPI)
- Review of Systems (ROS) findings
- Physical examination findings
- Vital signs (BP, HR, temp, RR, O2 sat, weight, height)
- General appearance
- System-specific findings (cardiac, pulmonary, etc.)
- Assessment and Plan by diagnosis
- Treatment plans
- Medications prescribed or adjusted
- Diagnostic tests ordered
- Follow-up plans
- Current medications list
- Allergies
- Social/family history updates
- Immunizations given
Response Format
All API responses follow a consistent JSON format:
Success Response
{
"success": true,
"data": {
"device_type": "blood-pressure",
"confidence": 0.95,
"extracted_data": {
"systolic": 120,
"diastolic": 80,
"pulse": 72,
"unit": "mmHg",
"timestamp": "2024-01-15T10:30:00Z"
},
"processing_time_ms": 1250,
"image_info": {
"width": 1920,
"height": 1080,
"format": "JPEG",
"size_bytes": 245760
}
}
}
Response Fields
- success (boolean): Indicates if the request was successful
- data (object): Contains the extracted information
- device_type (string): Detected device type
- confidence (float): AI confidence score (0.0-1.0)
- extracted_data (object): Device-specific measurements
- processing_time_ms (integer): Processing duration
- image_info (object): Image metadata
Device-Specific Data Examples
Blood Pressure Monitor
{
"systolic": 120,
"diastolic": 80,
"pulse": 72,
"unit": "mmHg",
"pulseUnit": "bpm",
"meanArterialPressure": 93,
"pulsePressure": 40,
"timestamp": "2024-01-15T10:30:00Z",
"batteryStatus": "normal",
"irregularHeartbeat": false,
"userProfile": 1,
"memoryReading": false
}
Digital Scale
{
"weight": 75.2,
"unit": "kg",
"bmi": 22.1,
"bodyFatPercentage": 15.2,
"muscleMass": 32.5,
"boneMass": 3.2,
"waterPercentage": 58.7,
"visceralFatRating": 8,
"metabolicAge": 28,
"basalMetabolicRate": 1650,
"userProfile": 2,
"timestamp": "2024-01-15T07:00:00Z",
"batteryLevel": "high",
"trend": "stable"
}
Glucose Meter
{
"glucoseLevel": 95,
"unit": "mg/dL",
"timestamp": "2024-01-15T08:15:00Z",
"testStripLot": "ABC123",
"mealIndicator": "before_meal",
"averages": {
"7day": 98,
"14day": 102,
"30day": 105
},
"highLowAlert": "normal",
"batteryLevel": "good",
"temperatureCompensation": true,
"userId": 1,
"memorySlot": 45
}
Pulse Oximeter
{
"oxygenSaturation": 98,
"pulse": 65,
"perfusionIndex": 12.5,
"signalStrength": "strong",
"waveformQuality": "good",
"lowPerfusionAlert": false,
"motionArtifact": false,
"pulseAmplitude": 2.8,
"sensorStatus": "connected",
"patientMode": "adult",
"alarmLimits": {
"spo2Low": 90,
"spo2High": 100,
"pulseLow": 50,
"pulseHigh": 120
},
"timestamp": "2024-01-15T09:45:00Z",
"batteryLevel": "medium"
}
Digital Thermometer
{
"temperature": 36.8,
"unit": "°C",
"location": "oral",
"feverIndicator": false,
"normalRange": "36.1-37.2°C",
"memoryReading": "last: 36.9°C",
"timestamp": "2024-01-15T07:45:00Z",
"batteryLevel": "good",
"probeCover": "detected",
"calibrationStatus": "valid",
"environmentalCompensation": true,
"autoShutoff": "2min"
}
Peak Flow Meter
{
"peakFlowRate": 420,
"unit": "L/min",
"personalBest": 495,
"personalBestPercentage": 85,
"zone": "yellow",
"predictedValue": 480,
"previousReading": 435,
"averageReadings": {
"daily": 425,
"weekly": 418
},
"patientAge": 35,
"patientHeight": 175,
"asthmaActionPlan": "yellow_zone",
"timestamp": "2024-01-15T11:15:00Z",
"calibrationDate": "2024-01-01"
}
ECG Monitor
{
"heartRate": 68,
"rhythm": "normal_sinus",
"qtInterval": 380,
"qtcInterval": 410,
"leadConfig": "lead_I",
"pWaveAnalysis": "normal",
"qrsDuration": 95,
"stSegment": "normal",
"tWave": "normal",
"arrhythmiaDetection": "none",
"heartRateVariability": 45,
"recordingDuration": "30s",
"signalQuality": "excellent",
"electrodeContact": "good",
"artifactDetection": "minimal",
"timestamp": "2024-01-15T12:30:00Z",
"batteryStatus": "75%"
}
Vaccine Certificate
{
"patientName": "John Doe",
"dateOfBirth": "1985-03-15",
"vaccineName": "COVID-19 mRNA Vaccine",
"manufacturer": "Pfizer-BioNTech",
"vaccinationDate": "2024-01-10",
"lotNumber": "ABC123",
"administrator": "Dr. Smith",
"healthcareProvider": "City Medical Center",
"doseNumber": 2,
"routeOfAdministration": "intramuscular",
"injectionSite": "left deltoid",
"nextDueDate": "2024-07-10",
"visDate": "2023-12-01",
"vaccineExpiration": "2024-06-30"
}
Dialysis Machine
{
"treatmentTime": "4:00",
"bloodFlowRate": 350,
"dialysateFlowRate": 500,
"ultrafiltrationRate": 800,
"transmembranePressure": 150,
"venousPressure": 120,
"arterialPressure": -80,
"fluidRemovalGoal": 2.5,
"ktVRatio": 1.4,
"treatmentStatus": "running",
"totalFluidRemoved": 1.8,
"conductivity": 14.0,
"temperature": 37.0,
"patientDryWeight": 72.7,
"sessionStartTime": "08:00",
"accessPressure": 165,
"alarmStatus": "none"
}
Pregnancy Test Kit
{
"testResult": "positive",
"testType": "digital",
"weeksIndicator": 3,
"controlLine": "visible",
"testLine": "strong",
"testDate": "2024-01-15T08:00:00Z",
"brandName": "Clearblue Digital",
"lotNumber": "LOT123",
"expirationDate": "2025-01-15",
"testTiming": "3",
"testValidity": "valid",
"sensitivityLevel": "25mIU/mL",
"sampleType": "urine"
}
5-Parameter Monitor
{
"heartRate": 78,
"systolic": 125,
"diastolic": 82,
"oxygenSaturation": 97,
"respiratoryRate": 16,
"temperature": 37.1,
"meanArterialPressure": 96,
"pulsePressure": 43,
"alarmIndicators": "none",
"leadConfiguration": "3-lead",
"waveformQuality": "good",
"nibpCycleTime": "auto",
"spo2SensorStatus": "connected",
"temperatureProbe": "core",
"patientInfo": "Bed 12A",
"timestamp": "2024-01-15T10:15:00Z",
"deviceStatus": "monitoring"
}
COVID Test Strip
{
"testResult": "negative",
"testType": "rapid antigen",
"manufacturer": "Abbott BinaxNOW",
"controlLine": "visible",
"testLine": "not visible",
"testDate": "2024-01-15T08:30:00Z",
"lotNumber": "ABC123",
"expirationDate": "2024-12-31",
"testTiming": "15",
"sampleType": "nasal swab",
"sensitivity": "84.6%",
"specificity": "98.5%",
"serialNumber": "BNX789",
"storageTemp": "2-30°C",
"qrCode": "detected"
}
Prescription Document
{
"patientName": "Jane Smith",
"patientDOB": "1980-05-20",
"patientAddress": "123 Main St",
"prescriber": "Dr. Johnson",
"prescriberNPI": "1234567890",
"prescriberDEA": "BJ1234567",
"pharmacy": "CVS Pharmacy",
"datePrescribed": "2024-01-15",
"medication": "Lisinopril",
"genericName": "Lisinopril",
"brandName": "Prinivil",
"strength": "10mg",
"quantity": 30,
"directions": "Take 1 tablet daily by mouth",
"refills": 5,
"daysSupply": 30,
"ndcNumber": "12345-678-90",
"diagnosis": "Hypertension",
"genericSubstitution": "allowed"
}
Discharge Summary
{
"patientName": "Robert Brown",
"patientDOB": "1965-08-12",
"medicalRecordNumber": "MRN123456",
"admissionDate": "2024-01-10",
"dischargeDate": "2024-01-15",
"primaryDiagnosis": "Acute Myocardial Infarction",
"secondaryDiagnoses": ["Diabetes Type 2", "Hypertension"],
"procedures": ["Cardiac catheterization", "Stent placement"],
"attendingPhysician": "Dr. Williams",
"dischargeMedications": "Aspirin 81mg daily, Metoprolol 50mg BID",
"followUp": "Cardiology clinic in 1 week",
"activityRestrictions": "No lifting >10lbs",
"dietInstructions": "Low sodium, cardiac diet",
"disposition": "Home with family",
"vitalSignsAtDischarge": "BP: 128/78, HR: 68",
"condition": "Stable"
}
Clinical Notes
{
"patientName": "Mary Johnson",
"patientDOB": "1975-11-03",
"medicalRecordNumber": "MRN789012",
"visitDate": "2024-01-15",
"visitTime": "14:30",
"provider": "Dr. Davis",
"visitType": "office visit",
"chiefComplaint": "Chest pain",
"historyOfPresentIllness": "3-day history of chest discomfort",
"reviewOfSystems": "Positive for chest pain, negative for SOB",
"physicalExam": "Heart regular rate and rhythm",
"vitalSigns": "BP: 130/85, HR: 72, Temp: 36.8°C, RR: 16, O2: 98%",
"assessment": "Stable angina",
"plan": "Continue current medications, stress test in 2 weeks",
"medications": "Atorvastatin 40mg daily, Metoprolol 25mg BID",
"allergies": "NKDA",
"followUp": "Return in 2 weeks"
}
Error Handling
Error Response Format
{
"success": false,
"error": "Error description",
"error_code": "ERROR_CODE",
"details": {
"field": "Additional error information"
}
}
HTTP Status Codes
| Status Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid or missing API key |
| 403 | Forbidden - Rate limit exceeded |
| 413 | Payload Too Large - Image exceeds size limit |
| 415 | Unsupported Media Type - Invalid image format |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error |
Common Error Codes
Authentication Errors
INVALID_API_KEY: API key is invalid or expiredMISSING_API_KEY: No API key providedRATE_LIMIT_EXCEEDED: Too many requests
Image Processing Errors
INVALID_IMAGE_FORMAT: Unsupported image formatIMAGE_TOO_LARGE: Image exceeds size limitIMAGE_PROCESSING_FAILED: Failed to process image
Data Extraction Errors
LOW_CONFIDENCE: Extraction confidence below thresholdUNREADABLE_DISPLAY: Cannot read device displayNO_DEVICE_DETECTED: No medical device found
success field before processing response data.
Rate Limits
Default Limits
| Plan | Requests/Hour | Requests/Day | Requests/Month |
|---|---|---|---|
| Free | 100 | 1,000 | 10,000 |
| Basic | 1,000 | 10,000 | 100,000 |
| Pro | 5,000 | 50,000 | 500,000 |
| Enterprise | Custom | Custom | Custom |
Rate Limit Headers
All responses include rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642248000
X-RateLimit-Window: 3600
Rate Limit Exceeded Response
{
"success": false,
"error": "Rate limit exceeded",
"error_code": "RATE_LIMIT_EXCEEDED",
"details": {
"limit": 1000,
"window_seconds": 3600,
"reset_time": "2024-01-15T11:00:00Z"
}
}
Best Practices
- Monitor Headers: Check rate limit headers in responses
- Implement Backoff: Use exponential backoff for retries
- Cache Results: Cache successful extractions when possible
- Batch Processing: Process multiple images efficiently
- Upgrade Plan: Consider upgrading for higher limits
Code Examples
JavaScript/Node.js
const fs = require('fs');
const FormData = require('form-data');
async function extractMedicalData(imagePath, deviceType = null) {
const form = new FormData();
form.append('image', fs.createReadStream(imagePath));
if (deviceType) {
form.append('device_type', deviceType);
}
try {
const response = await fetch('https://api.smartscanpro.ai/v1/extract-medical-data', {
method: 'POST',
headers: {
'X-API-Key': process.env.SMARTSCANPRO_API_KEY,
...form.getHeaders()
},
body: form
});
const result = await response.json();
if (result.success) {
console.log('Extracted data:', result.data.extracted_data);
return result.data;
} else {
console.error('Extraction failed:', result.error);
return null;
}
} catch (error) {
console.error('Request failed:', error);
return null;
}
}
// Usage
extractMedicalData('./blood_pressure_reading.jpg', 'blood-pressure')
.then(data => {
if (data) {
const extracted = data.extracted_data;
console.log(`Blood Pressure: ${extracted.systolic}/${extracted.diastolic} mmHg`);
console.log(`Pulse: ${extracted.pulse} BPM`);
}
});
Python
import requests
import os
class SmartScanProClient:
def __init__(self, api_key, base_url="https://api.smartscanpro.ai"):
self.api_key = api_key
self.base_url = base_url
def extract_medical_data(self, image_path, device_type=None, confidence_threshold=None):
"""Extract medical data from device image."""
url = f"{self.base_url}/v1/extract-medical-data"
headers = {"X-API-Key": self.api_key}
files = {"image": open(image_path, "rb")}
data = {}
if device_type:
data["device_type"] = device_type
if confidence_threshold:
data["confidence_threshold"] = confidence_threshold
try:
response = requests.post(url, headers=headers, files=files, data=data)
result = response.json()
if result.get("success"):
return result["data"]
else:
raise Exception(f"API Error: {result.get('error', 'Unknown error')}")
except requests.exceptions.RequestException as e:
raise Exception(f"Request failed: {str(e)}")
finally:
files["image"].close()
# Usage
client = SmartScanProClient(os.getenv("SMARTSCANPRO_API_KEY"))
try:
data = client.extract_medical_data(
"blood_pressure_reading.jpg",
device_type="blood-pressure"
)
extracted = data["extracted_data"]
print(f"Blood Pressure: {extracted['systolic']}/{extracted['diastolic']} {extracted['unit']}")
print(f"Pulse: {extracted['pulse']} BPM")
print(f"Confidence: {data['confidence']:.2%}")
except Exception as e:
print(f"Error: {e}")
cURL
# Basic request
curl -X POST \
https://api.smartscanpro.ai/v1/extract-medical-data \
-H "X-API-Key: dk_your_api_key_here" \
-F "image=@blood_pressure_reading.jpg" \
-F "device_type=blood-pressure"
# With confidence threshold
curl -X POST \
https://api.smartscanpro.ai/v1/extract-medical-data \
-H "X-API-Key: dk_your_api_key_here" \
-F "image=@glucose_reading.jpg" \
-F "device_type=glucose-meter" \
-F "confidence_threshold=0.8"
React Hook
import { useState, useCallback } from 'react';
export const useSmartScanProAPI = (apiKey) => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const extractData = useCallback(async (imageFile, options = {}) => {
setLoading(true);
setError(null);
try {
const formData = new FormData();
formData.append('image', imageFile);
if (options.deviceType) {
formData.append('device_type', options.deviceType);
}
const response = await fetch('/api/v1/extract-medical-data', {
method: 'POST',
headers: {
'X-API-Key': apiKey
},
body: formData
});
const result = await response.json();
if (!result.success) {
throw new Error(result.error);
}
return result.data;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
}, [apiKey]);
return { extractData, loading, error };
};
// Component usage
export const MedicalDeviceUploader = () => {
const { extractData, loading, error } = useSmartScanProAPI(process.env.REACT_APP_API_KEY);
const [result, setResult] = useState(null);
const handleFileUpload = async (event) => {
const file = event.target.files[0];
if (!file) return;
try {
const data = await extractData(file, {
deviceType: 'blood-pressure'
});
setResult(data);
} catch (err) {
console.error('Upload failed:', err);
}
};
return (
{loading && Processing image...
}
{error && Error: {error}
}
{result && (
Extracted Data:
{JSON.stringify(result.extracted_data, null, 2)}
)}
);
};
JavaScript SDK
A zero-dependency SDK for browser and Node.js that wraps every SmartScanPro API endpoint in a clean, promise-based interface. Copy-paste the integration examples below to get running in minutes.
How Authentication Works
The SDK supports two auth modes depending on where your code runs:
Browser (Frontend)
Auth method: Email + password → JWT token
The user logs in with their credentials. The SDK receives a short-lived JWT and attaches it as Authorization: Bearer <token> on every request. No API key is needed or exposed.
- Token stored in memory by default
- Enable
persistToken: trueto survive page reloads (uses localStorage) - Auto-clears on 401 and fires
onTokenExpiredcallback
Node.js (Backend)
Auth method: API key (X-API-Key header)
Your server holds the API key securely in an environment variable. The SDK attaches it on extraction endpoints. Use the proxy pattern to keep keys off the client.
- API key never leaves your server
- Can proxy requests for frontend clients
- Supports both API key and JWT simultaneously
Installation
Browser (script tag)
<script src="https://api.smartscanpro.ai/js/smartscanpro-sdk.js"></script>
<script>
const client = new SmartScanPro({
baseUrl: 'https://api.smartscanpro.ai'
});
</script>Node.js (CommonJS)
const SmartScanPro = require('./smartscanpro-sdk');
const client = new SmartScanPro({
baseUrl: 'https://api.smartscanpro.ai',
apiKey: process.env.SMARTSCANPRO_API_KEY
});ES Modules
import SmartScanPro from './smartscanpro-sdk.js';
const client = new SmartScanPro({
baseUrl: 'https://api.smartscanpro.ai'
});Configuration
| Option | Type | Default | Description |
|---|---|---|---|
baseUrl | string | required | API base URL (e.g. https://api.smartscanpro.ai) |
apiKey | string | null | API key for medical-data extraction endpoints (X-API-Key header) |
authToken | string | null | JWT token for authenticated endpoints (Authorization: Bearer header) |
persistToken | boolean | false | Store JWT in localStorage so it survives page reloads |
storageKey | string | 'ssp_token' | localStorage key used when persistToken is enabled |
onTokenExpired | function | null | Callback fired when a 401 response clears the stored token |
Integration Example — Login Page
A complete login form that authenticates via the SDK and redirects to the dashboard on success.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login -- MyClinic</title>
<script src="https://api.smartscanpro.ai/js/smartscanpro-sdk.js"></script>
</head>
<body>
<form id="loginForm">
<h2>Sign In</h2>
<input id="email" type="email" placeholder="Email" required />
<input id="password" type="password" placeholder="Password" required />
<button type="submit">Log In</button>
<p id="error" style="color:red; display:none;"></p>
</form>
<script>
const client = new SmartScanPro({
baseUrl: 'https://api.smartscanpro.ai',
persistToken: true // survive page reloads
});
document.getElementById('loginForm').addEventListener('submit', async (e) => {
e.preventDefault();
const errorEl = document.getElementById('error');
errorEl.style.display = 'none';
try {
await client.login(
document.getElementById('email').value,
document.getElementById('password').value
);
// Token is now stored — redirect to dashboard
window.location.href = '/dashboard.html';
} catch (err) {
errorEl.textContent = err.status === 401
? 'Invalid email or password.'
: 'Something went wrong. Please try again.';
errorEl.style.display = 'block';
}
});
</script>
</body>
</html>Integration Example — Protected Dashboard
A dashboard page that restores the session, guards against unauthenticated access, loads user data, and provides a logout button.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dashboard -- MyClinic</title>
<script src="https://api.smartscanpro.ai/js/smartscanpro-sdk.js"></script>
</head>
<body>
<nav>
<span id="greeting"></span>
<button id="logoutBtn">Log Out</button>
</nav>
<main id="content">Loading...</main>
<script>
const client = new SmartScanPro({
baseUrl: 'https://api.smartscanpro.ai',
persistToken: true,
onTokenExpired: () => {
alert('Session expired. Please log in again.');
window.location.href = '/login.html';
}
});
// Guard — redirect if not authenticated
if (!client.isAuthenticated()) {
window.location.href = '/login.html';
}
(async () => {
try {
// Load user info
const me = await client.getMe();
document.getElementById('greeting').textContent =
'Welcome, ' + me.user.email;
// Load patient profile
const profile = await client.getProfile();
document.getElementById('content').innerHTML =
'<h2>Your Profile</h2>' +
'<p>Age: ' + (profile.profile.age || 'N/A') + '</p>' +
'<p>Sex: ' + (profile.profile.biological_sex || 'N/A') + '</p>';
} catch (err) {
document.getElementById('content').textContent =
'Failed to load data: ' + err.message;
}
})();
// Logout
document.getElementById('logoutBtn').addEventListener('click', () => {
client.logout(); // clears token from memory + localStorage
window.location.href = '/login.html';
});
</script>
</body>
</html>Integration Example — Face Scan with Results
End-to-end flow: create a session, record consent, update the profile, submit vitals for preview, display vital cards, then save and fetch risk scores + FHIR bundle.
// Assumes `client` is already authenticated (see Example 1 & 2)
// -- Step 1: Create session & record consent ------------------
const session = await client.createScanSession();
const sid = session.session.id;
await client.recordConsent(sid, 'us',
'I consent to the collection of my biometric data for health analysis.');
// -- Step 2: Update patient profile ---------------------------
await client.updateProfile({
age: 42,
biological_sex: 'female',
height_cm: 165,
weight_kg: 68
});
// -- Step 3: Submit vitals (preview -- not saved yet) ----------
const vitals = {
heart_rate: 74,
hrv_sdnn: 48.3,
hrv_rmssd: 40.1,
breathing_rate: 15,
spo2: 98,
systolic_bp: 120,
diastolic_bp: 78,
stress_index: 35.7,
wellness_score: 82
};
const preview = await client.submitScanResults(sid, vitals, 0.88, false);
// save: false -> results returned but NOT persisted
// -- Step 4: Display vital cards ------------------------------
const container = document.getElementById('vitals');
preview.results.forEach(r => {
container.innerHTML += `
<div class="device-card">
<strong>${r.vital_name}</strong>: ${r.value} ${r.unit}
</div>`;
});
// -- Step 5: User clicks "Save" -> persist + fetch risk --------
document.getElementById('saveBtn').addEventListener('click', async () => {
// Save results permanently
await client.submitScanResults(sid, vitals, 0.88, true);
// Fetch risk scores
const risk = await client.getRiskScores(sid);
console.log('CV Risk:', risk.riskScores.cardiovascularRisk.score);
console.log('Vascular Age:', risk.riskScores.vascularAge.vascularAge);
// Fetch FHIR R4 Bundle
const fhir = await client.getFHIRBundle(sid);
console.log('FHIR entries:', fhir.bundle.entry.length);
});Integration Example — Medical Device Extraction
Extraction requires an API key, so the browser sends the image to your backend proxy -- never directly to the API.
Frontend -- file upload
<input type="file" id="devicePhoto" accept="image/*" />
<button id="extractBtn">Extract Readings</button>
<pre id="result"></pre>
<script>
document.getElementById('extractBtn').addEventListener('click', async () => {
const file = document.getElementById('devicePhoto').files[0];
if (!file) return alert('Select a photo first.');
const form = new FormData();
form.append('image', file);
form.append('deviceType', 'blood_pressure_monitor');
const res = await fetch('/api/proxy/extract', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('ssp_token') },
body: form
});
const data = await res.json();
document.getElementById('result').textContent = JSON.stringify(data, null, 2);
});
</script>Backend proxy -- Express + SDK
const express = require('express');
const multer = require('multer');
const SmartScanPro = require('./smartscanpro-sdk');
const app = express();
const upload = multer({ limits: { fileSize: 10 * 1024 * 1024 } });
// SDK client with API key from environment
const client = new SmartScanPro({
baseUrl: 'https://api.smartscanpro.ai',
apiKey: process.env.SMARTSCANPRO_API_KEY // never hardcode
});
app.post('/api/proxy/extract',
authMiddleware, // your JWT verification middleware
upload.single('image'),
async (req, res) => {
try {
// Forward user's JWT for audit trail
client.setAuthToken(req.user.token);
const result = await client.extractMedicalData(req.file.buffer, {
deviceType: req.body.deviceType || 'blood_pressure_monitor'
});
res.json(result);
} catch (err) {
res.status(err.status || 500).json({ error: err.message });
}
}
);
app.listen(3000);Integration Example — React Hook
A reusable useSmartScanPro() hook that auto-restores the session on mount and exposes login, logout, and loading state.
import { useState, useEffect, useCallback, useRef } from 'react';
import SmartScanPro from './smartscanpro-sdk';
export function useSmartScanPro(baseUrl) {
const clientRef = useRef(null);
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
// Initialise SDK once
useEffect(() => {
const c = new SmartScanPro({
baseUrl,
persistToken: true,
onTokenExpired: () => { setUser(null); }
});
clientRef.current = c;
// Auto-restore session
if (c.isAuthenticated()) {
c.getMe()
.then(res => setUser(res.user))
.catch(() => c.logout())
.finally(() => setLoading(false));
} else {
setLoading(false);
}
}, [baseUrl]);
const login = useCallback(async (email, password) => {
setLoading(true);
try {
await clientRef.current.login(email, password);
const me = await clientRef.current.getMe();
setUser(me.user);
} finally {
setLoading(false);
}
}, []);
const logout = useCallback(() => {
clientRef.current.logout();
setUser(null);
}, []);
return { client: clientRef.current, user, loading, login, logout };
}
// -- Usage in a Dashboard component ---------------------------
function Dashboard() {
const { client, user, loading, logout } = useSmartScanPro(
'https://api.smartscanpro.ai'
);
const [history, setHistory] = useState([]);
useEffect(() => {
if (!client || !user) return;
client.getVitalHistory('heart_rate', '30d')
.then(res => setHistory(res.data));
}, [client, user]);
if (loading) return <p>Loading...</p>;
if (!user) return <p>Please <a href="/login">log in</a>.</p>;
return (
<div>
<h1>Welcome, {user.email}</h1>
<p>Heart-rate readings: {history.length}</p>
<button onClick={logout}>Log Out</button>
</div>
);
}Integration Example — Node.js Backend Service
Server-side batch processing: log in as a service user, pull history, check anomalies, compare to cohort, and export a FHIR bundle.
const SmartScanPro = require('./smartscanpro-sdk');
async function nightlyReport() {
const client = new SmartScanPro({
baseUrl: 'https://api.smartscanpro.ai'
});
// Authenticate as a service account
await client.login(
process.env.SERVICE_EMAIL,
process.env.SERVICE_PASSWORD
);
// 1. Pull 90-day heart-rate history
const history = await client.getVitalHistory('heart_rate', '90d');
console.log(`Fetched ${history.data.length} heart-rate readings`);
// 2. Check the latest session for anomalies
const latestSessionId = history.data[0]?.session_id;
if (latestSessionId) {
const anomalies = await client.getAnomalies(latestSessionId);
anomalies.anomalies
.filter(a => a.isAnomaly)
.forEach(a => console.warn(`(!) ${a.vitalName}: ${a.value} (z=${a.zScore})`));
}
// 3. Compare resting heart rate to population cohort
const avgHR = history.data.reduce((s, d) => s + d.value, 0) / history.data.length;
const cohort = await client.getCohortComparison('heart_rate', Math.round(avgHR));
console.log(`Avg HR ${Math.round(avgHR)} bpm -> ${cohort.comparison.percentile}th percentile`);
// 4. Export FHIR R4 bundle for the latest session
if (latestSessionId) {
const fhir = await client.getFHIRBundle(latestSessionId);
require('fs').writeFileSync(
`reports/fhir-${latestSessionId}.json`,
JSON.stringify(fhir.bundle, null, 2)
);
console.log('FHIR bundle saved.');
}
// Clean up
client.logout();
}
nightlyReport().catch(console.error);Authentication Flow Diagram
How tokens and API keys move through the SDK in each environment. Browser apps use JWT bearer tokens from /api/auth/login; Node.js apps authenticate with a long-lived X-API-Key from an environment variable.
Rule of thumb: anything running in a browser or a mobile app uses Authorization: Bearer <jwt> obtained from
/api/auth/login. Anything running on a server you control uses a long-lived X-API-Key loaded from an environment variable.
Never ship dk_… keys to the browser — they have no expiry and are scoped to the whole project.
Error Handling
All SDK methods throw a SmartScanProError on non-2xx responses. Catch it to inspect the HTTP status and response body.
try {
const results = await client.getScanResults('invalid-id');
} catch (err) {
if (err.name === 'SmartScanProError') {
console.error('API Error:', err.message);
console.error('Status:', err.status); // e.g. 404
console.error('Details:', err.details); // full response body
// Retry logic for rate limits
if (err.status === 429) {
const retryAfter = err.details?.retryAfter || 5;
console.log(`Rate limited -- retrying in ${retryAfter}s`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
// retry the call...
}
} else {
console.error('Network Error:', err.message);
}
}Status Code Reference
| Status | Meaning | Common Cause |
|---|---|---|
400 | Bad Request | Missing required field, invalid vitals payload |
401 | Unauthorized | Missing or expired JWT token -- SDK auto-clears and fires onTokenExpired |
403 | Forbidden | Valid token but insufficient permissions (e.g. wrong role) |
404 | Not Found | Invalid session ID or result ID |
429 | Too Many Requests | Rate limit exceeded -- back off and retry |
500 | Server Error | Unexpected server issue -- contact support if persistent |
API Reference
| Method | Endpoint | Description |
|---|---|---|
| Session Management | ||
login(email, password) | POST /api/auth/login | Authenticate and auto-store JWT token |
register(email, password, name) | POST /api/auth/register | Create a new user account |
getMe() | GET /api/auth/me | Get the currently authenticated user |
isAuthenticated() | local | Check if a token is set (no network call) |
restoreSession() | local | Restore token from localStorage |
logout() | local | Clear token from memory + localStorage |
setAuthToken(token) | local | Manually set a JWT token |
setApiKey(key) | local | Set API key at runtime (Node.js only) |
| Medical Data Extraction | ||
extractMedicalData(imageData, options) | POST /api/v1/extract-medical-data | AI-powered device image extraction (requires API key) |
getDeviceTypes() | GET /api/device-types | List all supported medical device types |
| Face Scan | ||
createScanSession() | POST /api/face-scan/session | Start a new face-scan session |
submitScanResults(sessionId, vitals, quality, save) | POST /api/face-scan/results | Submit vitals from a scan (save: false for preview) |
getScanResults(resultId) | GET /api/face-scan/results/:id | Retrieve saved scan results |
deleteScanResults(resultId) | DELETE /api/face-scan/results/:id | Delete scan results permanently |
getScanSession(sessionId) | GET /api/face-scan/session/:id | Get session details and metadata |
getFHIRBundle(sessionId) | GET /api/face-scan/fhir/:sessionId | Get FHIR R4 Bundle for a session |
exportPDF(resultId) | POST /api/face-scan/results/:id/pdf | Export results as a downloadable PDF |
| Profile & Consent | ||
getProfile() | GET /api/face-scan/profile | Get the patient profile |
updateProfile(data) | PUT /api/face-scan/profile | Update patient profile (age, sex, height, weight) |
recordConsent(sessionId, jurisdiction, text) | POST /api/face-scan/consent | Record user consent for a session |
getConsent(sessionId) | GET /api/face-scan/consent/:session | Get consent record for a session |
deleteConsent(sessionId) | DELETE /api/face-scan/consent/:session | Delete consent + cascade associated data |
| History & Trends | ||
getVitalHistory(vital, period) | GET /api/face-scan/history/:vital | Get vital trend data (e.g. 'heart_rate', '30d') |
getDelta(sessionId) | GET /api/face-scan/history/delta/:id | Delta comparison from previous scan |
getAnomalies(sessionId) | GET /api/face-scan/history/anomalies/:id | Detect anomalous values via z-score analysis |
tagScan(sessionId, tag) | POST /api/face-scan/history/tag | Tag a scan session (e.g. 'morning', 'post-exercise') |
getScanTags(sessionId) | GET /api/face-scan/history/tags/:id | Get all tags for a scan session |
| Risk & Cohort | ||
getRiskScores(sessionId) | GET /api/face-scan/risk/:sessionId | Compute cardiovascular, vascular age, and 10-year risk scores |
getCohortComparison(vital, value) | GET /api/face-scan/risk/cohort/:vital | Compare a vital value to population cohort percentiles |
| Utility | ||
health() | GET /api/health | API health check -- returns server status |
/js/smartscanpro-sdk.js. Contributions welcome.