Representing a Patients list of Medications in FHIR

An interesting use case for FHIR is maintaining a list of a patients medications – i.e. the medications that they should be taking on a regular basis. Most EMR (Electronic Medical Record) systems will maintain such a list.

Each medication will have it’s own properties (such as drug name, dosage, how often to take, period of use and so forth), but for the purposes of this post we’ll focus on how to maintain the list on a day to day basis – including changes to the list – and consider the details of representing a single medication in a later post.

Knowing this list when treating a patient is, of course, of critical importance in healthcare as ‘medication related incidents’ – ranging from minor drug reactions through hospital admission and even death is a common cause of injury to the patient, as well as massive costs to the health system.

It is also important to know the history of changes to the list – i.e. when medications have been changed/stopped and new ones added, who made the change and the reasons why these changes have occurred. In some jurisdictions, this is called ‘reconciling’ the list from different sources of medication information such as dispense and administration information.

To represent this in FHIR, we’re going to need a number of resources.

Obviously we’ll need those that describe each medication. This is the MedicationPrescription resource that records the details of how a single medication should be taken. It includes references to the medication resource (representing the drug), the patient and the prescriber.

To represent the list that is active at any one time, we have a number of options.

Option 1: Query the MedicationPrescription resources for a patient

Each MedicationPrescription resource has a ‘status’ property whose value can be active, paused, completed or nullified. One option then is to get a list of all MedicationPrescription resources that have an active status like this:

GET /Patient/100/MedicationPrescription?status=active

(This uses the compartment feature to retrieve active MedicationPrescription resources for the patient with the ID of 100).

This would certainly work – but it becomes difficult to track changes over time – especially the reason for change.

Option 2: The document

Another option would be to place the medications in a FHIR document. We could have a section for the initial list of drugs and another section for the changed list of drugs. The advantage of this approach is that we can record the name of the person making the change, dates, locations etc. The disadvantage is that it’s a somewhat complex approach – requiring submitters and consumers to create and read documents.

Option 3: The List

There is a third approach that allows us to record these other data items as well as the actual list of medications – the List resource. This resource has been specifically created to maintain lists like this, and offers the following properties:

  • The type of list (we’ll use the LOINC code for ‘history of medication use’ to be consistent with CCDA). This is the code property, and is a codeableConcept datatype
  • The subject of the list – which will be a reference to the Patient resource
  • The source of the list. In this case it will be a reference to the Practitioner who created the list. The cool thing here is that when the list changes, we’ll create a new version of the list setting the source property to the Practitioner who changed it.
  • The date the list (or this version of the list) was created.
  • The mode of the list. In our scenario we’ll set this to ‘working’ as we intend it to be the on-going master list but there are other values that can be of use – eg ‘snapshot’ at a point in time which we may want to use in a referral for example.

Then there are any number of entries in the list. Each entry represents a single medication in the list, and has the following properties:

  • A reference to the medicationPrescription.
  • A flag for the entry. This allows us to indicate the nature of any change to the item between versions of the list – which is incredibly useful in reconciliation situations, or in Use Cases like representing the changes in medication when a patient is discharged from hospital. For example, one of the options could be ‘ceased’ to indicate that the patient was taking the medication on admission, but it was stopped while in hospital.
  • The deleted property. This allows us to explicitly state that this item is no longer active – it has been discontinued. In our case when we stop a medication we will also set the flag and the status in the

One thing that is missing in the entry is the reason for any change. For this we’ll add an extension to the entry element with a datatype of CodeableConcept and we’ll define a set of common reasons why a change occurred. In the example the extension is defined in a profile located at profile/mlomChangeReason

Putting all this together, the following example shows a medication list with two items:

  • Atenolol – which has been stopped due to an allergic reaction.
  • Labetolol – which was started in it’s place.

so the patient is actually only taking Labetolol. If you wanted the details of each prescription, you would get it from the reference in the list.
The list was created by Dr Welby on November 1st, 2011 for Mr I. Amanexample.

<?xml version="1.0" encoding="utf-16"?>
<!-- An example showinf a single item in the list - atenolol. As it is cancelled (due to an 
  allergic reaction), we know that the patient is not taking any medicines (as far as we know)-->
<List xmlns="http://hl7.org/fhir">
  <text>
    <status value="generated"/>
    <div xmlns="http://www.w3.org/1999/xhtml">
      <ul>
        <li>Atenolol 50mg at night was stopped due to an allergis reaction</li>
        <li>Labetolol 50mg at night was started as a replacement</li>
      </ul>
    </div>
  </text>
  <!-- This is the list Code - udentifying it as a list of medications -->
  <code>
    <coding>
      <system value="http://loinc.org"/>
      <code value="10160-0"/>
      <display value="History of Medication Use"/>
    </coding>
    <text value="Medication List"/>
  </code>
  <!-- The patient the list refers to -->
  <subject>
    <reference value="Patient/example"/>
    <display value="Mr I Amanexample"/>
  </subject>
  <!-- who created the list -->
  <source>
    <reference value="Practitioner/100"/>
    <display value="Dr Welby"/>
  </source>
  <date value="2013-11-01"/>
  <mode value='working'/>
  <!-- The first medication entry -->
  <entry>
    <!-- The reason for change -->
    <extension>
      <url value="profile/mlomChangeReason"/>
      <valueCodeableConcept>
        <coding>
          <system value="urn:oid:1.2.3.4"/>
          <code value="ar"/>
          <display value="Allergic Reaction"/>
        </coding>
        <text value="Developed a rash shortly after starting"/>
      </valueCodeableConcept>
    </extension>
    <!-- Indicates this is a concelled medication -->
    <flag>
      <coding>
        <system value="urn:oid:1.2.36.1.2001.1001.101.104.16592"/>
        <code value="03"/>
        <display value="Cancelled"/>
      </coding>
    </flag>
    <!-- So any consumner of this resource knows it is a cancelled med. The deleted property is a code with
    a fixed set of values, whereaes the flag is a codeableConcept, and the meaning depends on the terminology used.
    Every FHIR consumer MUST understand what a deleted property means...-->
    <deleted value="true"/>
    <date value="2013-11-01"/>
    <item>
      <!-- The reference is to the actual prescription resource. This will have details of dose, prescriber etc. -->
      <reference value="MedicationPrescription/100"/>
      <display value="Atelolol 50mg at night"/>
    </item>    
  </entry>
  <entry>
    <flag>
      <coding>
        <system value="urn:oid:1.2.36.1.2001.1001.101.104.16592"/>
        <code value="04"/>
        <display value="Prescribed"/>
      </coding>
      <text value="Started"/>
    </flag>
    <deleted value="true"/>
    <date value="2013-11-01"/>
    <!-- The reference is to the actual prescription resource. This will have details of dose, prescriber etc. -->
    <item>
      <reference value="MedicationPrescription/101"/>
      <display value="Labetolol 10mg at night"/>
    </item>
  
  </entry>
