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

# Migration Instructions

> Comprehensive guide for migrating insurance from legacy Patient Demographics API insurance endpoints to the new Insurance Management System

# Key Dates and Deprecation Timeline

* Summer 2025 — New Insurance Policy Endpoints `POST, PUT, DELETE /patients/{patient_id}/policies` were released
* April 1st, 2026 — The insurances section of the PatientDemographics resource (`/api/2.0/patients/{id}`) will be deprecated for writes (insurances section will become read only). You must migrate to the new endpoints before then to avoid disruption starting April 2nd and onward.

# Introduction

This comprehensive migration guide provides detailed information for migrating from the legacy Patient Demographics API insurance endpoints to the new Insurance Management System endpoints. After reviewing this guide, please refer to the [Insurance API FAQ](/articles/rest/insurance-api/faq) for answers to common questions about the migration process. If you need additional assistance or encounter issues not covered in this documentation, please contact our support team at [support@elationhealth.com](mailto:support@elationhealth.com).

> **Note:** The information in this guide specifically pertains to the `insurances` sub-property within Patient Demographics request objects. Other properties of Patient Demographics endpoints remain unchanged.

## Definitions & Terms

### Legacy Approach

The **Legacy Approach** refers to the original API patient demographics endpoint (`/api/2.0/patients/{id}`) and its insurance management methodology. This approach treats insurance information as a sub-property of patient demographics and only supports complete replacement of all insurance records with each update. Any modification to insurance information results in creating entirely new records, with no ability to update individual insurance entries in place or maintain a versioned history of changes.

### Versioned Approach

The **Versioned Approach** refers to the new Insurance Management System that is provided by a dedicated microservice with a set of specialized insurance endpoints. This approach enables granular control over individual insurance records, supporting in-place updates, record swapping, deactivation, and complete version history tracking. A key requirement of this approach is that you must first GET the current insurance information before making any modifications to ensure you have the latest version of the data.

### PatientInsurance

A `PatientInsurance` was used in the legacy system to identify a patient's insurance coverage. It served as the primary data structure for storing insurance information as part of the patient demographics endpoint, containing all insurance-related data in a single record tied to the patient.

### Policy

A `Policy` is used in the versioned approach to represent a patient's insurance coverage in the microservice. It is a first-class citizen with its own unique IDs and complete lifecycle management, enabling granular control over individual insurance records and supporting versioning, updates, and historical tracking.

### Enabling Insurance Versioning

Elation uses feature flags to control functionality across our system. The **Insurance Versioning** feature flag is enabled on a practice-by-practice basis and controls access to the new insurance management capabilities.

When Insurance Versioning is enabled for a practice:

* **New UI Access**: Users can access a new insurance management interface that displays historical versions of `Policy` models managed by the Insurance Management System
* **Enhanced Functionality**: The practice gains access to granular insurance record management, including in-place updates, record swapping, and complete version history tracking
* **API Behavior Changes**: The legacy patient demographics endpoints (`/api/2.0/patients/{id}`) begin to support `id` fields (PatientInsurance IDs) in insurance objects, enabling in-place updates instead of complete replacement

When Insurance Versioning is disabled:

* **Legacy UI Only**: Users continue to use the existing insurance management interface
* **Standard Legacy Behavior**: All insurance updates through the patient demographics endpoint result in complete replacement of insurance records
* **No Version History**: No historical tracking or in-place update capabilities are available

The feature flag primarily affects the user interface experience and the availability of advanced insurance management features, while the underlying API endpoints remain functional regardless of the flag status.

### Deleting vs. Archiving

The key difference between the two systems is how they handle record removal:

**PatientInsurance Models (Legacy System):**

* Can only be **deleted** (permanently removed)

**Policy Models (Insurance Management System):**

* Can be **archived** (preserved with history) or **deleted** (gone for good)

## Why This is Changing

We are introducing new dedicated insurance endpoints that will replace the insurance sub-property within the patient demographics endpoint. Let's examine the limitations of the current approach and how the new Insurance Versioning system addresses these challenges.

Legacy API (`/api/2.0/patients/{id}`) limitations:

* Only supported complete replacement of insurance information
* Any change created a new record with no "in place" updates
* No versioned history tracking
* Led to billing confusion
* Limited auditability
* Difficulty supporting accurate claims

