OZO FHIR implementation guide
0.7.7 - ci-build
OZO FHIR implementation guide - Local Development build (v0.7.7) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
This page covers individual messaging between RelatedPersons and Practitioners. For team-to-team messaging (e.g. pharmacy ↔ clinic), see Team-to-Team Messaging.
The messaging interaction consists of the following parts:
This IG distinguishes the following roles when processing messages:
CommunicationRequest, Communication, Task and AuditEvent.In practice, a single Subscription is enough for most clients and platforms:
Task?status=requested — required. Covers unread tracking and new-message notification for the recipient (the AAA proxy automatically scopes this to the current user's ownership). Use Task?id instead if you also need to detect read receipts (REQUESTED → COMPLETED transitions).Optional additional subscriptions:
Communication?id — optional. Only needed to see messages you sent yourself. Your own Task is set to COMPLETED on send and won't match status=requested, but the HTTP POST response usually gives you the same data.CommunicationRequest?id — optional. Only needed if you care about thread lifecycle events (DRAFT → ACTIVE approval, thread revoked/completed) separately from messages.In the Netherlands, healthcare data must not be pushed in subscription notifications. All subscriptions use the notify-then-pull pattern:
This means channel.payload must be left empty. The notification only signals that something matched the subscription criteria — the subscriber is responsible for fetching the actual data.
Each subscription serves a different purpose. Understanding when notifications fire is critical for correct client implementation:
| Subscription | Purpose | Required? | Fires when |
|---|---|---|---|
Task?status=requested |
Unread tracking and new-message notification for the recipient. Primary mechanism. | Required | Any change to a Task that matches status=requested. This includes status transitions to REQUESTED AND content changes (like focus) on Tasks already REQUESTED. |
Communication?id |
Visibility of your own sent messages (sender's Task goes to COMPLETED and won't match status=requested). |
Optional | A new Communication is created (POST). |
CommunicationRequest?id |
Thread lifecycle changes (DRAFT → ACTIVE, revoked, completed). | Optional | A CommunicationRequest is created or its status changes. |
Important: When a new message arrives, the OZO FHIR Api updates the Task's
focusfield to reference the newCommunication. This ensuresTask?status=requestedfires even when the task was already in REQUESTED status — thefocuschange creates a new resource version. Thefocusfield also gives clients a direct pointer to the most recent unread message.This means
Task?status=requestedis a reliable single subscription for both unread tracking and new-message notification. The other two subscriptions are optional and only needed for specific edge cases.
As client of the OZO FHIR Api can create a new thread. The process of creating a new thread looks as follows:
CommunicationRequest object, the following fields are set:
RelatedPersonPatient reference from the RelatedPersonCareTeam as part of recipient a new Task is created, the Task has the following fields:
CommunicationRequest reference.Patient referenceCommunicationRequest by Subscription:
CommunicationRequest to the recipientCommunicationRequest by setting the status to ACTIVEA practitioner in the OZO platform responds to a message from a caregiver by the following actions:
Communication with the following fields:
CommunicationRequest.Practitionerrecipient is not set — thread participants are defined on the CommunicationRequest.CareTeam as part of recipient and not the sender:
focus is updated to reference the new Communication (ensures the subscription fires even when status was already REQUESTED)CommunicationRequest reference.Patient referenceCommunication reference.Communication by Subscription and presents the message to the caregiver.AuditEvent with the following properties:
type is set to http://terminology.hl7.org/CodeSystem/iso-21089-lifecycle|accessaction is set to 'R'recorded field is set to 'now()'agent.who field is set to the RelatedPersonentity.what field has two values:
CommunicationCommunicationRequestTask is queried for the RelatedPerson as part of the agent.who of the AuditEventTask status is set to COMPLETEDTask status change (REQUESTED → COMPLETED) by Subscription:
RelatedPerson in the OZO platform.A caregiver in the OZO client responds to a message from a practitioner by the following actions:
Communication with the following fields:
CommunicationRequest.RelatedPersonrecipient is not set — thread participants are defined on the CommunicationRequest.CareTeam as part of recipient and not the sender:
focus is updated to reference the new Communication (ensures the subscription fires even when status was already REQUESTED)CommunicationRequest reference.Patient referenceCommunication reference.Communication by Subscription:
CareTeam.CareTeam reads the message, the message is marked as read for all the members in the CareTeam (the Task status is set to COMPLETED).AuditEvent.The diagram below displays the creation of threads, and responding for both the practitioner and related person. {::nomarkdown}
{:/}
The following walkthrough shows a concrete example using patient H. de Boer's care network (Netwerk-H-de-Boer), which includes:
Kees Groot sends a message to the care team about a fracture report — see Thread-Example for the full CommunicationRequest.
The OZO FHIR Api creates a Task (status requested) for each CareTeam member except the sender — see Notify-Manu-van-Weel and Notify-Mark-Benson for examples.
Notifications fired:
CommunicationRequest subscription → OZO platform notified of new threadTask?status=requested subscription → each practitioner notified of unread threadThe OZO platform receives the CommunicationRequest and sets status to ACTIVE.
Practitioner Manu van Weel reads the message and replies — see Reply-Manu-to-Kees for the full Communication.
The OZO FHIR Api updates Tasks:
requested (unread for Kees)completed (Manu is the sender)Notifications fired:
Communication subscription → OZO client notified of new messageTask?status=requested subscription → Kees notified of unread message (status changed from COMPLETED to REQUESTED, and focus now points to the new message)Kees opens the message in the OZO client. The client creates an AuditEvent — see Kees-Read-Messages for the full resource.
The OZO FHIR Api marks the Task as completed:
completed (was: requested)Notifications fired:
Task?status=requested subscription → no (Task moved to COMPLETED, not REQUESTED)Kees sends a follow-up message to the care team — see Reply-Kees-to-Netwerk for the full Communication.
The OZO FHIR Api updates Tasks for each CareTeam member — both status and focus (pointing to the new Communication):
requested (was: completed), focus → new Communicationrequested, focus → new Communication (triggers new version)Notifications fired:
Communication subscription → OZO platform notified of new messageTask?status=requested subscription → Manu notified (status changed from COMPLETED to REQUESTED)Task?status=requested subscription → Mark notified (focus changed — a new Task version is created and the Task still matches status=requested)Note: The
focusupdate solves the no-op problem. Even when a practitioner hasn't read the previous message (Task already REQUESTED), updatingfocusto point to the new Communication creates a new resource version, so the Task subscription fires.