# Comment stocker des dossiers médicaux en utilisant FHIR R4

> Tutoriel : créez un Patient, une Observation de tension artérielle et une Condition, utilisez une transaction, effectuez une recherche, mettez à jour avec l'historique et lisez la provenance — chaque requête avec curl et la réponse réelle, sur le bac à sable gratuit.

Source: https://developers.anpheros.com/fr/guides/store-medical-records-fhir

**Ce tutoriel stocke un petit dossier médical sous forme de ressources HL7 FHIR R4 : un `Patient`, une `Observation` de tension artérielle et un diagnostic sous forme de `Condition`, puis un patient et une mesure ensemble dans une seule transaction. Il les recherche, met à jour le diagnostic sans perdre la version précédente et lit qui a écrit quoi.** Chaque requête est en `curl` brut contre le bac à sable Anpheros gratuit, et chaque réponse affichée est ce que l'API renvoie.

Si vous débutez avec FHIR, lisez d'abord [Plateforme FHIR](https://developers.anpheros.com/fr/guides/fhir) pour les concepts. Cette page est la partie pratique.

## Les trois ressources avec lesquelles la plupart des dossiers commencent

| Ressource | Ce qu'elle contient | Codé avec |
|---|---|---|
| `Patient` | la personne concernée par le dossier : nom, date de naissance, genre, identifiants d'autres systèmes | vos systèmes d'identification |
| `Observation` | tout ce qui est mesuré ou rapporté : signes vitaux, résultats de laboratoire, un poids, un score de symptôme | LOINC, unités UCUM |
| `Condition` | un diagnostic ou un problème de santé, avec son statut au fil du temps | ICD-10 (SNOMED CT derrière un drapeau de licence) |

