> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hana.health/llms.txt
> Use this file to discover all available pages before exploring further.

# EHR Proxy API

> Complete API reference for HANA's EHR Proxy — a unified interface for patient, appointment, encounter, and clinical data operations across EHR systems.

## Overview

HANA's EHR Proxy provides a standardized REST API that abstracts the differences between EHR systems. Write once against HANA's API, and the Proxy handles translation to Epic, Cerner, Athena, AllScripts, or any FHIR-enabled system.

**Base URL:** `https://api.hana.health/v1`

**Authentication:** All requests require an `X-API-KEY` header and `X-ORG-ID` header.

```bash theme={null}
curl https://api.hana.health/v1/patients \
  --header 'X-API-KEY: <your-api-key>' \
  --header 'X-ORG-ID: <your-organization-id>'
```

***

## Patients

### List Patients

Retrieves a list of patients for a practitioner.

```
GET /v1/patients
```

**Parameters:**

| Name                | In     | Type    | Required | Description                     |
| ------------------- | ------ | ------- | -------- | ------------------------------- |
| X-API-KEY           | header | string  | Yes      | API key                         |
| X-ORG-ID            | header | string  | Yes      | Organization ID                 |
| practitioner\_id    | query  | string  | No       | Filter by practitioner          |
| practitioner\_email | query  | string  | No       | Alternative practitioner lookup |
| count               | query  | integer | No       | Results to return (default: 20) |
| include\_fhir       | query  | boolean | No       | Include raw FHIR in response    |

**Response (200):**

```json theme={null}
{
  "status": "ok",
  "data": [
    {
      "id": "pat_abc123",
      "first_name": "Maria",
      "last_name": "Garcia",
      "date_of_birth": "1985-03-14",
      "gender": "female",
      "phone": "+1-555-0142",
      "email": "maria.garcia@email.com",
      "primary_provider_id": "prov_xyz789"
    }
  ],
  "count": 1,
  "total": 1
}
```

### Create Patient

```
POST /v1/patients
```

**Request Body:**

```json theme={null}
{
  "first_name": "string",
  "last_name": "string",
  "date_of_birth": "YYYY-MM-DD",
  "gender": "male | female | other | unknown",
  "email": "string",
  "phone_numbers": ["string"],
  "address": {
    "street": "string",
    "city": "string",
    "state": "string",
    "postal_code": "string",
    "country": "string"
  },
  "practitioner_id": "string"
}
```

**Response (201):** Created patient object.

### Confirm Patient Identity

Validates if a patient exists. Requires either (first\_name + last\_name + date\_of\_birth) OR (phone\_number).

```
GET /v1/patients/exists
```

**Response (200):** Patient found with matching record.
**Response (404):** Patient not found.

***

## Patient Records

### Get Patient Record

Retrieves a comprehensive patient record.

```
GET /v1/patients/record
```

**Parameters:** Patient identified by (first\_name + last\_name + date\_of\_birth) OR (phone\_number).

**Response (200):**

```json theme={null}
{
  "status": "ok",
  "data": {
    "demographics": { },
    "conditions": [
      {
        "code": "I10",
        "display": "Essential hypertension",
        "status": "active",
        "onset_date": "2020-06-15"
      }
    ],
    "medications": [
      {
        "name": "Lisinopril",
        "dosage": "10mg",
        "frequency": "daily",
        "status": "active",
        "prescriber": "Dr. Smith"
      }
    ],
    "allergies": [
      {
        "substance": "Penicillin",
        "reaction": "rash",
        "severity": "moderate"
      }
    ],
    "vital_signs": [ ],
    "lab_results": [ ],
    "encounter_notes": [ ],
    "insurance": { }
  }
}
```

### Get Vital Signs

```
GET /v1/patients/record/vital-signs
```

### Update Vital Signs

```
PUT /v1/patients/record/vital-signs
```

### Get Lab Results

```
GET /v1/patients/record/lab-results
```

### Get Medications

```
GET /v1/patients/record/medications
```

### Get Insurance

```
GET /v1/patients/record/insurance
```

### Update Insurance

```
PUT /v1/patients/record/insurance
```

***

## Practitioners

### List Practitioners

