Many clinical scenarios span multiple visits over weeks, months, or years. A patient managing type 2 diabetes, for example, will have quarterly check-ups, lab orders, specialist referrals, and lifestyle interventions that all belong to the same ongoing case. A single [`Encounter`](/content/docs/api/fhir/resources/encounter/index.html) captures one visit, but it cannot represent the full arc of care.

FHIR provides two complementary resources for grouping this longitudinal activity: [`EpisodeOfCare`](/content/docs/api/fhir/resources/episodeofcare/index.html) for administrative encounter grouping, and [`CarePlan`](/content/docs/api/fhir/resources/careplan/index.html) for clinical planning. Together, they give you both the temporal grouping you need and the rich goal and activity context you want.

## Key Concepts

[`EpisodeOfCare`](/content/docs/api/fhir/resources/episodeofcare/index.html) is intentionally lightweight. Its job is purely administrative grouping — it acts as an umbrella that encounters attach to. It tracks which organization is responsible for a patient's care during a period, and which conditions are being addressed. It does not capture clinical planning details like goals, activities, or care team assignments.

[`CarePlan`](/content/docs/api/fhir/resources/careplan/index.html) handles the clinical layer. It defines treatment goals, scheduled activities, conditions being addressed, and care team members. A CarePlan sits alongside an EpisodeOfCare and provides the planning context that the episode intentionally omits.

A patient can have multiple concurrent episodes and care plans. For instance, one episode for diabetes management and another for a weight loss program, each with its own CarePlan. A single encounter (like a quarterly check-up) can be linked to multiple episodes through [`Encounter.episodeOfCare`](/content/docs/api/fhir/resources/encounter/index.html), which accepts an array of references.

## Resource Overview

| Resource | Role | Description |
| --- | --- | --- |
| [`EpisodeOfCare`](/content/docs/api/fhir/resources/episodeofcare/index.html) | Administrative grouping | Groups encounters into a named care episode for a specific condition |
| [`CarePlan`](/content/docs/api/fhir/resources/careplan/index.html) | Clinical protocol | Defines goals, activities, and conditions for the treatment plan |
| [`Encounter`](/content/docs/api/fhir/resources/encounter/index.html) | Visit record | Individual visit linked to one or more episodes |
| [`Condition`](/content/docs/api/fhir/resources/condition/index.html) | Problem / diagnosis | The clinical problem being tracked across the episode |
| [`Goal`](/content/docs/api/fhir/resources/goal/index.html) | Treatment objective | Measurable target within a care plan |

## How the Resources Fit Together

All resources below reference the Patient. The diagram omits those references to focus on the relationships that matter for longitudinal tracking.

episodeOfCare

episodeOfCare
diagnosis.condition
addresses
goal
supportingInfo
Encounter (Visit 1)
EpisodeOfCare
Encounter (Visit 2)
Condition
CarePlan
Goal

The key relationships are:

- Encounters link to their episode via `Encounter.episodeOfCare`
- Both EpisodeOfCare and CarePlan reference the same [`Condition`](/content/docs/api/fhir/resources/condition/index.html) resources, creating an implicit link through shared diagnoses
- `CarePlan.supportingInfo` explicitly references the EpisodeOfCare, providing a direct link from plan to episode
- [`Goal`](/content/docs/api/fhir/resources/goal/index.html) resources are referenced from the CarePlan via `CarePlan.goal`

Navigating between EpisodeOfCare and CarePlan

The `supportingInfo` link is one-directional: you can follow it from CarePlan to EpisodeOfCare, but there is no field on EpisodeOfCare that points back to a CarePlan. To navigate in the reverse direction (episode to plan), query by the shared Condition: `CarePlan?condition=Condition/{id}`. This is the natural clinical query — "show me all plans addressing this diagnosis" — and works regardless of how many episodes or plans reference that condition.

## Creating an Episode of Care

