Referrals, Orders and FHIR

One of the resources that didn’t make the DSTU was a resource to represent Referrals – and this is something that the Working Group is starting to address. However, the concept of referrals is something that crosses a number of concepts in FHIR, so I thought I’d make a few notes here before we get started. (and to give credit where it is due, I’ve had some pointers from Lloyd about the best fit within FHIR – I take responsibility for the errors!.)

Lets start by thinking what we mean by a referral – and what we would expect of a system managing referrals.

Fundamentally, referrals are a formal way of asking some other person to become involved in a patients care. A couple of examples:

  • A primary care clinician (ambulatory care) has a patient with severe osteoarthritis and refers her to an Orthopaedic Surgeon for consideration of hip replacement.
  • The same clinician sees another patient with raised HBA1c and other symptoms of diabetes and refers him to the local diabetes clinic for management.
  • A patient in hospital for a routine procedure has symptoms suggestive of angina, and is referred to the Cardiac team for assessment.
  • A patient is referred for physiotherapy after a stroke.

And there are lots of other examples of course (and I’ve glossed over some important things like responsibility for care).

So there are a number of ‘parts’ to the referral:

  • There’s the general workflow stuff – there’s a sender and a recipient. It’s about someone (and that could be the sender in a self referral for that matter). The sender wants to know that the referral was received, and is being actioned.
  • Then there’s more specific workflow that’s related to referral management. It’s common for multiple people to examine a referral – to triage it, put it in waiting lists, create appointments, and possibly re-direct it to other recipients. One referral might lead to another being made or to other orders (like radiology and laboratory investigations) being made. The sender should be aware of all these activities. This workflow can be specific to the recipient.
  • There’s clinical information about the referral – what is the reason for the referral. What is the urgency (from the view of the sender/patient). What are the expectations of the sender. What is the clinical information that is directly pertinent to the referral (such as the raised HBA1c in the example above).
  • And finally there’s the other clinical content that is not (perhaps) directly related to reason for referral, but is nevertheless important that the recipient know about. Usual medications, co-morbidities and allergies are examples of common clinical information that are almost always included in referrals regardless of the reason.

 

In FHIR, there are already a number of resources that manage some of these (and we hate duplication don’t we?).

There’s the Order and the OrderResponse resources that are intended to manage the workflow aspects of healthcare.  If we have workflow requirements that are not met by these resources, then we should enhance them rather than duplication in our referral. (For example, a likely requirement is going to be the ability for one referral to reference another – we might want to know all the actions that were associated with a referral for costing purposes – so we might want a ‘relatedTo’ reference on an Order).

And we often think of a referral as if it were a document – in fact, in manual systems a referral is often written on a predefined template supplied by the recipient to ensure they receive the information they need to properly manage the referral. So we have the Questionnaire as a mechanism for defining that template, and the Composition if we do want to represent the referral as a formal, signed & asserted document.

And if we do go down a document paradigm, then we might want to use the DocumentReference resource as a way being able to refer to the document (perhaps we wish to display the referral with other documents in the patient record, or find similar/related referrals)

And finally there are all the clinical resources that may be included.

(Which of these resources are actually needed in any specific implementation will depend on the overall system design and architecture, but we do want to be sure that they have been designed to work together and not overlap in terms of functionality.)

So what belongs in the referral resource?

Well, as a strawman proposal lets start with:

  • Sender, Patient and recipient. These are going to be duplicated in Order, but they are fundamental to a referral and so probably belong here as well. (And both DiagnosticOrder and MedicationPrescription which are similar have them, so we’re in good company).
  • The reason for the referral. This could be a CodeableConcept or a string – we possibly want both, one for analysis and automated management and the other for humans (though the CodeableConcept has a text property, so a separate property may be overkill)
  • Details of the referral. Clinicians commonly like narrative in a referral.
  • The Priority and Urgency
  • The actions we wish the recipient to perform. This might be a ‘please see and advise’ through to a ‘please perform this action’
  • Supporting clinical information. Likely the clinical impression that led to the referral will be mentioned in the details – here is where the other important stuff like medications and co-morbidities can go.
  • Attachments.
  • Possibly a direct link to a Careplan resource since careplans can indicate when a referral is required (as can a Protocol – when we have one).

Lets finish this off by working through a real scenario – with a given architecture – and see how all this might work. Note that this is only one possible design…

We’ll go with a document based metaphor and assume there is a document repository that can hold the referral and the referral templates, and an orders management system that holds the Order resource. These could be native FHIR servers, or existing components with a FHIR façade.

referrals

  1. The sender locates and downloads the questionnaire resource that has the referral requirements of the recipient
  2. The sender assembles a document that contains the referral resource, a composition and the clinical data plus attachments. The document is submitted to the registry/repository (there is probably a DocuemntReference resource in there as well).
  3. The sender creates a Order which has a reference back to the referral document and submits that to the Orders Management system
  4. The recipient has a ‘pub/sub’ feed from the Orders management, and so retrieves the order and from that the reference to the referral document.
  5. They download the document (Or, hopefully, process it ‘in place’).
  6. Over time, the recipient performs whatever processing is required, creating OrderResponse resource as appropriate. The sender has a pub/sub feed monitoring those resources and so is aware of the status of the referral at any time. (And can make direct queries at any time).

Although not explicit,  because Referral and Order are in repositories, other authorised people – including the patient – are able to review the progress at any time.

So to sum up, we’ve got a fair bit of work to do – but a lot of the bits are in place, and the art is going to be deciding what should go where!

More thoughts on notifications in FHIR

I’ve been thinking a bit more about notifications since my last post about wanting to alert the patients usual GP (General Practitioner) that there is a document generated as a result of an ambulance visit for them to review. In particular, I’ve been thinking about other scenarios where a sender not only wants to inform a recipient that there is a document for them, but also that there is some action that needs to be performed for the patient. There’s a relationship of some sort to Tasks as well…