</List>

We can retrieve this list as follows:

GET /Patient/100/List?code=10160-0

Notes:

  • This is actually a query in FHIR, so would return a bundle containing the List resource – and there should only ever be one that matches for a patient.

In the next post, we’ll look at how we can record changes to the medication list, using the versioning mechanism in FHIR, as well as updates to the medicationPrescription resources as well.

Victor Chai on HL7 & SOA

Victor Chai on HL7 & SOA

An insightful presentation by Victor Chai (HL7 Singapore) on HL7 in a SOA world, from v2 through to FHIR 

Adventures in FHIR Searching: Getting a list of patients in a Ward

Had an interesting set of exchanges on the implementers skype chat yesterday talking about searching in FHIR.

The background was that we are looking at building a tablet app to support the recording of medication dispensings. Orion has an application (a Hospital Information System or HIS) that records this using a desktop interface, so the plan is to build a FHIR server that will act as a ‘proxy’ between the HIS and the tablet, with the tablet app consuming JSON FHIR resources over a RESTful interface.

We are thinking that the user will log into the tablet, then get a list of the wards they are currently scheduled on. They will select a ward, which will give them a list of patients, then select the patient from which they will get the medications to administer (or a similar type of workflow). I was asked to help out with the design of the FHIR resources & calls – and started to think about how to get as far as the patient list (I’ll consider the medication administration stuff later).

Looking through the current FHIR resource list I found a Location resource that specifically mentions that it models a Ward, so my first thought was to add an extension to that resource of type List, and then the List could reference a collection of Patients. The proxy server would be responsible for communicating with the HIS and constructing the bundle of these resources, which could be returned to the tablet app on request.

I mentioned this on the skype chat, and after some discussion with Grahame and Lloyd, we figured that a better solution would be to model the relationships using an encounter, and then we could do a FHIR query to get the data we need, using an _include parameter on the query for efficiency (I’ll get to this later).

So the relationship between the resources is like this:

ward query

Our approach will be:

  1. get the ward we want
  2. then get the encounters that are associated with that ward
  3. and then we can get the patients from the encounter.

Getting the ward is a straight forward query. Suppose the name of the ward is ‘Ward1’ then it’s a simple GET query against Location:

GET /Location?name=Ward1

Note that we will get back a bundle, and we may need to check for multiples – eg Ward1 and Ward11 would be valid matches (it’s a string search). We might also want to include a Location.type parameter if that is appropriate in our situation. But, we now have the Location resource– the Ward – and the ID of that resource. Let’s pretend the ID is 100.

Now to get the Encounters associated with that Location. Encounter does have a location property which is a sub-object with properties of Location & Period. In other words, an encounter can have many locations, and each location has a period over which the location was valid. This makes sense of course, as a patient can be moved around different places (Wards, radiology, therapy etc). So, we want encounters that are associated with our specific Location (Ward) right now. (There are other subtleties, but let’s keep it simple for now). We’ll assume that if there is a Location that matches ours, and where the period.end property is not present then that means they are currently associated with our ward.

However, there is a problem: There is no search parameter defined for location against Encounter – and in fact we need 2 of them – one for the location.location property and one for the location.period property. There are 2 things we can do:

  1. Petition the FHIR team to add these parameters
  2. Make these search parameters that our server supports (which is quite legitimate, though does mean our query on’t work on other servers)

We will do both. We will define 2 search parameters:

  • location that matches Encounter.location.location (which is a reference)
  • location-period that matches Encounter.location.period (which is a date).

and also ask the core team to add them (actually it is the HL7 committee that has oversight of this resource – you can look this up from this page, but sending a message to the core team via any of the supported channels will achieve this).

So now we have:

GET /Encounter?location =100 &location-period => 25-10-2013

(assuming that the date today is 25th October 2013)

So, now we have the encounters we want – all we need are the patients.

We could make a query for each patient – we can get that from Encounter.subject – but we can also ask the server to do that in our query by using the _include parameter. This is an instruction to the server to include the referenced resources in our query as well as the directly matched resources. So our complete query is:

GET /Encounter?location =100 &location-period => 25-10-2013&_include=Encounter.subject

will return a bundle that will contain all the encounters currently associated with Ward1 (resourceID=100), plus all the patient resources that are in these encounters. Job done!

Some notes:

  • We have defined some server specific parameters. Should the committee decide not to add these parameters to the spec, then either we accept this (after all we’re only concerned with our server at the moment anyway), or we could re-jig the query. Another exercise for the reader…
  • Servers are not obliged to support all search parameters – even if they are named in the spec. If we wanted our client to be able to talk to another FHIR server, then we would need to examine its conformance resource to make sure it does.
  • Servers are also not obliged to honour the _include parameter. If they don’t, then it simply means that we have more work to do client side – we just make direct requests for each patient after we retrieve the encounters.
  • In an earlier version of this post I was querying ‘into’ search parameters – eg GET /Encounter?location.period=… – it doesn’t work like that – it’s not like a path. Part of the issue is that we can’t have ‘ad-hoc’ queries into resources  – to quote Grahame: we’ve agreed that clients can’t simply launch random queries into the content of the resources – it has to be pre-agreed fields – there’s no way for the server to make that efficient, except in the case of special technologies 
  • Date querying is complicated. There’s a whole section in the spec on it.

This became a rather longer post than I intended, but hopefully it is a useful exercise to run through the thinking behind what became quite an elegant query – and I learned a lot doing it. It’s not the only way to do it of course, but it was a fun process!

FHIR coding, and the codeableConcept datatype

Many elements in the FHIR resources have a coded value, of which one of the more common types is the  codeableConcept.  (The other two are the code and the coding datatypes – which we’ll meet shortly). Coded data allows for precision of data collection, more accurate reporting, and lays the foundation for Decision Support and so is very important in the recording of healthcare information.

(I’m going to preface this discussion by stating that coding clinical data is a complex topic, and this post does not go into all the details of coding data – it is intended to make sure that you have a basic understanding of how to use this datatype in FHIR. There are lots of links where you can go to get more information if you need it.)

In the words of the specification:  “A CodeableConcept represents a value that is usually supplied by providing a reference to one or more terminologies or ontologies, but may also be defined by the provision of text”. It’s actually quite well described in the specification (as most things are, in truth), but I thought I’d write a short note about it – mostly because I said I would at the end of the last post – but also because it’s so commonly used in FHIR that’s it’s worth being familiar with it.