An [`EpisodeOfCare`](/content/docs/api/fhir/resources/episodeofcare/index.html) represents an administrative period of care for a specific concern. Create one when a patient begins a new care episode, such as starting chronic disease management or entering a treatment program.

Key fields:

| Field | Purpose |
| --- | --- |
| `status` | Lifecycle state: `planned`, `waitlist`, `active`, `onhold`, `finished`, `cancelled` |
| `patient` | Reference to the patient |
| `type` | Category of care being provided |
| `diagnosis` | Conditions being addressed, with optional role (chief complaint, comorbidity) |
| `period` | Start and optional end date of the episode |
| `managingOrganization` | Organization responsible for the episode |

```ts
const episode = await medplum.createResource({

resourceType: 'EpisodeOfCare',

status: 'active',

patient: {

reference: 'Patient/homer-simpson',

display: 'Homer Simpson',

},

type: [\

{\

coding: [\

{\

system: 'http://terminology.hl7.org/CodeSystem/episodeofcare-type',\

code: 'hacc',\

display: 'Home and Community Care',\

},\

],\

},\

],

diagnosis: [\

{\

condition: {\

reference: 'Condition/diabetes-type-2',\

display: 'Type 2 Diabetes Mellitus',\

},\

role: {\

coding: [\

{\

system: 'http://terminology.hl7.org/CodeSystem/diagnosis-role',\

code: 'CC',\

display: 'Chief complaint',\

},\

],\

},\

},\

],

period: {

start: '2024-01-15',

},

managingOrganization: {

reference: 'Organization/springfield-clinic',

display: 'Springfield Medical Clinic',

},

});

console.log(episode);
```

## Linking Encounters to an Episode

When a patient has a visit related to an ongoing care episode, link the [`Encounter`](/content/docs/api/fhir/resources/encounter/index.html) to the episode via `Encounter.episodeOfCare`. This field is an array, so a single encounter can belong to multiple episodes simultaneously. This is useful when a visit addresses more than one ongoing concern.

```ts
const encounter = await medplum.createResource({

resourceType: 'Encounter',

status: 'finished',

class: {

system: 'http://terminology.hl7.org/CodeSystem/v3-ActCode',

code: 'AMB',

display: 'ambulatory',

},

subject: {

reference: 'Patient/homer-simpson',

display: 'Homer Simpson',

},

episodeOfCare: [{ reference: 'EpisodeOfCare/diabetes-episode' }, { reference: 'EpisodeOfCare/weight-loss-episode' }],

period: {

start: '2024-06-01T09:00:00Z',

end: '2024-06-01T09:30:00Z',

},

});

console.log(encounter);
```

In this example, the encounter is linked to both a diabetes episode and a weight loss episode, reflecting that both concerns were addressed during the same visit.

You are not limited to encounters that already took place. Link future visits to an episode by creating encounters in advance and pointing `Encounter.episodeOfCare` at the `EpisodeOfCare`. Use `Encounter.status` (for example planned) to record that the encounter is scheduled or not yet started, in line with FHIR’s encounter lifecycle.

## Creating a Care Plan with Goals

While the EpisodeOfCare groups encounters, the [`CarePlan`](/content/docs/api/fhir/resources/careplan/index.html) captures what should happen clinically. Start by creating [`Goal`](/content/docs/api/fhir/resources/goal/index.html) resources for the treatment objectives, then reference them from the CarePlan.

### Creating a Goal

```ts
const goal = await medplum.createResource({

resourceType: 'Goal',

lifecycleStatus: 'active',

description: {

text: 'Maintain HbA1c below 7%',

},

subject: {

reference: 'Patient/homer-simpson',

display: 'Homer Simpson',

},

target: [\

{\

measure: {\

coding: [\

{\

system: 'http://loinc.org',\

code: '4548-4',\

display: 'Hemoglobin A1c/Hemoglobin.total in Blood',\

},\

],\

},\

detailQuantity: {\

value: 7,\

unit: '%',\

system: 'http://unitsofmeasure.org',\

code: '%',\

},\

},\

],

});

console.log(goal);
```