Looking at some sample scenarios where the recipient is a GP:

  • The ambulance visits a patient after a fall and delivers them to hospital where they are admitted. The notification to the GP is just an FYI (for your information), and there is no expectation of action.
  • The ambulance visits a patient with asthma and nebulizes them. They do not need to go to the hospital, but should be reviewed the following day.
  • A hospital discharges a patient having started them on warfarin. The GP is requested to repeat an INR in 5 days and adjust the dose if required.
  • A patient visits a private ‘after hours’ service with a lacerated hand. The service sutures the wound and asks the GP to review the patient in 5 days to remove the sutures.
  • A patient is seen by an out-patient clinic and their anti-hypertensive medication adjusted. The GP is requested to monitor the Blood Pressure to endure that they don’t become hypotensive.
  • While in hospital for a routine appendicectomy, an elevated Glucose blood result is noted. The GP is asked to follow up to investigate the possibility of diabetes.
  • A District Nurse visits a patient to dress a wound, and notes that the Blood Pressure is high.

In many (but not all) of these scenarios, there is an expectation by the sender that the recipient GP is going to do something. So in those cases the sender really needs some way of knowing whether:

  • The GP has received the request and will perform the requested action
  • The GP has received the request and will not perform the requested action (maybe it was the wrong GP)
  • The GP never received the request at all.

(I appreciate that this overlaps with some other important concepts like ‘Transfer of Care’, ‘Care Plan’ or ‘Tasks’, but for the sake of this discussion I’m going to keep it simple and just focus on the interaction between sender and recipient).

So let’s extend the simple concept of a Notification and add a few more properties:

  • Expected action. This is optional – if not present then the Notification is an FYI. We’ll make this a CodeableConcept so we can define common set of actions if we want to, which might be good for reporting, but also supports plain text, which will be the most likely early on. We’ll make this multiple to cover the situation where there is more than one thing needed to do by the recipient. If there were multiple actions my different recipients, then we’d use separate Notifications for each recipient.
  • Date due. This only makes sense when there is an expected action, but gives the recipient some idea of when the requested follow-up should occur.
  • Recipient Status. This will be used to manage the state of the Notification – I’ll talk about this in a moment. It will be a code datatype, with a fixed set of values.
  • Recipient Status Comment. A General comment field.

That takes care of the properties of the Notification, but we need to figure out how to manage the workflow aspects of the process – as described above, how can the sender be sure that the GP will carry out the requested actions (or not)?

We’ll use FHIR’s versioning capacity – plus the Provenance resource – to do this. (There may well be better ways, but let’s see how this plays out). It’ll work something like this:

  1. The sender will create the Notification resource (actually an e Other resource, as there is no specific FHIR resource for notifications yet) , setting the recipient details plus the expected action and date due. The recipientStatus will be ‘waiting’
  2. The recipient will periodically poll for Notifications with a recipientStatus of waiting – This will be slightly different from the version in the last post, because it will always return waiting notifications. Note also that we are using th
GET [server]/Other?code='notification'&recipient={gp}&recipientStatus=waiting
  1. The recipient can then update the Notification resource, setting the recipientStatus to ‘accepted’ or ‘declined’. They can use the RecipientStatusComment for any comment they may need to make – e.g. the reason why the GP declined to accept the action. If it is necessary to be more explicit about the person making the change, then they can create a provenance resource that has that information (the easiest way to do this is to put the updated Notification & Provenance resources in a bundle as discussed in previous posts)
  2. Optionally, once the action has been completed, the RecipientStatus can be updated to completed.

The sender can then monitor the status of the notifications as required.

Notifications where the recipient has declined the action:

GET [server]/Other?code='notification'&author={sender}&recipientStatus=declined

Notifications that have not been reviewed by the recipient yet

GET [server]/Other?code='notification'&author={sender}&recipientStatus=waiting&dateCreated< {yesterday}

To get a full picture of all changes to a Notification, we will need 2 queries:

The history of changes to the Notification resource

GET [server]/Other/{id}/_history

The Provenance resources that are associated with the Notification

GET [server]/Provenance?target={notificationID}

Of course, if we were being a nice server, we’d bundle both of these into a simple service that would make the calls internally and return a bundle of resources that would contain all the versions of the Notification resource, plus any Provenance resources associated with them.

GET [server]/Service/Notification/{notificationID}/_history

This pattern might not be suitable for a more fully featured task management solution, but it would seem the be sufficient for the simple use cases that we identified above.

So the complete list of properties for our improved Notification resource is (and remember that this is actually an Other resource at this stage, and all the properties are extensions):

  • Code
  • Subject
  • Author
  • Date Created
  • About
  • Recipient (was Target)
  • Expected action
  • Date due
  • Recipient Status
  • Recipient Status Comment

Comments welcomed!

FHIR and the Ambulance: Notification of XDS documents

We had an interesting discussion today about how to ‘notify’ clinicians that there is a document in a repository for a patient that they are looking after.

The documents in question will be clinical summaries of ambulance visits, and will be held in a highly available repository hosted by the ambulance service, from which authorized users (including the patient) may view them. This repository will be part of an XDS style implementation, so the repository will create a metadata resource (DocumentReference) and send that to the Registry (which we’re terming a ‘Record Locator’ service).

Once there, clinicians and patients will be able to locate and view the documents in the ways that we’ve already discussed.

In addition to storing the document, we also want to be able to create a notification to the patients usual General Practitioner (Primary Care Provider to you US folk) so that they know that an ambulance visit has occurred and there is a new Transfer of Care document for them to review.

The reason for this is that it is very useful for the GP to know that their patient has been seen by the ambulance service, in case follow up is required. In many cases – particularly when the ambulance call does not involve a hospital visit – and hence there is no hospital discharge summary to the GP – they have no way of knowing that the visit occurred. An example of this is where the patient has an asthmatic attack and is nebulized successfully at home.

So the workflow will go something like this:

  1. The Ambulance system creates the document (likely a CDA) and saves it directly in its repository – along with all the other required metadata. (This is the integrated document source/repository actor in XDS).
  2. The Repository will generate a DocumentReference resource, and send that to the Registry.
  3. The Registry will save the DocumentReference resource, and also generate a new resource – the Notification resource – that is directed to the patients usual GP (which will be in the Patient.careProvider property). There’s nothing to stop it creating multiple notifications – eg to a patients care team – if there are business reasons for doing so.

Once this is done, GP’s will be able to receive the notification by means of an RSS feed querying the Notification resource like this:

GET [host]/Other?code='notification'&target=<GP>&_since=<lastQueryTime>