Insurance Versioning improvements:

* Ability to update individual insurance records
* Support for swapping insurance records
* Deactivation of individual records
* Complete history retention
* Reduced billing errors
* More reliable insurance management
* Better alignment with industry record-keeping practices

# What Changes for You

## Old Flow (Patient Demographics Endpoints)

* Updating insurance information meant sending the entire insurances array in a `PUT /api/2.0/patients/{id}` request.
* Every change replaced all insurances; any not present were deleted, and new ones were created
* Insurance card images were managed through patient insurance priority (primary, secondary, tertiary) rather than direct Policy IDs

## New Flow (Insurance Versioning Endpoints)

* It is now necessary to check the latest state of insurances before performing operations.
  * `GET /patients/{patient_id}/policies` - Get the list of policies
  * `GET    /patients/{patient_id}/policies/{policy_id}` – Get a specific policy by ID
* Use new endpoints such as:
  * `POST   /patients/{patient_id}/policies` – Create a new insurance policy
  * `PUT    /patients/{patient_id}/policies/{policy_id}` – Update an existing insurance policy in-place
  * `DELETE /patients/{patient_id}/policies/{policy_id}` – Deactivate (archive) a policy, preserving history
* Insurance card images are now tightly linked to Policy IDs (no more issues with "orphan" images). The new policy-based endpoints work directly with Policy IDs:
  * `POST /patients/{patient_id}/policies/{policy_id}/card-images` – Upload insurance card images
  * `GET  /patients/{patient_id}/policies/{policy_id}/card-images` – Get insurance card images
  * `DELETE /patients/{patient_id}/policies/{policy_id}/card-images/{image_rank}` – Delete specific insurance card image

## What's Backward Compatible

For now, the legacy `PUT /api/2.0/patients/{id}` endpoint remains available for insurance updates. With the new Insurance Management feature:

* If you include a PatientInsurance `id` for each insurance object in insurances, Elation will update that record in place.
* If you exclude the PatientInsurance `id`, a new record will be created.

Any insurance record not present in the submission is archived and moved to historical (not deleted). When using the original patient demographics endpoint without providing PatientInsurance IDs, associated insurance card images are automatically migrated to the new Policy records to ensure continuity.

## Field Differences

