💊 Shared Health Records (Pharmacy Focused)

Pharmacy Workflow Documentation(v1)

This document outlines the complete pharmacy workflow using the custom FHIR API implementation based on the provided Postman collection. The workflow covers patient registration, prescription submission, patient summary retrieval, refill balance calculation, and medication dispensing. NB: This documentation does not implement encryption workflows described at the beginning of this guide

1. Register/Update Patient Information

Before processing prescriptions, ensure that the patient exists in the system.

Endpoint

PUT {{base_url}}/v1/patient-resource?cr_id=CR06XX3268000-3-1

Authentication

Basic Authentication

Request Body

{
  "resourceType": "Patient",
  "id": "CR06XX3268000-3-1",
  "identifier": [
    {
      "use": "official",
      "system": "https://cr.tiberbu.app/app/client-registry/CR06XX3268000-3-1",
      "value": "CR06XX3268000-3-1"
    }
  ],
  "name": [
    {
      "text": "STEPHEN GITAU",
      "family": "GITAU",
      "given": [
        "STEPHEN"
      ]
    }
  ],
  "gender": "male"
}

Response

A successful response indicates the patient has been registered or updated in the system.

2. Post a Prescription (MedicationRequest)

Submit a new prescription for the patient.

Endpoint

POST {{base_url}}/v1/shr-submission?resource=MedicationRequest

Authentication

Basic Authentication

Request Body

{
  "resourceType": "MedicationRequest",
  "id": "a87e7dc1-3a8c-4f44-b5e7-891d73b783f2",
  "status": "active",
  "intent": "order",
  "medicationCodeableConcept": {
    "coding": [
      {
        "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
        "code": "197319",
        "display": "Amlodipine 5 MG Oral Tablet"
      }
    ],
    "text": "Amlodipine 5mg tablet"
  },
  "subject": {
    "reference": "Patient/CR06XX3268000-3-1",
    "display": "STEPHEN GITAU"
  },
  "authoredOn": "2025-03-28",
  "requester": {
    "reference": "Practitioner/123456",
    "display": "Dr. Jane Smith"
  },
  "recorder": {
    "reference": "Practitioner/123456",
    "display": "Dr. Jane Smith"
  },
  "reasonCode": [
    {
      "coding": [
        {
          "system": "http://hl7.org/fhir/sid/icd-10",
          "code": "I10",
          "display": "Essential (primary) hypertension"
        }
      ]
    }
  ],
  "dosageInstruction": [
    {
      "text": "Take one tablet by mouth once daily",
      "timing": {
        "repeat": {
          "frequency": 1,
          "period": 1,
          "periodUnit": "d"
        }
      },
      "route": {
        "coding": [
          {
            "system": "http://snomed.info/sct",
            "code": "26643006",
            "display": "Oral route"
          }
        ]
      },
      "doseAndRate": [
        {
          "type": {
            "coding": [
              {
                "system": "http://terminology.hl7.org/CodeSystem/dose-rate-type",
                "code": "ordered",
                "display": "Ordered"
              }
            ]
          },
          "doseQuantity": {
            "value": 1,
            "unit": "tablet",
            "system": "http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm",
            "code": "TAB"
          }
        }
      ]
    }
  ],
  "dispenseRequest": {
    "validityPeriod": {
      "start": "2025-03-28",
      "end": "2025-09-28"
    },
    "numberOfRepeatsAllowed": 5,
    "quantity": {
      "value": 30,
      "unit": "tablets",
      "system": "http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm",
      "code": "TAB"
    },
    "expectedSupplyDuration": {
      "value": 30,
      "unit": "days",
      "system": "http://unitsofmeasure.org",
      "code": "d"
    }
  },
  "substitution": {
    "allowedBoolean": true,
    "reason": {
      "coding": [
        {
          "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason",
          "code": "FP",
          "display": "formulary policy"
        }
      ]
    }
  },
  "note": [
    {
      "text": "Patient has reported dizziness with higher doses in the past."
    }
  ]
}

Response

A successful response confirms the prescription has been stored in the system.

3. Fetch International Patient Summary (IPS)

Retrieve the patient's complete health summary, including active medications and prescriptions.

Endpoint

GET {{base_url}}/v1/shr/summary?cr_id=CR06XX3268000-3-1

Authentication

Basic Authentication

Response

The response will be a FHIR Bundle containing the patient's health summary, including: - Patient demographics - Active medications - Allergies - Problem list - Immunizations - Recent lab results

