MyHealtheVet PHR FHIR API
0.3.9-current - ci-build United States of America flag

MyHealtheVet PHR FHIR API, published by VA Digital Services. This guide is not an authorized publication; it is the continuous build for version 0.3.9-current built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/department-of-veterans-affairs/mhv-fhir-phr-mapping/ and changes regularly. See the Directory of published versions

Vista Mapping

Page standards status: Informative

MyHealtheVet acts as a FHIR Server. It receives information from many sources and produces a given set of FHIR Resourrces

sourcefhirutilHDRVIAAllergyIntoleranceImmunizationConditionDiagnosticReportVIA-- lab-- imagingHDR-- chem-- hemSpecimen()Observation()DocumentReferenceProgress NoteDischarge SummaryConsultation NoteECG ReportObservationBLOOD PRESSUREHEIGHTWEIGHTPULSEPAINRESPIRATIONTEMPERATUREPatientMHV PatientPractitionerLocationOrganizationFHIR API
Figure: Data flow


Utility Resources

Note that these resources are used purely to provide linkage, they are minimally populated based on the information MHV receives. Often that means all that is populated is an identifier.

mapping Clinical Resources

This section is dedicated to instructions on how MHV will transition the data we receive into FHIR format. The priority order is:

  1. Allergy
  2. Immunization
  3. Notes
  4. Radiology Report
  5. Vitals
  6. Conditions
  7. Chem-Hem
  8. Micro / Path Lab Reports
  9. EKG/ECG - not likely to continue as no longer get useful reports

Allergy

Allergy and Intolerance Mapping Notes

Chem-Hem

Chem-Hem (CH) Diagnostic Report Mapping Notes

Condition

Conditions Mapping Notes

ECG

ECG Mapping Notes

Imaging Reports

Imaging Reports Mapping Notes

Immunization

Immunization Mapping Notes

Pathology LabReport

Pathology LabReport Mapping Notes

Microbiology LabReport

Microbiology LabReport Mapping Notes

Notes

Notes Mapping Notes

Vital-Sign

General Vital-Signs Mapping Notes

potential

other

  • Eventually this same API would support data from Cerner. Thus the same API providing comprehensive data from Vista and/or Cerner where ever it is.
  • Provenance – track where the data has come from, and if from multiple places track all.
  • Grahame - Intermediaries White Paper – https://confluence.hl7.org/display/FHIR/Intermediaries+White+Paper
  • HL7 FAST - Exchange Routing – http://hl7.org/fhir/R4/us/exchange-routing/

unknown (FHIR supports the following topics but unclear if this data exists in PHR)

  • care plan / care team resources
  • encounter resources
  • device resources
  • goal resources
  • procedure resources
  • questionnaire / questionnaireResponse resources
  • related person resources
  • service request resources
  • coverage resources

The use of FHIR AuditEvent should be used to track all uses of the FHIR API. This is a base configuration of the HAPI FHIR Server. See IHE Implementation Guide on the use of Basic Audit Log Patterns

Data input processing

General Pattern

  1. Our FHIR database will have a Patient resource that is created as needed from the MHV Patient Profile. It contains minimal elements. The Patient is intended simply for API use.
  2. Our FHIR database will assign Resource id value naturally using normal HAPI method (likely UUID)
  3. Our FHIR database will put external identifiers (e.g. Those from the Vista id such as ImmunizationTO.id) into the .identifier element
  4. The support Resources (Location, Organization, Practitioner, etc) will be contained in the primary clinical FHIR Resource. This because MHV is not told enough about these to properly identify and keep de-duplicated. For example when an Immunization was given at a specific location, we point at a Location resource that is contained in the Immunization with the details.
  5. Updates vs Deletes - using Index-Update-and-Delete
Backend Processingvets-websitevets-apiMHV APIPHR RefreshFHIR DBMHV Authen1GET /vitals2GET /status3POST /status4Kick off PHR Refreshfor single patientalt[PHR Refresh Not Complete]loop[Every Second until data is refreshed]5GET /status6GET /status7is refresh complete?8return 5009return 202[PHR Refresh Complete]10Populate FHIR DB11GET /status12GET /status13is refresh complete?14return 20015Auth16return 200with Bearer Tokenloop[for any clinical data (e.g. Vitals)]17GET /vitals (with Bearer Token)18return 200with vitals data19return 200with vitals data
Figure: Backend Processing flow


General Processing of clinical resources

