~/vladvisinescu_
<- cd ~/tutorials

tutorial

FHIR resources: the building blocks of an exchange

FHIR represents healthcare information as resources. Each resource has one defined purpose, a known type, a stable structure, and rules describing how its elements may be used.

That makes a resource more than an arbitrary JSON object. Its shape comes from a published definition that both producer and consumer can inspect.

Start with a Patient

Here is a deliberately small Patient resource:

{
  "resourceType": "Patient",
  "id": "example",
  "meta": {
    "profile": [
      "http://hl7.org/fhir/StructureDefinition/Patient"
    ]
  },
  "identifier": [
    {
      "system": "https://hospital.example.org/mrn",
      "value": "MRN-10492"
    }
  ],
  "name": [
    {
      "use": "official",
      "family": "Ionescu",
      "given": ["Ana"]
    }
  ],
  "gender": "female",
  "birthDate": "1988-04-12"
}

This is sample data, not a complete profile-compliant payload for a particular country or organization. It is enough to expose the main structural ideas.

resourceType

Every JSON resource identifies its type. A parser uses resourceType to know that fields such as name, gender, and birthDate should be interpreted according to the Patient definition.

id

The logical id identifies this resource on a particular server. If the server base URL is https://hospital.example.org/fhir, the resource could be addressed as:

https://hospital.example.org/fhir/Patient/example

The ID is an opaque technical identity. A client should not try to extract business meaning from it.

meta

The optional meta element carries technical and workflow metadata. It can include a version ID, last-updated timestamp, source, profiles, security labels, and tags. The base Resource definition documents these common elements.

The meta.profile array states which profiles the resource claims to conform to. Validation can then evaluate the resource against those additional rules.

Domain content

The remaining elements describe the patient:

  • identifier holds business identifiers issued by known systems.
  • name is repeatable because a person may have official, former, preferred, or other names.
  • gender is a coded primitive with a defined value-set binding.
  • birthDate is a FHIR date, which can represent a full or partial date.

FHIR definitions show the cardinality of each element. 0..1 means optional and singular, 1..1 means required and singular, and 0..* means optional and repeatable. Profiles may make optional base elements mandatory, but they cannot ignore the fundamental rules of the base resource.

Logical IDs and business identifiers are different

The Patient above has both:

id = example
identifier = https://hospital.example.org/mrn | MRN-10492

The distinction prevents a common integration mistake.

The logical ID belongs to a resource instance on a FHIR server. If the same patient record is copied to another server, its logical ID may change.

A business identifier is assigned by some real-world authority: a hospital medical-record number, a national identifier, a prescription number, or a device serial number. Its system URI establishes the namespace in which the value is meaningful.

Do not put every external identifier into id, and do not assume that two resources with the same logical ID on different servers represent the same real-world entity.

Resources connect through references

An Observation can point to the Patient it concerns:

{
  "resourceType": "Observation",
  "id": "heart-rate-1",
  "status": "final",
  "code": {
    "coding": [
      {
        "system": "http://loinc.org",
        "code": "8867-4",
        "display": "Heart rate"
      }
    ]
  },
  "subject": {
    "reference": "Patient/example",
    "display": "Ana Ionescu"
  },
  "effectiveDateTime": "2026-07-25T08:30:00+02:00",
  "valueQuantity": {
    "value": 72,
    "unit": "beats/minute",
    "system": "http://unitsofmeasure.org",
    "code": "/min"
  }
}

subject.reference is relative to the FHIR server base URL. References can also be absolute, version-specific, internal to a contained resource, or expressed through an identifier when a literal resource location is unavailable. The FHIR references documentation describes the resolution rules.

The display value helps a human recognize the target, but it is not a substitute for resolving the reference when the application needs the referenced data.

Choose the resource that matches the meaning

FHIR has related resource types because superficially similar data can represent different workflow states.

Consider medication information:

  • Medication describes the medication product.
  • MedicationRequest records an order or proposal for medication.
  • MedicationDispense records medication supplied to a patient.
  • MedicationAdministration records medication actually administered.
  • MedicationStatement records an assertion that medication is being or was taken.

