Fast Healthcare Interoperability Resources (FHIR) - это протокол для обмена медицинскими данными. Стандарт очень объемный, одних только ресурсов более полутора сотен, и цель данной статьи - дать стартовую точку для его изучения.

Это первый из запланированной серии постов посвященных FHIR технологиям, далее планирую добавить статьи с шагами регистрации и подключения к EPIC EHR, загрузки FHIR данных, их использования для формирования карты пациента и особенностями использования FHIR данных в AI чат-ботах.

Введение

FHIR - набор стандартизованных сущностей (resources) и веб-API к ним. Patient, Encounter, DiagnosticReport, Observation, MedicationRequest - всё это ресурсы с предсказуемыми схемами и ссылками друг на друга. С точки зрения пациента это по сути гигантский граф данных о нем, его анамнезе и взаимодействии с медицинскими учреждениями.

Основными источниками данных о этом стандарте являются сайты fhir.org и hl7.org/fhir.

В самом стандарте описано порядка полутора сотен ресурсов, а так же различные сценарии их использования клиниками. Поскольку домен FHIR чрезвычайно обширен в статье я сосредоточусь на ресурсах и задачах с которых стоит начать реализацию приложения ориентированного на пациента, которое позволит ему получить доступ к записям на прием, лабораторным результатам, диагнозам и назначенным препаратам.

Cхема уровней спецификации FHIR
Cхема уровней спецификации FHIR

Что нужно чтобы начать разработку

Для приложений, создаваемых под конкретную клинику, процесс подключения обычно очевиден - необходимые учётные данные предоставляет сама организация, и можно переходить к следующему разделу, авторизации.

Если же мы говорим о приложении не аффилированном с какой то клиникой, то прежде всего нужно определиться с теми Electronic Health Record (EHR) с которыми вы будете работать.

Например в случае Соединенных Штатов это могут быть Epic, Cerner, Veradigm, AthenaHealth и другие. Так же определенные государственные структуры тоже предоставляют доступ по FHIR протоколам к данным своих пациентов, например так делает U.S. Department of Veterans Affairs.

В варианте Великобритании можно рассчитывать на бесплатное подключение к системам NHS, что упрощает выбор.

К сожалению, в России пока нет единого публичного FHIR-доступа: интеграция возможна только через конкретные клиники и их медицинские информационные системы (МИС).

Как устроен поиск клиник и авторизация в FHIR

У крупных EHR, работающих с большим количеством клиник, вы можете получить так называемый User-access Brands and Endpoints, который представляет собой FHIR ресурс Bundle со списком ресурсов Organization и Endpoint, в которых будут метаданные всех организаций поддерживаемых этим EHR. Например для EPIC он доступен по адресу https://open.epic.com/MyApps/Endpoints.

Стандартным методом аутентификации пациента и получение доступа к FHIR API является протокол OAuth2. Про него есть много статей на хабре и других профильных ресурсах, например https://habr.com/ru/articles/899874/, так что отметим особенности подключения связанные именно с FHIR API.

Взяв из User-access Brands and Endpoints адрес конкретного FHIR сервера для начала нужно получить его CapabilityStatement. Это документ, содержащий информацию о том, какие ресурсы предоставляет данный FHIR сервис, и адреса его эндпоинтов авторизации и получения токена. Для этого нужно выполнить запрос к эндпоинту /metadata. Например для сервера https://epicsoap.altru.org/fhir/api/FHIR/R4/ это будет запрос вида:

curl --location 'https://epicsoap.altru.org/fhir/api/FHIR/R4/metadata' \
     --header 'Accept: application/json'

В ответ клиент получит JSON содержащий искомые ссылки , а также список поддерживаемых сервером ресурсов и параметров запросов к ним.

Еще одним полезным эндпоинтом является /.well-known/smart-configuration, который не входит в сам FHIR стандарт но является частью SMART App Launch Framework.

curl --location 'https://epicsoap.altru.org/fhir/api/FHIR/R4/.well-known/smart-configuration' \
     --header 'Accept: application/json'

он возвращает OAuth ссылки авторизации и токена, а также данные, которые могут быть полезными для настройки схемы авторизации на клиенте (какие grant_types и code_challenge поддерживаются, какие scope доступны).

Основываясь на полученных данных, клиент должен запустить OAuth авторизацию. В успешном случае он получит accessToken, идентификатор пациента patient и список scope, которые ему выданы (некоторые провайдеры позволяют пациенту модифицировать список scope в процессе авторизации).

В зависимости от выбора EHR вы можете столкнуться с необходимостью управлять разным количеством OAuth секретов: это может быть либо общий секрет на любую клинику с которой EHR работает - например Cerner, либо один ClientID но разные ClientSecret для каждой из клиник - такое будет при подключении к EPIC. Соответственно, еще до реализации желательно продумать архитектуру хранения и обновления секретов, а также учитывать то, что состав клиник, доступных через EHR постоянно меняется: добавляются одни и удаляются другие клиники, некоторые переходят от одного EHR к другому.

Ключевые FHIR-ресурсы с которых стоит начать изучение

Стандарт FHIR содержит более полутора сотен типов ресурсов, и не все из них скорее всего, будут нужны в вашем приложении. В данной статье мы сосредоточимся на ресурсах вероятнее всего потребующихся при разработке приложения для пациента.

Одним из самых важных ресурсов с этой точки зрения является Encounter, описывающий факт взаимодействия пациента с системой здравоохранения. Проще говоря — это визит, госпитализация, консультация, сеанс терапии или любое событие, в рамках которого пациент получает медицинскую помощь.

