Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Cómo almacenar expedientes médicos usando FHIR R4
Tutorial: crear un Paciente, una Observación de presión arterial y una Condición, usar una transacción, buscar, actualizar con historial y leer procedencia — cada solicitud con curl y la respuesta real, en el sandbox gratuito.
Este tutorial almacena un pequeño registro médico como recursos HL7 FHIR R4: un Patient, una Observation de presión arterial y un diagnóstico como Condition, luego un paciente y una medición juntos en una transacción. Los busca, actualiza el diagnóstico sin perder la versión anterior y lee quién escribió qué. Cada solicitud es curl plano contra el sandbox gratuito de Anpheros, y cada respuesta mostrada es lo que la API devuelve.
Si es nuevo en FHIR, lea primero Plataforma FHIR para conocer los conceptos. Esta página es la parte práctica.
Los tres recursos con los que comienzan la mayoría de los registros
| Recurso | Qué contiene | Codificado con |
|---|---|---|
Patient |
de quién es el registro: nombre, fecha de nacimiento, género, identificadores de otros sistemas | sus sistemas de identificadores |
Observation |
cualquier cosa medida o informada: signos vitales, resultados de laboratorio, un peso, una puntuación de síntomas | LOINC, unidades UCUM |
Condition |
un diagnóstico o un problema de salud, con su estado a lo largo del tiempo | ICD-10 (SNOMED CT detrás de una bandera de licencia) |
Los medicamentos (MedicationStatement), las alergias (AllergyIntolerance), las inmunizaciones y los documentos siguen el mismo patrón; los 26 tipos de recursos compatibles se enumeran en la declaración de capacidad en /fhir/R4/metadata.
Antes de empezar
Obtenga una clave de sandbox (sk_test_…) en platform.anpheros.com/dashboard con Get a sandbox key. Nada de lo que cree allí son datos reales de pacientes, y nada es visible para otros proyectos.
export BASE=https://platform.anpheros.com/fhir/R4
export KEY=sk_test_…
Paso 1: Crear un Paciente
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, con el id y la versión que el servidor asignó:
{"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"}}
Conserve sus propios ids en identifier con un system que usted controle (aquí un número de registro de clínica), para que siempre pueda encontrar al paciente de nuevo con GET $BASE/Patient?identifier=https://clinic.example/mrn|MRN-10442. El id de FHIR es el de la plataforma, y es específico de su proyecto: otro proyecto verá a la misma persona bajo un id diferente.
export PID=d09e3942-ed86-4458-b099-fa674ab21b84
Paso 2: Almacenar una medición como una Observación
La presión arterial es una observación con dos componentes, sistólica y diastólica, cada una con su propio código LOINC. Indique quién la midió: aquí un dispositivo doméstico.
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 respuesta es el recurso almacenado con id y meta.versionId: "1". Tres detalles son importantes para un registro utilizable:
- Códigos, no etiquetas.
85354-9significa "panel de presión arterial" en todos los sistemas FHIR; un texto libre "BP" no lo hace. Busque códigos conGET /v1/terminology/loinc?q=blood pressure(Sistemas de códigos FHIR). - Unidades UCUM (
mm[Hg],kg,mg/dL) envalueQuantity.code, para que los valores puedan compararse y convertirse. Idempotency-Key. Un reintento después de un tiempo de espera devuelve la primera respuesta en lugar de almacenar la lectura dos veces.
Los resultados de laboratorio son el mismo recurso con category laboratory y generalmente un referenceRange. Para incorporar informes de laboratorio completos, consulte Cómo importar resultados de laboratorio a un registro FHIR.
Paso 3: registrar un diagnóstico como una Condición
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) y verificationStatus (confirmed, provisional) están separados a propósito: un diagnóstico sospechado no es lo mismo que uno confirmado, y un problema resuelto sigue siendo parte del historial.
Paso 4: crear recursos relacionados en una transacción
Cuando un paciente y su primera medición llegan juntos, por ejemplo, desde un sistema de clínica, envíelos como un transaction Bundle. O todo se almacena o nada. Las referencias entre los nuevos recursos utilizan urn:uuid: ids temporales que el servidor reemplaza:
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"}}
]
}'
El transaction-response tiene una entrada por recurso, con "status": "201 Created", su location y el recurso almacenado. El subject de Observation ahora apunta al Patient/fad3665a-… real.
Paso 5: Búsqueda
curl "$BASE/Observation?patient=$PID&code=http://loinc.org|85354-9&date=ge2026-10-01&_sort=-date" \
-H "Authorization: Bearer $KEY"
Obtendrás un searchset Bundle con total y los recursos coincidentes, los más recientes primero. Otras búsquedas que usarás a menudo son: Condition?patient=$PID&clinical-status=active, Observation?patient=$PID&category=laboratory y Patient/$PID/$everything para el registro completo.
Paso 6: Actualizar sin perder historial
La hipertensión se resuelve. Cambie el estado y agregue la fecha de finalización, y use If-Match con la versión que leyó para que nunca sobrescriba el cambio de otra persona:
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 con ETag: W/"2". Si otra escritura llegó primero, obtendrá 412 y volverá a leer. La versión anterior todavía está allí:
curl "$BASE/Condition/$CID/_history" -H "Authorization: Bearer $KEY"
devuelve ambas versiones: versionId 2 (resolved) y 1 (active). GET $BASE/Condition/$CID/_history/1 lee la antigua. Nada en un registro se sobrescribe silenciosamente.
Paso 7: Ver quién escribió qué
Cada escritura crea un recurso Provenance. Para la lectura de presión arterial:
curl "$BASE/Provenance?target=Observation/$OBS" -H "Authorization: Bearer $KEY"
{"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": "…"}}]}
El tipo de autor que envió (device) se registra con el proyecto y la organización. Envíe X-Anpheros-Author-Ref: Practitioner/<id> para nombrar al clínico detrás de una escritura.
Paso 8: el registro como resumen
curl "$BASE/Patient/$PID/\$summary" -H "Authorization: Bearer $KEY"
devuelve un Resumen Internacional de Paciente (International Patient Summary): un document Bundle que comienza con un Composition y tiene secciones como Problemas, Medicamentos, Alergias y Signos Vitales, construido a partir de los recursos anteriores. Ese es el formato para entregar a otro sistema o imprimir para un médico (plataforma FHIR).
¿Prefiere JSON sin FHIR?
Los mismos datos están disponibles a través de una vista REST más simple, /v1, con los mismos ids: POST /v1/patients/{id}/observations toma {"code": "85354-9", "category": "vital-signs", "effective_at": "…", "components": […]} y almacena la misma FHIR Observation. Utilice la que mejor se adapte a su código. Consulte la API de datos médicos y los SDK.
Preguntas frecuentes
¿Cuál es la mejor manera de almacenar historiales médicos?
Como recursos codificados y versionados con un registro de quién escribió cada uno. HL7 FHIR R4 le proporciona la estructura (Patient, Observation, Condition y otros), sistemas de codificación estándar como LOINC e ICD-10, e historial; un backend FHIR añade búsqueda, consentimiento y procedencia.
¿Necesito un servidor FHIR para usar FHIR?
Necesita un lugar que almacene y busque recursos FHIR y que haga cumplir quién puede leerlos. Puede ejecutar su propio servidor FHIR de código abierto o utilizar uno gestionado como Anpheros; Cómo Anpheros se compara con otros servidores FHIR sopesa las opciones, y FHIR vs. una base de datos médica personalizada cubre la creación de su propio esquema en su lugar.
¿Cómo almaceno la presión arterial en FHIR?
Como una Observation con el código LOINC 85354-9 y dos entradas component: sistólica 8480-6 y diastólica 8462-4, cada una con un valueQuantity en mm[Hg].
¿Puedo cambiar un recurso almacenado?
Sí, con PUT y If-Match. Cada cambio crea una nueva versión; las versiones anteriores permanecen legibles a través de _history, y Provenance registra quién hizo cada cambio. Las eliminaciones son lógicas y conservan el historial.
Relacionado
- Plataforma FHIR: los conceptos, tipos de recursos y operaciones
- Sistemas de códigos FHIR: LOINC, ICD-10, ATC, UCUM
- Cómo importar resultados de laboratorio a un registro FHIR
- API de datos médicos: la vista REST más sencilla de los mismos datos
- Base de datos FHIR y sandbox gratuitos
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card