Uuid Toolkit

urn:uuid: in Bundle.entry.fullUrl and Why It Matters

Bundle.entry.fullUrl is where a Bundle assembles entries that reference each other atomically. The urn:uuid: prefix in that field is what makes cross-entry references work in a transaction Bundle where the resource ids do not exist yet. It is a small piece of syntax with an outsized effect on how transactions land. The site's fullUrl UUID spinner generates the UUIDs; the mechanic is worth understanding on its own. For the wider FHIR framing, more FHIR product comparisons has more.

What fullUrl Is

Bundle.entry.fullUrl is the identifier for the entry within the Bundle. It can be:

  • A relative URL — Patient/123 (identifies an existing resource)
  • An absolute URL — https://server/Patient/123
  • A urn:uuid: URN — placeholder for a resource not yet assigned an id

The third form is the interesting one for transactions.

Why urn:uuid: Matters

A transaction Bundle can create a Patient and an Observation in one call. The Observation needs to reference the Patient, but the Patient's server-assigned id does not exist yet. The urn:uuid: mechanism solves that:

  • The Patient entry has fullUrl = "urn:uuid:aa11..."
  • The Observation.subject references "urn:uuid:aa11..."
  • The server rewrites both to real ids atomically at commit

Without urn:uuid:, the transaction has to either be split into multiple round trips or the client has to know the ids up front.

For the choice-of-id question, when to use a UUID for a FHIR resource id vs a natural identifier covers the mechanics.

The Format

urn:uuid: followed by the standard 36-character UUID with hyphens:

`` "fullUrl": "urn:uuid:6b1e73b9-e14d-4c1b-9c33-2a5f8c1f9b4a" ``

Any valid UUID works; v4 is the common choice. For the v4 vs v7 discussion, UUID v4 vs v7: is the tradeoff meaningful for FHIR? is the entry.

Where It Doesn't Work

  • Batch Bundles — entries are independent, cross-entry references do not rewrite
  • Standalone resources — no fullUrl semantics outside a Bundle
  • Bundles used for storage (document, message, collection) — the URN is not rewritten by the server

The mechanic is transaction-Bundle-specific. Trying it in other Bundle types produces payloads that look valid and behave inconsistently.

Reference-Side Match

The reference inside the entry has to use the same urn:uuid: string exactly:

`` "subject": { "reference": "urn:uuid:6b1e73b9-e14d-4c1b-9c33-2a5f8c1f9b4a" } ``

Case-sensitive match. Prefix included. Trailing characters excluded. Any drift produces an unresolved reference at commit.

For the distinction between reference and identifier, [the difference between resource id and identifier[]](/uuid-toolkit/resource-id-vs-identifier-array/) is the entry.

Server Behavior At Commit

  • Server sees the urn:uuid: in fullUrl and any references
  • Server assigns real ids to each entry
  • Server rewrites every matching URN in the Bundle to the real id
  • Atomic commit or atomic rollback

The rewrite is server-side. Clients see the response Bundle with real ids in every location the URN appeared. For the client-side generation question, generating UUIDs at the edge vs at the server is the entry.

Duplicate URN Detection

Two entries with the same urn:uuid: fullUrl is a spec violation. Servers should reject. Callers who generate URNs by hand and accidentally reuse one produce quiet-fail transactions.

Use a UUID generator; do not hand-write.

The Short Version

urn:uuid: in fullUrl is what makes transaction Bundle cross-references work. Match the URN exactly on the reference side. Do not use it in batches or standalone. Generate with a proper UUID library, not by hand. For the fullUrl generator, /kit/spin-uuids-for-fullurl/ is the tool.

Halftone-comic diagram of a transaction Bundle with urn:uuid: fullUrl on entries and matching references rewritten at commit, with dot pattern shading and hot-pink accents on cream paper

Sources