---
{
  "title": "Introducción a FHIR Terminology: Los conceptos básicos",
  "description": "El segundo artículo de una serie sobre FHIR Terminology: valores codificados, sistemas de códigos, conjuntos de valores y mapas conceptuales",
  "date": "2026-08-17",
  "author": "Orlando Osorio",
  "tags": ["Terminology", "FHIR", "Tutorial"],
  "extra-scripts": [
    "/assets/js/demo/termbox/base.js",
    "/assets/js/demo/termbox/basics.js"
  ]
}
---

> For the complete documentation index, see [llms.txt](https://www.health-samurai.io/llms.txt).
> Use it to discover all available pages before guessing URLs.

---

Este es el segundo artículo de la [Serie de Introducción a FHIR Terminology](/blog/introduction-to-fhir-terminology). Repasaremos los conceptos fundamentales que conforman el Módulo de Terminology de FHIR. Veremos ejemplos concretos de los problemas que puede resolver y ofreceremos una visión general de cómo encajan las distintas piezas.

## Casos de uso

Como [mencionamos](/blog/introduction-to-fhir-terminology#why) anteriormente, hemos observado que los recién llegados a FHIR infrautilizan las soluciones de Terminology. Creemos que parte de la razón es la falta de conciencia sobre los problemas que puede resolver; algunas personas pueden asociar _Terminology_ con temas como estándares, conformidad, cumplimiento normativo y regulaciones. Por ello, pensamos que un buen punto de partida es mostrar algunos casos de uso concretos que se implementan fácilmente mediante un servidor de Terminology. De hecho, todos estos ejemplos se ejecutan en tiempo real contra nuestra instancia de sandbox.

Cada pestaña muestra un ejemplo en vivo, desde cuadros de búsqueda y menús desplegables hasta mapeo y traducción; abra el panel en la parte inferior del recuadro para ver las peticiones y respuestas reales[^1].


<div id="examples"></div>

## Contexto

Cuando un médico escribe «infarto de miocardio» y otro escribe «ataque al corazón», se refieren a lo mismo. Pero para un sistema de software, o cualquier flujo de trabajo a escala, no son más que dos cadenas de texto distintas. La capacidad de compartir significado entre las partes es fundamental para la interoperabilidad. Para eso sirven las terminologías sanitarias. Uno de los primeros ejemplos de terminología sanitaria es la Clasificación Internacional de Enfermedades (CIE), adoptada en 1893 para codificar las causas de muerte. Es anterior al software y sigue en uso hoy en día.

Trabajaremos con un conjunto de construcciones que se incluyen dentro de la definición de _una terminología_: taxonomías, ontologías, nomenclaturas, conjuntos de códigos, vocabularios y clasificaciones. A efectos prácticos, las llamaremos _terminologías_ y las definiremos como un conjunto de términos con un identificador estable legible por máquina. Pueden ser infinitas, tener sinónimos, propiedades, relaciones, estructura, etc. Pero la característica principal que necesitaremos es que cada elemento tenga un identificador estable (_código_) y alguna etiqueta textual (_término_/_display_).

En el desarrollo web «normal», los implementadores utilizan terminologías constantemente (aunque no se llamen así). Con frecuencia se implementan como enumeraciones o como una tabla de elementos con una vista de administración CRUD (es muy habitual que las enumeraciones sean sus propios códigos y que las tablas de elementos utilicen el ID de la base de datos como identificador). Los ejemplos anteriores podrían perfectamente haberse implementado con estos patrones.

FHIR proporciona un [Módulo de Terminology](https://build.fhir.org/terminology-module.html) diseñado para resolver estos y otros problemas. Un aspecto interesante es que las mismas abstracciones permiten expresar tanto ontologías estándar, conformes y autoritativas de gran tamaño como listas locales de códigos cortas similares a enumeraciones.

## Valores codificados

Muchos recursos FHIR tienen campos cuyo dominio de valores posibles se toma de una lista (una terminología). Sus valores son _códigos_ asignados externamente que identifican un _concepto_ definido. Por ejemplo:

```yaml
resourceType: Patient
name:
  - given: [Jane]
    family: Doe
gender: female
```

Observe que, en este caso, `name` es una propiedad no vinculada: puede tomar cualquier nombre de persona, mientras que `gender` solo puede tomar uno de cuatro valores: `male`, `female`, `other`, `unknown`. En este caso, `female` es un _valor codificado_.

Un valor codificado es principalmente un par compuesto por «system» y «code», donde `system` es una URL[^2] que identifica el sistema de códigos (terminología) que define los códigos. Esta decisión tiene implicaciones significativas en la capacidad de descubrimiento de los valores codificados: en lugar de encontrar una cadena de texto que parece un código LOINC, los valores codificados van acompañados de su identificador de sistema de códigos. En el caso del género anterior, el sistema es implícito (Administrative Gender, `http://hl7.org/fhir/administrative-gender`); veremos por qué en breve.

FHIR [define](https://build.fhir.org/terminologies.html) 3 tipos de datos principales para representar estos códigos[^3]: `code`, `Coding` y `CodeableConcept`.

- [`code`](https://build.fhir.org/datatypes.html#code): La instancia representa únicamente el código. El sistema es implícito.
- [`Coding`](https://build.fhir.org/datatypes.html#Coding): El tipo de dato contiene un código y un sistema que identifica el origen de la definición del código.
- [`CodeableConcept`](https://build.fhir.org/datatypes.html#CodeableConcept): Un tipo que representa un concepto mediante texto libre y/o uno o más elementos `coding`.

La mayoría de los elementos codificados en FHIR utilizan `CodeableConcept`, ya que ofrece la mayor flexibilidad. Permite múltiples codificaciones y texto libre para expresar, por ejemplo, lo que realmente escribió la persona que introdujo el dato, o los casos en que no hay ningún código disponible. También facilita las transiciones, ya que se pueden incluir códigos antiguos y nuevos en la misma estructura (véase el ejemplo de Observation más adelante).

El tipo de dato `Coding` se utiliza cuando la intención es hacer referencia a un código específico, no expresar un concepto de forma general. El uso de `Coding` es poco frecuente, ya que es menos flexible que `CodeableConcept` y no permite texto libre ni traducciones.

El tipo de dato `code` aparece habitualmente en escenarios similares a las enumeraciones. Típicamente, estos elementos tienen una fortaleza de vinculación `required`, es decir: el código debe provenir del conjunto de valores especificado y no es necesario transmitir un código alternativo. Generalmente, estos elementos pueden estar implicados en la lógica de negocio, como el despacho según un valor, la comparación exacta, etc. Por ejemplo: el estado de un recurso; el código del cliente podría ignorar los recursos `retired` o actuar solo sobre los `active`.

### Vinculación (Binding)

En los tipos de datos anteriores, los códigos son de tipo `string`; la forma de restringir el conjunto de valores que pueden tomar es mediante [vinculaciones (bindings)](https://build.fhir.org/terminologies.html#binding). La especificación _vincula_ el elemento a un _conjunto de valores (value set)_, lo que significa que solo puede tomar valores de esa lista.

Las vinculaciones tienen dos propiedades principales: `valueSet` y `strength`. `valueSet` define qué códigos son válidos para este elemento. `strength` indica cómo debe interpretarse la vinculación: `required`, `extensible`, `preferred`, `example`.

<div class="narrow">

![Binding example](binding.png "Patient spec fragment. Notice the highlighted elements, their datatypes, binding value sets and strengths")

</div>

En el ejemplo anterior, `Patient.gender` está vinculado al conjunto de valores `Administrative Gender` con una fortaleza `required`; por lo tanto, `gender` solo puede ser: `male`, `female`, `other`, `unknown`. Y `maritalStatus` está vinculado a `Marital Status Codes` con una fortaleza `extensible`, lo que significa que los códigos deben provenir de ese conjunto de valores a menos que el código esperado no esté cubierto por él.

### Ejemplos de valores codificados

{% tabs %}
{% tab title="Patient" %}
```yaml
resourceType: Patient
name:
  - given: [Jane]
    family: Doe
gender: female # code / AdministrativeGender (implicit)
maritalStatus: # CodeableConcept
  text: Married
  coding:
    - system: http://terminology.hl7.org/CodeSystem/v3-MaritalStatus
      code: M
      display: Married
```
{% endtab %}
{% tab title="Location" %}
```yaml
resourceType: Location
name : South Wing Neuro OR 1
status: suspended # code / LocationStatus (implicit)
operationalStatus: # Coding
  system: http://terminology.hl7.org/CodeSystem/v2-0116
  code: H
  display: Housekeeping
type: # CodeableConcept
  coding:
    - system: http://terminology.hl7.org/CodeSystem/v3-RoleCode
      code: RNEU
      display: Neuroradiology unit
form: # CodeableConcept without codings
  text: Room
```
{% endtab %}
{% tab title="Observation" %}
```yaml
resourceType: Observation
status: final # code / ObservationStatus (implicit)
code: # CodeableConcept with local and standard codings
 coding:
   - system: http://acmelabs.org
     code: 104177
     display: "Blood culture"
   - system: http://loinc.org
     code: 600-7
     display: Bacteria identified in Blood by Culture
valueCodeableConcept: # CodeableConcept
  coding:
    - system: http://snomed.info/sct
      code: 3092008
      display: Staphylococcus aureus
interpretation:
  text: Positive
  coding:
    - system: http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
      code: POS
```
{% endtab %}
{% endtabs %}

## Recursos

Veamos brevemente los recursos FHIR implicados en el Módulo de Terminology. En la práctica, raramente se crean directamente. Habitualmente se mantienen en otro lugar y se cargan[^4] en (o desde) un servidor de Terminology.

El Módulo de Terminology define cuatro recursos de Terminology principales: [CodeSystem](https://build.fhir.org/codesystem.html), [ValueSet](https://build.fhir.org/valueset.html), [ConceptMap](https://build.fhir.org/conceptmap.html) y [NamingSystem](https://build.fhir.org/namingsystem.html). Dedicaremos una entrada a cada uno de ellos. Por ahora ofreceremos una breve descripción general de `CodeSystem` y `ValueSet`.

### CodeSystem

CodeSystem es sin duda el recurso más importante en FHIR Terminology. Se utiliza para describir un sistema de códigos, sus atributos y contenidos. En su forma más habitual, contiene una lista de conceptos, cada uno con su código, designaciones y propiedades.

#### Ejemplos

{% tabs %}
{% tab title="AdministrativeGender" %}
```yaml
resourceType: CodeSystem
url: http://hl7.org/fhir/administrative-gender
version: 5.0.0
content: complete
status: active
concept:
  - code: male
    display: Male
  - code: female
    display: Female
  - code: other
    display: Other
  - code: unknown
    display: Unknown
```
{% endtab %}
{% tab title="ES Translation" %}
```yaml
resourceType: CodeSystem
content: supplement
supplements: http://hl7.org/fhir/administrative-gender
concept:
- code: male
  designation:
  - language: es
    value: Masculino
- code: female
  designation:
  - language: es
    value: Femenino
- code: other
  designation:
  - language: es
    value: Otro
- code: unknown
  designation:
  - language: es
    value: Desconocido
```
{% endtab %}
{% tab title="RxNorm fragment" %}
```yaml
resourceType: CodeSystem
url: http://www.nlm.nih.gov/research/umls/rxnorm
version: '03022026'
publisher: National Library of Medicine
content: complete
filter:
- code: concept
  operator: [is-a, generalizes, descendent-of]
  value: comma-separated list of concept codes for direct equality testing
- code: NDC
  operator: [=,in, exists]
  value: NDC code
property:
- {code: TTY, type: string}
- {code: NDC, type: string}
- {code: RXN_STRENGTH, type: string}
- {code: dose_form_of, type: code}
- {code: has_ingredient, type: code}
- {code: has_tradename, type: code}
# ...
concept:
- code: '5640'
  display: ibuprofen
  property:
  - code: TTY
    valueString: IN
  - code: has_tradename
    valueCode: '1100067'
  - code: ingredient_of
    valueCode: '1152223'
  - code: part_of
    valueCode: '821036'
  # ...
# ...
```
{% endtab %}
{% tab title="ICD-10-CM fragment" %}
```yaml
resourceType: CodeSystem
url: http://hl7.org/fhir/sid/icd-10-cm
version: '2025'
content: complete
property:
- description: Indicator [...] transactions ("billable code")
  type: integer
  code: valid
filter:
- description: Identify valid billable codes.
  value: 0 = "header" – not valid [...]
  code: valid
  operator: ["="]
valueSet: http://hl7.org/fhir/sid/icd-10-cm/vs
concept:
- code: Chapter-1
  display: Certain infectious and parasitic diseases (A00-B99)
  concept:
  - code: Section-A00-A09
    display: Intestinal infectious diseases (A00-A09)
    concept:
    - code: A00
      display: Cholera
      concept:
      - code: A00.0
        display: Cholera due to Vibrio cholerae 01, biovar cholerae
        property:
        - code: valid
          valueInteger: 1
# ...
```
{% endtab %}
{% endtabs %}

### ValueSet

Un recurso ValueSet especifica un conjunto de códigos extraídos de uno o más sistemas de códigos.

En nuestra experiencia, este es uno de los recursos más incomprendidos en FHIR Terminology. Una posible razón es que la diferencia entre los sistemas de códigos y los conjuntos de valores no siempre queda clara para los implementadores. No ayuda que, en el núcleo de FHIR, la mayoría de los recursos CodeSystem tengan un ValueSet equivalente que incluye todos sus códigos. Por ejemplo: `http://hl7.org/fhir/administrative-gender` y `http://hl7.org/fhir/ValueSet/administrative-gender`.

La distinción principal es que los sistemas de códigos contienen la definición de los conceptos, su origen, mientras que los conjuntos de valores _seleccionan_ códigos de los sistemas de códigos. Así, un conjunto de valores puede contener un subconjunto de un sistema de códigos, o incluso combinar varios.

Por ejemplo, RxNorm es una terminología farmacológica que incluye conceptos para nombres de marca, principios activos, formas farmacéuticas, etc. Podemos definir un conjunto de valores con los principios activos de RxNorm. Los conceptos incluidos seguirían siendo conceptos de RxNorm, pero solo tendríamos principios activos.

Otro caso de uso habitual de los conjuntos de valores es añadir una opción nula. Supongamos que usamos ISO 3166 (códigos de país) en un formulario. Muestra correctamente todos los países y sus códigos, pero no existe un código de país «Desconocido». Podemos definir un conjunto de valores que _incluya_ todos los códigos de ISO 3166 y el concepto `UNK` de [NullFlavor](http://terminology.hl7.org/CodeSystem/v3-NullFlavor).

#### Ejemplos

{% tabs %}
{% tab title="RxNorm Ingredients" %}
```yaml
resourceType: ValueSet
url: http://example.org/rxnorm-ingredients
title: RxNorm Ingredients
compose:
  include:
  - system: http://www.nlm.nih.gov/research/umls/rxnorm
    filter:
    - property: TTY
      op: =
      value: IN
```
{% endtab %}
{% tab title="LOINC Cholesterol" %}
```yaml
resourceType: ValueSet
url: http://hl7.org/fhir/ValueSet/example
title: LOINC Codes for Cholesterol in Serum/Plasma
compose:
  include:
  - system: http://loinc.org
    concept:
    - code: 14647-2
      display: Cholesterol [Moles/Volume]
    - code: 2093-3
      display: Cholesterol [Mass/Volume]
    - code: 35200-5
      display: Cholesterol [Mass Or Moles/Volume]
    - code: 9342-7
      display: Cholesterol [Percentile]
```
{% endtab %}
{% tab title="AdministrativeGender" %}
```yaml
resourceType: ValueSet
url: http://hl7.org/fhir/ValueSet/administrative-gender
status: active
compose:
  include:
  - system: http://hl7.org/fhir/administrative-gender
```
{% endtab %}
{% tab title="Yes / No / Dont Know" %}
```yaml
resourceType: ValueSet
url: http://hl7.org/fhir/ValueSet/yesnodontknow
name: YesNoDontKnow
compose:
  include:
  - valueSet: ["http://terminology.hl7.org/ValueSet/v2-0136"]
  - system: http://terminology.hl7.org/CodeSystem/data-absent-reason
    concept:
    - code: asked-unknown
      display: Don't know
```
{% endtab %}
{% endtabs %}

## Operaciones

La principal forma de interactuar con el módulo de Terminology y sus recursos es mediante operaciones. La especificación R6 define 8 operaciones específicas de Terminology. A lo largo de esta serie analizaremos la mayoría de ellas en detalle. En este artículo presentaremos `$expand`, la que impulsa la mayoría de los ejemplos anteriores.

### ValueSet/$expand

Dado un conjunto de valores, devuelve la lista de códigos que define. Esta operación es ideal para poblar elementos de interfaz de usuario: menús desplegables, campos de búsqueda, selectores de códigos, etc. Además del conjunto de valores, se puede especificar un filtro de búsqueda por texto, paginación, qué propiedades y designaciones devolver, en qué idioma responder, entre otros parámetros.

Tomemos nuestro primer ejemplo: un campo de búsqueda con completado automático sobre los hallazgos clínicos de SNOMED. Supongamos que queremos buscar «diabetes mellitus» y obtener 10 resultados. A continuación se muestra cómo podría ser una petición:

{% tabs %}
{% tab title="hurl" %}
```hurl
GET https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand
[Query]
url: http://snomed.info/sct?fhir_vs=isa/404684003
count: 10
filter: diabetes mellitus
```
{% endtab %}
{% tab title="curl" %}
```bash
curl -G 'https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand' \
  --data-urlencode 'url=http://snomed.info/sct?fhir_vs=isa/404684003' \
  --data-urlencode 'count=10' \
  --data-urlencode 'filter=diabetes mellitus'
```
{% endtab %}
{% endtabs %}

<div class="narrow">

| Parámetro | Valor | Explicación |
| --- | --- | --- |
| `url` | `http://snomed.info/sct?fhir_vs=isa/404684003` | URL implícita para los conceptos de hallazgos clínicos de SNOMED[^5] |
| `count` | `10` | Número de conceptos a encontrar |
| `filter` | `diabetes mellitus` | Texto a buscar |

</div>

También podemos proporcionar un conjunto de valores en línea en la petición; esto nos permite construir consultas sobre un sistema de códigos mediante propiedades. Por ejemplo, supongamos que queremos obtener todos los medicamentos de marca que contienen tanto cafeína como paracetamol (acetaminofén) como principios activos.

{% tabs %}
{% tab title="hurl" %}
```hurl
POST https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand
Content-Type: application/json
{
  "resourceType": "Parameters",
  "parameter": [
    {
      "name": "valueSet",
      "resource": {
        "resourceType": "ValueSet",
        "status": "active",
        "compose": {
          "include": [
            {
              "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
              "filter": [
                { "property": "TTY", "op": "=", "value": "BN" },
                { "property": "tradename_of", "op": "=", "value": "CUI:161" },
                { "property": "tradename_of", "op": "=", "value": "CUI:1886" }
              ]
            }
          ]
        }
      }
    }
  ]
}
```
{% endtab %}
{% tab title="curl" %}
```bash
curl -X POST 'https://tx-sandbox.health-samurai.io/fhir/ValueSet/$expand' \
  -H 'Content-Type: application/json' \
  -d '{
    "resourceType": "Parameters",
    "parameter": [
      {
        "name": "valueSet",
        "resource": {
          "resourceType": "ValueSet",
          "status": "active",
          "compose": {
            "include": [
              {
                "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
                "filter": [
                  { "property": "TTY", "op": "=", "value": "BN" },
                  { "property": "tradename_of", "op": "=", "value": "CUI:161" },
                  { "property": "tradename_of", "op": "=", "value": "CUI:1886" }
                ]
              }
            ]
          }
        }
      }
    ]
  }'
```
{% endtab %}
{% endtabs %}

<div class="narrow">

| Filtro | Valor | Explicación |
| --- | --- | --- |
| `TTY` | `BN` | Solo nombres de marca |
| `tradename_of` | `CUI:161` | Contiene paracetamol (acetaminofén) |
| `tradename_of` | `CUI:1886` | Contiene cafeína |

</div>

## A continuación

En nuestro próximo artículo analizaremos los canonicals: cómo se identifican los recursos de Terminology, qué convenciones se utilizan y cómo funciona el versionado y la resolución.

- Anterior: [Introducción a FHIR Terminology](/articles/introduction-to-fhir-terminology)
- Siguiente: Canonicals — _próximamente_

<!-- footnotes -->

[^1]: La forma más eficiente de implementar algunos de estos ejemplos es mediante [batching](https://build.fhir.org/http.html#transaction); mantenemos las peticiones aisladas para facilitar su inspección.

[^2]: Profundizaremos en el funcionamiento de estas URL en un artículo futuro sobre canonicals.

[^3]: En realidad, la especificación define 4 tipos de datos (y 3 adicionales). Sin embargo, `CodeableReference` se define en términos de `CodeableConcept` y los adicionales son casos especiales. Por eso nos centramos en los tres primeros. Véase https://build.fhir.org/terminologies.html.

[^4]: En un artículo futuro veremos un tutorial para configurar un servidor de Terminology desde cero para potenciar una aplicación sanitaria.

[^5]: Véase https://terminology.hl7.org/en/SNOMEDCT.html para consultar cómo utilizar SNOMED con FHIR Terminology. Dedicaremos un artículo futuro a SNOMED CT.