Examples of where you might use it include:

and there are lots of other situations as well – apart from a string it’s probably the most commonly used datatype in FHIR (I should write a short program to check that – perhaps I’ll leave it as ‘an exercise for the reader’!)

If you look at the definition of the codeableConcept, you will see that is actually a combination datatype:

  • a text property of type string
  • 0 or more coding properties of type coding

Evidently the coding datatype does most of the work. This structure allows you to capture the clinical information that is being coded (ie the description in plain text) as well as multiple representations of that text in the coding system of choice.

Confused? Well, imagine that the clinician entered “atopic asthma” and you wanted to represent that in a problem list. You might want to code that as “Allergic Asthma” in snomed (389145006) and “Extrinsic asthma – unspecified”  in ICD-9 (493.00). The codeableConcept allows you to have both of these codes, plus the original text entered by the clinician, and upon which the encoding was performed.

The coding datatype is the actual representation of the code in the coding system of choice. It has the following properties – all of them optional.

  • System. This is a URI that identifies the terminology (or collection of codes) from which the actual code value is chosen. Although marked as optional, if it is not present, then the value of the code is severely diminished. There are a number of places you can get this from:
    • There is a set of named lists in FHIR that has the most commonly used terminologies
    • The HL7 OID registry
    • Any other option that uniquely identifies the set of codes.
  • Version. The version of the terminology that the code is drawn from. This applies particularly to SNOMED, LOINC & ICD.
  • Code. The actual code from the terminology. If this is absent but there is a system property, then the meaning is that no suitable code could be found in that terminology. In all other circumstances, it doesn’t make a lot of sense not to include it.
  • Display. This is the display of this code in the terminology (which may not be the same as the text being coded).
  • Primary. If this is true, then it means that this code was explicitly chosen by the user – eg it was in a drop down or autocomplete that the user selected, rather than being generated ‘second hand’ – say by some coding algorithm, or mapping from some other terminology. The significance is that it will be the most accurate, if there is more than one coding present.
  • Valueset. This is included for 2 reasons:
    1. In some cases, the valueSet itself defines the code system and there’s no other way to determine the meaning of the codes (e.g. the codes are “a”, “b” or “c” from a questionnaire)
    2. There are some use cases where the set of choices available when the code was chosen is relevant to interpreting the code. – eg if the user only had 10 choices, they may have made a different choice than if there had been 100.

    However, even when using value set, you still need to populate the system.

So, lets create a  rendering of the asthma  example given above, assuming that we are placing this in a condition resource in the code property:


    <code>
        <!-- SNOMED code -->
        <coding>
            <system value="http://snomed.info/id"/>
            <version value="International Release – 20130731"/>
            <code value="389145006"/>
            <display value="Allergic Asthma"/>
            <primary value="true"/>
        </coding>
        <!-- ICD code -->
        <coding>
            <system value="urn:oid:2.16.840.1.113883.6.42"/>
            <version value="9"/>
            <code value="493.00"/>
            <display value="Extrinsic asthma - unspecified"/>
            <primary value="false"/>
        </coding>
        <text value="Atopic Asthma"/>
    </code>

From this we can tell that the clinician entered ‘atopic asthma’ but accepted the SNOMED code of allergic asthma.

When a terminology or codeset is associated with a particular resource property, this is called a binding. Each resource description in FHIR displays the bindings that are defined for that resource immediately below the description of the resource content. Each binding has the following properties:

  • Path. The resource property that is being bound.
  • Definition. Describes the binding.
  • Type. The ‘strength’ of the bindings. Options are:
    • Fixed means that there is a specific set of values defined in the spec than cannot be extended. Usually this is for ‘code’ datatypes (see below)
    • Incomplete means there is a recommended set of values but can be extended by implementers
    • Example – it is really up to each implementation to decide
    • Unknown – not yet decided
  • Reference. A link to the terminology or codeset.

Some other things to note:

  • In theory a resource could have a property with a datatype of coding – in practice this is not often done (if at all). The codeableConcept is far more flexible than coding – for example, it would support a property that *can* be coded, but for some reason is not in this specific instance – such a patient problem/condition where the problem description has been captured, but not yet formally coded.
  • There is also a code datatype that many resources employ. Generally this is used for ‘workflow’ type purposes, and the codeset from which it is drawn is defined – and fixed – by the designers of the resource. The mode property of the List resource is an example of this – it is important  that any user of a List resource should be able to correctly interpret this property on any list, with clinical safety issues if not.
  • The equivalent to the codeableConcept in v3 (or CDA) is the CD – Concept Descriptor – datatype. CD is more complex than codeableConcept, though the extra functionality it offers (such as translations) are not often needed in practice (which is why it was simplified in FHIR). Should you find that you need to do so, then the FHIR extension mechanism can be applied to datatypes as well as resources.

So, enjoy the codeableConcept!

Where there are sparks…

One of the (many) things I like about FHIR is the fact the test servers were established very early in the process, so that the ideas that were being proposed could be tried out before becoming part of the specification. They form a core part of the connectathons that are held at each HL7 Working Group Meeting, although these days there are other servers springing up – which is a great thing!

Originally there were two servers: Grahames (which is built in Java) and Ewouts (which is .net based).  (Grahame and Ewout are part of the 3 person ‘core team’ of FHIR – the other being Lloyd McKenzie. In fact, the FHIR logo can be thought of as “the sign of the three” – with apologies to  Sir Arthur Conan Doyle.)

In my examples thus far, I’ve been using Grahames server, but they work equally well on Ewouts server – so the following examples from the Elbonian proposal for a FHIR Patient registry work the same as on Grahames:

Note that the servers won’t always have the same version of FHIR (or the same data) – due to the current rapidity of FHIR evolution. This will stabilize once the spec reaches DSTU early next year. In fact, you should always check a servers conformance resource to see what version it supports.

Some other things:

  • Ewouts server is actually developed by a company based in the Netherlands called Furore, and he has a blog on FHIR that is worth following – it tends to be more technical than mine.
  • Furore is one of the early supporters of FHIR, and are planning a commercial FHIR server – which is great to hear. I do believe that FHIR is going to be a disruptive influence in the Health IT space, and the availability of commercial grade servers based on widely adopted standards is a key part of that. They also designed the current logo.
  • Ewout is also planning a couple of cool tools in the FHIR space:
    • A server validation tool codenamed ‘sprinkler’ that can be used to check that a server correctly implements FHIR, and disclosing any deficiencies.
    • A profile designer. Profiles are a very important part of FHIR, but not easy to understand, so an easy to use tool to develop them is a ‘good thing’ for the spec as a whole.

