> ## 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 filter reference

> Look up every field, operator, category, and validation rule of the FHIR Extraction resourceGroups and filters request fields

This page lists every field and rule of the two filtering fields in a FHIR Extraction request: `resourceGroups` and `filters`. For when to use them, with worked examples, see [Filter FHIR resources](https://docs.corti.ai/fhir/filtering.md).

## `resourceGroups`

A list of the resource groups to produce. Each entry names one group, and can narrow it to some of its categories.

| Parameter | Type | Definition |
| - | - | - |
| `type` | string | **Required.** `Condition`, `AllergyIntolerance`, `FamilyMemberHistory`, `Procedure`, `Observation`, `Patient`, or `Encounter`. |
| `categories` | array of strings | The categories to produce within the group. Omit it to produce all categories. Must not be empty. |

Rules:

* Omit the field to produce every group with every category. A group you leave out of the list is not produced.
* An empty list returns a 422. Omit the field instead.
* Listing the same group twice returns a 400.
* The response always contains one Patient and one Encounter. Listing them has no effect, and you cannot turn them off.

### Categories per resource group

Not every group has categories, and categories work differently per group. The values come from the R4 value sets for [Observation category](https://hl7.org/fhir/R4/valueset-observation-category.html), [Condition category](https://hl7.org/fhir/R4/valueset-condition-category.html), and [AllergyIntolerance category](https://hl7.org/fhir/R4/valueset-allergy-intolerance-category.html). The Procedure values are SNOMED CT concepts, in line with the R4 [procedure category](https://hl7.org/fhir/R4/valueset-procedure-category.html) example set.

| Resource group | Categories | What a selection does |
| - | - | - |
| Observation | `laboratory`, `vital-signs`, `survey`, `exam`, `social-history`, `imaging`, `procedure` | The endpoint only extracts the selected categories. It skips the rest, so the request uses fewer tokens. |
| Condition | `problem-list-item`, `encounter-diagnosis` | The endpoint extracts all Conditions, then drops those outside the selection. It also drops Conditions without a category. |
| AllergyIntolerance | `food`, `medication`, `environment`, `biologic` | Same as Condition. |
| Procedure | Nine values, listed below | Same as Condition. |
| FamilyMemberHistory | None | Omit `categories`. A list returns a 400. |
| Patient, Encounter | None | Always produced. |

**Procedure category values**

`Psychiatry procedure or service`, `Counseling`, `Education`, `Surgical procedure`, `Laboratory test`, `Imaging`, `Measurement`, `Chiropractic manipulation`, `Social service procedure`.

FHIR also defines the Observation categories `therapy` and `activity`. The endpoint does not produce them, and returns a 400 if you select them.

What the Observation categories hold:

| Category | Example from a note |
| - | - |
| `laboratory` | "HbA1c 7.2 %", "Potassium 4.1 mmol/L" |
| `vital-signs` | "BP 150/90", "Temp 38.2" |
| `survey` | "PHQ-9 score 14", "GCS 15" |
| `exam` | "Abdomen soft, non-tender", "No murmurs" |
| `social-history` | "Smokes 10 cigarettes a day", "Drinks 2 units a week" |
| `imaging` | "Chest X-ray shows right lower lobe consolidation" |
| `procedure` | Findings and measurements from procedures, such as "ECG shows sinus rhythm" |

## `filters`

A list of code filters. Each filter applies to one coding system.

| Parameter | Type | Definition |
| - | - | - |
| `systemId` | string | **Required.** The coding system to filter: `snomed-ct-int` (or your national SNOMED CT edition, such as `snomed-ct-uk`) or `loinc`. |
| `include` | [condition group](#condition-groups) | The endpoint only allows codes that match. Omit it to allow every code. |
| `exclude` | [condition group](#condition-groups) | The endpoint removes codes that match. Omit it to remove nothing. |
| `scope` | [object](#scope) | Where the filter applies. Omit it to apply the filter to every `code` field that uses this coding system. |

The allowed codes are the `include` set minus the `exclude` set, within the [built-in scope](https://docs.corti.ai/fhir/how-it-works.md#codes-come-from-a-fixed-scope) of each field.

### Condition groups

A condition group combines one or more conditions:

```json theme={null}
{
  "match": "all",
  "conditions": [
    { "property": "code", "op": "is-a", "value": "73211009" },
    { "property": "semantic_tag", "op": "in", "value": ["disorder"] }
  ]
}
```

This group allows codes that are diabetes mellitus (`73211009`) or a subtype of it, **and** that are SNOMED CT disorders.

| Parameter | Type | Definition |
| - | - | - |
| `match` | string | `all` requires every condition to match. `any` requires at least one. You can omit it when the group has one condition. |
| `conditions` | array | Conditions, or nested condition groups, up to three levels deep. Must not be empty. |

### Conditions

Each condition has a `property`, an `op`, and a `value`:

| `op` | Matches | `value` | Example |
| - | - | - | - |
| `is-a` | The code and all its descendants | Code, or list of codes | `{ "property": "code", "op": "is-a", "value": "72696002" }` matches knee region structure and every part of the knee |
| `descendent-of` | Only the descendants, not the code itself | Code, or list of codes | `{ "property": "code", "op": "descendent-of", "value": "73211009" }` matches diabetes subtypes, but not "Diabetes mellitus" itself |
| `in` | Any value in the list | List | `{ "property": "code", "op": "in", "value": ["4548-4", "17856-6"] }` matches two HbA1c LOINC codes |
| `=` | Exactly the value | Single value | `{ "property": "semantic_tag", "op": "=", "value": "disorder" }` |
| `exists` | Whether the property has a value | `true` or `false` | `{ "property": "semantic_tag", "op": "exists", "value": true }` |

The properties you can filter on:

| Property | Coding system | Operators |
| - | - | - |
| `code` | SNOMED CT, LOINC | `=`, `in`, `is-a`, `descendent-of` |
| `semantic_tag` | SNOMED CT, for example `disorder`, `finding`, `procedure` | `=`, `in`, `exists` |

### Scope

A `scope` narrows a filter to one resource group, one category, or one field:

| Parameter | Type | Definition |
| - | - | - |
| `resourceGroup` | string | The resource group, for example `Condition`. Omit it to apply to all groups. |
| `category` | string | A category of `resourceGroup`, for example `laboratory`. Requires `resourceGroup`. |
| `field` | string | The coded field: `code` (the default), `bodySite`, or `valueCodeableConcept`. |

Rules:

* A filter without `field` applies to the `code` field only. To filter body sites, set `field` to `bodySite`.
* A category scope on Observation restricts the whole category. On Condition, AllergyIntolerance, and Procedure, a category scope only applies to resources that have that category.

### How filters combine

When several filters apply to the same field, they combine:

* **Includes intersect.** A code must match every `include` that applies.
* **Excludes add up.** The endpoint removes a code that matches any `exclude` that applies.
* **The built-in scope always applies.** An `include` narrows the [built-in scope](https://docs.corti.ai/fhir/how-it-works.md#codes-come-from-a-fixed-scope) of a field. It cannot widen it.

### Filterable fields

A `scope` must point to a field that the endpoint actually codes. This table lists every valid combination. Any other combination returns a 400.

| Resource group | Category | Filterable fields |
| - | - | - |
| Condition | any | `code` (SNOMED CT), `bodySite` (SNOMED CT) |
| AllergyIntolerance | any | `code` (SNOMED CT) |
| FamilyMemberHistory | none | `code` (SNOMED CT) |
| Procedure | any | `code` (SNOMED CT), `bodySite` (SNOMED CT) |
| Observation | `laboratory` | `code` (LOINC) |
| Observation | `vital-signs` | `code` (LOINC), `bodySite` (SNOMED CT) |
| Observation | `survey` | `code` (LOINC), `bodySite` (SNOMED CT) |
| Observation | `exam` | `code` (SNOMED CT), `bodySite` (SNOMED CT) |
| Observation | `social-history` | `code` (SNOMED CT, LOINC), `bodySite` (SNOMED CT) |
| Observation | `imaging` | `code` (SNOMED CT, LOINC), `bodySite` (SNOMED CT), `valueCodeableConcept` (SNOMED CT) |
| Observation | `procedure` | `code` (SNOMED CT, LOINC), `bodySite` (SNOMED CT) |
| Patient, Encounter | none | none |

Three Observation categories use two coding systems for `code`: LOINC for measurements, such as "20 pack-years", and SNOMED CT for findings, such as "never smoked". A LOINC filter on these categories only affects the measurements. See [Measurements and findings](https://docs.corti.ai/fhir/resource-groups/observation.md#measurements-and-findings).

`valueCodeableConcept` is only filterable on `imaging`, where it holds a qualifier such as Present, Absent, or Severe. The other finding categories use a fixed Present or Absent pair.

The FHIR R4 AllergyIntolerance and FamilyMemberHistory resources have no `bodySite` field, so you cannot filter one.

## Validation rules

The endpoint checks every filter before it starts. A filter that would have no effect is an error, so you never get a silently ignored filter.

The request returns a 400 when:

* `systemId` names a coding system the endpoint does not use. The error message lists the valid ones.
* `scope.category` is set without `scope.resourceGroup`.
* A category does not belong to its group, or the group has no categories.
* The combination of `resourceGroup`, `field`, and `systemId` is not in the [filterable fields](#filterable-fields) table, for example `bodySite` in LOINC.
* The filter applies to a group or category that `resourceGroups` turns off.
* A condition is invalid: an unknown property or `op`, `is-a` or `descendent-of` on a property other than `code`, a code that does not exist, or an unknown `semantic_tag`.
* `resourceGroups` lists the same group twice, or lists `categories` for FamilyMemberHistory, Patient, or Encounter.

The request returns a 422 when:

* `resourceGroups`, `categories`, or a group's `conditions` is an empty list.
* A condition's `value` does not fit its `op`: `in` needs a list, `exists` needs `true` or `false`, and `is-a` and `descendent-of` need a code or a list of codes.
* A group has more than one condition and no `match`.
* Condition groups nest more than three levels deep.

## Next steps

> [card] [Filter FHIR resources](https://docs.corti.ai/fhir/filtering.md)
>
> See worked examples for each kind of filter.

> [card] [Observation resource group](https://docs.corti.ai/fhir/resource-groups/observation.md)
>
> See how each Observation category looks in the response.


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