Python SDK for HealthCloud APIs.
Project description
HealthCloud SDK for Python
All-in-one Python SDK for the *.health.cloud APIs.
HealthCloud endpoints do not wrap responses in a generic envelope. Each endpoint returns its own JSON body directly, and each SDK exposes typed request and response models for those endpoint-specific shapes.
The one shape that is universal across the SDK is connectivity: every service's GET /connect returns ConnectResponse.
The one endpoint with no fixed HealthCloud response shape is insurance eligibility. HealthCloud forwards the request to Stedi and relays Stedi's response, so the return type is intentionally a generic JSON value.
Installation
pip install healthcloud-sdk
For local development before publishing:
pip install -e ./packages/pip
Quick start
from healthcloud import HCSDK
sdk = HCSDK(
environment="dev", # "dev" | "uat" | "prod"
tenant_id="eclinicapi",
)
# 1. Register
registration = sdk.auth.register(
email="patient@example.com",
password="SecurePassword123!",
first_name="Jane",
last_name="Doe",
date_of_birth="1990-06-15",
sex_at_birth="female",
)
{
"cognito_sub": "xxxxxxxx-...",
"fhir_patient_id": "yyyyyyyy-...",
"email_otp_sent": false,
"email_verified": true,
"access_token": "eyJhbGci...",
"id_token": "eyJhbGci...",
"expires_in": 3600
}
In dev, registration.access_token is already usable. In uat/prod, call verify_email and then login.
# 2. Verify email OTP, uat/prod only
sdk.auth.verify_email(
user_id=registration.cognito_sub,
otp="123456",
)
# 3. Login — token is stored automatically on the SDK instance
sdk.auth.login(
email="patient@example.com",
password="SecurePassword123!",
)
# 4. All subsequent calls use the token automatically
patient = sdk.patient.get_profile("patient-id")
{
"access_token": "eyJhbGci...",
"id_token": "eyJhbGci...",
"expires_in": 3600
}
Configuration
sdk = HCSDK(
environment="dev",
tenant_id="eclinicapi",
access_token="existing-token",
)
sdk.set_access_token("my-token")
token = sdk.get_access_token()
| Environment | Pattern | Example |
|---|---|---|
dev |
https://dev-api-{service}.health.cloud |
https://dev-api-patient.health.cloud |
uat |
https://uat-api-{service}.health.cloud |
https://uat-api-vitals.health.cloud |
prod |
https://api-{service}.health.cloud |
https://api-diagnostics.health.cloud |
tenant_id is injected into /auth/* request bodies only; it is never sent as a header.
Service groups
sdk.auth
sdk.patient
sdk.vitals
sdk.diagnostics
sdk.provider
sdk.ehr
sdk.appointments
sdk.rppg
sdk.session
sdk.telehealth
sdk.field_agent
sdk.mcp
field_agent talks to *-api-fieldagent.health.cloud and has its own login. A single HCSDK instance holds one bearer token. Use two SDK instances when you need patient and field-agent sessions at the same time.
Authentication
registration = sdk.auth.register(
email="patient@example.com",
password="SecurePassword123!",
first_name="Jane",
last_name="Doe",
date_of_birth="1990-06-15",
sex_at_birth="female",
)
Dev response:
{
"cognito_sub": "xxxxxxxx-...",
"fhir_patient_id": "yyyyyyyy-...",
"email_otp_sent": false,
"email_verified": true,
"access_token": "eyJhbGci...",
"id_token": "eyJhbGci...",
"expires_in": 3600
}
UAT/prod response:
{
"cognito_sub": "xxxxxxxx-...",
"fhir_patient_id": "yyyyyyyy-...",
"email_otp_sent": true,
"email_verified": false
}
sdk.auth.verify_email(user_id=registration.cognito_sub, otp="123456")
{ "verified": true }
auth_response = sdk.auth.login(
email="patient@example.com",
password="SecurePassword123!",
)
{
"access_token": "eyJhbGci...",
"id_token": "eyJhbGci...",
"expires_in": 3600
}
Patient API
Profile, dashboard, phone, address, race, demographics
profile = sdk.patient.get_profile("patient-id")
{
"patient_id": "patient-id",
"fhir_id": "uuid",
"mrn": "MRN-XXXXXXXX",
"name": { "use": "official", "first_name": "Jane", "last_name": "Doe" },
"date_of_birth": "1990-06-15",
"gender": "unknown",
"sex_at_birth": "female",
"preferred_language": "en",
"communications": [{ "language": "en", "preferred": true }],
"email": "patient@example.com",
"active": true,
"created_by": "field-agent-fhir-id",
"created_date": "2026-06-24T04:54:17Z"
}
dashboard = sdk.patient.get_dashboard("patient-id")
{
"patient_id": "uuid",
"summary": {},
"recent_encounters": [],
"active_medications": [],
"upcoming_appointments": [],
"latest_vitals": null,
"alerts": []
}
sdk.patient.update_phone("patient-id", phone="+15550001234")
{ "sms_otp_sent": true }
sdk.patient.verify_sms("patient-id", otp="654321")
{ "verified": true }
sdk.patient.update_address(
"patient-id",
street="123 Main St",
city="San Francisco",
state="CA",
zip="94102",
)
{ "updated": true }
sdk.patient.update_race("patient-id", races=["white"])
{ "updated": true }
sdk.patient.update_demographics(
"patient-id",
date_of_birth="1990-06-15",
sex_at_birth="female",
gender_identity="woman",
ethnicity="not_hispanic_or_latino",
marital_status="married",
nationality="ZA",
preferred_language="en",
communications=[{"language": "en", "preferred": True}],
)
{ "updated": true }
Photo, face match, ID document OCR
upload_url = sdk.patient.get_photo_upload_url("patient-id")
{
"url": "https://s3.wasabisys.com/...",
"key": "patients/{id}/photo.png"
}
sdk.patient.upload_photo(
"patient-id",
data="base64-image-data",
content_type="image/jpeg",
)
{ "binary_id": "fhir-binary-uuid" }
photo = sdk.patient.get_photo("patient-id", binary_id="binary-id")
sdk.patient.compare_face_match(
"patient-id",
selfie_data="base64-selfie-data",
reference_binary_id="binary-id",
similarity_threshold=80.0,
)
{
"match": true,
"confidence": 96.42,
"similarity_threshold": 80.0,
"face_detected_in_selfie": true
}
sdk.patient.scan_identity_document(
"patient-id",
document_data="base64-document-data",
verify_against_demographics=True,
)
{
"first_name": "JANE",
"last_name": "DOE",
"date_of_birth": "06/15/1990",
"document_number": "D1234567",
"verified": true
}
Insurance
sdk.patient.create_insurance(
"patient-id",
priority="primary",
payer_name="Blue Cross Blue Shield",
member_id="M001",
relationship="self",
)
{ "coverages_created": 1, "patient_id": "patient-id" }
eligibility = sdk.patient.check_insurance_eligibility(
payer_id="BCBSM",
member_id="M001",
first_name="Jane",
last_name="Doe",
date_of_birth="1990-06-15",
)
This response is passed through from Stedi and is returned as a generic JSON value.
Medications
medication = sdk.patient.create_medication(
"patient-id",
name="Amoxicillin",
route="oral",
dosage={"value": 500, "unit": "mg", "frequency": "twice_daily"},
status="active",
)
{
"medication_id": "med-id",
"fhir_id": "med-uuid",
"resource_type": "MedicationRequest",
"name": "Amoxicillin",
"route": "oral",
"dosage": { "value": 500.0, "unit": "mg", "frequency": "twice_daily" },
"status": "active",
"intent": "order"
}
meds = sdk.patient.list_medications("patient-id")
{
"medications": [
{
"medication_id": "med-id",
"fhir_id": "med-uuid",
"resource_type": "MedicationRequest",
"name": "Amoxicillin",
"route": "oral",
"dosage": { "value": 500.0, "unit": "mg", "frequency": "twice_daily" },
"status": "active",
"intent": "order"
}
],
"total": 1
}
med = sdk.patient.get_medication("patient-id", "med-id")
sdk.patient.update_medication_status("patient-id", "med-id", status="completed", notes="course finished")
{ "updated": true, "fhir_id": "med-uuid" }
Nearest locations
locations = sdk.patient.list_nearest_locations(
lat=33.4484,
lon=-112.0740,
radius_km=10,
type="hospital",
)
{
"locations": [
{
"place_id": "hc_static_001",
"name": "HealthCloud Primary Care Clinic",
"vicinity": "123 Medical Center Drive",
"types": ["health", "point_of_interest"],
"geometry": { "location": { "lat": 30.27, "lng": -97.74 } },
"rating": 4.5,
"open_now": true,
"phone": "+1-800-555-0100",
"distance_km": 1.2
}
],
"total": 3,
"radius_km": 10.0,
"source": "hardcoded",
"note": "Set GOOGLE_PLACES_API_KEY to enable live results"
}
Encounters
encounter = sdk.patient.create_encounter(
patient_id="patient-id",
status="in-progress",
encounter_class="AMB",
)
{
"encounter_id": "id",
"fhir_id": "encounter-uuid",
"status": "in-progress",
"encounter_class": "AMB",
"patient_id": "patient-uuid",
"participants": [],
"diagnoses": [],
"locations": [],
"created_by": "self",
"created_date": "2026-06-24T04:54:27Z"
}
encounters = sdk.patient.list_encounters(patient_id="patient-id")
encounter = sdk.patient.get_encounter("encounter-id")
{
"encounters": [
{
"fhir_id": "encounter-uuid",
"patient_id": "patient-uuid",
"status": "in-progress",
"encounter_class": "AMB"
}
],
"total": 1
}
Use fhir_id from the create response as the ID for get_encounter and for vitals encounter_id.
Questionnaires
questionnaire = sdk.patient.create_questionnaire(
name="health-intake",
title="Health Intake",
status="active",
items=[
{"link_id": "q1", "text": "Allergies?", "type": "boolean"},
{"link_id": "q2", "text": "Meds?", "type": "string"},
],
)
{ "fhir_id": "questionnaire-uuid" }
response = sdk.patient.create_questionnaire_response(
"questionnaire-id",
patient_id="patient-id",
encounter_id="encounter-id",
status="completed",
items=[
{"link_id": "q1", "answers": [{"value_boolean": False}]},
{"link_id": "q2", "answers": [{"value_string": "None"}]},
],
)
{ "fhir_id": "questionnaire-response-uuid" }
Assistant API
classify_voice_command, ocr_identity_document, and ask_assistant are public. Knowledge and actions routes use bearer-token auth.
classification = sdk.patient.classify_voice_command(text="start the test for this patient")
{ "Action": "start_test" }
ocr = sdk.patient.ocr_identity_document(image="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...")
{
"type": "ocr_result",
"ok": true,
"fields": {
"name": "JANE DOE",
"documentType": "PASSPORT",
"documentNumber": "X1234567",
"dateOfBirth": "1990-06-15",
"sex": "F",
"nationality": "US"
}
}
chat = sdk.patient.ask_assistant(message="What PPE should I wear for screening?")
{
"answer": "For field screening, you should wear gloves, a surgical mask or N95 respirator, eye protection, and a disposable gown for close-contact screening...",
"citations": [
{ "id": "kb_004", "title": "Standard PPE for field screening", "collection": "ppe" }
],
"suggestedActions": [
{ "id": "open_symptom_checker", "label": "Open symptom checker" }
],
"disclaimer": "Informational and screening support only. This is not a diagnosis and not a substitute for a clinician or public-health authority."
}
kb = sdk.patient.list_knowledge(collection="ppe")
results = sdk.patient.search_knowledge(q="swab collection", limit=5)
actions = sdk.patient.list_assistant_actions()
{
"collections": [
{ "id": "screening", "name": "Screening & Triage" },
{ "id": "ppe", "name": "PPE & Safety" },
{ "id": "sample_collection", "name": "Sample Collection" },
{ "id": "field_ops", "name": "Field Operations" }
],
"entries": [
{ "id": "kb_004", "collection": "ppe", "title": "Standard PPE for field screening", "tags": ["ppe", "gloves", "mask", "gown", "safety"] }
],
"total": 3
}
{
"query": "swab collection",
"results": [
{
"id": "kb_007",
"collection": "sample_collection",
"title": "Nasal swab collection steps",
"body": "Use the swab provided in the kit...",
"tags": ["sample", "swab", "nasal", "collection", "test"]
}
],
"total": 1
}
{
"actions": [
{ "id": "start_assessment", "label": "Start assessment" },
{ "id": "start_test", "label": "Start test" },
{ "id": "capture_result", "label": "Capture result" },
{ "id": "onboard_patient", "label": "Onboard patient" },
{ "id": "medication_order", "label": "Medication order" },
{ "id": "view_records", "label": "View records" },
{ "id": "view_alerts", "label": "View alerts" },
{ "id": "open_symptom_checker", "label": "Open symptom checker" },
{ "id": "view_case", "label": "View case" },
{ "id": "connect_clinician", "label": "Connect with a clinician" }
],
"total": 10
}
Vision API
result = sdk.patient.compare_faces_by_url(
image_url_1="https://example.com/photo-a.jpg",
image_url_2="https://example.com/photo-b.jpg",
similarity_threshold=90.0,
)
{
"samePerson": true,
"confidence": 99.21,
"similarityThreshold": 90.0,
"faceDetectedInImage1": true,
"faceDetectedInImage2": true
}
A 500 with {"error": "<detail>"} is expected when an image has no detectable face.
CareConnect Communications API
state = sdk.patient.get_communications_state()
{
"presence": [{ "id": "c-self", "contactId": "c-self", "presence": "online", "lastActiveAt": "2026-06-16T09:12:00" }],
"groups": [{ "id": "grp-1", "name": "Field Team Alpha", "groupKind": "team", "memberIds": ["c-self", "c-2"], "createdBy": "c-self", "callEnabled": true, "createdAt": "...", "updatedAt": "..." }],
"conversations": [{ "id": "conv-1", "kind": "group", "groupId": "grp-1", "title": "Field Team Alpha", "unreadCount": 0, "createdAt": "...", "updatedAt": "..." }],
"messages": [{ "id": "msg-1", "conversationId": "conv-1", "senderId": "c-self", "kind": "text", "body": "On site, starting screening.", "status": "sent", "createdAt": "..." }],
"invites": [{ "id": "inv-1", "name": "Jordan Lee", "destination": "jordan@example.com", "channel": "email", "role": "field_worker", "status": "queued", "inviteCode": "9F3KQ7XZ", "createdAt": "..." }]
}
sdk.patient.upsert_presence(contact_id="c-self", presence="online")
presence = sdk.patient.list_presence()
{ "id": "c-self", "contactId": "c-self", "presence": "online", "lastActiveAt": "2026-06-16T09:12:00Z" }
{ "presence": ["..."], "total": 1 }
sdk.patient.upsert_group(id="grp-1", name="Field Team Alpha", group_kind="team", member_ids=["c-self", "c-2"], call_enabled=True)
groups = sdk.patient.list_groups()
{ "id": "grp-1", "name": "Field Team Alpha", "groupKind": "team", "memberIds": ["c-self", "c-2"], "callEnabled": true }
{ "groups": ["..."], "total": 1 }
sdk.patient.upsert_conversation(id="conv-1", kind="group", group_id="grp-1", title="Field Team Alpha")
conversations = sdk.patient.list_conversations()
{ "id": "conv-1", "kind": "group", "groupId": "grp-1", "title": "Field Team Alpha" }
{ "conversations": ["..."], "total": 1 }
sdk.patient.upsert_message(id="msg-1", conversation_id="conv-1", sender_id="c-self", kind="text", body="On site, starting screening.")
messages = sdk.patient.list_messages(conversation_id="conv-1")
{ "id": "msg-1", "conversationId": "conv-1", "senderId": "c-self", "kind": "text", "body": "On site, starting screening.", "status": "sent" }
{ "messages": ["..."], "total": 1 }
sdk.patient.upsert_invite(id="inv-1", name="Jordan Lee", destination="jordan@example.com", channel="email", role="field_worker")
invites = sdk.patient.list_invites()
{ "id": "inv-1", "name": "Jordan Lee", "destination": "jordan@example.com", "channel": "email", "inviteCode": "9F3KQ7XZ", "status": "queued" }
{ "invites": ["..."], "total": 1 }
sdk.patient.mint_rtc_token(channel_name="case-123", uid="c-self")
{ "error": "Live calling is not configured", "configured": false }
{
"appId": "...",
"channelName": "case-123",
"uid": "c-self",
"rtcToken": "006...",
"role": "publisher",
"ttlSeconds": 3600,
"expiresAt": "2026-06-16T10:12:00Z"
}
Vitals API
sdk.vitals.record(
"patient-id",
temperature=36.6,
weight_kg=70.5,
height_cm=175.0,
heart_rate=72,
systolic=120,
diastolic=80,
oxygen_saturation=98,
)
{ "observations": 7, "patient_id": "patient-uuid" }
vitals = sdk.vitals.list("patient-id")
{
"vitals_id": "vitals-uuid",
"patient_id": "patient-uuid",
"blood_pressure": { "systolic": 120.0, "diastolic": 80.0 },
"heart_rate": { "rate": 72.0 },
"temperature": { "value": 36.6, "route": "oral" },
"weight": { "value": 70.5, "clothed": false },
"height": { "value": 175.0 },
"pulse_oximetry": { "spo2": 98.0, "on_supplemental_oxygen": false },
"status": "final"
}
Diagnostics API
sdk.diagnostics.create_rapid_test(
"patient-id",
type="covid19",
result="negative",
encounter_id="encounter-id",
)
{
"test_id": "id",
"fhir_id": "test-uuid",
"type": "covid19",
"result": "negative",
"status": "final",
"specimen_type": "nasopharyngeal_swab",
"encounter_id": "encounter-uuid"
}
tests = sdk.diagnostics.list("patient-id")
{
"observations": [
{ "observation_id": "uuid", "loinc_code": "97097-0", "display": "SARS-CoV-2 (COVID-19) Ag [Presence] ...", "status": "final" }
],
"total": 1
}
Field Agent API
agent_registration = sdk.field_agent.register(
first_name="Field",
last_name="Agent",
email="agent@example.com",
password="Agent@2025!",
badge_number="FA-001",
department="QA",
)
{
"cognito_sub": "uuid",
"email_otp_sent": false,
"email_verified": true,
"access_token": "eyJ...",
"id_token": "eyJ...",
"expires_in": 3600
}
sdk.field_agent.login(email="agent@example.com", password="Agent@2025!")
sdk.field_agent.reset_password(email="agent@example.com")
{ "reset_initiated": true, "message": "A reset code has been sent to your email." }
agent = sdk.field_agent.get_agent("cognito-sub")
{
"agent_id": "sub",
"fhir_person_id": "uuid",
"cognito_sub": "sub",
"tenant_id": "cdcprotect",
"email": "agent@example.com",
"first_name": "Field",
"last_name": "Agent",
"title": null,
"phone": null,
"badge_number": "FA-001",
"license_number": null,
"department": "QA",
"organization": null,
"address_street1": null,
"address_state": null,
"status": "active"
}
sdk.field_agent.update_agent("cognito-sub", title="Senior Agent", phone="+15551230000")
dashboard = sdk.field_agent.get_dashboard("cognito-sub")
{
"agent_id": "sub",
"date": "2026-06-24",
"counts": { "patients": 18, "tests": 17, "test_results": 0 },
"assigned_patients": [],
"recent_encounters": [],
"pending_tasks": [],
"alerts": [],
"summary": { "patients": 18, "tests": 17, "test_results": 0 }
}
upload_url = sdk.field_agent.get_photo_upload_url("cognito-sub")
sdk.field_agent.upload_photo("cognito-sub", data="base64-png", content_type="image/png")
photo = sdk.field_agent.get_photo("cognito-sub", binary_id="uuid")
patients = sdk.field_agent.list_patients(created_by=agent.fhir_person_id, limit=20)
encounters = sdk.field_agent.list_encounters(limit=20)
{
"patients": [
{ "patient_id": "id", "fhir_id": "uuid", "mrn": "MRN-XXXX", "name": { "first_name": "Jane", "last_name": "Doe" }, "created_by": "agent-fhir-id" }
],
"total": 1,
"next_page_token": null,
"created_by": "agent-fhir-id"
}
MCP API
handshake = sdk.mcp.patient({
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {},
})
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"serverInfo": { "name": "HC Patient MCP", "version": "1.0.0" }
}
}
result = sdk.mcp.patient({
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {"name": "get_patient", "arguments": {"patient_id": "patient-id"}},
})
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [{ "type": "text", "text": "..." }],
"isError": false
}
}
Patient tools: get_patient, get_patient_dashboard, update_demographics, update_address, list_encounters, create_encounter, get_encounter, list_medications, create_medication, add_insurance, check_insurance_eligibility, find_nearest_locations, ask_assistant, classify_voice_command.
Field-agent tools: get_agent, get_agent_dashboard, update_agent, list_patients, list_encounters, get_agent_photo_upload_url, upload_agent_photo, get_agent_photo.
Connectivity and service stubs
sdk.patient.connect()
sdk.vitals.connect()
sdk.diagnostics.connect()
sdk.provider.connect()
sdk.ehr.connect()
sdk.appointments.connect()
sdk.rppg.connect()
sdk.session.connect()
sdk.telehealth.connect()
sdk.field_agent.connect()
sdk.mcp.connect()
{ "status": "connected", "service": "patient-api", "environment": "dev" }
{ "status": "connected", "service": "provider-api" }
Provider, EHR, Appointments, rPPG, Session, and Telehealth currently expose connectivity only plus a low-level request escape hatch.
sdk.appointments.request("GET", "/appointments")
sdk.ehr.request("GET", "/records")
sdk.rppg.request("POST", "/sessions")
sdk.session.request("POST", "/sessions")
sdk.telehealth.request("POST", "/consultations")
Error handling
from healthcloud import SDKError
try:
sdk.patient.get_profile("patient-id")
except SDKError as error:
print(error.status_code)
print(error.message)
print(error.response)
print(error.__cause__)
| Scenario | Status code | Message |
|---|---|---|
| Network failure | 0 |
OS/network error message |
| Missing path param | 0 |
Path parameter message |
| No access token | 401 |
SDK message |
| Backend 4xx/5xx | HTTP status | Backend message / error / detail |
| 204 No Content | — | returns None |
Integration examples
cd examples/pip
pip install -e ../../packages/pip
python auth_login.py
python get_patient.py
python submit_vitals.py
Build
cd packages/pip
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
python -m build
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file healthcloud_sdk-0.5.0.tar.gz.
File metadata
- Download URL: healthcloud_sdk-0.5.0.tar.gz
- Upload date:
- Size: 28.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b943699d421b0bdbe2a3514dd26c57f97535a0422f409f26d9d2ac35ab1239f
|
|
| MD5 |
a896a7b1c8922a14e4ab3a834e232b97
|
|
| BLAKE2b-256 |
42ea05325bd907dd8d134df92f8880e9a9da66543006fc65a1b89294e89906a2
|
File details
Details for the file healthcloud_sdk-0.5.0-py3-none-any.whl.
File metadata
- Download URL: healthcloud_sdk-0.5.0-py3-none-any.whl
- Upload date:
- Size: 31.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e656a8de312230eafdc562046c335e148042c0673e34209091300785e4a15c0e
|
|
| MD5 |
95f5cca8b707b3d6230aca4367b9da93
|
|
| BLAKE2b-256 |
d4bd50752090eee0179e0ed1784fab1701419aee341a66b918ef5b6aff1e989f
|