When I know more about the new tools, I’ll post about them…

Using FHIR to expose a Patient Identity Registry lookup service – part 2

In the previous post we discussed the use of the patient resource as part of an Identity registry service. In this post we will discuss the behavior of that service.

To review the specific scenarios we are supporting:

  1. Retrieving a list of matching patients based on criteria such as name, gender, Date of Birth and such like.
  2. If we do have an identifier, retrieving the resource (or resources) that have that identifier.

1. Searching for a patient

The first scenario is a simple search – as we have already discussed. We’ll support searching on name, gender and age. The spec gives the details of these search parameters.

Name is straightforward – it is a string and the spec states that the server will match our string with both family and given names which have that string within the name. The following GET request will return all patients with ‘eve’ in their name.

http://hl7connect.healthintersections.com.au/svc/fhir/patient?name=eve

Gender is a token. Reviewing the bindings for gender we see that the options are currently ‘M’, ‘F’ or ‘UN’, so the following GET request will return all males with ‘eve’ in their name

http://hl7connect.healthintersections.com.au/svc/fhir/patient?name=eve&gender=M

Age is a bit trickier. We could always use Date of Birth (and maybe we should) but often we’ll only know approximately how old a person is. For this to work we’re going to need modifiers on the query. I won’t describe the details (refer to the spec for that), but basically you can do things like specify before and after as shown in the example below for a child less that 3 years old (The users UI should be able to create dates from ages without difficulty).

http://hl7connect.healthintersections.com.au/svc/fhir/patient?birthdate:after=2010-01-01&birthdate:before=2013-12-31

Couple of notes:

  • I’ve used Grahames server rather than the elbonian example I used in the previous post so you can try it out for yourself.
  • Also, the last query actually returns an animal – at least it did when I tried it. FHIR supports veterinary as well as human health information.

Naturally the response for all of these examples will be a bundle of patient resources, as previously discussed.

2. Getting the details when the Identifier is known

So finding a patient by searching on name or other parameters is straightforward. What if we already know the identifier? We can just GET that patient resource, right?

Well, no we can’t. We still need to do a search, except that the parameter we are using is the identifier. If we stop to think about it for a second it is obvious why. We can only retrieve a resource directly if we know its ID – and therefore its URI. But the ID and the identifier are not the same (as we discussed in the last post) – so a search is needed, and we will get a bundle back – hopefully with only a single resource in it.

Try the following link:

http://hl7connect.healthintersections.com.au/svc/fhir/patient?identifier=444222222

When I tried this I got a couple of resources back – well it is only a test server. But – this does point out that FHIR does not enforce the ‘uniqueness’ of an identity – it is the responsibility of the application behind it that does that.

But there are still a couple  more things to consider.

  • First, depending on how we configure the server, we may or may not get inactive records back. Recall the merge example in the last post, where we merged WER4568 with PRP1660 – de-activating WER4568. What should we get back if we search for WER4568? It makes sense to still return the resource, but it does mean that we need to check the ‘active’ property when we get it to make sure it is still in use (and we can use the link property to get the resource to which it was merged if not).
  • We also need to think a bit about the details of the identifier search. It’s a token, so if we just search on the value, there’s a chance that the same identifier could exist in different namespaces. To be safe we need to specify the namespace as well as the value – thus the identifier parameter for PRP1660 becomes something like www.moh.elbonia.govt/nhi/PRP1660 rather than just PRP1660.

So we’ve got a REST service that allows us to query a patient identity service using simple GET requests and supporting a number of parameters.

What about Security & Privacy? We won’t consider these yet. They depend on a number of aspects of FHIR that we have yet to discuss such as tags and oAuth – we’ll revisit this topic when we’ve done that.

But we can create a conformance resource. This is a resource that can be used by both server and client – but we’ll just think about the server at the moment. The conformance resource allows a server to declare – in a computable way – what resources it supports, and what actions against those resources. Here is an example:


<Conformance xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir">
   <text>
     <status value="generated"/>
     <div xmlns="http://www.w3.org/1999/xhtml">
       <p>This conformance statement id for the Patient Identity service for the Elbonian Ministry of Health</p>
       <p>The Registry supports the Read transactions for the resource Person.</p>
     </div>
   </text>

   <identifier value="68D043B5-9ECF-4559-A57A-396E0D452311"/>
   <version value=".1"/>
   <name value="Elbonian Patient Registry Conformance statement"/>
   <publisher value="Elbonian MOH"/>
   <telecom>
     <system value="email"/>
     <value value="wile@elbonia.govt"/>
   </telecom>
   <description value="This is the FHIR conformance statement describing the Patient Registry for the
     Elbonian Ministry Of Health.
     It allows a user to search on patients, and retrieve the details of a patient based on their identifier.
     No security is required as Elbonians do not have any concept of privacy"/>
   <date value="2012-10-14"/>
   <software>
     <name value="PatientRegister"/>
     <version value="0.34.76"/>
   </software>
   <fhirVersion value="0.12"/>
   <acceptUnknown value="false"/> <!--   this system does not accepts unknown content in the resources   -->

   <!--   this system can do either xml or json. (Listing both implies full support for either, with interconversion)   -->
   <format value="xml"/>
   <format value="json"/>
   <!-- We only support REST interfaces at this time -->
   <rest>
     <mode value="server"/>
     <resource>
       <type value="Patient"/>
       <operation>
         <code value="read"/>
       </operation>
       <searchParam>
         <name value="name"/>
         <type value="string"/>
         <documentation value="Lookup by patient name. Only active patients will be returned. All parts of the name are searched."/>
       </searchParam>
       <searchParam>
         <name value="identifier"/>
         <type value="token"/>
         <documentation value="Lookup by identifier. Both active and inactive patients will be returned."/>
       </searchParam>
       <searchParam>
         <name value="birthDate"/>
         <type value="date"/>
         <documentation value="Lookup by patient birts date. Supports the :before and :after modifiers to allow for age ranges"/>
       </searchParam>
     </resource>
   </rest>
 </Conformance>

The conformance resource allows a potential client to understand the capabilities – and requirements – of our Registry service. It should be self-explanatory, so I won’t go into it in much more detail. However conformance statements – and the associated concepts of profiles – are a lot more powerful than this, and will receive more attention in due course. In some ways, they are analogous to UDDI and WSDL in the SOAP world – but much easier to understand.

According to the spec the server should deliver this resource in two way:

  • GET [base]/metadata {?_format=[mime-type]}
  • OPTIONS [base] {?_format=[mime-type]}

Thus a GET to :

http://hl7connect.healthintersections.com.au/svc/fhir/metadata