```
GET /v1/practitioners
```

**Parameters:**

| Name          | In    | Type    | Required | Description                     |
| ------------- | ----- | ------- | -------- | ------------------------------- |
| count         | query | integer | No       | Results to return (default: 20) |
| include\_fhir | query | boolean | No       | Include FHIR format             |

**Response (200):**

```json theme={null}
{
  "status": "ok",
  "data": [
    {
      "id": "prov_xyz789",
      "first_name": "Sarah",
      "last_name": "Johnson",
      "email": "sjohnson@clinic.com",
      "specialty": "Family Medicine",
      "npi": "1234567890",
      "locations": ["loc_main", "loc_satellite"]
    }
  ]
}
```

***

## Appointments

### List Appointments

```
GET /v1/appointments
```

**Parameters:**

| Name                | In    | Type    | Required | Description               |
| ------------------- | ----- | ------- | -------- | ------------------------- |
| start\_date\_time   | query | string  | Yes      | Start of range (ISO 8601) |
| end\_date\_time     | query | string  | Yes      | End of range (ISO 8601)   |
| practitioner\_id    | query | string  | No       | Filter by practitioner    |
| patient identifiers | query | various | No       | Filter by patient         |
| count               | query | integer | No       | Results to return         |

**Response (200):**

```json theme={null}
{
  "status": "ok",
  "data": [
    {
      "id": "appt_001",
      "patient_id": "pat_abc123",
      "practitioner_id": "prov_xyz789",
      "start": "2026-02-10T09:00:00Z",
      "end": "2026-02-10T09:30:00Z",
      "status": "confirmed",
      "type": "follow-up",
      "reason": "Hypertension management"
    }
  ]
}
```

### Book Appointment

```
POST /v1/appointments
```

**Request Body:**

```json theme={null}
{
  "patient_id": "string",
  "practitioner_id": "string",
  "start_date_time": "ISO 8601",
  "end_date_time": "ISO 8601",
  "reason": "string",
  "notes": "string"
}
```

### Reschedule Appointment

```
PUT /v1/appointments
```

**Request Body:**

```json theme={null}
{
  "patient_id": "string",
  "appointment_start_date_time": "ISO 8601 (original)",
  "new_start_date_time": "ISO 8601",
  "new_end_date_time": "ISO 8601",
  "reason": "string"
}
```

### Cancel Appointment

```
DELETE /v1/appointments
```

### Get Open Slots

```
GET /v1/appointments/open-slots
```

**Parameters:**

| Name              | In    | Type   | Required | Description            |
| ----------------- | ----- | ------ | -------- | ---------------------- |
| start\_date\_time | query | string | Yes      | Start of search window |
| end\_date\_time   | query | string | No       | End of search window   |
| practitioner\_id  | query | string | No       | Filter by practitioner |

### Pre-Visit Notes

```
GET /v1/appointments/pre-visit/notes
PUT /v1/appointments/pre-visit/notes
```

***

## Encounters & Clinical Notes

### Get Encounter Notes

```
GET /v1/appointments/encounters/notes
```

Retrieves clinical notes for a given encounter or patient.

### Create Encounter Note

```
POST /v1/appointments/encounters/notes
```

**Request Body:**

```json theme={null}
{
  "text_content": "string (markdown or plain text)",
  "json_content": {
    "subjective": "string",
    "objective": "string",
    "assessment": "string",
    "plan": "string"
  }
}
```

### Update Encounter Note

```
PUT /v1/appointments/encounters/notes
```

### Delete Encounter Note

```
DELETE /v1/appointments/encounters/notes
```

### SOAP Note Sections

Get or update individual SOAP sections:

```
GET /v1/appointments/encounters/notes/soap/sections/{section_id}
PUT /v1/appointments/encounters/notes/soap/sections/{section_id}
```

### Add Chief Complaints

```
POST /v1/appointments/encounters/notes/chief-complaints
```

**Request Body:** `["string"]`

### Add Intake Questionnaire

```
POST /v1/appointments/encounters/notes/intake-questionnaire
```

***

## Clinical Codes

### Add ICD-10 Codes

```
POST /v1/appointments/encounters/notes/codes/icd10
```

