Overview
ClinicalPilot supports multiple input formats for patient data:
FHIR R4 Bundles — Structured HL7 FHIR resources
EHR PDFs — Scanned or printed EHR documents
EHR CSVs — Tabular patient data exports
All upload endpoints parse the input and return a structured PatientContext object that can be used with the analyze endpoint .
POST /api/upload/fhir
Upload a FHIR R4 Bundle for parsing.
Endpoint
POST http://localhost:8000/api/upload/fhir
Request Body
FHIR R4 Bundle resource (JSON object)
The bundle must conform to the FHIR R4 specification. Supported resource types: Patient, Condition, MedicationRequest, Observation, AllergyIntolerance.
Response
Parsed patient data in ClinicalPilot’s unified schema
Human-readable clinical summary of the parsed data
Example Request
curl -X POST http://localhost:8000/api/upload/fhir \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Bundle",
"type": "collection",
"entry": [
{
"resource": {
"resourceType": "Patient",
"id": "example",
"birthDate": "1960-01-01",
"gender": "male"
}
},
{
"resource": {
"resourceType": "Condition",
"id": "diabetes",
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "44054006",
"display": "Diabetes mellitus type 2"
}
]
},
"subject": {"reference": "Patient/example"}
}
},
{
"resource": {
"resourceType": "MedicationRequest",
"id": "metformin",
"medicationCodeableConcept": {
"coding": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"code": "6809",
"display": "Metformin"
}
],
"text": "Metformin 1000mg"
},
"dosageInstruction": [
{
"text": "1000mg twice daily"
}
],
"subject": {"reference": "Patient/example"}
}
}
]
}'
Example Response
{
"patient_context" : {
"age" : 65 ,
"gender" : "male" ,
"weight_kg" : null ,
"height_cm" : null ,
"conditions" : [
{
"code" : "44054006" ,
"display" : "Diabetes mellitus type 2" ,
"onset_date" : null ,
"status" : "active"
}
],
"medications" : [
{
"name" : "Metformin" ,
"dose" : "1000mg" ,
"frequency" : "twice daily" ,
"route" : "oral" ,
"status" : "active"
}
],
"labs" : [],
"vitals" : [],
"allergies" : [],
"current_prompt" : "" ,
"raw_text" : "" ,
"source_type" : "fhir" ,
"timestamp" : "2026-03-03T10:30:00.000000"
},
"summary" : "65-year-old male patient \n PMH: Diabetes mellitus type 2 \n Medications: Metformin 1000mg twice daily"
}
Error Responses
500 Internal Server Error
{
"detail" : "FHIR parsing failed: [error details]"
}
POST /api/upload/ehr
Upload a PDF or CSV EHR document for parsing.
Endpoint
POST http://localhost:8000/api/upload/ehr
Request Body
Multipart form-data file upload (PDF or CSV)
Supported file types: .pdf (scanned/printed EHR documents) and .csv (tabular patient data)
Response
Parsed patient data in ClinicalPilot’s unified schema
Human-readable clinical summary of the parsed data
Example Request (PDF)
curl -X POST http://localhost:8000/api/upload/ehr \
-F "file=@patient_record.pdf"
Example Request (CSV)
curl -X POST http://localhost:8000/api/upload/ehr \
-F "file=@patient_data.csv"
The CSV parser expects the following column names (case-insensitive):
Demographics : age, gender, weight_kg, height_cm
Conditions : condition, diagnosis, problem
Medications : medication, drug, med
Labs : lab, lab_name, lab_value, lab_unit
Vitals : vital, vital_name, vital_value
Allergies : allergy, allergen
age, gender, condition, medication, dose, frequency, lab_name, lab_value, lab_unit
65, male, Diabetes mellitus type 2, Metformin, 1000mg, BID, HbA1c, 7.2, %
65, male, Hypertension, Lisinopril, 20mg, daily, Creatinine, 1.3, mg/dL
Example Response
{
"patient_context" : {
"age" : 65 ,
"gender" : "male" ,
"weight_kg" : null ,
"height_cm" : null ,
"conditions" : [
{
"code" : "" ,
"display" : "Diabetes mellitus type 2" ,
"onset_date" : null ,
"status" : "active"
},
{
"code" : "" ,
"display" : "Hypertension" ,
"onset_date" : null ,
"status" : "active"
}
],
"medications" : [
{
"name" : "Metformin" ,
"dose" : "1000mg" ,
"frequency" : "BID" ,
"route" : "oral" ,
"status" : "active"
},
{
"name" : "Lisinopril" ,
"dose" : "20mg" ,
"frequency" : "daily" ,
"route" : "oral" ,
"status" : "active"
}
],
"labs" : [
{
"name" : "HbA1c" ,
"value" : "7.2" ,
"unit" : "%" ,
"reference_range" : "" ,
"date" : null ,
"flag" : ""
},
{
"name" : "Creatinine" ,
"value" : "1.3" ,
"unit" : "mg/dL" ,
"reference_range" : "" ,
"date" : null ,
"flag" : ""
}
],
"vitals" : [],
"allergies" : [],
"current_prompt" : "" ,
"raw_text" : "" ,
"source_type" : "ehr_csv" ,
"timestamp" : "2026-03-03T10:35:00.000000"
},
"summary" : "65-year-old male patient \n PMH: Diabetes mellitus type 2, Hypertension \n Medications: Metformin 1000mg BID, Lisinopril 20mg daily \n Labs: HbA1c: 7.2 %, Creatinine: 1.3 mg/dL"
}
Error Responses
400 Bad Request
{
"detail" : "No file provided"
}
{
"detail" : "Unsupported file type. Use PDF or CSV."
}
500 Internal Server Error
{
"detail" : "EHR parsing failed: [error details]"
}
Using Uploaded Data with /api/analyze
After uploading a FHIR bundle or EHR document, you can use the returned patient_context directly with the analyze endpoint:
# 1. Upload FHIR bundle
curl -X POST http://localhost:8000/api/upload/fhir \
-H "Content-Type: application/json" \
-d @fhir_bundle.json > patient.json
# 2. Extract patient_context and add a clinical prompt
jq '.patient_context | .current_prompt = "Patient presents with chest pain"' patient.json > analysis_request.json
# 3. Run full analysis
curl -X POST http://localhost:8000/api/analyze \
-H "Content-Type: application/json" \
-d @analysis_request.json
PatientContext Schema
Show Full PatientContext Schema
One of: male, female, other, unknown
Patient weight in kilograms
Patient height in centimeters
List of Condition objects:
code (string): SNOMED/ICD code
display (string): Human-readable diagnosis
onset_date (string, optional): ISO date
status (string): “active”, “resolved”, etc.
List of Medication objects:
name (string): Drug name
dose (string): Dose with units (e.g., “1000mg”)
frequency (string): Frequency (e.g., “BID”, “daily”)
route (string): Route of administration (default: “oral”)
status (string): “active”, “discontinued”, etc.
List of LabResult objects:
name (string): Lab test name
value (string): Result value
unit (string): Unit of measurement
reference_range (string): Normal range
date (string, optional): ISO date
flag (string): “high”, “low”, “critical”, or empty
List of Vital objects:
name (string): Vital sign name (e.g., “blood_pressure”)
value (string): Value
unit (string): Unit
date (string, optional): ISO date
List of Allergy objects:
substance (string): Allergen name
reaction (string): Reaction description
severity (string): “mild”, “moderate”, “severe”
The clinical question or presenting complaint
Anonymized raw text for full context
One of: text, fhir, ehr_pdf, ehr_csv
ISO 8601 timestamp of parsing
Notes
PDF parsing uses OCR and LLM-based extraction. Accuracy depends on document quality and formatting.
All uploaded data is automatically anonymized before processing to remove PHI (Protected Health Information).
FHIR parsing supports a subset of FHIR R4 resources. Unsupported resource types are silently ignored.