Metadata-Version: 2.4
Name: healthcloud-sdk
Version: 0.5.0
Summary: Python SDK for HealthCloud APIs.
Author: Healthcheck Systems Inc
License-Expression: MIT
Keywords: api,health-cloud,healthcare,healthcloud,sdk
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# 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

```bash
pip install healthcloud-sdk
```

For local development before publishing:

```bash
pip install -e ./packages/pip
```

---

## Quick start

```python
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",
)
```

```json
{
  "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`.

```python
# 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")
```

```json
{
  "access_token": "eyJhbGci...",
  "id_token": "eyJhbGci...",
  "expires_in": 3600
}
```

---

## Configuration

```python
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

```python
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

```python
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:

```json
{
  "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:

```json
{
  "cognito_sub": "xxxxxxxx-...",
  "fhir_patient_id": "yyyyyyyy-...",
  "email_otp_sent": true,
  "email_verified": false
}
```

```python
sdk.auth.verify_email(user_id=registration.cognito_sub, otp="123456")
```

```json
{ "verified": true }
```

```python
auth_response = sdk.auth.login(
    email="patient@example.com",
    password="SecurePassword123!",
)
```

```json
{
  "access_token": "eyJhbGci...",
  "id_token": "eyJhbGci...",
  "expires_in": 3600
}
```

---

## Patient API

### Profile, dashboard, phone, address, race, demographics

```python
profile = sdk.patient.get_profile("patient-id")
```

```json
{
  "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"
}
```

```python
dashboard = sdk.patient.get_dashboard("patient-id")
```

```json
{
  "patient_id": "uuid",
  "summary": {},
  "recent_encounters": [],
  "active_medications": [],
  "upcoming_appointments": [],
  "latest_vitals": null,
  "alerts": []
}
```

```python
sdk.patient.update_phone("patient-id", phone="+15550001234")
```

```json
{ "sms_otp_sent": true }
```

```python
sdk.patient.verify_sms("patient-id", otp="654321")
```

```json
{ "verified": true }
```

```python
sdk.patient.update_address(
    "patient-id",
    street="123 Main St",
    city="San Francisco",
    state="CA",
    zip="94102",
)
```

```json
{ "updated": true }
```

```python
sdk.patient.update_race("patient-id", races=["white"])
```

```json
{ "updated": true }
```

```python
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}],
)
```

```json
{ "updated": true }
```

### Photo, face match, ID document OCR

```python
upload_url = sdk.patient.get_photo_upload_url("patient-id")
```

```json
{
  "url": "https://s3.wasabisys.com/...",
  "key": "patients/{id}/photo.png"
}
```

```python
sdk.patient.upload_photo(
    "patient-id",
    data="base64-image-data",
    content_type="image/jpeg",
)
```

```json
{ "binary_id": "fhir-binary-uuid" }
```

```python
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,
)
```

```json
{
  "match": true,
  "confidence": 96.42,
  "similarity_threshold": 80.0,
  "face_detected_in_selfie": true
}
```

```python
sdk.patient.scan_identity_document(
    "patient-id",
    document_data="base64-document-data",
    verify_against_demographics=True,
)
```

```json
{
  "first_name": "JANE",
  "last_name": "DOE",
  "date_of_birth": "06/15/1990",
  "document_number": "D1234567",
  "verified": true
}
```

### Insurance

```python
sdk.patient.create_insurance(
    "patient-id",
    priority="primary",
    payer_name="Blue Cross Blue Shield",
    member_id="M001",
    relationship="self",
)
```

```json
{ "coverages_created": 1, "patient_id": "patient-id" }
```

```python
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

```python
medication = sdk.patient.create_medication(
    "patient-id",
    name="Amoxicillin",
    route="oral",
    dosage={"value": 500, "unit": "mg", "frequency": "twice_daily"},
    status="active",
)
```

```json
{
  "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"
}
```

```python
meds = sdk.patient.list_medications("patient-id")
```

```json
{
  "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
}
```

```python
med = sdk.patient.get_medication("patient-id", "med-id")
sdk.patient.update_medication_status("patient-id", "med-id", status="completed", notes="course finished")
```

```json
{ "updated": true, "fhir_id": "med-uuid" }
```

### Nearest locations

```python
locations = sdk.patient.list_nearest_locations(
    lat=33.4484,
    lon=-112.0740,
    radius_km=10,
    type="hospital",
)
```

```json
{
  "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

```python
encounter = sdk.patient.create_encounter(
    patient_id="patient-id",
    status="in-progress",
    encounter_class="AMB",
)
```

```json
{
  "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"
}
```

```python
encounters = sdk.patient.list_encounters(patient_id="patient-id")
encounter = sdk.patient.get_encounter("encounter-id")
```

```json
{
  "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

```python
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"},
    ],
)
```

```json
{ "fhir_id": "questionnaire-uuid" }
```

```python
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"}]},
    ],
)
```

```json
{ "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.

```python
classification = sdk.patient.classify_voice_command(text="start the test for this patient")
```

```json
{ "Action": "start_test" }
```

```python
ocr = sdk.patient.ocr_identity_document(image="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...")
```

```json
{
  "type": "ocr_result",
  "ok": true,
  "fields": {
    "name": "JANE DOE",
    "documentType": "PASSPORT",
    "documentNumber": "X1234567",
    "dateOfBirth": "1990-06-15",
    "sex": "F",
    "nationality": "US"
  }
}
```

```python
chat = sdk.patient.ask_assistant(message="What PPE should I wear for screening?")
```

```json
{
  "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."
}
```

```python
kb = sdk.patient.list_knowledge(collection="ppe")
results = sdk.patient.search_knowledge(q="swab collection", limit=5)
actions = sdk.patient.list_assistant_actions()
```

```json
{
  "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
}
```

```json
{
  "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
}
```

```json
{
  "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

```python
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,
)
```

```json
{
  "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

```python
state = sdk.patient.get_communications_state()
```

```json
{
  "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": "..." }]
}
```

```python
sdk.patient.upsert_presence(contact_id="c-self", presence="online")
presence = sdk.patient.list_presence()
```

```json
{ "id": "c-self", "contactId": "c-self", "presence": "online", "lastActiveAt": "2026-06-16T09:12:00Z" }
```

```json
{ "presence": ["..."], "total": 1 }
```

```python
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()
```

```json
{ "id": "grp-1", "name": "Field Team Alpha", "groupKind": "team", "memberIds": ["c-self", "c-2"], "callEnabled": true }
```

```json
{ "groups": ["..."], "total": 1 }
```

```python
sdk.patient.upsert_conversation(id="conv-1", kind="group", group_id="grp-1", title="Field Team Alpha")
conversations = sdk.patient.list_conversations()
```

```json
{ "id": "conv-1", "kind": "group", "groupId": "grp-1", "title": "Field Team Alpha" }
```

```json
{ "conversations": ["..."], "total": 1 }
```

```python
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")
```

```json
{ "id": "msg-1", "conversationId": "conv-1", "senderId": "c-self", "kind": "text", "body": "On site, starting screening.", "status": "sent" }
```

```json
{ "messages": ["..."], "total": 1 }
```

```python
sdk.patient.upsert_invite(id="inv-1", name="Jordan Lee", destination="jordan@example.com", channel="email", role="field_worker")
invites = sdk.patient.list_invites()
```

```json
{ "id": "inv-1", "name": "Jordan Lee", "destination": "jordan@example.com", "channel": "email", "inviteCode": "9F3KQ7XZ", "status": "queued" }
```

```json
{ "invites": ["..."], "total": 1 }
```

```python
sdk.patient.mint_rtc_token(channel_name="case-123", uid="c-self")
```

```json
{ "error": "Live calling is not configured", "configured": false }
```

```json
{
  "appId": "...",
  "channelName": "case-123",
  "uid": "c-self",
  "rtcToken": "006...",
  "role": "publisher",
  "ttlSeconds": 3600,
  "expiresAt": "2026-06-16T10:12:00Z"
}
```

---

## Vitals API

```python
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,
)
```

```json
{ "observations": 7, "patient_id": "patient-uuid" }
```

```python
vitals = sdk.vitals.list("patient-id")
```

```json
{
  "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

```python
sdk.diagnostics.create_rapid_test(
    "patient-id",
    type="covid19",
    result="negative",
    encounter_id="encounter-id",
)
```

```json
{
  "test_id": "id",
  "fhir_id": "test-uuid",
  "type": "covid19",
  "result": "negative",
  "status": "final",
  "specimen_type": "nasopharyngeal_swab",
  "encounter_id": "encounter-uuid"
}
```

```python
tests = sdk.diagnostics.list("patient-id")
```

```json
{
  "observations": [
    { "observation_id": "uuid", "loinc_code": "97097-0", "display": "SARS-CoV-2 (COVID-19) Ag [Presence] ...", "status": "final" }
  ],
  "total": 1
}
```

---

## Field Agent API

```python
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",
)
```

```json
{
  "cognito_sub": "uuid",
  "email_otp_sent": false,
  "email_verified": true,
  "access_token": "eyJ...",
  "id_token": "eyJ...",
  "expires_in": 3600
}
```

```python
sdk.field_agent.login(email="agent@example.com", password="Agent@2025!")
sdk.field_agent.reset_password(email="agent@example.com")
```

```json
{ "reset_initiated": true, "message": "A reset code has been sent to your email." }
```

```python
agent = sdk.field_agent.get_agent("cognito-sub")
```

```json
{
  "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"
}
```

```python
sdk.field_agent.update_agent("cognito-sub", title="Senior Agent", phone="+15551230000")
dashboard = sdk.field_agent.get_dashboard("cognito-sub")
```

```json
{
  "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 }
}
```

```python
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)
```

```json
{
  "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

```python
handshake = sdk.mcp.patient({
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {},
})
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": { "name": "HC Patient MCP", "version": "1.0.0" }
  }
}
```

```python
result = sdk.mcp.patient({
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {"name": "get_patient", "arguments": {"patient_id": "patient-id"}},
})
```

```json
{
  "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

```python
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()
```

```json
{ "status": "connected", "service": "patient-api", "environment": "dev" }
```

```json
{ "status": "connected", "service": "provider-api" }
```

Provider, EHR, Appointments, rPPG, Session, and Telehealth currently expose connectivity only plus a low-level request escape hatch.

```python
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

```python
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

```bash
cd examples/pip
pip install -e ../../packages/pip
python auth_login.py
python get_patient.py
python submit_vitals.py
```

---

## Build

```bash
cd packages/pip
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
python -m build
```