will return the conformance statement for Grahames server, and hopefully you can imagine what the equivalent for the elbonian server would be.

(The reason why there are two ways is that while the GET method is pretty much universally supported by HTTP clients, the OPTIONS method is not.)

Well, that brings us to the end of this short series (2 posts) on FHIR-enabling a patient registry service. We now have a “simple to use” service that allows any user to search our patient registry using standard tools – either from the command line of as part of an application. We could easily extend it to support updates as well – perhaps when a patient changes address or contact details these updates could be applied directly using a PUT against the resource URI. If we did allow such a thing, then authentication and authorization become a lot more important – and we’d probably also want to have some sort of person mediated workflow and checking involved rather than just a direct update. But the point is we can do that if we choose to do so.

Although fairly high level, hopefully this gives a ‘real-world’ example of where FHIR can add real benefit in health interoperability, as correctly identifying the patient is the cornerstone of accurately recording health information.

Next post will be back to basics – the codeableconcept datatype deserves some attention…

Using FHIR to expose a Patient Identity Registry lookup service – part 1

Now that we’ve covered a bit of the theory and background to FHIR, let’s look at a concrete example of where we might apply these principles. The Use Case we’re going to look at is to provide a REST based lookup service in front of a patient Identity Server.

Some notes before we start:

  • We assume that there is already an existing registry that we are providing a front end for. It handles all the assigning of identifiers, managing merges & un-merges and such like. In other words this is a read-only service (at the moment).
  • Every patient will have a single identifier (although that may change over time). We’re going to assume that this has national scope so we’ll call it a National Health Identifier – or NHI. This won’t apply in all domains of course, but it simplifies the issue for now.
  • So that we can create full URL’s, we need a server name. We’re also going to need some namespaces (more on that shortly) so, in a nod to Dilbert, we’re going to assume that the country we are building this for is elbonia.

The scenarios we will support are:

  • Retrieving a list of matching patients based on criteria such as Name, Gender, Date of Birth and such like – what you’d use if you were wanting to find someones NHI.
  • If we do have an NHI identifier, retrieving the resource (or resources) that have that NHI.

This is going to be a rather long post, so I’ll split it into 2 separate posts:

  • In this one we’ll talk in some detail about the resource, and cover the special importance of the datatype of the properties of the resource, and how to manage merging where we have duplicates.
  • In the second post, we’ll talk about the behavior of our registry service.

First, which resource to use? Well, the obvious candidate is the patient resource. It has the base demographics we need, plus an identifier (in fact multiple identifiers).

This is the first time that we’ve looked at a resource in any depth so it’s worth spending a bit of time on it. Each resource has a specific page in the spec, and each page has a number of sections:

  • A description of what the resource is intended to represent. The size and content varying according to the complexity of the resource.
  • A UML representation of the resource – a class diagram – containing the core properties with the property name, multiplicity and datatype. The datatype of the property is especially interesting as it can range from a single string to a more complex structure – an object in its own right. We will see more of this structure as we explore the patient resource, but it’s important to realize that the datatypes are the same for all resources.
  • A XML representation of the properties with the same information as the class diagram – with the addition of a brief description of each property. The name is hyperlinked to a formal description, and the datatype/s hyperlinked to the detailed description of the datatype. (Many resource properties allow multiple datatypes – you choose which one is the most appropriate when creating – or updating – the resource).
  • The terminology bindings for those properties that are bound to a code set or terminology.
  • Other constraints – generally those that cannot be represented by XSD schema.
  • Any other comments of note.
  • The specific search parameters defined for that resource.

Each resource will also have a specific XML schema and schematron file – these can  all be downloaded from the spec in a single zip file.

Of the main representations, I find the XML format the easiest to follow, so let’s look at some of the properties for the patient resource (at least those that have special points to discuss).

Patient.identifier

First up is the identifier property. This will hold our NHI identifier (though it can have others as well – e.g. a drivers license). If you look at the XML, you will see that the datatype is also called Identifier (it is in a green font, and is a hyperlink). Click on that link – it will take you to the description of what an identifier datatype is, and what properties it has.

There are a few that are of interest to us (and note that it is extensively hyperlinked to get more information as you need it).

  • The use property describes how this identifier is going to be used. We’re the official registry so ‘official’ seems most appropriate – but we note with interest that ‘temp’ or temporary might also apply in some scenarios.
  • The label is for humans – so let’s use NHI for that
  • The system needs to define the namespace within which the actual identifier value is valid – and unique. It’s a URI, so let’s base it on the address for the Elbonian Ministry of Health – so we get http://nhi.moh.elbonia.govt (Note that this doesn’t have to be a ‘real’ address, so long as it is globally unique).
  • The actual value of the identifier – eg PRP1660, or whatever we choose to use. FHIR makes no comment about the format of the identifier – that’s up to the implementation. We might decide, for example, to incorporate a checksum digit to help with error checking.
  • The period over which the identifier is valid. That could be useful if we have to ‘retire’ an identifier, but for now we’re going to assume that if our service returns an identifier it is currently valid and is intended to remain so, so we won’t use it for now.
  • We could use the assigner to give more data about the organization that maintains the registry.

Patient.name

Next property is the name of the patient. It has a datatype of HumanName, and contains properties such as family name, given name and use. There is also a text property that can be used for the complete name. Whether the text property and/or the individual items are used is at the discretion of the resource author, although profiles can be used to control usage to some extent.

This is a good place to mention that you could – if you needed to – use extensions to add other properties to datatypes. For example, you might want to add a salutation to the name. I’ll talk more about extensions in another post.

Patient.gender

This has the datatype of codeableconcept. Codeableconcept is an incredibly important datatype as it represents coded data and is extensively used within FHIR. It deserves its own post, so for the moment I’ll just point out that there is a particular set of codes that can be used here (if you look in the terminology bindings section you will see a reference to the set).

Patient.link

Patient identification is a critical part of recording healthcare information – and one that is prone to error, for example a single person being registered multiple times. The link property in FHIR us used to assert that two (or more) patient resources are, in fact the same person.

And now is a good time to describe the difference between resource ID and the identifier.

As described in previous posts, all resources have an ID – the resource ID – which  along with the server and resource type comprise the unique URI of the resource. The resource ID cannot change, and so something like the registry identifier is not a good candidate for the resource ID because it can change. You should think of the resource ID like a database primary key – let the server assign it, and attach no semantic meaning to it. (A client can also assign the ID – though you need to be careful if doing this).

An example might help.