**Request Body:** `["I10", "E11.9", "F32.1"]`

### Add CPT Codes

```
POST /v1/appointments/encounters/notes/codes/cpt
```

**Request Body:** `["99213", "99490", "96127"]`

***

## Medications & Patient Instructions

### Add Medications

```
POST /v1/appointments/encounters/notes/medications
```

**Request Body:** `["Lisinopril 10mg daily", "Metformin 500mg BID"]`

### Add Patient Instructions

```
POST /v1/appointments/encounters/notes/patient-instructions
```

**Request Body:** `["Schedule follow-up in 2 weeks", "Monitor blood pressure daily"]`

***

## Conversations

### Create Conversation

Initiate an AI-driven patient conversation.

```
POST /v1/conversations
```

**Request Body:**

```json theme={null}
{
  "patient_id": "string",
  "protocol": "intake | follow_up | ccm_checkin | bhi_screen | care_gap | custom",
  "protocol_config": {
    "custom_protocol_id": "string (if protocol=custom)"
  },
  "channel": "voice_outbound | voice_inbound | sms",
  "scheduled_at": "ISO 8601 (optional, for scheduled outbound)",
  "priority": "normal | high | urgent",
  "metadata": {}
}
```

**Response (201):**

```json theme={null}
{
  "status": "ok",
  "data": {
    "conversation_id": "conv_abc123",
    "status": "scheduled",
    "scheduled_at": "2026-02-10T14:00:00Z",
    "patient_id": "pat_abc123",
    "protocol": "ccm_checkin"
  }
}
```

### Get Conversation

```
GET /v1/conversations/{conversationId}
```

**Response (200):**

```json theme={null}
{
  "status": "ok",
  "data": {
    "id": "conv_abc123",
    "status": "completed",
    "patient_id": "pat_abc123",
    "protocol": "ccm_checkin",
    "started_at": "2026-02-10T14:00:12Z",
    "completed_at": "2026-02-10T14:07:45Z",
    "duration_seconds": 453,
    "outcome": {
      "goals_completed": 4,
      "goals_total": 5,
      "escalated": false,
      "quality_score": 4.5,
      "extracted_data": { }
    },
    "transcript_url": "https://api.hana.health/v1/conversations/conv_abc123/transcript"
  }
}
```

### List Conversations

```
GET /v1/conversations
```

**Parameters:** Filter by patient, protocol, status, date range.

### Get Transcript

```
GET /v1/conversations/{conversationId}/transcript
```

***

## Metadata

### List Protocols

```
GET /v1/protocols
```

### List Note Templates

```
GET /v1/appointments/encounters/notes/templates
```

### List Note Fields

```
GET /v1/appointments/encounters/notes/fields
```

***

## Monitoring

### Health Check

```
GET /v1/health
```

### EHR Connection Health

```
GET /v1/ehr/health
```

**Response (200):**

```json theme={null}
{
  "status": "connected",
  "ehr_system": "Epic",
  "last_sync": "2026-02-07T13:45:00Z",
  "latency_ms": 145
}
```

***

## Error Handling

All errors follow a consistent format:

```json theme={null}
{
  "status": "error",
  "error": {
    "code": "PATIENT_NOT_FOUND",
    "message": "No patient found matching the provided identifiers.",
    "details": {}
  }
}
```

**Common Error Codes:**

| Code                    | HTTP Status | Description                        |
| ----------------------- | ----------- | ---------------------------------- |
| UNAUTHORIZED            | 401         | Invalid or missing API key         |
| FORBIDDEN               | 403         | Insufficient permissions           |
| PATIENT\_NOT\_FOUND     | 404         | No matching patient                |
| APPOINTMENT\_NOT\_FOUND | 404         | No matching appointment            |
| INVALID\_INPUT          | 400         | Malformed request                  |
| EHR\_UNAVAILABLE        | 503         | EHR system temporarily unreachable |
| RATE\_LIMITED           | 429         | Too many requests                  |

## Rate Limits

| Tier       | Requests/minute | Burst |
| ---------- | --------------- | ----- |
| Standard   | 60              | 100   |
| Scale      | 300             | 500   |
| Enterprise | 1,000           | 2,000 |
