Files

16 KiB

AI Patient Onboarding API — Complete Frontend Integration Guide

Version: 1.0.0
Target Audience: Frontend Engineers (React / React Native / Vue / Next.js / Mobile)
Backend Framework: FastAPI (Python 3.13)
Supported Protocols: HTTP/1.1 REST, JSON, Multipart/Form-Data Formats
Interactive API Documentation:

  • Swagger UI: {BASE_URL}/docs
  • ReDoc: {BASE_URL}/redoc
  • OpenAPI Schema: {BASE_URL}/openapi.json

1. Executive System Overview

The AI Patient Onboarding API is an enterprise multi-modal clinical intake system designed for hospitals, clinics, a

nd digital health platforms. It automates patient registration, symptom intake, medical history collection, document extraction, and specialty triage before a physician consultation.

Key Capabilities for Frontend Applications:

  1. Multi-Modal Onboarding:
    • Text-Based Onboarding: Interactive chat-based intake powered by clinical LLM orchestrator.
    • Voice-First Onboarding: Natural conversational voice intake supporting English (en-IN), Tamil (ta-IN), Hindi (hi-IN), Telugu (te-IN), Kannada (kn-IN), Malayalam (ml-IN), and Marathi (mr-IN) using Sarvam AI ASR/TTS.
  2. Medical Document Analysis: Vision-based processing of lab reports, prescriptions, and discharge summaries (JPEG, PNG, WEBP, PDF up to 10MB).
  3. Session-Based State Engine: Stateful intake tracking stored in persistent backend database.
  4. Structured EHR Output: Automatic clinical JSON result extraction matching standard Electronic Health Record (EHR) models.

2. Server Base URLs & CORS Configuration

Server Base URLs:

  • Local Development: http://localhost:8000 or http://127.0.0.1:8000
  • Staging / Production: Configured via environment variable ({BASE_URL})

CORS (Cross-Origin Resource Sharing) Policy:

The backend enforces production-safe CORSMiddleware.

  • Allowed Origins: http://localhost:3000, http://localhost:5173, http://127.0.0.1:3000, http://127.0.0.1:5173, https://onboarding.skyheal.ai (configurable via CORS_ORIGINS).
  • Allowed Credentials: true (Access-Control-Allow-Credentials: true).
  • Allowed Headers: Authorization, Content-Type, X-API-Key, X-Patient-ID, X-Request-ID, Accept, Origin.
  • Exposed Headers: X-Request-ID.

3. Quick Start Integration Flow

[ Frontend App ]
       │
       ├── 1. POST /v1/onboarding/start (or /v1/voice-onboarding/start)
       │      └─► Returns session_id (e.g. "ONB-8F12A9C4" or "VOICE-D3CAEA5C")
       │
       ├── 2. POST /v1/onboarding/{session_id}/message (or /turn for voice)
       │      └─► Exchanges multi-turn symptom history & receiving AI responses
       │
       ├── 3. POST /v1/documents/{session_id}/upload (Optional)
       │      └─► Uploads medical reports / lab results
       │
       └── 4. POST /v1/onboarding/{session_id}/complete
              └─► Returns final structured EHR result (PatientOnboardingResult)

4. Master API Endpoint Directory

HTTP Method Endpoint Path Auth Required Rate Limit Purpose
GET /health No None Service health check & AI provider status
POST /v1/onboarding/start Yes 30 req/min Start text onboarding session
POST /v1/onboarding/{session_id}/message Yes 30 req/min Send text intake message to AI
POST /v1/onboarding/{session_id}/complete Yes 30 req/min Finalize text session & output structured result
POST /v1/voice-onboarding/start Yes 30 req/min Start voice onboarding session
POST /v1/voice-onboarding/{session_id}/turn Yes 30 req/min Process speech recording or text fallback turn
POST /v1/voice-onboarding/{session_id}/complete Yes 30 req/min Finalize voice session & output structured result
GET /v1/voice-onboarding/audio/{audio_id} No None Stream TTS audio response (WAV/MP3)
POST /v1/documents/{session_id}/upload Yes 10 req/min Upload medical document / report (10MB max)