Les médicaments (`MedicationStatement`), les allergies (`AllergyIntolerance`), les immunisations et les documents suivent le même schéma ; les [26 types de ressources pris en charge](https://developers.anpheros.com/fr/guides/fhir) sont listés dans la déclaration de capacité à `/fhir/R4/metadata`.

## Avant de commencer

Obtenez une clé sandbox (`sk_test_…`) sur [platform.anpheros.com/dashboard](https://platform.anpheros.com/dashboard/) en cliquant sur **Get a sandbox key**. Rien de ce que vous créez ici ne correspond à de véritables données de patients, et rien n'est visible par d'autres projets.

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

## Étape 1 : créer un Patient

```bash
curl -X POST "$BASE/Patient" -H "Authorization: Bearer $KEY" -H "Content-Type: application/fhir+json" -d '{
  "resourceType": "Patient",
  "identifier": [{"system": "https://clinic.example/mrn", "value": "MRN-10442"}],
  "name": [{"family": "Marin", "given": ["Ioana"]}],
  "gender": "female",
  "birthDate": "1979-04-12"
}'
```

`201 Created`, avec l'id et la version attribués par le serveur :

```json
{"resourceType": "Patient",
 "identifier": [{"system": "https://clinic.example/mrn", "value": "MRN-10442"}],
 "name": [{"family": "Marin", "given": ["Ioana"]}], "gender": "female", "birthDate": "1979-04-12",
 "id": "d09e3942-ed86-4458-b099-fa674ab21b84",
 "meta": {"versionId": "1", "lastUpdated": "2026-10-12T20:16:51.043Z"}}
```

Conservez vos propres identifiants dans `identifier` avec un `system` que vous contrôlez (ici un numéro de dossier de clinique), afin de pouvoir toujours retrouver le patient avec `GET $BASE/Patient?identifier=https://clinic.example/mrn|MRN-10442`. Le `id` FHIR est celui de la plateforme, et il est spécifique à votre projet : un autre projet verra la même personne sous un id différent.

```bash
export PID=d09e3942-ed86-4458-b099-fa674ab21b84
```

## Étape 2 : stocker une mesure en tant qu'Observation

La pression artérielle est une observation comportant deux composantes, systolique et diastolique, chacune avec son propre code LOINC. Indiquez qui l'a mesurée : ici, un appareil domestique.

```bash
curl -X POST "$BASE/Observation" -H "Authorization: Bearer $KEY" -H "Content-Type: application/fhir+json" \
     -H "X-Anpheros-Author-Type: device" -H "Idempotency-Key: bp-2026-10-10-0830" -d '{
  "resourceType": "Observation",
  "status": "final",
  "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs"}]}],
  "code": {"coding": [{"system": "http://loinc.org", "code": "85354-9", "display": "Blood pressure panel"}]},
  "subject": {"reference": "Patient/'$PID'"},
  "effectiveDateTime": "2026-10-10T08:30:00Z",
  "component": [
    {"code": {"coding": [{"system": "http://loinc.org", "code": "8480-6"}]},
     "valueQuantity": {"value": 138, "unit": "mmHg", "system": "http://unitsofmeasure.org", "code": "mm[Hg]"}},
    {"code": {"coding": [{"system": "http://loinc.org", "code": "8462-4"}]},
     "valueQuantity": {"value": 88, "unit": "mmHg", "system": "http://unitsofmeasure.org", "code": "mm[Hg]"}}
  ]
}'
```

La réponse est la ressource stockée avec `id` et `meta.versionId: "1"`. Trois détails sont importants pour un enregistrement utilisable :

- **Codes, pas des libellés.** `85354-9` signifie "panel de pression artérielle" dans tous les systèmes FHIR ; un texte libre "BP" ne le fait pas. Recherchez les codes avec `GET /v1/terminology/loinc?q=blood pressure` ([Systèmes de codes FHIR](https://developers.anpheros.com/fr/guides/fhir-code-systems)).
- **Unités UCUM** (`mm[Hg]`, `kg`, `mg/dL`) dans `valueQuantity.code`, afin que les valeurs puissent être comparées et converties.
- **`Idempotency-Key`.** Une nouvelle tentative après un délai d'attente renvoie la première réponse au lieu de stocker la mesure deux fois.

Les résultats de laboratoire sont la même ressource avec `category` `laboratory` et généralement un `referenceRange`. Pour intégrer des rapports de laboratoire complets, consultez [Comment importer des résultats de laboratoire dans un enregistrement FHIR](https://developers.anpheros.com/fr/guides/import-lab-results-fhir).

## Étape 3 : enregistrer un diagnostic en tant que Condition

```bash
curl -X POST "$BASE/Condition" -H "Authorization: Bearer $KEY" -H "Content-Type: application/fhir+json" \
     -H "X-Anpheros-Author-Type: practitioner" -d '{
  "resourceType": "Condition",
  "subject": {"reference": "Patient/'$PID'"},
  "clinicalStatus": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/condition-clinical", "code": "active"}]},
  "verificationStatus": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", "code": "confirmed"}]},
  "code": {"coding": [{"system": "http://hl7.org/fhir/sid/icd-10", "code": "I10", "display": "Essential (primary) hypertension"}]},
  "onsetDateTime": "2026-03-02"
}'
```

`clinicalStatus` (active, resolved, in remission) et `verificationStatus` (confirmed, provisional) sont séparés intentionnellement : un diagnostic suspecté n'est pas la même chose qu'un diagnostic confirmé, et un problème résolu fait toujours partie de l'historique.

## Étape 4 : créer des ressources associées en une seule transaction

Lorsque qu'un patient et sa première mesure arrivent ensemble, par exemple depuis un système de clinique, envoyez-les dans un `transaction` Bundle. Soit tout est stocké, soit rien ne l'est. Les références entre les nouvelles ressources utilisent des `urn:uuid:` ids temporaires que le serveur remplace :

```bash
curl -X POST "$BASE" -H "Authorization: Bearer $KEY" -H "Content-Type: application/fhir+json" -d '{
  "resourceType": "Bundle", "type": "transaction",
  "entry": [
    {"fullUrl": "urn:uuid:9f1c0d1e-0000-4000-8000-000000000001",
     "resource": {"resourceType": "Patient", "name": [{"family": "Stan", "given": ["Mihai"]}], "gender": "male", "birthDate": "1990-02-01"},
     "request": {"method": "POST", "url": "Patient"}},
    {"resource": {"resourceType": "Observation", "status": "final",
       "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs"}]}],
       "code": {"coding": [{"system": "http://loinc.org", "code": "29463-7", "display": "Body weight"}]},
       "subject": {"reference": "urn:uuid:9f1c0d1e-0000-4000-8000-000000000001"},
       "effectiveDateTime": "2026-10-10",
       "valueQuantity": {"value": 82.4, "unit": "kg", "system": "http://unitsofmeasure.org", "code": "kg"}},
     "request": {"method": "POST", "url": "Observation"}}
  ]
}'
```

Le `transaction-response` a une entrée par ressource, avec `"status": "201 Created"`, son `location` et la ressource stockée. Le `subject` de l'Observation pointe maintenant vers le vrai `Patient/fad3665a-…`.

## Étape 5 : recherche

```bash
curl "$BASE/Observation?patient=$PID&code=http://loinc.org|85354-9&date=ge2026-10-01&_sort=-date" \
     -H "Authorization: Bearer $KEY"
```

Vous obtenez un `searchset` Bundle avec `total` et les ressources correspondantes, les plus récentes en premier. Autres recherches que vous utiliserez souvent : `Condition?patient=$PID&clinical-status=active`, `Observation?patient=$PID&category=laboratory` et `Patient/$PID/$everything` pour l'ensemble du dossier.

## Étape 6 : mise à jour sans perte d'historique

L'hypertension se résout. Modifiez le statut et ajoutez la date de fin, et utilisez `If-Match` avec la version que vous avez lue pour ne jamais écraser la modification de quelqu'un d'autre :

```bash
curl -X PUT "$BASE/Condition/$CID" -H "Authorization: Bearer $KEY" -H "Content-Type: application/fhir+json" \
     -H 'If-Match: W/"1"' -d '{ …the same Condition…, "clinicalStatus": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/condition-clinical", "code": "resolved"}]}, "abatementDateTime": "2026-10-11" }'
```

`200 OK` avec `ETag: W/"2"`. Si une autre écriture est arrivée avant, vous obtenez `412` et relisez. La version précédente est toujours là :

```bash
curl "$BASE/Condition/$CID/_history" -H "Authorization: Bearer $KEY"
```

renvoie les deux versions : `versionId` 2 (`resolved`) et 1 (`active`). `GET $BASE/Condition/$CID/_history/1` lit l'ancienne. Rien dans un enregistrement n'est écrasé silencieusement.

## Étape 7 : voir qui a écrit quoi

Chaque écriture crée une ressource `Provenance`. Pour la mesure de la pression artérielle :

```bash
curl "$BASE/Provenance?target=Observation/$OBS" -H "Authorization: Bearer $KEY"
```

```json
{"resourceType": "Provenance",
 "target": [{"reference": "Observation/d83d9075-…/_history/1"}],
 "recorded": "2026-10-12T20:16:51.056000Z",
 "activity": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-DataOperation", "code": "CREATE"}]},
 "agent": [{"type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/provenance-participant-type", "code": "author"}]},
            "who": {"identifier": {"system": "https://anpheros.com/fhir/CodeSystem/author-type", "value": "device"}, "display": "proj_…"},
            "onBehalfOf": {"identifier": {"system": "https://anpheros.com/fhir/sid/organization", "value": "org_…"}, "display": "…"}}]}
```

Le type d'auteur que vous avez envoyé (`device`) est enregistré avec le projet et l'organisation. Envoyez `X-Anpheros-Author-Ref: Practitioner/<id>` pour nommer le clinicien derrière une écriture.

## Étape 8 : le dossier comme résumé

```bash
curl "$BASE/Patient/$PID/\$summary" -H "Authorization: Bearer $KEY"
```

renvoie un International Patient Summary : un `document` Bundle qui commence par un `Composition` et contient des sections telles que Problèmes, Médicaments, Allergies et Signes vitaux, construits à partir des ressources ci-dessus. C'est le format à transmettre à un autre système ou à imprimer pour un médecin ([Plateforme FHIR](https://developers.anpheros.com/fr/guides/fhir)).

## Vous préférez JSON sans FHIR ?

Les mêmes données sont disponibles via une vue REST plus simple, `/v1`, avec les mêmes identifiants : `POST /v1/patients/{id}/observations` prend `{"code": "85354-9", "category": "vital-signs", "effective_at": "…", "components": […]}` et stocke la même Observation FHIR. Utilisez celle qui convient le mieux à votre code. Voir [API de données médicales](https://developers.anpheros.com/fr/guides/medical-data-api) et les [SDK](https://developers.anpheros.com/fr/guides/sdks).

## Foire aux questions

### Quelle est la meilleure façon de stocker des dossiers médicaux ?
Tel qu'encodées, des ressources versionnées avec un enregistrement de qui a écrit chacune d'elles. HL7 FHIR R4 vous donne la structure (Patient, Observation, Condition et autres), des systèmes de codage standard tels que LOINC et ICD-10, et l'historique ; un backend FHIR ajoute la recherche, le consentement et la provenance par-dessus.

### Ai-je besoin d'un serveur FHIR pour utiliser FHIR ?
Vous avez besoin d'un endroit qui stocke et recherche des ressources FHIR et qui applique qui peut les lire. Vous pouvez exécuter vous-même un serveur FHIR open-source ou utiliser un serveur géré tel qu'Anpheros ; [Comment Anpheros se compare aux autres serveurs FHIR](https://developers.anpheros.com/fr/guides/fhir-server-comparison) pèse les options, et [FHIR vs une base de données médicale personnalisée](https://developers.anpheros.com/fr/guides/fhir-vs-custom-database) couvre la création de votre propre schéma à la place.

### Comment stocker la tension artérielle dans FHIR ?
Comme une `Observation` avec le code LOINC `85354-9` et deux entrées `component` : systolique `8480-6` et diastolique `8462-4`, chacune avec une `valueQuantity` en `mm[Hg]`.

### Puis-je modifier une ressource stockée ?
Oui, avec `PUT` et `If-Match`. Chaque modification crée une nouvelle version ; les versions antérieures restent lisibles via `_history`, et les enregistrements de Provenance indiquent qui a effectué chaque modification. Les suppressions sont douces et conservent l'historique.

## Liens utiles

- [Plateforme FHIR](https://developers.anpheros.com/fr/guides/fhir) : concepts, types de ressources et opérations
- [Systèmes de codes FHIR](https://developers.anpheros.com/fr/guides/fhir-code-systems) : LOINC, ICD-10, ATC, UCUM
- [Comment importer des résultats de laboratoire dans un enregistrement FHIR](https://developers.anpheros.com/fr/guides/import-lab-results-fhir)
- [API de données médicales](https://developers.anpheros.com/fr/guides/medical-data-api) : la vue REST simplifiée des mêmes données
- [Base de données et bac à sable FHIR gratuits](https://developers.anpheros.com/fr/guides/free-fhir-database)