which will return a bundle (Atom feed) of Notification resources for that GP. They can then use the Notification (specifically the DocumentReference property) to retrieve the actual document for viewing.

So what is this Notification Resource? Well, it doesn’t actually exist yet. To implement notifications we need to use the Other resource, which has been specifically designed for situations like this: we need a resource that is not yet defined (or maybe won’t be). It has a simple structure:

  • Code – the type of resource. This will indicate that it is a notification resource.
  • Subject – the patient
  • Author – in this case the ambulance system
  • Created – the date of creation

And then you add as many other properties (as extensions) that you want. We’ll probably need:

  • Type – the type of Notification – eg that there is a new document for them. We could get fancier if we want to…
  • About – the DocumentReference reference
  • Target – a Provider resource reference to the GP

Why have we specified a separate resource for the notification, rather than just storing the GP as an extension to the DocumentReference resource and querying on that? Well:

  • A tight coupling in this way would mean that the ‘notification’ is for DocumentReference resources only, and we may want to support other Use Cases – such as a notification that a patient has been admitted into hospital.
  • More complex workflow – like the ability to record that the notification has been viewed and accepted (or declined) would be tricky. (Actually this is more Task type behaviour – but then, a Notification could be thought of as a type of task)
  • It feels like we’re binding together behaviour that doesn’t belong together.

Some other notes:

  • We’ll probably get the registry to provide a special service for this ‘save metadata and create notification’ functionality – eg POST /service/DocumentReference/saveAndNotify that takes the DocumentReference resource and does the rest. (I’ve grown rather fond of these services since Keith suggested them!)
  • Because the  notification query is based on an extension, the server needs to map the ‘target‘ query parameter to the target extension. We really want to be able to search on the identifier property of the Practitioner resource that is the target property of the Notification, so we’ll need to set up the profile accordingly.

And finally, in our particular situation there are a couple of wrinkles:

  • The delivery timeframe of the project is before the Record Locator service is likely to be in place
  • This design requires that the vendors of Practice Management Systems that the GP’s use need to implement the RSS/Atom query mechanism

For the first wrinkle, the RSS/Atom lookup will initially be provided directly by the Ambulance Repository application. Then, when the remainder of the infrastructure is in place the consumers will simply need to change URL’s to switch to the Record Locator/Registry and the system will otherwise work unchanged.

In the second case, there are a number of portal applications in use in New Zealand – we’ll add the display of notifications to those portals so that when GP’s and patients log into the Portals they will receive the notifications in the same way as they would from within their GP PMS. Hopefully, this will allow the PMS vendors to see the value of this approach, and implement the functionality directly (it’s not that hard for a consumer after all!)

Since writing this post, I’ve written another one, further extending the concept of Notifications, thinking about how to manage workflow.

FHIR XDS: revisiting the patient identity.

While at the HINZ conference this year, I was at dinner with Grahame and ‘Friendly FHIR’ (your identity is safe with me), and we were talking about the roles of the Identity Source and XDS Registry in the context of a FHIR XDS implementation. In previous posts I had indicated that the Identity Source could simply expose a FHIR Patient endpoint – and that is still an option for general use – but in the case of the XDS Registry, Grahame pointed out 2 issues with that approach:

  • If the XDS infrastructure is heavily used, then the load on the Identity Source is going to be high
  • Merged patients are an issue because DocumentReference resources in the registry will continue to have references to patients that have been merged with another and it needs to return all references to all merged patients when responding to a query for a single patient.

So, the registry really does need to maintain it’s own store of patients – though this is really a specialized ‘cache’ that is only updated by the Identity Source. This also means that there is really no need for a Document Consumer to access the Identity Source directly – at least in the XDS context – which is a bonus.

We’ve talked before about how FHIR represents merged patients (Actually, just checking the specs I note that there is now a link type property that must be set to ‘replace’ to indicate the merge), so I won’t repeat that here, but it is worth thinking about how this could all work in the context of an Identity Source needing to update an XDS Registry.

The requirement is that when there are changes to patient information at the identity source, then that needs to be communicated to the XDS registry somehow. We don’t need all the patient details all of the time – the more we store then the greater the volume of updates –  but we probably want the ID, the links, the identifier information and the basic name/Date of Birth/Gender stuff. We would want to be notified about:

  • new patients
  • changes to the patient data we are storing
  • any merges

The XDS registry then needs to maintain an internal data store of some sort that maintains those links between patients so that when a document consumer queries the registry, all the DocumentReference resources for that patient and any patients merged to it are returned as well. (And note that each DocumentReference resource will continue to refer to the Patient it was associated with at creation time – it is the patient that is merged and not the other resources that refer to it).

There are a couple of ways we could do this:

  • Either the Identity Source could push changes to the XDS registry as they occur (a ‘push’ model)
  • Or the Registry could periodically request changes from the Identity Source. (a ‘pull’ model).

Lets consider the push model first.

When the Identity Source merges a patient with another, there are 2 Patient resources to change:

  • The Primary resource (the one you want to keep) has a reference to the secondary resource (that is being replaced) with a link type of ‘replace’.
  • The Secondary resource has a link back to the primary (also with a type of replace) and has it’s ‘active’ property set to false.

As these really need to be managed as a transaction, then the Identity Source places the two resources in a bundle and either:

  • Posts it to the root of the XDS registry
  • Or (and this is probably more explicit) the XDS registry exposes a service (maybe /service/patient/merge) that takes the bundle of resources

In either case, the registry updates its data store. It might return an OperationOutcome resource to indicate the outcome.

So that is the push from the Identity Source to the XDS registry – how would the pull model work?

Well, because FHIR is built using standard internet type technologies, there’s a pre-existing standard that is intended for communicating changes and updates between systems, and that is the Atom feed – which we’ve seen used as the bundling mechanism when we want to move multiple resources around.

In this use, we’re implementing a ‘pub/sub’  architecture where the client (the XDS registry) subscribes to a feed of changes published by the Identity Source. Reviewing the spec, we note that the history operation allows a server to publish changes for a specific resource, a type of resource, or all resources on that server. In our use case, we’d go for the middle option – we want a feed from the Identity Source that publishes all changes for any Patient resource.

So what happens is something like this:

