Skip to main content

Step 3: Model the medication plan

What we are building​

A small synthetic plan expressed as FHIR R4 MedicationRequest resources, ready for the patient app to read.

What you should already have​

  • The sandbox project and patient access policy from step 2.
  • A synthetic Patient resource created through an authorized sandbox or clinical setup flow.
  • Permission to create the sample plan as a project administrator or another authorized test operator.

The implementation​

Choose the FHIR resources​

Ovok does not expose a separate medication-plan API. Use the FHIR resource that matches each fact:

NeedResourceUse in this tutorial
A prescribed or intended plan with dose instructionsMedicationRequestThe app reads active requests for the signed-in Patient.
A reusable coded or detailed medication definitionMedicationOptional. A request may instead use medicationCodeableConcept.
A statement that a patient is or was taking medication over a periodMedicationStatementNot used for each individual reminder occurrence.
One occurrence reported as completed or not doneMedicationAdministrationUsed in step 8 for patient-reported taken/skipped events.

The CapabilityStatement at GET /fhir/R4/metadata advertises create, read, update, delete, history, and search interactions for these medication resources in the current sandbox. Always check the target environment before deploying.

Create synthetic requests outside the patient app​

Create the following requests in the sandbox using an authorized setup tool. Do not put an administrator token in the mobile app. This is non-clinical sample data; replace nothing here with a real medication or prescribing instruction.

{
"resourceType": "MedicationRequest",
"status": "active",
"intent": "order",
"medicationCodeableConcept": { "text": "Demo medicine A" },
"subject": { "reference": "Patient/REPLACE_WITH_SYNTHETIC_PATIENT_ID" },
"authoredOn": "2026-10-07T09:00:00Z",
"dosageInstruction": [
{
"text": "Demo instructions only.",
"timing": {
"repeat": {
"frequency": 1,
"period": 1,
"periodUnit": "d",
"timeOfDay": ["08:00:00"],
"boundsPeriod": { "start": "2026-10-07", "end": "2026-11-06" }
}
}
}
]
}

Create two more active MedicationRequest resources for the same synthetic Patient: one with frequency: 2 and timeOfDay: ["08:00:00", "20:00:00"], and one with frequency: 1, timeOfDay: ["18:30:00"], and its own neutral dosageInstruction.text. Give each resource a different medicationCodeableConcept.text and a different server-assigned resource id. These examples demonstrate one daily dose, two daily doses, and an instruction such as “Demo instructions only; meal context supplied by the test plan.” They are not recommendations.

The sample authoredOn, boundsPeriod.start, and boundsPeriod.end values are illustrative. Before creating the sample requests, update the start/end dates to a current test window so they remain active during your walkthrough.

MedicationRequest.medication[x] and subject are required. The dosageInstruction carries the display text and timing. timeOfDay is a FHIR time, so it has no UTC offset. The tutorial interprets this simple example as the patient's local wall-clock time; step 4 defines that product decision and its limitations.

Read the plan with the FHIR client​

Once step 5 has created the client and authenticated patient profile, the app reads only active requests belonging to that Patient:

const plan = await loadMedicationPlan(client, patient.id);

loadMedicationPlan is implemented in step 5 using the client's paginated search method. Keep the subject filter in the request and let the AccessPolicy enforce the same boundary server-side.

Important Ovok decisions​

  • MedicationRequest.status describes the request's lifecycle. Only active requests are included in this simple Today view; cancelled, stopped, completed, or entered-in-error requests must not be shown as current.
  • A Medication resource is optional when the request has a usable medicationCodeableConcept. Do not create duplicate Medication resources simply to display a text label.
  • A MedicationStatement is not a dose-by-dose adherence log. The tutorial uses one MedicationAdministration per reported occurrence and makes clear it is patient-reported.
  • Dosage.timing can express more than this tutorial's daily timeOfDay subset. The app must not guess a reminder time from when, frequency, or free text. Unsupported timing needs an explicit product/clinical interpretation before scheduling.

Expected result​

The sandbox contains three synthetic MedicationRequest resources linked to one test Patient, and the authenticated patient search returns only that patient's active requests.

Common errors and troubleshooting​

  • No requests are returned: verify the subject reference is exactly Patient/{id}, the request is active, and the user is signed in as that patient.
  • The plan displays a misleading schedule: inspect the source Dosage.timing. The tutorial supports explicit local timeOfDay entries; it does not parse free-text instructions into times.
  • A write returns 403: create the sample plan through an authorized setup identity. The patient app should not receive a privilege that lets it prescribe or edit the plan.

Previous / Next​

Previous: step 2: create and configure the Ovok project · Continue to step 4: set up localisation and time handling.