ediverse Explore the platform

Spotlight PEPPOL BIS Billing 3.0 The EU e-invoicing mandate is here — France Sept 2026, Belgium Jan 2026, Germany 2025.

GraphDefinition — Describing a resource graph

How to pull "everything connected to a patient" in a single request? GraphDefinition formally describes the expected resource graph and feeds the $graph operation.

Purpose

GraphDefinition is the metadata describing a directed graph of FHIR resources linked by References. It serves two main purposes:

  • Feeds the $graph operation — invoked on a root resource, it returns a searchset Bundle including every reachable resource according to the definition.
  • Documents in an Implementation Guide what a Bundle (document, message, transaction) must contain for a given use case.

Key fields

FieldTypeCardinalityRole
urluri0..1Canonical URL.
namestring1..1Machine name.
statuscode1..1Publication status.
startcode1..1Root resource type of the graph.
nodeBackboneElement[]0..*Graph nodes (types + profiles).
node.nodeIdid1..1Local node ID.
node.typecode1..1FHIR type of the node.
node.profilecanonical0..1Profile on the type.
linkBackboneElement[]0..*Directed edges.
link.sourceIdid1..1Source node.
link.targetIdid1..1Target node.
link.pathstring0..1FHIRPath or reference type.
link.min / link.maxinteger / string0..1 eachLink cardinality.

JSON example

Graph: Patient → Encounter → CareTeam → Practitioner. Usable with GET /Patient/123/$graph?graph=http://hl7.org/fhir/GraphDefinition/example:

json graphdefinition-careteam.json
{
  "resourceType": "GraphDefinition",
  "id": "example",
  "url": "http://hl7.org/fhir/GraphDefinition/example",
  "version": "5.0.0",
  "name": "PatientCareTeamGraph",
  "status": "active",
  "experimental": false,
  "date": "2026-05-14",
  "publisher": "HL7 (FHIR Project)",
  "description": "Graph Patient + Encounter + CareTeam + Practitioner.",
  "start": "Patient",
  "node": [
    {
      "nodeId": "encounter",
      "type": "Encounter",
      "profile": "http://hl7.org/fhir/StructureDefinition/Encounter"
    },
    {
      "nodeId": "careteam",
      "type": "CareTeam",
      "profile": "http://hl7.org/fhir/StructureDefinition/CareTeam"
    },
    {
      "nodeId": "practitioner",
      "type": "Practitioner",
      "profile": "http://hl7.org/fhir/StructureDefinition/Practitioner"
    }
  ],
  "link": [
    {
      "description": "Patient → Encounter",
      "min": 0,
      "max": "*",
      "sourceId": "Patient",
      "targetId": "encounter",
      "path": "Encounter.subject.where(reference.startsWith('Patient/'))"
    },
    {
      "description": "Encounter → CareTeam",
      "sourceId": "encounter",
      "targetId": "careteam",
      "path": "CareTeam.encounter"
    },
    {
      "description": "CareTeam → Practitioner",
      "sourceId": "careteam",
      "targetId": "practitioner",
      "path": "CareTeam.participant.member"
    }
  ]
}

Common pitfalls

  • Unbounded cyclic graphs — a graph Patient → RelatedPerson → Patient without max can recurse infinitely. Always bound.
  • Non-indexable FHIRPath — a link.path too complex (heavy filters) cannot be executed by the server.
  • Target profile not loaded — if node.profile points to an unknown StructureDefinition, expansion fails.
  • Confusing $graph and $everything$everything is defined on Patient and CareTeam only and returns the full record, $graph is parameterised by an arbitrary GraphDefinition.
  • StructureDefinition — profiles on the nodes.
  • OperationDefinition — describes the $graph operation consuming a GraphDefinition.
  • MessageDefinition — may reference a graph via graph.
  • Bundle — container returned by $graph.