Periodically the XDS registry issues a GET request to the Identity Source like this:

GET /identityServer/Patient/_history?_since=<dateLastQueried>

This will return a bundle containing all the changed resources since the last request. The registry can then process the Patient resources in that bundle and update it’s internal data store as required.

So which pattern to choose? Well, that depends on your implementation.

The ‘classical’ XDS way is the push from Identity Source to Registry, and that is probably the simplest  (though in practice you might want to put an integration engine in the middle so the Identity Source doesn’t need to be concerned with communication issues – and could support other systems that maintain patient caches).

However the pull feed option might be useful if there are multiple clients needing updates, of if that technology is already supplied by the Identity Source.

Hopefully that finishes off XDS stuff for a while, because I’d like to start thinking about FHIR documents…

FHIR XDS – updating a document

It’s not uncommon for a document to need to be updated after it has been posted to a repository and registry. Sometimes new information has come to hand that affects the document, or there may be normal workflow where a ‘draft’ document is saved, and is subsequently updated or finalized, or maybe the original was just plain wrong and needs to be retracted.

None of these are unique to a document of course, but there are some ‘quirks’ – for want of a better word – to the DocumentReference resource for a couple of reasons:

  • It is a resource whose main role is to refer to another entitity – so there are 2 lifecycles to consider.
  • Documents are often summaries of clinical care (e.g. Discharge Summaries, Progress notes, Clinic notes) and it’s very common for clinical decisions to be made on the contents. Keeping an easily accessible (to the end user) ‘audit trail’ of changes is very important for medico-legal reasons.

When thinking about changes to a document, there are 2 ‘types’ of change to consider:

  • Changes to the metadata (e.g. the document type was incorrect)
  • Changes to the content of the document itself.

We’ll consider these separately.

Changes to the metadata

If the change is only to the metadata – the contents of the DocumentReference resource itself, then it can be updated it in the usual way – i.e. retrieve the existing version, make the changes, and PUT the document back. The standard FHIR versioning process will manage the update of the resource. (Resource versioning is not required by FHIR – but highly recommended). There are some caveats to this approach, as mentioned in a minute…

Changes to the document.

This is more tricky. What we need to do is:

  • Update the document in it’s location (e.g. as a binary resource on a FHIR /Binary endpoint)
  • Update the existing DocumentReference resource that points to it, setting the status property to ‘superseded’
  • Create a new DocumentReference resource that references the updated document (and if it’s a FHIR server that we may want to make this a version specific reference), setting the relatesTo.code to ‘supercedes’, and the relatesTo.target as a reference to the original DocumentReference resource
  • We might also want to create a provenance resource to indicate who has made the change.

Because this needs to be managed as a transaction, we’ll use a FHIR bundle and we’ll use the same pattern as when we submitted the document in the first place – i.e. have the repository server manage the updating process. (Other patterns are possible of course).

So our bundle will contain:

  • The updated document as a base-64 encoded binary resource. It will have a real ID so the server knows to update it
  • The original DocumentReference resource, with updated status. It will also have a real ID so the server knows to update it
  • The new DocumentReference resource – largely a copy of the original with the relatesTo property set. It will have a ‘cid:’ ID so the server knows to add it as new.
  • Optionally a provenance resource with the details of who made the change – and when. The provenance resource refers to the resource being changed (not the other way around) so it will have 2 targets – the 2 DocumentReference resources that are effected in this transaction. It also has a cid: ID.

The repository server will process the bundle as described above.

Although this second approach is more complex, it does make it quite obvious that a significant change has occurred. For this reason, some metadata changes – such as a change of subject or author – might be better managed this way rather than a simple update to the DocumentReference resource. It’s up to you…

All of this does raise an interesting point that we didn’t think about when considering how to query the registry for documents (i.e. a query against /DocumentReference) – the response will include DocumentReference resources that have been superseded as well as current ones.

If we don’t add the status parameter in the query, then we will get back all DocumentReference resource’s – so we will need to check this value when assembling the list of documents for the consumer (Of course, we may want to do this anyway so that we can place some visual indication in the display that changes have occurred – it’s up to the implementer, as it should be…)

Otherwise we can be explicit that we only want current documents, so the examples we gave in the previous post becomes:

GET  http://registryserver/DocumentReference?subject= 100&status=current&period > 2013-01-01

and

GET  http://registryserver/DocumentReference?subject= 100&status=current&type= http://loinc.org|34108-1

And as a last word, and following on from the post that Keith Boone made about task orientated services, we may choose to define specific service end points for this functionality (and even for the ‘add document’ scenario), perhaps:

  • /service/document/new
  • /service/document/update

both of which receive the bundles we’re described.

Getting documents from a FHIR XDS infrastructure

So far in our little mini series on FHIR and XDS we’ve had an overview of how FHIR resources support a document sharing infrastructure, looked at how a document creator can create and submit documents to a repository and/or registry, and spent a bit of time talking about the DocumentReference resource.  Time to think about the consumer of these services.

There are 2 main scenarios that we want to support:

  • Getting a list of documents for a patient (with various search parameters – e.g. a date range, type of document etc.) and displaying the metadata in a list to the consumer
  • Retrieving a particular document to view

Getting the list of documents

Let’s think about the first scenario, and to keep it simple we’ll aim to retrieve all the documents for a patient. Given that the metadata about the document is represented by a DocumentReference resource hosted by the registry server we are using, then this is obviously going to be a query against the DocumentReference endpoint. There are a couple of ways we could to this, and the way we choose depends on whether the have the patients ID or their identity (in fact, it’s exactly the same issue as the document creator had – so refer to that post for more discussion on this).

If we know the patient ID (let’s say it’s 100), then our query will be something like:

GET  http://registryserver/DocumentReference?subject= 100

(assuming that the patient identity is also on the registry server – if not then the patient ID would need to be the absolute reference to the patient resource).

If we don’t have the patient ID, but we do have an identifier (e.g. PRP1660) then we have a couple of options (as always!):

  • Look up the patient ID by a query against the Patient endpoint first
  • Query the DocumentReference with the patient identifier using a chained query, like so:

GET http://registryserver/DocumentReference?subject.identifier= PRP1660