5. Authentication & Patient Security

Authentication Mechanisms:

Method A: HTTP Bearer Token (Standard)

Authorization: Bearer <ACCESS_TOKEN>

Method B: X-API-Key Custom Header

X-API-Key: <API_KEY>

Supported Access Tokens:

  1. Service Secret API Key: skyheal_secure_api_key_2026 (configurable via API_SECRET_KEY in server environment).
  2. Patient Development Tokens: test_token_<PATIENT_ID> (e.g. test_token_PAT-10023). Automatically establishes patient identity context.

Patient Isolation & IDOR Protection Rules:

  1. When starting a session (/v1/onboarding/start), patient.id is bound as session owner (session.patient_id).
  2. Subsequent requests verify caller's authenticated patient_id matches session owner.
  3. Access attempts by other patients return HTTP 403 Forbidden.

6. Text Onboarding API Specifications

6.1. POST /v1/onboarding/start

Starts a new text-based clinical onboarding intake session.

Request Headers:

Content-Type: application/json
Authorization: Bearer test_token_PAT-10023

Request Body (StartOnboardingRequest):

{
  "patient": {
    "id": "PAT-10023",
    "name": "Kavitha Ramesh",
    "age": 35,
    "gender": "female",
    "phone": "+919876543210",
    "abha_id": "91-1234-5678-9012",
    "insurance_scheme": "PMJAY",
    "dietary_habits": "Vegetarian"
  },
  "category": {
    "type": "general",
    "code": "general_medicine",
    "name": "General Medicine"
  },
  "language": "en"
}

Field Descriptions:

Field Type Required Validation Rules Description
patient.id string Yes Min length 1 Unique patient identifier
patient.name string No Optional Full name of patient
patient.age integer No 0 \le \text{age} \le 120 Patient age in years
patient.gender string No Optional Gender identity ("male", "female", "other")
category.type string Yes "general" or "speciality" Onboarding workflow type
category.code string Yes Min length 1 Specialty classification code
category.name string Yes Min length 1 Category display name
language string No Default "en" Preferred intake language

Successful Response (200 OK - StartOnboardingResponse):

{
  "success": true,
  "session_id": "ONB-8F12A9C4",
  "patient_id": "PAT-10023",
  "category": {
    "type": "general",
    "code": "general_medicine",
    "name": "General Medicine"
  },
  "language": "en",
  "status": "in_progress",
  "stage": "symptoms",
  "message": "Hello Kavitha Ramesh! I am your clinical onboarding assistant. What symptoms are you experiencing today?"
}

6.2. POST /v1/onboarding/{session_id}/message

Sends a patient chat response to the AI intake orchestrator.

Request Body (SendMessageRequest):

{
  "message": "I have had severe chest tightness and shortness of breath for 2 days."
}

Successful Response (200 OK - SendMessageResponse):

{
  "success": true,
  "session_id": "ONB-8F12A9C4",
  "stage": "medical_history",
  "message": "Thank you for sharing. Does the chest tightness radiate to your arm or jaw, and do you have any history of high blood pressure?",
  "status": "in_progress",
  "response_time_ms": 1529.74,
  "response_time_sec": 1.53
}

6.3. POST /v1/onboarding/{session_id}/complete

Finalizes the intake session and outputs the structured clinical EHR payload.

Request Body (CompleteOnboardingRequest):

{
  "confirmed": true
}

Successful Response (200 OK - CompleteOnboardingResponse):

