> ## 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.

# Filter FHIR resources

> Learn how to choose which FHIR resources the FHIR Extraction endpoint produces and restrict which codes it may assign

By default, the FHIR Extraction endpoint produces every resource it finds in a note, with any code that fits. Two optional request fields let you narrow that down:

* `resourceGroups` chooses **what** the endpoint produces. For example: Conditions and Procedures, but no Observations.
* `filters` restricts **which codes** the endpoint may assign. For example: only body sites under the knee.

The two fields work independently. You can use one, both, or neither. This guide shows an example for each common case. [Filter reference](https://docs.corti.ai/fhir/filter-reference.md) lists every field, operator, and validation rule.

## When to filter

* **You already have the data in structured form.** Lab results from your lab system or vital signs from monitors are more reliable than the same values read from a note. Turn those categories off. [Reduce extraction errors](https://docs.corti.ai/fhir/reduce-errors.md#skip-data-you-already-have-in-structured-form) explains why.
* **Your workflow only needs part of the result.** A problem-list app has no use for exam findings. A smaller response is easier to process, and Observation categories you leave out are not extracted at all, so the request uses fewer tokens.
* **Your downstream system only accepts some codes.** A diabetes registry only takes diabetes diagnoses, and an orthopedic app only cares about knee structures.

> [!NOTE]
>
> A filter limits which codes the endpoint may choose. It does not make the endpoint find more. When no allowed code fits a mention, the endpoint leaves the resource out rather than assign a code that does not fit. A tight filter can therefore remove resources you expected to see.

## Choose which resources to produce

List the resource groups you want in `resourceGroups`. A group you leave out is not produced. To narrow a group further, add `categories`:

```json theme={null}
"resourceGroups": [
  { "type": "Condition" },
  { "type": "Observation", "categories": ["exam", "social-history"] }
]
```

Patient and Encounter are always produced, so you do not need to list them. [Categories per resource group](https://docs.corti.ai/fhir/filter-reference.md#categories-per-resource-group) lists the categories of each group.

> [accordion] Example: Skip lab results and vital signs
>
> *Your lab system and monitors already send lab results and vital signs. Produce everything else.*
>
> > [tab] What it does
> >
> > | Resource group | Categories produced |
> > | - | - |
> > | Condition | all |
> > | AllergyIntolerance | all |
> > | FamilyMemberHistory | all |
> > | Procedure | all |
> > | Observation | `exam`, `social-history`, `imaging`, `survey`, `procedure` |
> >
> > The endpoint skips the `laboratory` and `vital-signs` extraction. "HbA1c 7.2 %" and "BP 150/90" produce no Observation, so the values from your lab system and monitors stay the only source. "Smokes 10 cigarettes a day" still produces a social-history Observation.
>
> > [tab] Request JSON
> >
> > ```json theme={null}
> > {
> >   "context": { "context_type": "other", "data": "Known asthma since childhood. Smokes 10 cigarettes a day. HbA1c 7.2 %. BP 150/90." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "resourceGroups": [
> >     { "type": "Condition" },
> >     { "type": "AllergyIntolerance" },
> >     { "type": "FamilyMemberHistory" },
> >     { "type": "Procedure" },
> >     {
> >       "type": "Observation",
> >       "categories": ["exam", "social-history", "imaging", "survey", "procedure"]
> >     }
> >   ]
> > }
> > ```

> [accordion] Example: Build a problem list
>
> *Produce only the diagnoses that belong on a problem list.*
>
> > [tab] What it does
> >
> > | Resource group | Categories produced |
> > | - | - |
> > | Condition | `problem-list-item` |
> >
> > The response holds the Patient, the Encounter, and the Conditions with category `problem-list-item`. A chronic condition such as "Type 2 diabetes for 10 years" stays. A diagnosis that only concerns this visit, such as "Acute bronchitis", has category `encounter-diagnosis`, so the endpoint drops it. No Observations, Procedures, allergies, or family history appear.
>
> > [tab] Request JSON
> >
> > ```json theme={null}
> > {
> >   "context": { "context_type": "other", "data": "Type 2 diabetes for 10 years. Today: acute bronchitis. BP 138/84." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "resourceGroups": [
> >     { "type": "Condition", "categories": ["problem-list-item"] }
> >   ]
> > }
> > ```

## Restrict which codes the endpoint assigns

Each entry in `filters` applies to one coding system, named in `systemId`. It allows codes with `include`, removes codes with `exclude`, and can narrow where it applies with `scope`:

```json theme={null}
"filters": [
  {
    "systemId": "snomed-ct-int",
    "scope": { "resourceGroup": "Condition", "field": "bodySite" },
    "include": {
      "conditions": [
        { "property": "code", "op": "is-a", "value": "72696002" }
      ]
    }
  }
]
```

Without a `scope`, a filter applies to the `code` field of every resource group that uses the coding system. The examples below go from the widest scope to the narrowest.

> [accordion] Example: Remove a whole branch of SNOMED CT
>
> *Do not assign codes under "Mental disorder" (`74732009`) anywhere.*
>
> > [tab] What it does
> >
> > | Coding system | Applies to | Restriction |
> > | - | - | - |
> > | SNOMED CT | the `code` field, in every resource group | removes `74732009` Mental disorder and all its descendants |
> >
> > Use this when your application must not store a sensitive kind of diagnosis. "Generalized anxiety disorder" produces no Condition, and "Mother has depression" produces no FamilyMemberHistory. "Known asthma" still produces a Condition.
> >
> > The filter leaves `bodySite` and `valueCodeableConcept` alone, because a filter without a scope only applies to `code`.
>
> > [tab] Request JSON
> >
> > ```json theme={null}
> > {
> >   "context": { "context_type": "other", "data": "Known asthma. Generalized anxiety disorder, on sertraline. Mother has depression." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "filters": [
> >     {
> >       "systemId": "snomed-ct-int",
> >       "exclude": {
> >         "conditions": [
> >           { "property": "code", "op": "is-a", "value": "74732009" }
> >         ]
> >       }
> >     }
> >   ]
> > }
> > ```

> [accordion] Example: Restrict one resource group
>
> *Only allow disorders as Condition codes.*
>
> > [tab] What it does
> >
> > | Coding system | Applies to | Restriction |
> > | - | - | - |
> > | SNOMED CT | `code` searches on Conditions | only disorders are eligible, not findings or events |
> >
> > Condition codes always come from SNOMED CT disorders, findings, and events. This filter narrows that built-in scope to disorders, so "Chest pain on exertion" (a finding) produces no Condition.
>
> > [tab] Request JSON
> >
> > ```json theme={null}
> > {
> >   "context": { "context_type": "other", "data": "Known asthma since childhood. Chest pain on exertion." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "filters": [
> >     {
> >       "systemId": "snomed-ct-int",
> >       "scope": { "resourceGroup": "Condition" },
> >       "include": {
> >         "conditions": [
> >           { "property": "semantic_tag", "op": "in", "value": ["disorder"] }
> >         ]
> >       }
> >     }
> >   ]
> > }
> > ```

> [accordion] Example: Restrict one category
>
> *Only allow the two HbA1c LOINC codes for laboratory results.*
>
> > [tab] What it does
> >
> > | Coding system | Applies to | Restriction |
> > | - | - | - |
> > | LOINC | laboratory Observations, field `code` | only the HbA1c codes `4548-4` and `17856-6` are eligible |
> >
> > The filter leaves the other Observation categories alone.
>
> > [tab] Request JSON
> >
> > ```json theme={null}
> > {
> >   "context": { "context_type": "other", "data": "Left knee pain. HbA1c 7.2 %. BP 150/90." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "filters": [
> >     {
> >       "systemId": "loinc",
> >       "scope": { "resourceGroup": "Observation", "category": "laboratory" },
> >       "include": {
> >         "conditions": [
> >           { "property": "code", "op": "in", "value": ["4548-4", "17856-6"] }
> >         ]
> >       }
> >     }
> >   ]
> > }
> > ```

> [accordion] Example: Restrict one field
>
> *Only allow knee structures as the body site of a Condition.*
>
> > [tab] What it does
> >
> > | Coding system | Applies to | Restriction |
> > | - | - | - |
> > | SNOMED CT | the `bodySite` field on Conditions | only `72696002` Knee region structure and its descendants are eligible |
> >
> > The filter leaves the Condition `code` field alone.
>
> > [tab] Request JSON
> >
> > ```json theme={null}
> > {
> >   "context": { "context_type": "other", "data": "Left knee pain. HbA1c 7.2 %. BP 150/90." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "filters": [
> >     {
> >       "systemId": "snomed-ct-int",
> >       "scope": { "resourceGroup": "Condition", "field": "bodySite" },
> >       "include": {
> >         "conditions": [
> >           { "property": "code", "op": "is-a", "value": "72696002" }
> >         ]
> >       }
> >     }
> >   ]
> > }
> > ```

## Combine filters

When several filters apply to the same field, a code must match every `include` and no `exclude`. A filter can also only narrow the [built-in scope](https://docs.corti.ai/fhir/how-it-works.md#codes-come-from-a-fixed-scope) of a field, never widen it. [How filters combine](https://docs.corti.ai/fhir/filter-reference.md#how-filters-combine) lists the rules.

> [accordion] Example: Combine two filters
>
> *Allow a short list of LOINC codes for all Observations, and narrow laboratory results further.*
>
> > [tab] What it does
> >
> > | Coding system | Applies to | Restriction |
> > | - | - | - |
> > | LOINC | `code` searches in every Observation category that uses LOINC | only heart rate, blood pressure, respiratory rate, and HbA1c codes are eligible |
> > | LOINC | laboratory Observations, field `code` | only the HbA1c codes `4548-4` and `17856-6` are eligible |
> >
> > Both filters apply to laboratory Observations, so a laboratory code must match both includes. Only the HbA1c codes pass. The other Observation categories only need to match the first include.
>
> > [tab] Request JSON
> >
> > ```json theme={null}
> > {
> >   "context": { "context_type": "other", "data": "BP 150/90, heart rate 88, respiratory rate 16. HbA1c 7.2 %." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "filters": [
> >     {
> >       "systemId": "loinc",
> >       "scope": { "resourceGroup": "Observation" },
> >       "include": {
> >         "conditions": [
> >           { "property": "code", "op": "in", "value": ["8867-4", "8480-6", "8462-4", "9279-1", "4548-4", "17856-6"] }
> >         ]
> >       }
> >     },
> >     {
> >       "systemId": "loinc",
> >       "scope": { "resourceGroup": "Observation", "category": "laboratory" },
> >       "include": {
> >         "conditions": [
> >           { "property": "code", "op": "in", "value": ["4548-4", "17856-6"] }
> >         ]
> >       }
> >     }
> >   ]
> > }
> > ```

## Fix a rejected filter

The endpoint checks every filter before it starts. A filter that could never change the response, such as a filter on a field the resource does not have, returns a 400 instead of being ignored. The error `message` names the part of the filter that failed. For a value outside a fixed list, such as an unknown category or `op`, `details` names the field instead. Check it against [Validation rules](https://docs.corti.ai/fhir/filter-reference.md#validation-rules).

> [accordion] Example: A rejected filter
>
> *An AllergyIntolerance `bodySite` filter fails, because the resource has no body site field.*
>
> > [tab] Why it fails
> >
> > The request scopes a SNOMED CT filter to the `bodySite` field of AllergyIntolerance. A FHIR R4 AllergyIntolerance has no `bodySite` field, so the filter could never change the response. The endpoint returns a 400 instead of ignoring the filter.
>
> > [tab] Request and response
> >
> > ```json title="Request" theme={null}
> > {
> >   "context": { "context_type": "other", "data": "Penicillin gives her a rash." },
> >   "patient": {
> >     "identifier": "<your-patient-id>",
> >     "name": "Anna Miller",
> >     "gender": "female",
> >     "birthDate": "1968-04-02"
> >   },
> >   "encounter": {
> >     "identifier": "<your-encounter-id>",
> >     "status": "finished",
> >     "class": "ambulatory",
> >     "priority": "routine",
> >     "type": "Follow-up visit",
> >     "serviceType": "General practice",
> >     "reasonCode": "Routine follow-up",
> >     "period": { "start": "2026-11-03T09:00:00+01:00", "end": "2026-11-03T09:20:00+01:00" }
> >   },
> >   "filters": [
> >     {
> >       "systemId": "snomed-ct-int",
> >       "scope": { "resourceGroup": "AllergyIntolerance", "field": "bodySite" },
> >       "exclude": {
> >         "conditions": [
> >           { "property": "code", "op": "is-a", "value": "72696002" }
> >         ]
> >       }
> >     }
> >   ]
> > }
> > ```
> >
> > ```json title="Response (400)" theme={null}
> > {
> >   "error": {
> >     "code": "VALIDATION_ERROR",
> >     "message": "Filter for resource group 'AllergyIntolerance', field 'bodySite', system 'snomed-ct-int' does not name a search this service performs.",
> >     "request_id": "<request-id>"
> >   }
> > }
> > ```

## Next steps

> [card] [FHIR filter reference](https://docs.corti.ai/fhir/filter-reference.md)
>
> Look up every field, operator, category, and validation rule.

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

> [!NOTE]
>
> Please [contact us](mailto:help@corti.ai) if you need help configuring your filters.


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