Note that the server is not obliged to support chained queries – check their conformance resource to see if they do. Also, I didn’t include the identifier system in the query – depending on the implementation I may need to do so. Chained queries make a clients life easier (but a servers life harder) – but as the FHIR philosophy is to make it as easy for clients as possible, it’s to be hoped that servers do support that capability.

In either case, the result will be a bundle of DocumentReference resources – the difference between the two being that if we specified the patient ID, then we know that all the DocumentReference resources are for the right person. If we used the identifier, then we are trusting that the identifier is unique (which means that we should probably not be lazy and include the system in the query).

But what if we want a more targeted search? Perhaps we’re only interested in documents created in the past year, or only outpatient summaries?

Well, checking the defined search parameters for DocumentReference we see a period parameter (date of the service) and a type parameter (document type) which would seem to suit our purpose, so (assuming we have the Patient ID):

GET  http://registryserver/DocumentReference?subject= 100&period= >= 2013-01-01

and

GET  http://registryserver/DocumentReference?subject= 100&type= http://loinc.org|34108-1

And of course we can mix and match parameters as we need to (provided the server supports them as documented in their conformance resource)

Retrieve a particular document.

So now we have a list of documents which we can display to our user, how do we retrieve a particular document for them? Well, hopefully the DocumentReference resource that describes the document we want has the location property. Then it’s just an HTTP call away. If the repository where the document is stored doesn’t support a direct GET, then you’ll need to drop back to the XDS ‘Retrieve Document’ profile, the access details for which should be on the DocumentReference.service property.

Assuming you can make a GET call, the repository should include the HTTP standard headers in the response like content-type (which is also recorded in the DocumentReference.mimeType property of course), so rendering by the viewer should be straightforward. Of course, it can get a lot more complex than that – especially in the case of a structured document like a CDA or FHIR-document, when specialized client-side renderers (like XSLT stylesheets) will be required. The metadata in the DocumentReference resource (and possibly HTTP headers)  should indicate what renderer is going to be needed, so all should be well.

Note that the GET call will return the document directly, whatever it is – eg a PDF or CDA document – not a FHIR resource of any sort.

A short (and grossly incomplete) comment on FHIR security.

FHIR itself doesn’t define security protocols – rather it provides the ‘hooks’ that a security framework can use when deciding whether to deliver up a particular document – or even whether to include the document metadata in the original list of documents.

There is an assumption that anyone accessing any of these services is authenticated (identified) and oAuth is the recommended (though not mandated) way to do this.

FHIR supports the concepts of tags – that can be applied to any resource, and allow a privacy policy framework to apply rules when determining whether to deliver up information p and those rules can become arbitrarily complex.  In addition, the DocumentReference resource has the specific confidentiality property that can also be used.

There is also the SecurityEvent resource (analogous to the IHE ATNA profile) that can be used to record significant events such as the release of a document to a viewer. This resource can then be used as the basis of functionality such as “Who has viewed my data?”, and can be created at any time that is appropriate in the overall workflow. The provenance resource indicates the context in which a resource was obtained – e.g. the person who created it.

So, it is the responsibility of the governing body for the document sharing infrastructure to make these policy decisions – and to enforce them! And the IHE ‘Affinity Domain’ concept is a good source of information.

Incidentally, for health security issues in general, check out John Moehrkes blog as a good source of inspiration!

We’re getting towards the end of our little mini series – one of the longer ones so far! We’ll wrap up the loose ends in the final post – in particular we need to think about the best approach when a document source needs to update a document it has already sent to a repository.

The FHIR DocumentReference resource

In the previous FHIR-XDS post we discussed how a document source actor (ie a system that creates a document) could create a document and DocumentReference resource and send them to the Repository server. (Actually, we described a couple of ways that this could be done – and there are a few subtleties yet to discuss about server behaviour – but we’ll hold that for later).

However, we didn’t have a lot of time to talk about the DocumentReference resource itself. This resource represents the metadata about the document and allows a consumer to search the registry (or any server hosting these resources) to retrieve matching documents. From these results, a consumer can then generate a list of documents so that a consumer can select one to view.

The documents themselves can be of any allowed type (CDA, PDF, FHIR document, text etc) and can be stored on any server accessible via HTTP – and they do not need to be FHIR servers. It is quite legitimate for a DocumentReference resource to refer to a static document on any server (or, for that matter, a URL that generates a document ‘on the fly’, though you’d want some way to persist the generated document for medico-legal reasons as described in the ‘IHE on-demand document‘ profile). And, if one is being particularly pedantic, then even HTTP is not really required – you could use FTP or any other supported protocol.

It is important to note that although the DocumentReference resource was developed to support some of the requirements of an XDS infrastructure, it is not restricted to that purpose and can be used in any situation where the business requirement is to create a ‘list of available documents’, from which one or more can be chosen for viewing.

In fact, the FHIR specification defines a specific XDS profile that describes how the DocumentReference resource is to be used in the context of an XDS installation – for example some fields that are optional in the resource, are required when acting as a proxy to XDS. The link also gives guidance for mapping between XDS and FHIR elements, including fields required for XDS that are not in the DocumentReference and so represented by extensions.