Связи Encounter с ресурсами пациента
Связи Encounter с ресурсами пациента

К нему привязываются остальные события — диагноз (Condition), наблюдения и результаты измерений (Observation), назначения лекарств (MedicationRequest), выписки и документы (DocumentReference).

Именно через Encounter все эти данные объединяются в единый контекст медицинского эпизода: что, где, когда и кем было сделано для конкретного пациента.

Например:

  • Пациент приходит на приём (Appointment) → создаётся Encounter с состоянием in-progress.

  • Во время визита врач ставит диагноз (Condition), измеряет давление (Observation) и выписывает рецепт (MedicationRequest).

  • После визита формируется отчёт (DiagnosticReport) и сохраняется документ с результатами (DocumentReference).

  • После завершения приёма Encounter получает статус completed.

Таким образом, Encounter — это основная ось клинического контекста в FHIR. Он связывает между собой пациента, медперсонал, место оказания помощи, время события и все медицинские действия, происходящие в рамках этого взаимодействия.

Данная статья носит обзорный характер и не ставит задачу обозреть все 156 типов FHIR ресурсов, тем более что не все из них имеют смысл в контексте приложений для пациента. Ниже в таблице приведен список с которого стоит начать ознакомление со стандартом с моей точки зрения, включая ссылки на документацию:

Название

Краткое описание

Важные поля ресурса на которые стоит обратить внимание

Связи

Patient

Карточка пациента

identifier[], name[], gender, birthDate

Базовый ресурс: Encounter, Observation, Condition и др. привязаны Patient

Encounter

Эпизод/визит

status, class, type, period, subject

Объединяет наблюдения и отчёты в клинический контекст

Condition

Диагноз или состояние

clinicalStatus, verificationStatus, code, onset[x]

Encounter, Observation

ServiceRequest

Запрос на исследование/услугу

code, subject, authoredOn, requester

Observation, DiagnosticReport

Procedure

Факт выполнения процедуры

status, code, performed[x], subject

Может ссылаться на отчёты (DiagnosticReport, DocumentReference)

Observation

Измерение (давление, пульс, уроверь глюкозы и т.п.)

code, value[x], effective[x], referenceRange[]

Сгруппированы через hasMember другого Observation или входят в DiagnosticReport

DiagnosticReport

Лабораторный отчет, рентген, MRI, CT

status, code, result[] (Observation), conclusion

Содержит Observations, может ссылаться на Binary через DocumentReference

DocumentReference

Ссылка на документ (PDF, снимок)

content[], type, author[], date

Может ссылаться на Binary

Binary

Сырой файл

contentType, data/url

Medication

Описание лекарства (справочник)

code, form, ingredient[]

MedicationRequest

Назначение лекарства

medication[x], dosageInstruction[], intent, status

Связан с Encounter, Condition

MedicationStatement

Факт приёма лекарств

status, effective[x], medication[x]

AllergyIntolerance

Аллергии и непереносимости

code, criticality, reaction[], verificationStatus

Immunization

Запись о вакцинации

vaccineCode, occurrence[x], lotNumber

Device

Устройство

deviceName[], status, patient

Appointment

Запись на приём

status, start/end, participant[]

Типичные ошибки patient-facing интеграций

Авторизация

  • Запрашивать лишние scope, которые вам не нужны - пользователи могут подозрительно относиться к излишним правам.

  • Пытаться читать ресурсы из запрошенных, но не полученных scope - пациент мог убрать часть во время авторизации, тот же EPIC это позволяет

  • Игнорировать провайдерские лимиты и не притормаживать загрузку данных - получите постоянные ошибки при загрузке, поскольку провайдеры обычно накладывают request rate limit на все приложение (ClientId), а не на отдельные его инсталляции

Получение данных

  • Не проверять на отсутствие данных в необязательных полях, если один провайдер в них что-то возвращает, то другой может вернуть NULL и у вас будет ошибка. В FHIR ресурсах ОЧЕНЬ много необязательных полей.

  • Пытаться читать из Bundle элементов больше, чем указано в поле Total, и не забывать проверять что Total != NULL (он тоже необязательный).

  • При экспорте данных пытаться загрузить сразу все ресурсы (особенно Binary) в память - часто они могут быть довольно большого объема что ведет к out-of-memory.

Визуализация

  • Показывать все, что есть в DocumentReference - он может содержать больше одного вложения, но не факт что вам нужны все, т.к. чаще всего это копии одного и того же документа в разном формате - plain-text, rtf, PDF, XML ClinicalNote, etc.

  • При проектировании UI не учитывать, что Observations - это иногда не одна величина, а целая коллекция других Observation

  • Путать MedicationRequest и MedicationStatement - первое это назначение лекарства пациенту, а последнее - факт приема.

Заключение

На западе FHIR уже стал стандартом для доступа к медицинским данным. Например, Apple Health использует FHIR, в Великобритании NHS Digital предоставляет открытые FHIR API, через которые можно получать данные о рецептах, вакцинации и записях на приём. Для разработчиков это значит - меньше хаоса в интеграциях, единые контракты и предсказуемые модели для анализов, распространение носимых устройств с его поддержкой.

Но самое ценное - то, как эти данные можно теперь использовать. Структурированные данные, в отличие от простых PDF документов, позволяют расширить их применимость, например - автоматически формировать анамнез для врача в зависимости от его специализации или запроса.

А если сюда еще подключить RAG и/или AI для выборки данных, это может перевести привычную организацию медицины на новый уровень, снизив человеческий фактор и требуемое время на взаимодействие с врачом, что позволит увеличить доступность медицины.

Комментарии (0)