{
  "resourceType": "Bundle",
  "type": "document",
  "id": "58a6f841-3a23-4a19-9f96-9852cb481763",
  "timestamp": "2025-03-28T10:58:27.831+00:00",
  "entry": [
    {
      "fullUrl": "urn:uuid:945dcd5f-3d9e-4bc1-8892-621f9a987a32",
      "resource": {
        "resourceType": "Composition",
        "id": "945dcd5f-3d9e-4bc1-8892-621f9a987a32",
        "status": "final",
        "type": {
          "coding": [
            {
              "system": "http://loinc.org",
              "code": "60591-5",
              "display": "Patient summary Document"
            }
          ]
        },
        "subject": {
          "reference": "Patient/CR06XX3268000-3-1"
        },
        "date": "2025-03-28T10:58:27+00:00",
        "author": [
          {
            "reference": "Practitioner/789012"
          }
        ],
        "title": "Patient Summary",
        "section": [
          {
            "title": "Allergies and Intolerances",
            "code": {
              "coding": [
                {
                  "system": "http://loinc.org",
                  "code": "48765-2",
                  "display": "Allergies and adverse reactions Document"
                }
              ]
            },
            "entry": [
              {
                "reference": "AllergyIntolerance/87654321"
              }
            ]
          },
          {
            "title": "Medication List",
            "code": {
              "coding": [
                {
                  "system": "http://loinc.org",
                  "code": "10160-0",
                  "display": "History of Medication use Narrative"
                }
              ]
            },
            "entry": [
              {
                "reference": "MedicationRequest/a87e7dc1-3a8c-4f44-b5e7-891d73b783f2"
              }
            ]
          }
        ]
      }
    },
    {
      "fullUrl": "urn:uuid:7f60d206-66c5-4998-a812-6d666c3f1111",
      "resource": {
        "resourceType": "Patient",
        "id": "CR06XX3268000-3-1",
        "identifier": [
          {
            "system": "https://cr.tiberbu.app/app/client-registry/CR06XX3268000-3-1",
            "value": "CR06XX3268000-3-1"
          }
        ],
        "name": [
          {
            "text": "STEPHEN GITAU",
            "family": "GITAU",
            "given": [
              "STEPHEN"
            ]
          }
        ],
        "gender": "male"
      }
    }
    // Other resources like MedicationRequest, AllergyIntolerance, etc.
  ]
}

4. Post a Medication Dispense

To record a medication dispensation, create a MedicationDispense resource.

Endpoint

POST {{base_url}}/v1/shr-submission?resource=MedicationDispense

Authentication

Basic Authentication

Request Body

{
  "resourceType": "MedicationDispense",
  "id": "c98765a4-321b-4cde-f567-8ab9c0123def",
  "status": "completed",
  "medicationCodeableConcept": {
    "coding": [
      {
        "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
        "code": "197319",
        "display": "Amlodipine 5 MG Oral Tablet"
      }
    ],
    "text": "Amlodipine 5mg tablet"
  },
  "subject": {
    "reference": "Patient/CR06XX3268000-3-1",
    "display": "STEPHEN GITAU"
  },
  "performer": [
    {
      "actor": {
        "reference": "Practitioner/pharm-789",
        "display": "Pharmacist Bob Green"
      }
    },
    {
      "actor": {
        "reference": "Organization/org-123",
        "display": "Community Pharmacy"
      }
    }
  ],
  "authorizingPrescription": [
    {
      "reference": "MedicationRequest/a87e7dc1-3a8c-4f44-b5e7-891d73b783f2"
    }
  ],
  "type": {
    "coding": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
        "code": "RF",
        "display": "Refill"
      }
    ]
  },
  "quantity": {
    "value": 30,
    "unit": "tablets",
    "system": "http://terminology.hl7.org/CodeSystem/v3-orderableDrugForm",
    "code": "TAB"
  },
  "daysSupply": {
    "value": 30,
    "unit": "days",
    "system": "http://unitsofmeasure.org",
    "code": "d"
  },
  "whenPrepared": "2025-04-27T09:15:00Z",
  "whenHandedOver": "2025-04-27T10:30:00Z",
  "dosageInstruction": [
    {
      "text": "Take one tablet by mouth once daily"
    }
  ],
  "note": [
    {
      "text": "Patient reported no side effects with current dosage."
    }
  ]
}

Response

A successful response confirms the dispense has been recorded in the system.

5. Computing Medication Refill Balance

Since the Postman collection doesn't include a direct endpoint for querying refill balances, we need to create a process for computing this. Here's a Python script to calculate the refill balance based on the IPS data:

import requests
import json
from datetime import datetime, timedelta
import base64

def get_auth_header(username, password):
    """Generate the basic auth header for API requests"""
    credentials = f"{username}:{password}"
    encoded = base64.b64encode(credentials.encode()).decode()
    return {"Authorization": f"Basic {encoded}"}

def get_patient_summary(base_url, cr_id, auth_header):
    """Fetch the patient's health summary"""
    url = f"{base_url}/v1/shr/summary?cr_id={cr_id}"
    response = requests.get(url, headers=auth_header)

    if response.status_code != 200:
        raise Exception(f"Failed to get patient summary: {response.status_code}")

    return response.json()