The following description refers to the generic DocumentReference resource. Note that there are a number of properties whose value should come from a ValueSet defined by the governance body that oversees the overall installation (an Affinity Domain in XDS-speak – though the affinity domain covers much more than just code sets). We will talk a bit more about ValueSet’s after this list.

  • The masterIdentifier is the identifier of the document as created by the source. It is version specific – i.e. a new one is required if the document is updated (We’ll talk about updating documents in a separate post).
  • There can be any number of other document identifiers that make sense. For example, there might be a version independent identifier here.
  • The subject is who the document is about. Generally this is a patient, but the specification also supports a Practitioner, a Group or a Device.
  • The type and class indicate what kind of document this is- (eg a discharge summary). A ValueSet should be defined for each. (Note that ‘class’ has been called ‘sub-type’ in some versions of this resource)
  • There is at least one author, which is a Practitioner.
  • There can be an Organization which is the custodian of the document – responsible for maintaining the document
  • There’s a policyManager link to a URL that describes the access policies to the document.
  • The authenticator of the document can be an Organization or a Practitioner.
  • The created date is when the document was created (not necessarily related to the period of the service that the document may describe – this is in the context.period element).
  • The indexed date which is when the DocumentReference resource was created.
  • The status allows minimal workflow of this DocumentReference resource (NOT the underlying document). Options are current, superseded or error. We’ll talk more about this status when we talk about updating a document in a later post.
  • The docStatus and supercedes allow a document to be updated (superseded) or otherwise have it’s status changed. This is a CodeableConcept, and so can accommodate a specific workflow defined by the affinity domain such as preliminary, final, amended or whatever, as documented in the ValueSet.
  • The description is the title of the document. If you’re displaying list of documents then this would be a good property to use.
  • The Confidentiality property allows a privacy policy to control the access to a document. The policy can also use the generic tags functionality in FHIR.
  • The PrimaryLanguage element indicates exactly that – no surprises here. It is a code, and is bound to the IETF Language tag.
  • mimeType and format indicate how the document is represented – eg xml, pdf, msword etc.
  • Size allows a client to estimate download time of the document, and the hash can ensure integrity.
  • The Location is a URI that indicates from where the document can be downloaded. This does not need to be a FHIR server. The client will (generally) not know what this is when creating the resource as it will be related to the ID that the server assigns. However, either it or the service property is required, so it may be necessary to create a ‘dummy’ resource using the cid: prefix so the server knows it is not real – or define a service. You would define a local policy to describe this, which could be identified in the policyManager link above.
  • The service is used if the location is not known. You would use this if you weren’t using simple FHIR REST, so for the moment we’ll ignore it.
  • The context allows you to specify the clinical context of the document – at least the context that is useful in searching or displaying the document list. The period that the document refers to and the facility type are present, but you can add codes that make sense here as well.

For reference, the following fields need to have their options defined by the governing body using a ValueSet. These can either be defined directly in the ValueSet or be a sub-set of an external Terminology like LOINC or SNOMED.

  • type
  • subtype
  • docStatus
  • confidentiality
  • mimeType
  • format
  • context.code
  • context.facilityType

The recommended way to document this is to create a Profile resource that describes the implementation, and refers to the appropriate ValueSets – with the whole lot being saved in FHIR server/s so that they can be easily located. The option below shows a minimal profile that sets the ValueSet for the confidentiality property.

&lt;Profile xmlns=&quot;http://hl7.org/fhir&quot;&gt;
     &lt;text&gt;
         &lt;status value=&quot;additional&quot;/&gt;
         &lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;Minimal profile for confidentiality codes in DocumentReference&lt;/div&gt;
     &lt;/text&gt;
     &lt;name value=&quot;Elbonian XDS Profile&quot;/&gt;
     &lt;status value=&quot;draft&quot;/&gt;
     &lt;structure&gt;
         &lt;type value=&quot;DocumentReference&quot;/&gt;
         &lt;name value=&quot;XDSDocumentReference&quot;/&gt;
         &lt;element&gt;
             &lt;path value=&quot;DocumentReference.confidentiality&quot;/&gt;
             &lt;name value=&quot;ConfidentialityOptions&quot;/&gt;

             &lt;definition&gt;
                 &lt;short value=&quot;Confidentiality Code options&quot;/&gt;
                 &lt;formal value=&quot;Confidentiality Code options&quot;/&gt;
                 &lt;min value=&quot;1&quot;/&gt;
                 &lt;max value=&quot;1&quot;/&gt;
                 &lt;isModifier value=&quot;false&quot;/&gt;
                 &lt;binding&gt;
                     &lt;name value=&quot;List of confidentiality options&quot;/&gt;
                     &lt;isExtensible value=&quot;false&quot;/&gt;
                     &lt;referenceResource value=&quot;/ValueSet/ConfidentialityOptions&quot;/&gt;
                 &lt;/binding&gt;
             &lt;/definition&gt;
         &lt;/element&gt;
     &lt;/structure&gt;
 &lt;/Profile&gt;

and the ValueSet that it references could look like:

&lt;ValueSet xmlns=&quot;http://hl7.org/fhir&quot;&gt;
     &lt;text&gt;
         &lt;status value=&quot;additional&quot;/&gt;
         &lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;The value set for confidentiality codes in the elbonian document sharing
         project. The codes are defined directly by the valueset, rather than references to an external terminology&lt;/div&gt;
     &lt;/text&gt;
     &lt;name value=&quot;ConfidentialityOptions&quot;/&gt;
     &lt;description value=&quot;ConfidentialityOptions&quot;/&gt;
     &lt;status value=&quot;draft&quot;/&gt;
     &lt;!-- Define the  options in the resource rather than an external terminology--&gt;
     &lt;define&gt;
         &lt;system value=&quot;http://fhir.moh.elbonia.com/confidentiality&quot;/&gt;
         &lt;concept&gt;
             &lt;code value='N'/&gt;
             &lt;display value=&quot;Normal&quot;/&gt;
             &lt;definition value=&quot;That the document is of normal confidentiality - is able to be viewed for any authenticated user&quot;/&gt;
         &lt;/concept&gt;
         &lt;concept&gt;
             &lt;code value='H'/&gt;
             &lt;display value=&quot;High&quot;/&gt;
             &lt;definition value=&quot;Then the document is Highly confidential - eg Mental health - and can only be viewed by people authorized to access documents at that level&quot;/&gt;
         &lt;/concept&gt;
     &lt;/define&gt;
 &lt;/ValueSet&gt;

Finishing up…

In the previous post I promised that I would talk about the DocumentManifest resource. This is a new addition to the FHIR family, and has been introduced to support the ability for a document source to submit a collection of documents in a single batch as XDS does.

In truth, I’m not entirely clear how this resource should be used. It does have the recipient element, which provides the basis for a notification system, but beyond that the main value would seem to be that there can be more than a single document in a batch submission to the Repository server. I’ll update the post when I learn more.

So, we have saved a document in the repository and updated the registry. In the next post, we’ll switch our attention to the Document Consumer and discuss how to query the registry for documents, and to get the actual document itself.

FHIR and XDS – Submitting a document from a Document Source

This post will focus on the XDS Document Source actor and the mechanics behind submitting a document and its metadata to an XDS system. But before we do that, we need to review some aspects of the way that’s going to work in our RESTful context.

