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

# FHIR basics

> Learn the FHIR building blocks you need to read FHIR Extraction output: resources, CodeableConcepts, choice fields, references, and Bundles

FHIR (Fast Healthcare Interoperability Resources) is the HL7 standard that most electronic health records (EHRs) use to exchange clinical data. FHIR Extraction returns standard [FHIR R4](https://hl7.org/fhir/R4/) JSON. If you have not worked with FHIR before, the output can look verbose.

This page explains the five building blocks that make up every response, one at a time, with a small example for each:

1. [Resources](#resources): one JSON object per clinical fact
2. [CodeableConcepts](#codeableconcepts): a code plus a label
3. [Choice fields](#choice-fields): fields such as `onset[x]` that can hold different types
4. [References](#references): links from one resource to another
5. [Bundles](#bundles): the list that holds all resources

For the exact fields of each datatype, see [FHIR datatypes](https://docs.corti.ai/fhir/datatypes.md). For the rules the endpoint follows when it fills these building blocks, see [How FHIR Extraction works](https://docs.corti.ai/fhir/how-it-works.md).

## Resources

A **resource** is one JSON object that describes one clinical fact. Its `resourceType` field tells you what kind of fact it is. Because every system agrees on the same resource types, field names, and code systems, a resource that one system writes, another system can read.

```json theme={null}
{
  "resourceType": "Condition",
  "code": { "text": "Asthma" }
}
```

FHIR defines the fields each resource type may have. The [FHIR R4 resource list](https://hl7.org/fhir/R4/resourcelist.html) shows every resource type, and each one has its own page with all its fields, for example [Condition](https://hl7.org/fhir/R4/condition.html). A `Condition` has `clinicalStatus`, `severity`, and `bodySite`. An `Observation` has `valueQuantity` and `interpretation`. The endpoint only fills a field when the note supports it, apart from the references and a few fixed defaults such as `clinicalStatus: active`, and leaves out every empty field. Two Condition resources from the same response can therefore have different sets of fields.

| Note says | Fields on the Condition |
| - | - |
| "Asthma." | `code`, `clinicalStatus` |
| "Mild asthma since 2018." | `code`, `clinicalStatus`, `severity`, `onsetDateTime` |
| "Possible asthma, to be confirmed with spirometry." | `code`, `clinicalStatus`, `verificationStatus` |

## CodeableConcepts

Most coded fields in FHIR are **CodeableConcepts** ([R4 definition](https://hl7.org/fhir/R4/datatypes.html#CodeableConcept)). A CodeableConcept wraps one or more codes in a `coding` list, plus a human-readable `text`. Each entry in `coding` has three parts:

| Part | What it is | Example |
| - | - | - |
| `system` | A URI that names the code system | `http://snomed.info/sct` (SNOMED CT) |
| `code` | The machine-readable code | `195967001` |
| `display` | The code system's label for the code | `Asthma` |

A coding from SNOMED CT or LOINC can also carry a `version` with the version of the code system the endpoint used. The examples in these docs leave it out.

Simplified, you can read a CodeableConcept as "code plus label": `195967001` Asthma. In JSON, it looks like this:

```json theme={null}
{
  "coding": [
    {
      "system": "http://snomed.info/sct",
      "code": "195967001",
      "display": "Asthma"
    }
  ],
  "text": "Asthma"
}
```

Always compare `system` and `code` together. The code `8480-6` means "Systolic blood pressure" in LOINC, but nothing in SNOMED CT.

### One concept, two codings

Some CodeableConcepts carry two codings for the same meaning. The endpoint puts the FHIR value-set code first, and adds the SNOMED CT equivalent second. For example, a family member's relationship:

```json theme={null}
{
  "coding": [
    {
      "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode",
      "code": "MTH",
      "display": "mother"
    },
    {
      "system": "http://snomed.info/sct",
      "code": "72705000",
      "display": "Mother"
    }
  ],
  "text": "mother"
}
```

If your system only reads `coding[0]`, it gets the FHIR code. If your system understands SNOMED CT, it can use the second coding.

### Text-only CodeableConcepts

Some fields describe things that the endpoint does not code, such as the reason for a procedure. Those CodeableConcepts carry only `text`:

```json theme={null}
{ "text": "Suspected appendicitis" }
```

### Plain codes

A few FHIR fields are not CodeableConcepts but plain strings from a fixed list. Examples are `Observation.status` (`"final"`), `AllergyIntolerance.criticality` (`"high"`), and `Patient.gender` (`"female"`). You read those directly.

## Choice fields

FHIR writes some fields as `onset[x]`, `value[x]`, or `performed[x]`. The R4 specification calls these [choice elements](https://hl7.org/fhir/R4/formats.html#choice). The `[x]` means the field can hold different data types, and the type becomes part of the field name. A resource only ever has one variant.

FHIR Extraction uses a date field only when the note states the date as a year or an ISO 8601 date, and falls back to a text field otherwise:

| Note says | Field on the Condition |
| - | - |
| "Asthma since 2018" | `"onsetDateTime": "2018"` |
| "Asthma since 2020-03-15" | `"onsetDateTime": "2020-03-15"` |
| "Asthma since March 2020" | `"onsetString": "March 2020"` |
| "Asthma since childhood" | `"onsetString": "childhood"` |
| "Asthma for two years" | `"onsetString": "two years"` |

Observations use the same pattern for their result:

| Note says | Field on the Observation |
| - | - |
| "Heart rate 88" | `"valueQuantity": { "value": 88, "unit": "beats/min" }` |
| "No murmurs" | `"valueCodeableConcept"` with the SNOMED CT code for Absent |
| "GCS 14" | `"valueInteger": 14` |

When you read a choice field, check each variant you support, for example `onsetDateTime` first and `onsetString` second.

## References

Resources point to each other with **references** ([R4 definition](https://hl7.org/fhir/R4/references.html#Reference)). Every clinical resource points to the Patient of the note, with `subject` or, on AllergyIntolerance and FamilyMemberHistory, `patient`. Every Condition, Procedure, and Observation also points to the Encounter of the note:

```json theme={null}
"encounter": {
  "reference": "urn:uuid:4a6f6e1e-1d5c-5b8a-9a52-0f3a1e2c7d10",
  "type": "Encounter",
  "identifier": {
    "system": "http://corti.app/fhir/identifier/encounter",
    "value": "4a6f6e1e-1d5c-5b8a-9a52-0f3a1e2c7d10"
  }
}
```

`reference` names the `fullUrl` of the Encounter's entry in the same Bundle, and `identifier` repeats the Encounter's business ID, so you can link the resources when you import them. AllergyIntolerance and FamilyMemberHistory carry no `encounter` reference, because allergies and family history outlast a single visit. R4 defines an optional `encounter` on AllergyIntolerance, but the endpoint does not fill it.

Some references carry only a `display` name, for example the clinician who asserted a diagnosis:

```json theme={null}
"asserter": { "display": "Dr. Patel" }
```

## Bundles

A **Bundle** is a FHIR resource that holds other resources ([FHIR R4 Bundle](https://hl7.org/fhir/R4/bundle.html)). The endpoint returns a Bundle of type `transaction`. Each item in `entry` wraps one resource, and its `fullUrl` matches the resource's `id`, so references between the resources resolve inside the Bundle. Each `request` tells a FHIR server to create the resource, so you can POST the Bundle as it is to your server:

```json theme={null}
{
  "resourceType": "Bundle",
  "type": "transaction",
  "timestamp": "2026-11-03T09:14:22.512345+00:00",
  "entry": [
    {
      "fullUrl": "urn:uuid:b49ecda5-92db-5325-a7a9-f82c71500bad",
      "resource": { "resourceType": "Patient", "id": "b49ecda5-92db-5325-a7a9-f82c71500bad" },
      "request": { "method": "POST", "url": "Patient", "ifNoneExist": "identifier=http://corti.app/fhir/identifier/patient|pat-10442" }
    },
    {
      "fullUrl": "urn:uuid:29543af8-9ec2-528e-8a3b-1e891822d99d",
      "resource": { "resourceType": "Encounter", "id": "29543af8-9ec2-528e-8a3b-1e891822d99d" },
      "request": { "method": "POST", "url": "Encounter", "ifNoneExist": "identifier=http://corti.app/fhir/identifier/encounter|enc-88213" }
    },
    {
      "fullUrl": "urn:uuid:3b3921ad-2029-560e-b13c-0505d69698bd",
      "resource": { "resourceType": "Condition", "id": "3b3921ad-2029-560e-b13c-0505d69698bd" },
      "request": { "method": "POST", "url": "Condition" }
    }
  ]
}
```

The order is always the same: Patient, Encounter, then Conditions, AllergyIntolerances, FamilyMemberHistories, Procedures, and Observations.

## Put it together

Here is a short note and the Condition the endpoint produces from it, first simplified and then as the real JSON.

```text theme={null}
Possible asthma since childhood, to be confirmed with spirometry.
```

> [tab] Simplified
>
> | Field | Value |
> | - | - |
> | `code` | `195967001` Asthma |
> | `clinicalStatus` | `active` |
> | `verificationStatus` | `provisional` |
> | `onsetString` | `childhood` |
> | `subject` | the Patient of this note |
> | `encounter` | the Encounter of this note |

> [tab] JSON
>
> ```json theme={null}
> {
>   "resourceType": "Condition",
>   "clinicalStatus": {
>     "coding": [
>       {
>         "system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
>         "code": "active",
>         "display": "Active"
>       }
>     ],
>     "text": "Active"
>   },
>   "verificationStatus": {
>     "coding": [
>       {
>         "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status",
>         "code": "provisional",
>         "display": "Provisional"
>       }
>     ],
>     "text": "Provisional"
>   },
>   "code": {
>     "coding": [
>       {
>         "system": "http://snomed.info/sct",
>         "code": "195967001",
>         "display": "Asthma"
>       }
>     ],
>     "text": "Asthma"
>   },
>   "subject": { "reference": "urn:uuid:b49ecda5-92db-5325-a7a9-f82c71500bad", "type": "Patient" },
>   "encounter": {
>     "reference": "urn:uuid:4a6f6e1e-1d5c-5b8a-9a52-0f3a1e2c7d10",
>     "type": "Encounter",
>     "identifier": {
>       "system": "http://corti.app/fhir/identifier/encounter",
>       "value": "4a6f6e1e-1d5c-5b8a-9a52-0f3a1e2c7d10"
>     }
>   },
>   "onsetString": "childhood"
> }
> ```

The real response also carries `extension` entries that point back to the words in the note. [Every value points back to the note](https://docs.corti.ai/fhir/how-it-works.md#every-value-points-back-to-the-note) explains them.

## Next steps

> [card] [How FHIR Extraction works](https://docs.corti.ai/fhir/how-it-works.md)
>
> Learn why codes are positive, and how to read status fields.

> [card] [FHIR datatypes](https://docs.corti.ai/fhir/datatypes.md)
>
> Look up every datatype, with its fields and an example.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.