# Symptom data API: concepts, FHIR terminology and patient-reported symptoms

> Stable symptom identifiers mapped to ICD-10, served as REST and as FHIR CodeSystem, ValueSet and ConceptMap; how a patient-reported symptom Observation looks and how to validate one.

Source: https://developers.anpheros.com/guides/symptom-data-api

**Anpheros gives every symptom a stable identifier (`SYM-0047` is headache), maps it to ICD-10, and serves the list through a REST endpoint and as FHIR R4 terminology (`CodeSystem`, `ValueSet`, `ConceptMap`, `$lookup`). Symptoms that patients report are stored as FHIR `Observation`s that carry both codes, the person's own words, the intensity and, when known, when the symptom started and ended.** This page shows how to find a concept, how a patient-reported symptom looks, how to check one you write yourself, and what the data deliberately does not contain.

## What is in the release

| | |
|---|---|
| Release | `2026.10.1` (every response says which) |
| Concepts | 86: 70 symptoms (ICD-10 R00–R69, plus the WHO code where WHO classifies the symptom elsewhere: G47, H53.2, H53.8, H93.1, K59.0, L29.9, M25.5, M54) and 16 findings (R70–R94) |
| Identifier system | `https://anpheros.com/fhir/CodeSystem/symptom` |
| Codes and English titles | checked against WHO ICD-10 Version 2019 (15 October 2026), with its inclusion and exclusion notes |
| Labels served | the WHO English title (`source`), the Romanian labels and match terms used by Anpheros Daily (`in_use`), and lay labels in 19 more languages (`ai_reviewed`: machine translations reviewed with AI assistance, not by a professional medical translator) |
| Clinical review | `clinical_review: false` — no clinician has reviewed the release; no causes or condition associations |
| Warning signs | 32, for 14 concepts, quoted word for word from CDC and NIDDK pages (`review: source_verified`) |

Identifiers are never reused. A concept that is withdrawn stays in the list with `status: deprecated`.

## Find a concept (REST)

```bash
export API=https://platform.anpheros.com/v1
export KEY=sk_test_…

curl "$API/terminology/symptoms?q=headache" -H "Authorization: Bearer $KEY"
```

`q` matches the concept id, the ICD-10 code, the labels and the match terms. Other parameters: `icd10=R51` (the concept for one code), `kind=symptom|finding|all`, `lang=de` (the language of `display`: the preferred label, else the lay label, else English), `limit` and `offset`.

```json
{
  "data": [{
    "concept_id": "SYM-0047",
    "system": "https://anpheros.com/fhir/CodeSystem/symptom",
    "kind": "symptom",
    "status": "active",
    "display": "Headache",
    "display_lang": "en",
    "icd10": {"system": "http://hl7.org/fhir/sid/icd-10", "code": "R51", "display": "Headache", "equivalence": "equivalent"},
    "labels": [
      {"lang": "ro", "use": "preferred", "text": "Durere de cap (cefalee)", "review": "in_use"},
      {"lang": "de", "use": "lay", "text": "Kopfschmerzen", "review": "ai_reviewed"}
    ],
    "match_terms": [{"lang": "ro", "text": "durere de cap"}, {"lang": "ro", "text": "cefalee"}],
    "clinical_review": false,
    "release": "2026.10.1"
  }],
  "total": 1,
  "release": "2026.10.1"
}
```

`labels` lists every served label (20 languages; shortened here). One concept: `GET $API/terminology/symptoms/SYM-0047`.

## The same list as FHIR terminology

```bash
export BASE=https://platform.anpheros.com/fhir/R4

curl "$BASE/CodeSystem/anpheros-symptom" -H "Authorization: Bearer $KEY"
curl "$BASE/CodeSystem/\$lookup?system=https://anpheros.com/fhir/CodeSystem/symptom&code=SYM-0047&displayLanguage=ro" -H "Authorization: Bearer $KEY"
curl "$BASE/ValueSet/\$expand?url=https://anpheros.com/fhir/ValueSet/anpheros-symptoms&filter=cough" -H "Authorization: Bearer $KEY"
curl "$BASE/ConceptMap/anpheros-symptom-to-icd10" -H "Authorization: Bearer $KEY"
```

- `CodeSystem/anpheros-symptom` — `content: complete`, `status: draft` until the release is clinically reviewed; properties `kind`, `status`, `icd10`; Romanian labels, match terms and lay labels as `designation`s.
- `ValueSet/anpheros-symptoms` — the active symptoms (findings excluded); `$expand` takes `filter`, `displayLanguage`, `count` and `offset`.
- `ConceptMap/anpheros-symptom-to-icd10` — `equivalent`, or `wider` when the ICD-10 code covers more than the concept (H53.8 "Other visual disturbances" is broader than blurred vision).
- All of them are read-only and listed in the server's `CapabilityStatement` (`GET $BASE/metadata`).