| **Field Category**         | **Patient Demographics Insurance**       | **Insurance Management Service**                         | **Relationship**       | **Notes**                                                                                                                                                                                                                           |       |
| -------------------------- | ---------------------------------------- | -------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| **Patient Info**           |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Patient DOB                | `patient_dob: str`                       | `patient_dob: date`                                      | **Type Change**        | Patient Demographics Insurance uses string, Insurance Management Service uses date (JSON: "YYYY-MM-DD" format)                                                                                                                      |       |
| **Policy Details**         |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Policy Rank                | `rank: int`                              | `rank: Optional[int]`                                    | **Nullability Change** | Patient Demographics Insurance required, Insurance Management Service optional                                                                                                                                                      |       |
| Copay Amount               | `copay: Optional[float]`                 | `copay: Optional[str]`                                   | **Type Change**        | Patient Demographics Insurance uses float, Insurance Management Service uses string. String representation is more predictable across different clients and languages. Validated with regex: \`^-?\d{1,8}(.\d{1,10})?\$             | ^\$\` |
| Deductible Amount          | `deductible: Optional[float]`            | `deductible: Optional[str]`                              | **Type Change**        | Patient Demographics Insurance uses float, Insurance Management Service uses string. String representation is more predictable across different clients and languages. Validated with regex: \`^-?\d{1,8}(.\d{1,10})?\$             | ^\$\` |
| **Insurance References**   |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Carrier ID                 | `insurance_company: Optional[int]`       | `carrier_id: Optional[int]`                              | **Name Change**        | Same value, different field name                                                                                                                                                                                                    |       |
| Plan ID                    | `insurance_plan: Optional[int]`          | `plan_id: Optional[int]`                                 | **Name Change**        | Same value, different field name                                                                                                                                                                                                    |       |
| **Insurance Names**        |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Carrier Name               | `carrier: Optional[str]`                 | `carrier_name: Optional[str]`                            | **Name Change**        | Same value, different field name                                                                                                                                                                                                    |       |
| Plan Name                  | `plan: Optional[str]`                    | `plan_name: Optional[str]`                               | **Name Change**        | Same value, different field name                                                                                                                                                                                                    |       |
| **Status & Control**       |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Active Status              | N/A                                      | `status: Status`                                         | **New Field**          | Insurance Management Service adds status enum: "active" or "inactive"                                                                                                                                                               |       |
| **Insured Person Details** |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Insured Person DOB         | `insured_person_dob: Optional[str]`      | `insured_person_dob: Optional[date]`                     | **Type Change**        | Patient Demographics Insurance uses string, Insurance Management Service uses date (JSON: "YYYY-MM-DD" format)                                                                                                                      |       |
| Insured Person Gender      | `insured_person_gender: Optional[str]`   | `insured_person_sex_at_birth: Optional[str]`             | **Name Change**        | Same value, different field name                                                                                                                                                                                                    |       |
| Relationship to Insured    | `relationship_to_insured: Optional[str]` | `relationship_to_insured: Optional[InsurerRelationship]` | **Type Change**        | Patient Demographics Insurance uses string, Insurance Management Service uses enum: "self", "child", "spouse", or "other"                                                                                                           |       |
| **Payment & Programs**     |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Payment Program            | `payment_program: Optional[str]`         | `payment_program: Optional[InsurancePaymentProgram]`     | **Type Change**        | Patient Demographics Insurance uses string, Insurance Management Service uses enum: "medicare\_part\_b", "medicare\_advantage", "medicaid", "commercial\_hmsa", "commercial\_sfhp", "commercial\_other", or "workers\_compensation" |       |
| **Timestamps**             |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Created Date               | `created_date: Optional[str]`            | N/A                                                      | **Removed**            | Patient Demographics Insurance has this field, Insurance Management Service doesn't                                                                                                                                                 |       |
| Deleted Date               | `deleted_date: Optional[str]`            | N/A                                                      | **Removed**            | Patient Demographics Insurance has this field, Insurance Management Service doesn't                                                                                                                                                 |       |
| **Insurance Card Images**  |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Front Image Path           | N/A                                      | `front_image_path: Optional[str]`                        | **New Field**          | Pre-signed URL to the original, uncompressed front image of the insurance card. Can be used to display or download the full-resolution front image.                                                                                 |       |
| Back Image Path            | N/A                                      | `back_image_path: Optional[str]`                         | **New Field**          | Pre-signed URL to the original, uncompressed back image of the insurance card. Can be used to display or download the full-resolution back image.                                                                                   |       |
| **Internal Fields**        |                                          |                                                          |                        |                                                                                                                                                                                                                                     |       |
| Vendor Company ID          | N/A                                      | `vendor_company_id: Optional[int]`                       | **New Field**          | Internal field for data migration/processing                                                                                                                                                                                        |       |
| Vendor External ID         | N/A                                      | `vendor_external_id: Optional[str]`                      | **New Field**          | Internal field for data migration/processing                                                                                                                                                                                        |       |

## Summary of Field Changes

### Field Name Changes

* `insurance_company` → `carrier_id`
* `insurance_plan` → `plan_id`
* `carrier` → `carrier_name`
* `plan` → `plan_name`
* `insured_person_gender` → `insured_person_sex_at_birth`

### Type Changes

* `patient_dob`: `str` → `date` (JSON: "YYYY-MM-DD" format)
* `insured_person_dob`: `str` → `date` (JSON: "YYYY-MM-DD" format)
* `copay`: `float` → `string` (String representation is more predictable across different clients and languages. Validated with regex: `^-?\d{1,8}(\.\d{1,10})?$|^$`)
* `deductible`: `float` → `string` (String representation is more predictable across different clients and languages. Validated with regex: `^-?\d{1,8}(\.\d{1,10})?$|^$`)
* `relationship_to_insured`: `str` → `InsurerRelationship` enum ("self", "child", "spouse", or "other")
* `payment_program`: `str` → `InsurancePaymentProgram` enum ("medicare\_part\_b", "medicare\_advantage", "medicaid", "commercial\_hmsa", "commercial\_sfhp", "commercial\_other", or "workers\_compensation")

### New Fields in Insurance Management Service

* `status` (enum: "active" or "inactive")
* `front_image_path`, `back_image_path` (Pre-signed URLs to original, uncompressed insurance card images)
* `vendor_company_id`, `vendor_external_id` (Internal fields for data migration/processing)

### Removed Fields

* `created_date`, `deleted_date` (timestamp fields)

### Nullability Changes

* `rank`: Required in Patient Demographics Insurance → Optional in Insurance Management Service

# Key Migration Gotchas

* Do not manipulate the PatientInsurance "id" field directly; provide it to update, omit to create new.
* When using the original patient demographics endpoint without PatientInsurance IDs, insurance card images are automatically migrated to new Policy records.
* Practices with Insurance Versioning enabled will reject insurance card uploads without a Policy ID, returning 422 errors.
* `PUT` of an empty insurances array on legacy endpoints will archive (deactivate) all policies.
* Fields required for /policies (some must be passed even on update): `patient_dob`, `patient_first_name`, `patient_last_name`.

# Syncing Flows

The following sections go much deeper into how the legacy `PatientInsurance` model is modified via the original API patient demographics endpoints, and how those modifications translate into the new `Policy` models managed by Insurance Management System.

> **Note:**  The following is optional documentation and shared so that you can better understand how the two APIs are currently supported.  This is only necessary to understand if you are using `PatientInsurance` IDs with the Legacy endpoints.  It may also be helpful in understanding how data flows between the new Insurance Versioning UI and the legacy UI.

In the following discussion we're going to use the acronym IMS to represent the Insurance Management System.

## Key Decision Points

The major difference between these scenarios is whether you provide PatientInsurance `id` values in your insurance objects. **Providing a PatientInsurance ID allows the system to update existing records in place**, preserving associated data like insurance card images. **Omitting PatientInsurance IDs forces the creation of new records**, which archives the old ones, but when using the original patient demographics endpoint, insurance card images are automatically migrated to maintain continuity.

```mermaid theme={null}
flowchart LR
    A[Patient Demographics Update] --> B{Has PatientInsurance id?}
    B -->|Yes| C[Update in-place]
    B -->|No| D[Create new record]
    
    C --> E[Preserve existing Policy]
    D --> F[Archive old Policy]
    
    E --> G[✅ Images remain linked]
    F --> H["✅ Previous Policy Images Migrated (Legacy endpoint only)"]