{
  "success": true,
  "session_id": "ONB-8F12A9C4",
  "status": "completed",
  "result": {
    "patient_id": "PAT-10023",
    "abha_id": "91-1234-5678-9012",
    "phone": "+919876543210",
    "insurance_scheme": "PMJAY",
    "category": {
      "type": "general",
      "code": "general_medicine",
      "name": "General Medicine"
    },
    "chief_complaint": "Chest tightness and shortness of breath for 2 days",
    "symptoms": [
      {
        "name": "Chest tightness",
        "duration": "2 days",
        "severity": "severe",
        "description": "Triggered during exertion"
      }
    ],
    "medical_history": ["Prehypertension"],
    "medications": ["Metformin 500mg"],
    "allergies": ["Penicillin"],
    "dietary_habits": "Vegetarian",
    "additional_information": "Patient confirmed details.",
    "language": "en",
    "onboarding_completed": true
  },
  "message": "Onboarding successfully completed and saved to patient record.",
  "response_time_ms": 4075.41,
  "response_time_sec": 4.08
}

7. Voice Onboarding API Specifications

7.1. POST /v1/voice-onboarding/start

Starts a voice-first onboarding session with Sarvam AI multilingual speech engine.

Supported Languages:

en-IN (Indian English), ta-IN (Tamil), hi-IN (Hindi), te-IN (Telugu), kn-IN (Kannada), ml-IN (Malayalam), mr-IN (Marathi).

Request Body:

{
  "patient": {
    "id": "PAT-VOICE-1",
    "name": "Ramesh G",
    "age": 34,
    "gender": "male"
  },
  "category": {
    "type": "general",
    "code": "general_medicine",
    "name": "General Medicine"
  },
  "language": "ta-IN"
}

Successful Response (200 OK):

{
  "success": true,
  "session_id": "VOICE-D3CAEA5C",
  "patient_id": "PAT-VOICE-1",
  "category": {
    "type": "general",
    "code": "general_medicine",
    "name": "General Medicine"
  },
  "language": "ta-IN",
  "status": "in_progress",
  "stage": "greeting",
  "greeting_text": "வணக்கம் Ramesh G, CureSelect மருத்துவமனைக்கு வரவேற்கிறோம். இன்று உங்களுக்கு என்ன சுகவீனம் உள்ளது?",
  "audio_url": "/v1/voice-onboarding/audio/aud_a1b2c3d4e5f6",
  "response_time_ms": 78.32,
  "response_time_sec": 0.08
}

7.2. POST /v1/voice-onboarding/{session_id}/turn

Processes a conversational voice turn using audio recording or text fallback.

Multipart Form Data:

  • audio: Binary audio recording file (WAV, WEBM, MP3, OGG up to 10MB).
  • text_fallback: String text transcript (used if WebSpeech STT processed client-side).

Successful Response (200 OK):

{
  "success": true,
  "session_id": "VOICE-D3CAEA5C",
  "patient_transcript": "எனக்குகடந்த 3 நாளா நெஞ்சு பாரமா இருக்குங்க.",
  "ai_text": "நன்றி. இந்த நெஞ்சு பாரம் உடற்பயிற்சி செய்யும் போது அதிகமாகிறதா?",
  "stage": "symptoms",
  "completed": false,
  "audio_url": "/v1/voice-onboarding/audio/aud_f9e8d7c6b5a4",
  "audio_base64": null,
  "suggested_specialty": {
    "specialty": "Cardiology",
    "reason": "Chest tightness reported"
  },
  "response_time_ms": 1412.37,
  "response_time_sec": 1.41
}

7.3. GET /v1/voice-onboarding/audio/{audio_id}

Streams generated TTS audio for browser or mobile playback.

const audio = new Audio(`${BASE_URL}/v1/voice-onboarding/audio/${audioId}`);
await audio.play();

8. Medical Document Analysis API

POST /v1/documents/{session_id}/upload

Uploads a medical report / prescription for vision extraction.

  • Content-Type: multipart/form-data
  • File Limit: Max 10MB (10,485,760 bytes).
  • Allowed Formats: image/jpeg, image/png, image/webp, application/pdf.

Successful Response (200 OK):