Choosing the type based only on the screen label “medication” discards important meaning. Start with the event or statement you need to represent, then read the resource’s scope and boundaries.

Other common families include:

  • People and organizations: Patient, RelatedPerson, Practitioner, PractitionerRole, Organization.
  • Clinical statements: Condition, Observation, Procedure, AllergyIntolerance.
  • Workflow: ServiceRequest, Task, Appointment, Encounter.
  • Conformance: CapabilityStatement, StructureDefinition, ValueSet, CodeSystem.

Data types carry their own rules

Resource elements use FHIR data types rather than plain programming-language primitives alone.

HumanName, Address, CodeableConcept, Quantity, Identifier, and Reference are complex types with reusable semantics. A CodeableConcept, for example, can contain several codings from different code systems plus human-readable text.

This is why two strings that look alike may not be interchangeable. A display label, a coded value, and a canonical URL serve different purposes even if each is serialized as text.

When implementing a resource, inspect both the resource definition and the linked FHIR data-type definition.

Bundles package resources together

A REST search does not return a bare JSON array. It returns a Bundle whose type is searchset. Documents, messages, transactions, batches, and history results also use Bundles with different type-specific rules.

A small search response might look like:

{
  "resourceType": "Bundle",
  "type": "searchset",
  "total": 1,
  "entry": [
    {
      "fullUrl": "https://hospital.example.org/fhir/Patient/example",
      "resource": {
        "resourceType": "Patient",
        "id": "example"
      },
      "search": {
        "mode": "match"
      }
    }
  ]
}

A Bundle is not just a convenient list. Its type changes the rules for fields such as links, requests, responses, and entry ordering. The Bundle specification explains the supported purposes and how references are resolved within a Bundle.

Profiles narrow the base resource

The base Patient definition allows many combinations because it must work internationally. A project profile can:

  • require one or more elements;
  • restrict cardinalities;
  • constrain referenced resource types;
  • bind coded elements to specific value sets;
  • define slices for repeated elements;
  • require or prohibit specific extensions.

Profiles are published as StructureDefinition resources. A resource declares conformance through meta.profile, but that declaration is only a claim until a validator checks it.

An implementation guide normally defines the profile set, terminology, examples, search expectations, and interaction rules for one use case. Read it before deciding that a base-valid resource is sufficient.

Extensions are part of the design

No base standard can anticipate every legitimate healthcare requirement. FHIR therefore includes a governed extension mechanism.

An extension has a canonical URL that defines its meaning and a value shaped by that definition:

{
  "extension": [
    {
      "url": "https://example.org/fhir/StructureDefinition/patient-preferred-contact-time",
      "valueCode": "afternoon"
    }
  ]
}

Extensions are not miscellaneous custom fields. A consumer must be able to locate or otherwise understand the definition behind the URL. Modifier extensions require even greater care because ignoring them could change the interpretation of the containing element.

Before inventing an extension, check the applicable implementation guide and published extension registries. If an existing resource element already expresses the concept, use it.

Validate structure and meaning

Validation should happen against the correct FHIR version and the profiles named by the implementation guide. Useful checks include:

  • valid JSON or XML representation;
  • recognized resource and element names;
  • cardinalities and data types;
  • fixed values and invariants;
  • terminology bindings;
  • resolvable profile and extension definitions;
  • reference constraints imposed by profiles.

FHIR defines a standard $validate operation, and several standalone validators implement the same underlying conformance artifacts. Passing validation is necessary, but it does not prove that the data is clinically correct or appropriate for the workflow.

Keep the version explicit

R4 and R5 share the resource-based architecture, but resource details can change between releases. Elements may be introduced, renamed, moved, or assigned a different maturity level.

Do not paste an R5 example into an R4 project without checking the R4 definition. Use version-specific package dependencies, canonical artifacts, and implementation guides. When conversion is required, treat HL7’s R4-to-R5 maps as implementation aids that still need project-specific review.

With these foundations—identity, structured elements, references, data types, Bundles, profiles, and validation—you can read most resource definitions systematically. The next practical step is to choose a real use case and trace the smallest set of resources needed to represent it.

  1. 01 FHIR explained: a common language for healthcare data