### Creating the Care Plan

The CarePlan brings together the condition being addressed, the goals to achieve, scheduled activities, and a reference to the associated EpisodeOfCare via `supportingInfo`.

```ts
const carePlan = await medplum.createResource({

resourceType: 'CarePlan',

status: 'active',

intent: 'plan',

title: 'Diabetes Management Plan',

subject: {

reference: 'Patient/homer-simpson',

display: 'Homer Simpson',

},

addresses: [\

{\

reference: 'Condition/diabetes-type-2',\

display: 'Type 2 Diabetes Mellitus',\

},\

],

goal: [\

{\

reference: 'Goal/hba1c-goal',\

display: 'Maintain HbA1c below 7%',\

},\

],

activity: [\

{\

detail: {\

kind: 'ServiceRequest',\

code: {\

coding: [\

{\

system: 'http://loinc.org',\

code: '4548-4',\

display: 'Hemoglobin A1c',\

},\

],\

},\

description: 'Quarterly HbA1c lab test',\

status: 'scheduled',\

scheduledPeriod: {\

start: '2024-07-01',\

},\

},\

},\

],

supportingInfo: [\

{\

reference: 'EpisodeOfCare/diabetes-episode',\

display: 'Diabetes Management Episode',\

},\

],

});

console.log(carePlan);
```

### Cross-Linking EpisodeOfCare and CarePlan

FHIR R4 does not provide a direct field on EpisodeOfCare that points to a CarePlan, so the link between them is asymmetric. The recommended pattern uses two complementary strategies:

1. `CarePlan.supportingInfo` directly references the EpisodeOfCare. This gives you an explicit, unambiguous pointer when reading a CarePlan — follow `supportingInfo` to find the episode it belongs to.
2. Both resources reference the same [`Condition`](/content/docs/api/fhir/resources/condition/index.html) resources (`EpisodeOfCare.diagnosis.condition` and `CarePlan.addresses`). This shared condition serves as the queryable link in the reverse direction: starting from an EpisodeOfCare, read its conditions and then search `CarePlan?condition=Condition/{id}` to find the associated plans.

| Direction | How to navigate |
| --- | --- |
| CarePlan → EpisodeOfCare | Follow `CarePlan.supportingInfo` directly |
| EpisodeOfCare → CarePlan | Query `CarePlan?condition={shared-condition-id}` |

Together, these two strategies cover both navigation directions. The `supportingInfo` pointer is explicit and fast for single-resource reads; the shared Condition query handles the reverse direction and is the natural clinical question ("what plans address this diagnosis?").

## Querying Longitudinal Data

### Finding All Encounters for an Episode

Retrieve every visit associated with a care episode using the `episode-of-care` search parameter on [`Encounter`](/content/docs/api/fhir/resources/encounter/index.html).

```ts
const encounters = await medplum.searchResources('Encounter', 'episode-of-care=EpisodeOfCare/diabetes-episode');

console.log(encounters);
```

### Finding Care Plans for a Condition

Find all care plans addressing a specific condition for a patient.

```ts
const carePlans = await medplum.searchResources(

'CarePlan',

'patient=Patient/homer-simpson&condition=Condition/diabetes-type-2'
);

console.log(carePlans);
```

### Finding All Episodes for a Patient

List all active care episodes for a patient to see their ongoing cases at a glance.

```ts
const episodes = await medplum.searchResources('EpisodeOfCare', 'patient=Patient/homer-simpson&status=active');

console.log(episodes);
```

## Example: Concurrent Care Episodes

Consider a patient, Homer Simpson, who is managing two ongoing concerns: type 2 diabetes and a weight loss program. Each concern has its own EpisodeOfCare and CarePlan, but some visits address both.

- Each concern has its own EpisodeOfCare, Condition, CarePlan, and Goal.
- The Q2 check-up Encounter is linked to both episodes because both concerns were addressed during that visit.
