FHIR enabling an immunization registry

In New Zealand (and other places as well I expect) we’ve had a national registry for immunizations for a number of years – the National Immunization Register or NIR

It’s currently fed by HL7 version 2 messages and there’s a User Interface for authorized users, but there was always a plan to introduce a FHIR interface to some point – something that has been accelerated by the current COVID pandemic of course.

So what would a FHIR API look like? Well, let’s have a look at the use cases that we might want the registry to support. To keep the blog simple, we will constrain our discussion a bit:

  • We’ll focus on paediatric immunizations, as they can become quite complex. (For all its importance, COVID vaccinations are comparatively simple – your turn for a vaccine comes, you get it and the administration is recorded)
  • We’ll focus on the individual rather than the population. So we’ll ignore reporting and any workflow around tracking or reminders for immunizations (Maybe another post)
  • We won’t store reactions in the registry. Whether they belong there or some other registry will be something to debate.
  • Terminology will – as always – be a big part of this. Eg how to we code the vaccines? But – it is a big topic, so let’s leave that out for now.
  • We won’t consider security at all, though that will be a major consideration in a real implementation of course.

So with those constraints – what are the use cases we want to support?

  1. We want to be able to record that an immunization was given – what it was, who it was given to, who gave it, when and where it was given and so forth
  2. We want to be able find out what immunizations a specific individual has received. This will just be a list of the vaccines – not any kind of measure of the ‘protection against disease’ that an individual has (though that would be nice).
  3. It would be really nice for the registry to have a service that could generate recommended immunizations for an individual – what they are due to receive (This would be especially useful for parents I suspect)
  4. We should be able to supply the standard protocol in some computable format – not everyone would want to use the service we provide

Before getting too far into the API design, let’s think about the ‘data model’ that we’re going to need – at the FHIR resource level. This might change a bit as we delve into the details of the data elements, but we should be able to create a ‘first cut’ that we can use for review.

As you know, FHIR has the concept of ‘Resources’ – individual ‘chunks’ of data that represent specific components of healthcare data that are joined together in graphs of interconnected pieces to represent a particular set of data – much as Lego blocks are connected together to form a larger model. Our data model becomes a ‘resource model’ – showing these interconnections.

Here’s the list of candidate resources. 

  • Patient – the person who received the immunization
  • Practitioner – who gave it to them
  • Immunization – the actual vaccine that was given (includes the vaccine, and how/where on the body it was administered to the recipient
  • Location – the physical place where the vaccination took place – eg at the patients school or GP
  • PlanDefinition / ActivityDefinition – the immunization protocol being followed

That’ll do for now. The list may be refined as the analysis proceeds, but we’ve enough to get started.

And here’s how they are connected together to record a single administration. I used the clinFHIR Graph Builder to generate this picture. It’s a great way to visualize these inter-connections – and we can also generate sample data which is useful to validate that we have a ‘place’ for all the data items we need.

Note that there isn’t a direct reference to the protocol resources (PlanDefinition / ActivityDefinition) from the immunization (which is why there’s no line to them). If we do want to make this explicit then we’ll need to create an extension.

Now that we have that, we can start to think about what the API might look like. For now, we’ll assume a direct REST interface – though there are other possibilities.

We’ll start by thinking about the first use case – how to record an administration

This seems reasonably straightforward – we need to create an Immunization resource and POST it to the registry (thus creating a new administration record) – ie:

POST [host]/Immunization 

with the Immunization resource as the payload

But there are a few fish hooks when we start to think about how we represent all the references we need (Patient, Practitioner, Location etc)

There are a few options.

  • We could require the client to look up each of these referenced resources from the registry to get their resource ids which are then included in the Immunization resource. But – this is a lot of work for the client, and requires the registry to expose interfaces for all the referenced resources – which they may not have.
  • Assuming that the referenced resources all have some unique identifier (and in New Zealand they do), we could reference by that identifier rather than by the target resource id. See (the spec for more details on these ‘logical’ references). The registry is then responsible for figuring out how to record the connections internally (which is fine by us). Of course, we need to factor in failure here – what if the identifier is incorrect? Depending on how the registry does this, it may not be possible to do in real time…
  • We could ‘contain’ all the referenced resources within the Immunization (hopefully including enough information in each one for the registry to figure out who/what we’re referring to)
  • We could abandon the real-time RESTful API and instead move to a Message based paradigm – including all the referenced resources in a bundle along with a MessageHeader resource to indicate what the message is about. For us in New Zealand, this is analogous to what we’re doing now, it’s the FHIR version of v2 messaging. FHIR messaging can still occur over a direct HTTP interface, so no need for an intermediate messaging service (though that can still be supported of course).
  • A Document is another possibility – this would also support signing the document. This does seem a bit of a stretch though…

There are other possibilities, but one thing does seem clear: for every method other than the first one (requiring the client to look up all the resources in advance) the registry is going to have to do a significant amount of work – it can’t just take an incoming Immunization resource and save it. And we’ll need to allow for failure – missing / incorrect identifiers for example.

Right now, we can’t say which one of these (or some other) we’re going to use – there’s more design work to do. If I had to choose, then the message based approach is attractive as it mirrors what we’re already doing using v2 messaging so the back end services should substantially be in place – and it’s less of a change to the client. But there’s much design work to do before a decision is made, and we also need to involve the implementer community in the decision.

Once all these issues are all resolved, the second use case – looking up what immunizations a patient has received – is almost trivial, it’s a simple query against the registry immunization endpoint using the Patients NHI() identifier in a chained() query:

GET [host]/Immunization?patient.identifier = {nhi}

Almost anticlimactic!

Well, that’s enough for now. We’ll consider the other 2 use cases – what immunizations a person should receive, and representing the immunization protocol in the next post.

About David Hay
I'm an independent contractor working with organizations like Lyniate, CSIRO in Australia and the New Zealand Ministry Of Health. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the new FHIR standard.

7 Responses to FHIR enabling an immunization registry

  1. Paco Novillo says:

    Hi David!
    Nice work you have ahead!

    We are currently working in the registry of covid-19 vaccines with FHIR as well, and I wonder if you have already arrive at the point of analyse how to relate the two dosis of the vaccine people usually receive (with moderna and pfizer at least).
    It seems clear that it has to be two Immunization instances, but there is no field in the resource to link one Immunization with another. We are thinking in a extension in the second dosis, something like:

    “extension”: [
    “url”: “https://server/fhir/R4/ImmunizationBoosterOf”,
    “valueUri”: {
    “value”: “/fhir/R4/Immunization/799126”,

    Any thoughts?

  2. Pingback: Dew Drop – March 26, 2021 (#3410) – Morning Dew by Alvin Ashcraft

  3. Peter Jordan says:

    David, I’m wondering why you have suggested using PlanDefinition / ActivityDefinitiion rather than ImmunizationRecommendation?

    • David Hay says:

      All will become clear in the next post! Basically I’m proposing PlanDefinition for the national programme, and ImmunizationRecommendation applied to an individual…

  4. Pingback: FHIR enabling an immunization registry – part 2 | Hay on FHIR

  5. Pingback: FHIR enabling an Immunization Registry- part 3 | Hay on FHIR

  6. Pingback: FHIR enabling an Immunization registry – part 4 | Hay on FHIR

Leave a Reply

%d bloggers like this: