> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://imo.ferndocs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://imo.ferndocs.com/_mcp/server.

# Enrichment with clinical context

`POST /precision/normalize/enrichment` is a **Problem-domain-only** engine that
applies enhanced AI models and prioritizes the clinical context you pass with
each record.

> **Note**
>
> Enrichment accepts only `domain: "Problem"`. For every other domain use
> [`normalize`](/documentation/guides/normalize).

## Why context matters

`hypertension` in a 4-year-old and `hypertension` in a 78-year-old are not
clinically the same problem. The standard engine matches the string; enrichment
weighs the patient.

**`TypeScript`**

```typescript title="TypeScript"
const result = await client.normalize.enrich({
  clientRequestId: "enrich-001",
  preferences: { threshold: 0.6, size: 3 },
  requests: [
    {
      recordId: "1",
      domain: "Problem",
      inputTerm: "shortness of breath on exertion",
      context: {
        age: 71,
        sex: "M",
        icd10Codes: ["I50.9", "J44.9"],
        sourceText:
          "Patient reports increasing dyspnea climbing one flight of stairs.",
      },
    },
  ],
});
```

**`Python`**

```python title="Python"
from imo_precision_normalize import (
    NormalizeEnrichmentRequestPreferences,
    NormalizeEnrichmentRequestRequestsItem,
    NormalizeEnrichmentRequestRequestsItemContext,
)

result = client.normalize.enrich(
    client_request_id="enrich-001",
    preferences=NormalizeEnrichmentRequestPreferences(threshold=0.6, size=3),
    requests=[
        NormalizeEnrichmentRequestRequestsItem(
            record_id="1",
            domain="Problem",
            input_term="shortness of breath on exertion",
            context=NormalizeEnrichmentRequestRequestsItemContext(
                age=71,
                sex="M",
                icd10_codes=["I50.9", "J44.9"],
                source_text="Patient reports increasing dyspnea climbing one flight of stairs.",
            ),
        )
    ],
)
```

**`Java`**

```java title="Java"
NormalizeEnrichmentResponse result = client.normalize().enrich(
    NormalizeEnrichmentRequest.builder()
        .clientRequestId("enrich-001")
        .requests(List.of(
            NormalizeEnrichmentRequestRequestsItem.builder()
                .recordId("1")
                .domain(Domain.PROBLEM)
                .inputTerm("shortness of breath on exertion")
                .context(Context.builder()
                    .age(71)
                    .sex(Sex.M)
                    .icd10Codes(List.of("I50.9", "J44.9"))
                    .build())
                .build()))
        .build());
```

## Context fields

**`age`** `integer`

Patient age in years. Drives age-appropriate lexical selection — the response
metadata's `age_indicator` flag reports which band was applied.

---

**`sex`** `enum`

`M` or `F`. Filters sex-specific problems and surfaces the `sex_indicator` flag.

---

**`icd10_codes`** `string[]`

The patient's existing ICD-10 codes. Comorbidity history is the single highest-
leverage context field — pass it whenever you have it.

---

**`source_text`** `string`

The surrounding clinical narrative the term was extracted from. Gives the model
the sentence-level context a bare term loses.

---

**`use_count`** `integer`

How often your users have previously selected this term. Nudges ranking toward
what your population actually means.

---

### Provenance fields

`application_id`, `facility_id`, `encounter_id`, `document_id`, and `project_id`
are optional identifiers echoed back in the response. They don't affect matching —
they exist so you can trace a normalization back to where it originated.

## Reading the result

The response mirrors `normalize`, with `context` echoed back on each record so
you can confirm what the model actually considered:

```json
{
  "summary": { "count": 1, "error_count": 0 },
  "client_request_id": "enrich-001",
  "requests": [
    {
      "record_id": "1",
      "domain": "Problem",
      "input_term": "shortness of breath on exertion",
      "context": { "age": 71, "sex": "M", "icd10_codes": ["I50.9", "J44.9"] },
      "response": {
        "match_field": "input_term",
        "match_includes_assumptions": true,
        "explanation": "Matched with consideration of documented heart failure and COPD.",
        "items": [
          {
            "lexical_code": "48291",
            "lexical_title": "Dyspnea on exertion",
            "score": 0.94,
            "certainty": "High"
          }
        ]
      }
    }
  ]
}
```

> **Tip**
>
> `response.match_includes_assumptions` is your audit signal: when `true`, the
> engine inferred something beyond the literal input. Pair it with `explanation`
> when surfacing results to clinicians for review.

## Choosing an engine

| Use                                          | Engine                   |
| -------------------------------------------- | ------------------------ |
| Any domain other than Problem                | `normalize`              |
| Bulk code-to-code translation                | `normalize` (code-based) |
| Custom lexical maps                          | `normalize`              |
| Problem terms with patient context available | `enrich`                 |
| Ambiguous free text from notes               | `enrich`                 |