## A patient-reported symptom

This is how Anpheros Daily writes a symptom a person reported as present, about themselves:

```json
{
  "resourceType": "Observation",
  "status": "final",
  "meta": {"profile": ["https://anpheros.com/fhir/StructureDefinition/anpheros-symptom-observation"]},
  "category": [{"coding": [{"system": "urn:anpheros:observation-category", "code": "symptom"}]}],
  "code": {
    "text": "Mă doare capul de 3 zile",
    "coding": [
      {"system": "http://hl7.org/fhir/sid/icd-10", "code": "R51", "display": "Headache"},
      {"system": "https://anpheros.com/fhir/CodeSystem/symptom", "code": "SYM-0047", "display": "Headache"}
    ]
  },
  "subject": {"reference": "Patient/…"},
  "effectivePeriod": {"start": "2026-10-11T08:00:00+03:00", "end": "2026-10-14T18:00:00+03:00"},
  "valueQuantity": {"value": 6, "unit": "1-10", "system": "http://unitsofmeasure.org", "code": "{score}"}
}
```

- `code.text` is always the person's own words, in their language (`Observation.language`); the codes sit next to it.
- `effectivePeriod` is used when the person said when it started or ended; otherwise `effectiveDateTime` is the moment they noted it. Times keep the offset of the phone that recorded them.
- `valueQuantity` is the intensity on a 1–10 scale; without one there is no value.
- When the person edits a symptom, the same resource gets a new version — read earlier ones with `GET $BASE/Observation/{id}/_history`.
- Filter by category with `?category=symptom`; consent scopes such as `patient/Observation.rs?category=symptom` work the same way.

### What is never published as a symptom

Only symptoms that are **present** and **about the patient** become Observations, and only after the free text has been normalized. "My head no longer hurts", "maybe a fever tomorrow", "my mother has a cough" or a text the normalizer could not read do not become a patient's symptom; if a published symptom is later corrected to one of these, its Observation is withdrawn (soft delete — the history stays). Relatives' complaints are not turned into family history automatically.

## Check a symptom you write

```bash
curl -X POST "$BASE/Observation/\$validate?profile=anpheros-symptom" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/fhir+json" -d @symptom.json
```

The `anpheros-symptom` profile (canonical `https://anpheros.com/fhir/StructureDefinition/anpheros-symptom-observation`) reports, as an `OperationOutcome`:

| Rule | Severity |
|---|---|
| Category `urn:anpheros:observation-category\|symptom` (the HL7 `observation-category` system has no `symptom` code) | error |
| `code.text` present | error |
| An Anpheros concept that exists and matches the ICD-10 code | error |
| `subject` is a Patient; `status` final, amended, corrected or entered-in-error; `effective[x]` present; `effectivePeriod.end` not before `start` | error |
| Intensity as UCUM `{score}` between 0 and 10 | error |
| Only free text, no codes | information (still valid) |

Like the other profiles, it reports and does not reject writes. A `meta.profile` you send is kept on the stored resource.

## Limits

- The release is not clinically reviewed; use it for coding and search, not for medical decisions.
- Warning signs are quoted word for word from public-domain US federal pages (CDC: stroke and heart attack signs; NIDDK: diarrhea and constipation) and were checked against those pages on 15 October 2026. Each item carries the source's own heading (`context`), its advice (`quote`), the group it applies to (`applies_to`), the source with licence and attribution, `review: source_verified` and the note that it is not a diagnosis and not reviewed by a clinician. The sources are American: where a quote says 9-1-1, the note adds that the emergency number in Europe is 112.
- No causes or condition associations are served: `associations` stays empty until a clinician reviews an item. An association is always "may be associated with".
- SNOMED CT codes are written only where the licence allows it (see [FHIR code systems](https://developers.anpheros.com/guides/fhir-code-systems)).
- Earlier symptom Observations receive the Anpheros concept coding the next time they are updated.

## Related

- [FHIR code systems](https://developers.anpheros.com/guides/fhir-code-systems): every code system per resource type
- [Longitudinal patient data API](https://developers.anpheros.com/guides/longitudinal-patient-data-api)
- [How to store medical records using FHIR R4](https://developers.anpheros.com/guides/store-medical-records-fhir)
- [FHIR platform](https://developers.anpheros.com/guides/fhir)
