Referencing Resources in Transactions

When creating multiple resources by using a FHIR Bundle, sometimes you have to refer to a resource that hasn’t yet been created in the FHIR server.

That poses a challenge. How do you reference an ID that hasn’t been assigned?

This is a common problem when using FHIR, and in this tutorial we will look at two approaches, using hardcoded IDs and using temporary references.

Approach 1: Hardcode an ID and use it with PUT

The first method is to assign an ID yourself when creating a resource. This is done by using a PUT request and specifying the chosen ID in the URL.

For example, here is a batch Bundle where we create a Patient with ID 123, and also create an Observation that references the patient.

{
   "resourceType": "Bundle",
   "type": "batch",
   "entry": [
       {
           "request": {
               "method": "PUT",
               "url": "Patient/123"
           },
           "resource": {
               "resourceType": "Patient",
               "id": "123",
               "name": [
                   {
                       "given": ["Sidharth"],
                       "family": "Ramesh"
                   }
               ],
               "telecom": [
                   {
                       "system": "email",
                       "value": "sidharth@medblocks.com"
                   }
               ]
           }
       },
       {
           "resource": {
               "resourceType": "Observation",
               "status": "final",
               "code": {
                   "coding": [
                       {
                           "system": "http://loinc.org",
                           "code": "4548-4",
                           "display": "Hemoglobin A1c/Hemoglobin.total in Blood"
                       }
                   ]
               },
               "valueQuantity": {
                   "value": 6.3,
                   "unit": "%",
                   "system": "http://unitsofmeasure.org",
                   "code": "%"
               },
               "subject": {
                   "reference": "Patient/123"
               }
           },
           "request": {
               "method": "POST"
           }
       }
   ]
}

This approach has the following drawbacks,

  • Not all servers allow client-assigned IDs
  • Many servers enforce rules about valid ID formats
  • You might run into conflicts if the ID is already taken
  • If one request fails, the bundle may execute inconsistently

The preferred and safer method is to use a transaction bundle, and assign temporary references in the fullUrl field.

Here’s how it works,

  1. Assign each resource a unique, temporary fullUrl (e.g. urn:uuid:patient-123)
  2. Reference that fullUrl in related resources (like Observations)
  3. When the Bundle is processed, the server replaces temporary references with real IDs

Also, since we are using a transaction, all resources succeed or fail, which ensures consistency.

Here’s an example of a transaction bundle that uses fullUrl,

{
   "resourceType": "Bundle",
   "type": "batch",
   "entry": [
       {
           "fullUrl": "urn:uuid:patient-123"
           "request": {
               "method": "POST"
           },
           "resource": {
               "resourceType": "Patient",
               "name": [
                   {
                       "given": ["Sidharth"],
                       "family": "Ramesh"
                   }
               ],
               "telecom": [
                   {
                       "system": "email",
                       "value": "sidharth@medblocks.com"
                   }
               ]
           }
       },
       {
           "resource": {
               "resourceType": "Observation",
               "status": "final",
               "code": {
                   "coding": [
                       {
                           "system": "http://loinc.org",
                           "code": "4548-4",
                           "display": "Hemoglobin A1c/Hemoglobin.total in Blood"
                       }
                   ]
               },
               "valueQuantity": {
                   "value": 6.3,
                   "unit": "%",
                   "system": "http://unitsofmeasure.org",
                   "code": "%"
               },
               "subject": {
                   "reference": "Patient/urn:uuid:patient-123"
               }
           },
           "request": {
               "method": "POST"
           }
       }
   ]
}

To submit the above bundle to the server, use the base URL,

POST https://fhir-bootcamp.medblocks.com/fhir

On analysing the server response, you can see that a real ID is assigned to the Patient, and Observation.subject is updated to reference this new Patient ID.

Since we used a transaction the resources are created atomically, that is either all succeed or all fail.

Summary

When creating related resources in a FHIR Bundle,

  • You can hardcode IDs with PUT, but this is fragile and sometimes not supported
  • The recommended approach is to use a transaction Bundle with temporary references specified via fullUrl

This ensures that resource creation happens atomically (all-or-nothing), server-assigned IDs are safely resolved and referential integrity is preserved.

Comments (0)

No comments yet. Be the first to comment!