def calculate_refill_balance(ips_bundle, medication_request_id):
    """Calculate remaining refills based on the IPS data"""

    # Initialize variables
    medication_request = None
    medication_dispenses = []

    # Process IPS bundle to find the MedicationRequest and related MedicationDispense resources
    for entry in ips_bundle.get("entry", []):
        resource = entry.get("resource", {})

        if resource.get("resourceType") == "MedicationRequest" and resource.get("id") == medication_request_id:
            medication_request = resource

        if resource.get("resourceType") == "MedicationDispense":
            for prescription in resource.get("authorizingPrescription", []):
                if prescription.get("reference") == f"MedicationRequest/{medication_request_id}":
                    medication_dispenses.append(resource)

    if not medication_request:
        return {
            "error": f"MedicationRequest {medication_request_id} not found in patient summary"
        }

    # Calculate refill information
    total_allowed_fills = medication_request.get("dispenseRequest", {}).get("numberOfRepeatsAllowed", 0) + 1
    total_dispenses = len(medication_dispenses)
    remaining_refills = total_allowed_fills - total_dispenses

    # Find next refill date based on most recent dispense
    next_refill_date = None
    if medication_dispenses:
        # Sort by dispense date
        sorted_dispenses = sorted(
            medication_dispenses,
            key=lambda x: x.get("whenHandedOver", ""),
            reverse=True
        )

        latest_dispense = sorted_dispenses[0]
        latest_dispense_date = datetime.fromisoformat(latest_dispense["whenHandedOver"].replace("Z", "+00:00"))
        days_supply = latest_dispense.get("daysSupply", {}).get("value", 30)

        next_refill_date = (latest_dispense_date + timedelta(days=days_supply)).isoformat()

    # Check if prescription is still valid
    is_valid = True
    current_date = datetime.now()

    if "dispenseRequest" in medication_request and "validityPeriod" in medication_request["dispenseRequest"]:
        end_date_str = medication_request["dispenseRequest"]["validityPeriod"].get("end")
        if end_date_str:
            end_date = datetime.fromisoformat(end_date_str.replace("Z", "+00:00"))
            if current_date > end_date:
                is_valid = False

    return {
        "medicationRequestId": medication_request_id,
        "totalAllowedFills": total_allowed_fills,
        "fillsDispensed": total_dispenses,
        "remainingRefills": remaining_refills,
        "nextRefillDueDate": next_refill_date,
        "isPrescriptionValid": is_valid,
        "prescriptionExpiryDate": medication_request.get("dispenseRequest", {}).get("validityPeriod", {}).get("end")
    }

# Example usage
base_url = "https://api.example.org"
username = "your_username"
password = "your_password"
cr_id = "CR06XX3268000-3-1"
medication_request_id = "a87e7dc1-3a8c-4f44-b5e7-891d73b783f2"

auth_header = get_auth_header(username, password)
ips_bundle = get_patient_summary(base_url, cr_id, auth_header)
refill_info = calculate_refill_balance(ips_bundle, medication_request_id)

print(json.dumps(refill_info, indent=2))

Example Output:

{
  "medicationRequestId": "a87e7dc1-3a8c-4f44-b5e7-891d73b783f2",
  "totalAllowedFills": 6,
  "fillsDispensed": 2,
  "remainingRefills": 4,
  "nextRefillDueDate": "2025-05-27T10:30:00+00:00",
  "isPrescriptionValid": true,
  "prescriptionExpiryDate": "2025-09-28"
}

Complete Workflow Example

  1. Patient Registration/Update:

    • PUT {{baseurl}}/v1/patient-resource?crid=CR06XX3268000-3-1
    • Ensures the patient exists in the system
  2. Prescription Creation:

    • POST {{base_url}}/v1/shr-submission?resource=MedicationRequest
    • Creates an initial prescription with 5 refills allowed
  3. Initial Dispensing:

    • POST {{base_url}}/v1/shr-submission?resource=MedicationDispense
    • Records the initial fill of the medication
  4. Patient Summary Retrieval:

    • GET {{baseurl}}/v1/shr/summary?crid=CR06XX3268000-3-1
    • Gets current health information including prescription/dispensing history
  5. Refill Balance Calculation:

    • Use the provided Python code with data from the IPS
    • Determines if patient is eligible for refill
  6. Subsequent Dispensing:

    • POST {{base_url}}/v1/shr-submission?resource=MedicationDispense
    • Records additional refills as they occur

The workflow continues with repeated IPS retrievals and dispensing records until the prescription expires or all refills are used.

Discard
Save
Review Changes ← Back to Content
Message Status Space Raised By Last update on