We’ll use the DocumentReference to record the metadata, but one of the tricky bits is going to be managing the ‘entity identifiers’ – particularly for patient, practitioner and organisation that XDS needs, vs the resource ID that FHIR requires for references.

A bit of background.

An Identifier is something that identifies an object or identity – like a patient. It has a number of properties, of which the most relevant to this discussion are the system and the value.

The system is the namespace within which the value is unique. A single entity/patient can potentially have many different identifiers – for example a patient might have:

  • An identity within a national identity service
  • An identity in their local doctors system
  • A drivers license
  • A library card

and so on. It is also possible that a single person could accidentally have multiple identifiers in the same system – for example when an administrator creates a new identifier for a patient without first checking whether they already have one. In fact one of the jobs of the identity service is to locate these duplicates and merge them, but I digress…

IHE recommends that the participants agree in advance on which identifier systems will be used in XDS, and provides a profile called the PIX profile (Patient Identity Cross reference) that describes how to manage and cross reference these identifiers – so that if you have one identifier you can get the matching ones for that patient. There is another query – PDQ – or Patient Demographic Query that describes how to query a registry using name, Date of Birth and other demographics and get back a list of patients – including known identifiers. Often, a single system will implement both of these profiles – and the term PIX/PDQ to describe them is not uncommon.

But when a Document Source submits a document to a repository using FHIR, it needs a resource reference to the patient – which is a URI to the patient resource – not an identifier.

This is a problem for a client that only has an identifier for a patient.

Reviewing what PIX/PDQ does, this all seems suspiciously like queries against the FHIR Patient resource. If we imagine that there is a server that exposes a /Patient endpoint and is backed up by all the identity matching and update functionality of an identity registry, then queries against this endpoint will perform much the same functionality as PIX/PDQ queries – for example:

  • GET /Patient?name=power&gender=M      (PDQ-ish)
  • GET /Patient?identifier=PRP1660                   (PIX-ish)

would both return a list of matching patients, each of which would contain all the identifiers known for a patient. We can even ask for previous versions of the resource if we need them, and Patient resources can link to merged resources using the link property. This is actually what we discussed in an earlier post, though we didn’t really talk about merging and linking patients (a topic for another post perhaps).

So – provided that we have such a server (which is kind of fulfilling the role of Identity Source in XDS) then we have our ‘identifier lookup’ sorted. But we’re still not quite there. Who should do this lookup?

There are a couple of options:

  • We could off load the problem to the repository – require it to be able to receive an identifier, query the /Patient server using that identifier and get the resource ID. There’s even a way of doing that using a bundle in FHIR (part of transaction processing)  – but this has the limitation that it only works on the same server as the search, which would mean duplicating patient data on all repositories. That doesn’t really sound right.
  • We could require that the Document Source perform that lookup, and include the full FHIR reference in the submission.

Although we are asking the Document Source to perform more work, this does place the responsibility for correctly identifying the patient on the Document Source, which feels like the right place. We will go with this solution, so the updated diagram now shows a line between the Document Source and the Identity Source, indicating that lookup.

Updated FHIR XDS

Similar issues exist for the Practitioner (author) and the Organisation (custodian), and we will adopt the same attitude – i.e. that it is the responsibility of the Document Source to locate the required resource ID. Fortunately, it’s a bit easier for these two as it’s not so critical to absolutely identify them (in a FHIR sense). If we can’t do that, then we can use FHIRs ability to contain an unidentified resource within the DocumentReference resource (and, in fact, it was this issue that led to the concept of contained resources in the first place, early on in FHIR’s evolution). There are, of course down-sides to this approach – but sometimes it’s the only way.

A couple of notes:

  • Astute readers will note that the DocumentReference resource can have subjects other than Patient. We’re not thinking about them at the moment, but if/when we do then the same rule will apply – the Source needs to specify the resource ID – i.e. identify the resource.
  • We do have the option of creating a custom Web Service (could be REST or SOAP) on the repository that performs the lookup – i.e. takes an identity and performs the query on the appropriate server on behalf of the source. We’d want to carefully think through the implications of that approach.
  • Having a copy of the Patient resources on the repository and using the bundle search facility to create local ID’s remains an option – after all from the perspective of XDS it is the identifiers we are after. It doesn’t feel right to me, but those more expert in REST than I might have a different opinion.

So we have our identifiers and ID’s sorted – now to submit the document! This is going to involve updating both the repository and the registry – in other words a transaction. As always, there are a number of options:

  • The Document Source could send the document to the repository – getting back an ID (or in some other way having a URI that allows a consumer to retrieve it), and then create and send a DocumentReference resource to the registry. This is a perfectly legitimate approach – and is required in some situations such as a non-FHIR repository – but it does mean that the client needs to manage the transaction, as we discussed with medications. That may or may not be an issue.
  • We could use FHIRs transaction functionality to off load the responsibility to the Repository Server.

The rest of this post will describe the second approach.

The steps we need to follow are:

  1. Create a new bundle
  2. Get the document we want to store, base-64 encode it, and save it in a bundle as a Binary resource
  3. Create the DocumentReference resource and place that in the bundle
  4. Send the bundle to the repository root
  5. Process the response (succeed or fail)

1. Create a bundle

This is a simple matter of creating the basic structure of the bundle.

2. Get the document.

Retrieve the document from whatever local store it is help in, base 64 encode it, and create an entry for it in the bundle using the binary resource. Its ID should be a cid: ID so that the repository server knows to create a new resource (i.e. treat it as a create operation).

3. Create the DocumentReference resource

This is where the work is. The DocumentReference resource contains all the metadata required for the document to be located via a query, and the contents will depend on what information is available and what is specified in the Affinity Domain (i.e. what are the valid options for each of the properties in the DocumentReference resource).

In addition, the ‘generic’ DocumentReference resource has been profiled specifically to suit the XDS requirements. It’s going to take a while to go over the details of this, so we’ll hold that discussion over until we’ve finished the mechanics of transmission.

The DocumentReference resource will also contain the references to other resources we need, which may be:

  • A straightforward resource reference to the resource – e.g. the patient resource – on a server. There’s no need to include the resource in the bundle, though we can if we want to.
  • A contained resource if we were unable to resolve the link.

When complete, add the resource to the bundle.