Suppose you create 2 patient resources. One has the ID of 100 with an identifier of PRP1660, and the other has an ID of 200 with an identifier of WER4568. After storing clinical data against these resources (and using the resource ID as the linking mechanism) you discover that they are actually the same person. You determine that the identifier you wish to keep is PRP1660, and wish to ‘shift’ all the records currently pointing to WER4568 to point to PRP1660, and inactivate WER4568. You cannot (or should not) change the ID in the resource reference of all the other resources that currently point to WER4568. The correct action is to set the link of each patient resource to the other one (thus they point to each other), and set the active property of WER4568 to false. This should be done in a transactionally safe manner.

In this way it is obvious to any subsequent view of the record what has happened, and which is the correct resource.

Before merging

Identifier ID Active link
PRP1660 100 True (or absent)
WER4568 200 True (or absent

After merging:

Identifier ID Active link
PRP1660 100 True (or absent) 200
WER4568 200 False 100

(Note that the link is actually a resource reference, and so has a slightly more complex format than a single string)

And while we’re talking about errors, what do you do if – rather than having duplicated patients, you just set the subject link of another resource (say a condition resource) to the wrong patient? Well, that is what the versioning facility in FHIR is for – you create an updated version of the condition resource with the ID of the correct patient resource, thus maintaining the history of change.

The other properties are all important but I won’t talk any further about them here, as their meaning and use should be evident from their description and from the discussion above.

It’s also worth pointing out that in a real scenario, if there were properties that we needed and weren’t in the FHIR specification (for example the reason for a merge, or to store realm specific information like iwi), then we can always use the extension mechanism to add them.

Well, that is all we’re going to say about patient – next post will describe how we use the patient resource in our registry REST service

FHIR searching

In this post I’m going to talk a little about searching using the REST paradigm within FHIR. This is a large topic, and I certainly won’t cover it in detail, but my intention is to provide enough detail for you to get started. (For the full details of searching (or queries) refer to the specification).

We’re going to focus on searching for a single type of resource – e.g. find a patient – how to specify the search parameters and how FHIR returns the results.

Each resource has a list of pre-defined search parameters that are defined in the specification for that resource. These are at the bottom of the page that describes each resource – for example here are the patient search parameters. Note that there is no requirement on a FHIR server that it must support all of these search parameters – and a server is also able to define their own searches – these are simply the list of parameters that the committee that defined the resource believes are the most common, or most obvious search parameters.

A FHIR server can indicate which parameters it supports for each resource in its conformance resource.

The format for this basic searching uses the GET method as follows:

GET [base]/[type]?[parameters] &_format=[mime-type]

or

GET [base]/[type]/_search?[parameters] &_format=[mime-type]

Where:

  • Base is the base URL to the server
  • Type is the resource type (like ‘Patient’)
  • Parameters are the search parameters you wish to use (and there can be more than one)
  • Format is the format (xml or json) you want the results in. (HTTP headers are the more elegant way to specify this, but it might not always be possible to easily set the headers, which is why this format is supported – in fact, it also applies to simple resource retrieval as well)

The parameters are expressed in name/value pairs, eg

http://hl7connect.healthintersections.com.au/svc/fhir/Patient?name=eve

would return all patients whose name contains the word ‘eve’

http://hl7connect.healthintersections.com.au/svc/fhir/Patient?name=eve&_format=json

is the same search, but specifying that the result should be in a json format rather than the default XML format.

Each resource parameter has a type that defines how it behaves – e.g. whether it is text, a number or part of a code set (a token). In most cases this is reasonably straightforward (though there are subtleties in some cases) – The one that causes the most difficulty at first is where one of the parameters is a resource reference – e.g. you want all the conditions for a particular patient. (In fact, this particular scenario has a specific solution – the compartment – that I’ll cover in a separate post, so bear with me for the moment).

The following search:

http://hl7connect.healthintersections.com.au/svc/fhir/condition?subject=351

will return all conditions where the ID of the subject (which is a patient) is 351 (The assumption is that you have previously performed a search on the patient to locate that ID). It is possible to get more complicated than that – for example you can chain query parameters to get, say, all conditions for patients whose name is david. Go look at the spec if that functionality is important in your use case. (Note: the format of this type of query has changed recently and not all servers may support it yet)

So we’ve talked about how to find resources based on matching their properties to some value, how to find resources based on their link to some other resource but we haven’t talked about the format that the results are returned in. It can’t just be the resource – as there will likely be more then one that matches – it has to be a set of some sort.

In fact, FHIR uses the Atom format to return the results of any search – regardless of how many resources matched the search – and we call this a bundle. Bundles are, in fact, used in a number of parts of FHIR – they form the basis of FHIR Documents and FHIR Messages, as well as the ability to batch multiple commands into a single transaction, but lets stay focussed on search for now.

If you look at the definition of the bundle, you’ll see it’s made up of a feed element, which contains any number of entry elements. Considering first the feed:

  • The root element is  <feed> – and it’s in the atom namespace. This means that any Atom reader can consume FHIR bundles – which raises a number of interesting possibilities that will likely be the subject of future posts! (Grahame, for example, uses this to monitor activity against his server, and it could be the basis for server replication). It also places some constraints on what we can do with bundles – it must remain compliant with the Atom spec.
  • There is a <title> element on both the feed and each entry within the feed. This is required by the Atom spec, but is not treated specially by FHIR. In particular, the contents should not be used for any automated processing.
  • Every feed has an <id> that must be a unique URI. In theory, a server could use this as the basis of an audit log, although that is not required by FHIR.
  • The feed has a number of <link> elements used for purposes such as pagination, as well as an element for the number of total number of results that matched the query (not just in this feed). These are optional.
  • An <updated> element that indicates the instant that the feed was created.
  • The <author> of the feed. Atom requires this – FHIR doesn’t care.
  • An optional <category> that contains tags associated with the feed. I’ll cover tags in a separate post – they’re used for things like security & privacy.
  • A <Signature> element that can be used for digital signatures.

Now lets’ look at the <entry> elements. Each entry element represents a single resource (in this case that matched the search/query) and has the following characteristics:

  • A <title> element (just like on the feed).
  • An <id> element. This is a URI that refers to the resource that is contained in the entry. It is NOT a version specific URI – it will refer to the most recent version of the resource on the server.
  • A <link rel=’self’> element that IS a version specific URI. This is not required (as not all servers will support versioning) but is recommended
  • An <updated> element. This is the date that the resource was last updated on the server – not when it was retrieved from the server. (There is a <published> element that states when it was copied into the feed – I’m not sure how useful this really is – maybe if you’re using the feed for server replication).
  • The <author> of the entry. If used, this will be the person who created the resource.
  • Any number of <category> elements. As in the feed, this is used to indicate the tags associated with the resource, and is much more useful when applied to a resource.
  • A <content> element that has the actual resource. This is what you are after as the result from the search. This will be the standard representation of the resource, with the resource type as the parent element, and the remaining properties as children (at least in XML – the format in JSON is in flux at the moment)
  • A <summary> element – this should be the same content as the text element within the resource, and is used to support the ability to display a feed using an XSLT transform – without needing to understand the FHIR resource structure.

And, of course, a bundle – and its contents – can be expressed in json as well as XML.

So, to summarize, a search in RESTful FHIR is quite simple

  1. Send a GET request with the desired parameters as name/value pairs in the URL
  2. Iterate over the <entry> elements in the response to get the results (or just use an XSLT transform displaying the title & summary elements if all you are doing is displaying it to the user or similar simple processing)

(you can even do this from a browser, though Graham will wrap the response in a UI if you do this – so the POSTman type approach I used in the previous post gives a result closer to the spec.).

Has a final note, it is also possible to use a POST to specify a search: as the query page states:  “or as an x-multi-part-form submission for a POST”, though this does seem to break the rules of REST as POST is not an idempotent operation, and in general is used to update a servers associated data store rather than query against it.

Manipulating a single FHIR Patient Resource

Following on from the previous post about REST in general, let’s dig in a bit more and start manipulating a single resource in FHIR. We’ll read an existing resource, update it and create a new one.

First task is to set up the tools we’re going to need to experiment. There are at least 2 sets of tools you’ll need to do this properly:

  • Something to send and receive HTTP requests. This will to allow you to specify the content, the HTTP method and request headers, and also to view the response headers, Status Code and any response body that the server returns. (refer to my previous post if these terms are new to you)
  • Something to create and view XML and JSON resources. You might also want to download the FHIR schema files from the spec (look for the link that says ‘FHIR Schema & Schematrons).

Depending on your environment, there are many options for both of these. To keep thing simple I’m going to use a chrome browser extension (Postman) for making the HTTP requests, and the Oxygen XML editor for the XML/JSON stuff, but you choose what works for you. I’m going to assume that you know how to use these tools – or are at least willing to find out!

Reading an existing resource

Before we start – an important message about the ‘@’ symbol. Currently, the FHIR specification uses the ‘@’ symbol in a URI to make it clear which part of the URI is the ID for the resource. This is going to change in the next version of the spec, and it will be removed, however it might take some time for the test servers to be modified. If you get weird errors when trying the instructions below, then remove the ‘@’ and see if that helps.

To read an existing resource when you know its URI (i.e. the server location and ID on that server) you use an HTTP GET request. I’m using Grahames’ server for this example which is a public server that anyone can change, so the details may be different for you.

Here’s what I got using Postman to retrieve the Patient resource with an ID of 2:

Screen Shot 2013-10-16 at 8.50.37 PM

Note that:

  • The full URI to that resource on Grahams’ server is http://hl7connect.healthintersections.com.au/svc/fhir/Patient/@2
  • I asked the server to return the resource in the XML format, by setting a request header – Accept – to ‘application/xml+fhir. I could have set the Accept header to ‘application/json+fhir to get a JSON formatted resource – try it! Here is a bit more on these mime-types.
  • The Status Code was 200 – which means that everything worked OK.

In Postman, I can also look at the response headers – which the server sets – as shown below:

get with headers

Notes:

  • The Content-Location header has the value http://hl7connect.healthintersections.com.au/svc/fhir/patient/@2/history/@2 . This is a ‘version specific’ URI – it specifies not only the resource Id, but also the specific version of this resource – in this case it’s the second version.
  • The content-type header tells us that this is an XML format.
  • There are a number of other useful headers that we won’t go into right now.

Updating a resource

Lets update this resource. What we’ll do is to copy the resource we just retrieved into our XML editor, make some changes, paste them back into Postman and PUT them to the server. Optionally, we’ll validate the updated resource using the FHIR schema before we send it to the server.

Step 1: Copy the resource you just downloaded

Step 2: Paste the resource into your XML editor

Step 3: Change the file – for example you could add a new name just after the existing name, like so:

...
&lt;!-- Original Name --&gt;
&lt;name&gt;
    &lt;use value=&quot;official&quot;/&gt;
    &lt;family value=&quot;SASHA&quot;/&gt;
    &lt;given value=&quot;BOJICIC&quot;/&gt;
&lt;/name&gt;
&lt;!-- New Name --&gt;
&lt;name&gt;
    &lt;use value=&quot;usual&quot;/&gt;
    &lt;family value=&quot;As&quot;/&gt;
    &lt;given value=&quot;Otherwise known&quot;/&gt;
&lt;/name&gt;
...

If you want to, you can check that this is valid against the FHIR schema by associating the updated file with the correct XML schema (it will be Patient.xsd in whatever folder you downloaded the schema to) and clicking the ‘validate’ button in your editor.

Step 4: Copy the changed resource

Step 5: In Postman, change the GET to a PUT and paste the updated resource into the body of the request (the raw tab is the best)

Step 6: press the Send button.

All going well, the server should accept the changed resource, and return a response with a status code of 200. The Content-Location header should show that the version has been incremented. Here’s what I got:

Updated after PUT

Notes:

  • The spec does not require that version numbers are sequential ones – although Grahames server does do this. Others (like Ewouts) use a different scheme – all that matters is that a new version of a resource gets a new version number.
  • We used PUT and not POST because we knew the full URI (including the resource ID). POST would have indicated that we wanted to create a new resource – as we’ll do in a minute.
  • If you PUT to a URI, and there is no existing resource at that URI then it will still be saved, but the status code that is returned will be 201 rather than 200.
  • At the moment, when you update (or create) a resource, then the FHIR server will return the resource it saved. This behaviour will be changed to be more consistent with the HTTP spec in the next FHIR version, and the resource will no longer be returned.

And before we move off the topic of updates – and versions:

  • You can always retrieve a specific version of a resource using the version specific URI that was returned when the resource was updated – eg http://hl7connect.healthintersections.com.au/svc/fhir/patient/@2/history/@3
  • You can get a list of all the versions that exist for a resource (if any) by appending the term ‘history’ to the URI of the resource – eg  http://hl7connect.healthintersections.com.au/svc/fhir/patient/@2/history
    • (Note that this will return a list of resources in a bundle – I’ll cover bundles in the next post when I discuss searching)

Creating  new resource

So, that’s getting an existing resource and updating it – what about creating an entirely new one? Well that’s easy – and you can do it right now. All you have to do is:

  • Use the POST method instead of the PUT method
  • Send the request to the root for that resource on the server – e.g. http://hl7connect.healthintersections.com.au/svc/fhir/Patient in the case of Grahames’ server – rather than to a URI (after all, you don’t know what ID the server is going to assign to the new resource yet).

All you have to do is to change the URL in POSTMan (get rid of the /@2 at the end of the line), change the method to POST and press <Send>.

The server will process the request and return a response. This time the status code will be 201 – indicating a new resource was created. The actual URI for the resource will be in the Content-Location header (and it will, of course, be a version specific URI).

How hard is that?

A question that came up from the previous REST post was about who creates the resource ID’s. In particular, can a client create the ID rather than the server?

It is certainly possible for the client to assign the ID – in FHIR, if a client PUT’s a resource to a URI (i.e. includes the ID) and there is no resource already there, then the server will create the resource using that ID (it returns a 201 status to indicate that this has happened). The issue with this of course is in potential ID collisions – what prevents 2 clients using the same ID for different resources?

However, FHIR takes the view that this is a deployment decision, and is up to the implementers and trading partners using the server. They could insist on GUID’s as the IDs for example.

Do play around with reading, creating and updating Patient resources. You can try creating entirely new resources in your editor (and don’t forget to use the schema validation so you know you have a valid resource). Read the documentation for the Patient resource to find out what properties you can add, and don’t forget to look at the examples that are in the spec (in a tab at the top of the page).

The next post in this series will start to explore the topic of searching – how do you find a resource when you don’t know its URI  – and where we’ll be introduced to a new construct – the resource bundle.

Cheers…

A REST primer – FHIR style – part 1.

In this post I’m going to talk a little about REST – REpresentational State Transfer – in the context of FHIR. The FHIR specification goes into some detail about how REST and FHIR work together, so go there for more details.

As mentioned in a previous post, FHIR works across many different interoperability paradigms, but REST is the best established at this point in time – and by far the easiest to use (as you will see). It’s the one used by companies such as google, amazon and twitter to provide access to their services (as well as 37 signals – which was the original inspiration for FHIR).

Despite the complicated sounding name, it’s actually quite simple – in fact, it’s the way the web works. The term REST was first used by a chap called Roy Feilding – one of those uber-smart guys that defined many of the basic web protocols that we take for granted today. In a PhD dissertation, he took some of the basic web concepts, and described an ‘architectural style’ that took advantage of those concepts in an easy to use way. (sounds like the goals of FHIR – right)?

The basics are really quite simple.

  • REST is built on top of the HTTP protocol – the same protocol you use when requesting a web page in your browser. HTTP (short for HyperText Transfer Protocol) is simply a set of rules that both server and client (in this case a browser) use to exchange data over the web. HTTP is a ‘request/response’ protocol – you make a request (which can contain data), the server responds and that’s it.
  • REST thinks in terms of resources, each of which has an identity by which it can be manipulated. This is the URI (Uniform Resource Identifier), and uniquely specifies the location of a resource. It is specific to a particular server.
  • When manipulating resources, there are a fixed number of methods that you can use. The ones that are of particular interest to FHIR include:
    • GET – retrieve a particular resource based on its URI (server location + id). FHIR uses the GET method both to retrieve a single resource, and to perform a search which could potentially return multiple resources.
    • POST – create a new resource at a specified endpoint. In REST the server will assign an id, and the combination of server location and id becomes the URI for that resource.
    • PUT – update an existing resource. The client that is executing the PUT needs to know the URI of the resource (which, in FHIR, means that they know the id of the resource as well as the server where it is stored). In FHIR, this will create a new version of the resource.
    • DELETE – remove a resource. Again the URI must be known. It is recommended (though not mandated) in FHIR that a copy of the resource is maintained, and potentially reachable using a version aware read, and the history by a history request, but a plain GET should not return the resource any more. (It will, however, return a status code telling the user that a resource was deleted – read on!)
    • OPTIONS – this is a ‘special’ method in FHIR, that is directed to the root of the server, and returns a conformance resource that informs the client what the capabilities of the server are. I’ll write about this some other time – it’s actually quite useful, though not necessary to know for normal operation.
  • When a server responds to an HTTP REST request, it processes the request according to the method and its internal business logic, and then returns a response to the client. The response has a number of parts to it:
    • The body of the response is what the client is requesting from the server – generally in response to a GET request. Most of the other methods do not return a response. (Note: in the current version of the spec they actually do – but that will be removed soon).
    • The server always returns a status code – which informs the client what the outcome of the request was – did it succeed, or did it fail – with some further details about the nature of the outcome. The status code is a number, which has a well defined meaning within the HTTP protocol. FHIR defines an operationOutcome resource, which the server can use to give the client detailed information about any failure.
    • Both the request and the response can contain headers. These provide extra information about the request or response to assist the server or client to properly process the transaction. Examples include:
      • Both request and response use the Content-type header to tell the other party whether a resource is in xml or json format.
      • A client will use the Accept header to tell the server what format (xml/json) it would prefer to get back when making a GET (though the server is not obligated to honor this)
      • The server will use the Location header to tell the client the URI of a newly created resource
      • And so on.

    Well, that’s enough background – lets actually do something in FHIR. Let’s get a patient resource from one of the on line FHIR test servers.

    Paste the following command (which is actually a URI) into your browser:

    What this does is to instruct your browser to make a GET request to the specified URI, and display the results in your browser. You should see an XML version of the Patient resource that has the id of 4165431. Simple – eh?

    http://fhirtest.uhn.ca/baseDstu3/Patient/4165431

    Dissecting the instruction a bit:

    • HTTP:// – specified the HTTP protocol
    • fhirtest.uhn.ca/baseDstu3/ – the endpoint on the Public HAPI server that responds to FHIR requests
    • Patient/ – specified that the operation was to be on the Patient resource
    • 4665431 – specified the patient with the id of 4665431.

    A couple of notes:

    • I needed to know what the Id was. It was fairly safe in this case because the public HAPI server is a test server with some fixed resources, and unless someone else deletes that resource it should be available (try another number if that happens). You could use this technique to retrieve any type of resource from any FHIR server – provided that you knew the Id – and passed any security mechanisms.
    • The only thing you can do through the browser (at least this way) is to issue GET requests.
    • For better results (and to use the other verbs) use a REST client like POSTMan
    • I haven’t talked at all about security.

    In the next post I’m going to delve into REST a bit further – how to search for resources if you don’t know the id, how to change existing ones or create new one. And, if there is time, how to do queries across resources – e.g. all the conditions associated with a specific patient.

    BTW – if the link above doesn’t work, then try    http://fhirtest.uhn.ca/baseDstu3/Patient.  What you’ll get is a collection of Patients rather than a single one.