{
  "success": true,
  "session_id": "ONB-8F12A9C4",
  "document_type": "lab_report",
  "summary": "Report indicates elevated HbA1c (7.2%) and stage 1 hypertension (130/85 mmHg).",
  "findings": [
    {
      "test": "HbA1c",
      "value": "7.2",
      "unit": "%",
      "interpretation": "Elevated"
    }
  ],
  "medications_found": ["Metformin 500mg"],
  "allergies_found": ["Penicillin"],
  "message": "Medical document analyzed and integrated into onboarding session."
}

9. Error Handling & Status Codes

HTTP Status Code Meaning Cause & Resolution
400 Bad Request Bad Request Invalid category or unsupported file format.
401 Unauthorized Unauthorized Missing or invalid Authorization: Bearer or X-API-Key header.
403 Forbidden Forbidden (IDOR) Authenticated patient_id does not match session owner.
404 Not Found Not Found Session ID does not exist in backend database.
413 Payload Too Large File Too Large Uploaded document exceeds 10MB limit.
422 Validation Error Pydantic Error Request body violates schema rules (e.g. age < 0).
429 Too Many Requests Rate Limited Exceeded rate limit bucket (30 req/min). Check Retry-After header.
500 Internal Error Server Error Unhandled backend failure.

10. Frontend React & TypeScript Implementation Examples

React API Client (src/api/onboardingClient.ts)

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000';

export interface PatientContext {
  id: string;
  name?: string;
  age?: number;
  gender?: string;
  phone?: string;
  abha_id?: string;
}

export interface CategoryContext {
  type: 'general' | 'speciality';
  code: string;
  name: string;
}

async function fetchApi<T>(endpoint: string, options: RequestInit = {}, patientId: string): Promise<T> {
  const token = `test_token_${patientId}`;
  const headers = new Headers(options.headers || {});
  headers.set('Authorization', `Bearer ${token}`);
  if (!(options.body instanceof FormData)) {
    headers.set('Content-Type', 'application/json');
  }

  const response = await fetch(`${API_BASE_URL}${endpoint}`, { ...options, headers });
  if (!response.ok) {
    const errorBody = await response.json().catch(() => ({ detail: 'Network response error' }));
    throw new Error(errorBody.detail || `HTTP Error ${response.status}`);
  }
  return response.json();
}

export async function startOnboarding(patient: PatientContext, category: CategoryContext, language: string = 'en') {
  return fetchApi<any>('/v1/onboarding/start', {
    method: 'POST',
    body: JSON.stringify({ patient, category, language }),
  }, patient.id);
}

export async function sendMessage(sessionId: string, patientId: string, message: string) {
  return fetchApi<any>(`/v1/onboarding/${sessionId}/message`, {
    method: 'POST',
    body: JSON.stringify({ message }),
  }, patientId);
}

export async function completeOnboarding(sessionId: string, patientId: string, confirmed: boolean = true) {
  return fetchApi<any>(`/v1/onboarding/${sessionId}/complete`, {
    method: 'POST',
    body: JSON.stringify({ confirmed }),
  }, patientId);
}

11. Frontend Integration Checklist

[ ] Configure API_BASE_URL in environment (VITE_API_BASE_URL=http://localhost:8000)
[ ] Verify CORS preflight request from localhost:3000 / localhost:5173
[ ] Attach Authorization: Bearer test_token_<PATIENT_ID> header
[ ] Call POST /v1/onboarding/start and store session_id
[ ] Multi-turn chat message sending via POST /v1/onboarding/{session_id}/message
[ ] Handle 401 Unauthorized & 403 Forbidden errors
[ ] Upload medical documents via POST /v1/documents/{session_id}/upload (10MB max)
[ ] Call POST /v1/onboarding/{session_id}/complete to retrieve final PatientOnboardingResult
[ ] Test voice onboarding audio streaming via GET /v1/voice-onboarding/audio/{audio_id}