(There may be other resources to include – like attachments to documents – that we can talk about some other time.)

4. Send the bundle to the server and process the response.

POST the bundle to the root of the Repository server, as we discussed in the post on medications. The server will perform the required processing which has the following steps:

  1. Save the document in the local store, which will generate an ID. It will subsequently by available by a query against the /Binary endpoint of the server – eg GET /Binary/{ID}
  2. Update the location property in the DocumentReference resource to the local URI
  3. POST the DocumentReference resource to the registry
  4. Return a response to the client.

Note that we are assuming that the repository is managing the transaction. If there are errors back from the registry (eg missing or invalid data) – then it should remove the document from the local store and return an error to the client (ideally with a OperationOutcome resource).

Note also that the above processing – ie that the server should manage bundles containing DocumentReference and Binary resources by POSTing the DocumentReference to a configured Registry Server is one that depends on local policy and configuration. It may be clearer to create a custom endpoint to make this processing explicit.

There are other processing options for the server (eg asynchronous processing) – again, something to be discussed in a later post.

5. Process the response

The HTTP status code will indicate success or failure, and in the event of a failure then the server should return an OperationOutcome  resource with details.

So, we have finally saved a document in the repository and updated the registry. We didn’t have the space available to talk about the DocumentReference resource in any detail, and it’s kind of important to know what to put in there, so in the next post we’ll talk about that resource (and touch on the DocumentManifest), after which we can start to think about the consumer.

FHIR and XDS – an Overview

One of the ‘sweet spots’ for FHIR is establishing RESTful interfaces to an IHE XDS (Cross Enterprise Document Sharing) implementation. IHE had already started down this path when it created the ‘Mobile Access to Health Documents’ – MHD – profile as a way of making it easier for mobile devices to access XDS installations, but with the emergence of FHIR, the two efforts have been merged and the intention is that the MHD version 2 profile will be FHIR based. This is not to say that FHIR can replace XDS – there are circumstances where the native XDS interfaces can be required – especially in larger deployments, but the ease of use of FHIR makes an attractive façade in many situations.

It should also be mentioned that it is quite feasible to implement an ‘XDS-like’ system that follows the overall pattern of XDS, but doesn’t have an XDS ‘back-end’ if it meets the use cases.

This will be the first in a series of posts that talks about implementing the FHIR as a front end to XDS, and will be an overview to XDS and how FHIR resources match the profile.

For those who are not familiar with XDS, its purpose is to enable the sharing of documents between healthcare enterprises. The image below is the standard representation of XDS:

XDS-Actor-Transaction-b

It shows 5 principal actors:

  • The Document Registry that is the ‘index’ to available documents. Within a single implementation there is only a single registry, though there are profiles (like XCA) that support ‘inter-registry’ queries where there are multiple co-operating deployments
  • One or more Document Repositories that actually hold the documents
  • Multiple Document Sources that actually create the document, and submit them to a repository
  • Multiple Document Consumers that query the registry for documents, and then retrieve the documents from the indicated repository
  • A single Identity Source, that manages patient identity

There are a number of transactions defined, and the ones that are of interest to us are as follows:

  • Register and provide document set (ITI-41), where a document source assembles a package containing 1 or more documents, with associated metadata (which we’ll talk about shortly) and sends that to a repository for storage.
  • Register document set (ITI-42) where the repository forwards the metadata to the registry.
  • Registry stored query (ITI-18) which is the consumer making a query of the registry to retrieve specific documents based on some search criteria.
  • Retrieve document set (ITI-43) defines how a consumer retrieves a specific document. Generally, this will be after they have queried the registry.
  • Patient Identity Feed (ITI-8, ITI-44) shows the identity source updating the registry with demographic information about patients – especially ‘merges’ where a single patient is known by more than one identifier.

Refer to the XDS profile for more details.

Applying  FHIR resources to this picture, gives us the following:

FHIR-XDS

We can see that there is a good match (not unsurprisingly) between the XDS transactions & the FHIR resource end points.

  • A document source can submit the document and metadata to the repository via a transaction (like the medication update)
  • The repository updates the registry by posting a resource to the registries DocumentReference endpoint
  • A Consumer searches for documents via a query against the registries DocumentReference endpoint, and retrieves the document via a GET against the repositories /binary endpoint.
  • A SecurityEvent resource that records accesses of significance.

Note that for the purpose of this discussion (to keep things simple), we are ignoring the DocumentManifest resource, and only using the DocumentReference resource – which means that we will only be submitting and retrieving a single document at a time. The DocumentReference resource describes the metadata (and supplies the base data for searching) for a single document. The DocumentManifest resource ‘groups’ multiple documents (for example a document and an attachment) into a single package. We’ll come back to this in a later part of this series.

It’s also possible for the document source to update the registry directly. They may do this if the document is being stored outside of the XDS infrastructure (e.g. to support a repository that is not otherwise functioning as an XDS repository). We’ll also touch in this later on.

We’ve talked about a ‘document’ quite a lot – but what is a document? Well, in regards to this discussion it’s pretty much anything you need it to be – the spec states:

A document is some sequence of bytes that is identifiable, establishes it’s own context (e.g. what subject, author etc), can be displayed to the user, and has defined update management

It could be a CDA, a PDF, a text file, a FHIR document or even a Microsoft Word document. It’s the DocumentReference that has the metadata about the document – which includes the format of the document (as the mime type)

The last thing that we’ll touch on in this introduction is the concept of the Affinity Domain. IHE defines the affinity domain as “a group of healthcare enterprises that have agreed to work together using a common set of policies and share a common infrastructure”

In practice this includes things like:

  • The security & privacy policy that members will adhere to
  • Confidentiality codes & their meanings
  • What are the document ‘types’ and ‘sub-types’ – e.g. LOINC codes for things like ‘Patient Summary’, ’Discharge Summary’, ‘Clinic Note’ etc.
  • The supported document formats – eg the mimeType or more detailed descriptions
  • What are the possible statuses that a document can be in
  • The types of facility that are recognised (Primary Care, Hospital, Rest Home)
  • Clinical service (Orthopaedic, Paediatric, ED…)

There are other characteristics that can be applied to a document, but these are the most important that the affinity domain needs to agree on.

In the next post, we’ll dig into how the client sends a document to the server.