Update mhv-fhir-phrtriggered by PHR Refresh for a given Patientread data VIA(VPR) and HDRreceive a multiple entry SOAP messagewith current informationGET existing id/identifier matrixfor this Domain from FHIR into matrixconvert data to FHIRconvert VIA/HDR.idto FHIR.identifierAdd to FHIR Bundlemore data?yescompare Bundle identifiers with id/identifier matrixany missed id/identifier add Delete to FHIR Bundlefor id/identifier matrixmore id/identifieryesSubmit Transaction Bundle to FHIRFHIR server will match each entry on.identifier and update or create neweach Domainmore domains?yesnono
Figure: Clinical Resource Processing flow


  • We do updates based on the .identifier. HAPI will find that resource, compare what it has with what we put in the bundle, and NOT do an update if there is no change. Thus we rely on HAPI to properly detect changes, so MHV code does not have to.
  • The current/historic list could be used to place the current id on entries with the given identifier, these entries can be then marked as conditional update. Where as today it is a conditional update based on a lookup on the .identifier. This will improve the performance of the HAPI server as it will remove an indirect lookup. We can also know which entries are NEW, so we can mark them as create. MHV-54038

Entered-in-Error

As data are removed or marked as entered-in-error on Vista, the MHV often is simply not informed about that object any more. With MHV eVault, this was handled by simply purging all PHR data each refresh. With FHIR database, we are a step away from the database and thus purging the database is not possible. We thus need some way to handle the cases where we previously learned of a resource, but it was then deleted, and we now are no longer told about it. The following are potential candidates. Wipe-and-Replace was used for atime, but it resulted in a large historic version filling up the FHIR database with no value.

Now using Index-Update-and-Delete, with the exception that Allergies we mark them with entered-in-error as we receive that status from HDR.

  1. Index-Update-and-Delete: This model:
    1. pulls current FHIR resource .identifier values (use _elements parameter to limit results to just identifiers, id),
    2. When updating the new data, remember the .identifier that were refreshed.
    3. At the end, we can know which .identifier values were not updated. (most of the time there will be no unrefreshed data)
    4. We can delete those that were not updated
    5. – Note: Did not require moving to new HAPI Server.
  2. Index-Update-and-Expunge: This model:
    1. pulls current FHIR resource .identifier values (use _elements parameter to limit results to just identifiers, id, status),
    2. When updating the new VIA feed data, remember the .identifier that were refreshed.
    3. At the end, we can know which .identifier values were not updated. (most of the time there will be no unrefreshed data)
    4. We can patch those that were not updated, by .id, status to entered-in-error,
    5. – Note: Patch is not supported in our current HAPI server.
  3. Update-and-Expunge: This model is made available with an updated HAPI Server (6.10.0) that has the ability to disable history. However with this version we can't use Wipe-and-Replace as that will result in new id values being assigned at each refresh. So Update-and-Expunge is designed. Each VIA feed we convert to FHIR and request an update, but the HAPI server is smart enough to notice that nothing changed so it will not update the meta.lastUpdated. So we will add to our update the use of the http://hl7.org/fhir/R4/StructureDefinition/lastSourceSync extension, with todays date/time (now). This will force an update. Thus after we have fully processed the VIA feed, we can then look for entries older than now that are still active. This will most of the time return an empty set, but if it does return resources, we will change them to entered-in-error and update them.
  4. Wipe-and-Replace: Delete the patient's specific Resource (e.g. delete all the Immunizations for this patient) and write using update current data from the VIA refresh – similar to eVault PHR today. The HAPI server notices an update, by business identifier, of a previously deleted resource, so it brings it back to non-deleted. Thus after a VIA refresh, only current resources are not-deleted. The drawback is that this keeps historic versions, with two versions per refresh, and _lastUpdated is always the refresh time. Also, the ones removed are not marked as entered-in-error. – January 2024, decided to abandon this as the database fills to fast with history, and we don't need this history
  5. Get VIA updated
  6. Get VDIF to expose their data
  7. Get VDIF to expose their data in FHIR form
  8. Use Lighthouse FHIR, and thus have the 24 hour problem
  9. Use Lighthouse FHIR, and use a hack for short-term data. Where we only add vitals seen in VIA in the last 24 hours (or some timeframe).
  10. Use HDR
  11. Use CDW somehow
  12. new event service? slack #ves-event-bus
  13. track updates, and notice when a VIA update does not include a record we previously had. This would be very expensive and memory intensive. Thus might be something we do only occationally at low compute time.

References

Source of data received from VIA using a SOAP xml schema that might be from one of:

Vista Model