```

## Insurance Management System to Legacy System Synchronization

```mermaid theme={null}
sequenceDiagram
    participant API as API Client
    participant IMS as Insurance Management Service
    participant EventStream as Event Stream
    participant Legacy as Legacy System
    participant DB as Legacy Database

    API->>IMS: POST/PUT/DELETE /patients/\{id\}/policies
    IMS->>IMS: Process Policy Change
    IMS->>EventStream: Publish Policy Event
    Note over EventStream: Event contains policy data and change type (create/update/delete)
    EventStream->>Legacy: Consume Policy Event
    Legacy->>Legacy: Transform to PatientInsurance format
    Legacy->>DB: Update Patient Demographics
    Note over Legacy,DB: Legacy PatientInsurance records are updated/created/deactivated
    Legacy-->>IMS: Event Processing Complete
```

### Legacy System to Insurance Management System Synchronization

```mermaid theme={null}
sequenceDiagram
    participant API as API Client
    participant Legacy as Legacy System
    participant EventStream as Event Stream
    participant IMS as Insurance Management Service
    participant DB as IMS Database

    API->>Legacy: PUT /api/2.0/patients/\{id\} (legacy)
    Legacy->>Legacy: Process PatientInsurance Changes
    Legacy->>EventStream: Publish PatientDemographics Event
    Note over EventStream: Event contains legacy PatientInsurance data
    EventStream->>IMS: Consume PatientDemographics Event
    IMS->>IMS: Transform to Policy format
    IMS->>DB: Create/Update Policy Records
    Note over IMS,DB: New Policy records created or existing ones updated
    IMS->>IMS: Migrate Card Images
    Note over IMS,IMS: Only migrated if PatientInsurance is not provided in legacy flow
    IMS-->>Legacy: Event Processing Complete
```
