Pharmacy Information System Integration Specifications
Integration Summary
| ID | Target System | Direction | Trigger Event | Data Exchanged | Protocol | Frequency | Auth |
|---|---|---|---|---|---|---|---|
| INT-PIS-001 | CPOE | Bidirectional | Order signed; order verified/dispensed | Inbound: medication orders. Outbound: dispensing status, pharmacist interventions | HL7 v2.5.1 (RDE^O11) + FHIR R4 (MedicationRequest, MedicationDispense, DetectedIssue) |
Real-time | mTLS (internal) |
| INT-PIS-002 | EHR (Patient Chart) | Outbound | Medication dispensed, administered, or reconciled | Medication list, eMAR records, pharmacy notes | Internal API + FHIR R4 (MedicationStatement, MedicationAdministration, MedicationRequest, Annotation) |
Real-time | Internal token / mTLS |
| INT-PIS-003 | LIS (Antimicrobial Stewardship) | Bidirectional | Culture finalized; antimicrobial order placed | Inbound: culture/sensitivity results. Outbound: antimicrobial orders and stewardship linkage | Internal REST/Message API | Real-time | mTLS (intra-DC) |
| INT-PIS-004 | Billing & Claims | Outbound | Medication dispensed | Dispensing charges (drug, quantity, RxNorm/NDC, cost, payer linkage) | Internal API + HL7 v2.5.1 DFT^P03 |
Real-time | mTLS |
| INT-PIS-005 | NABIDH (Dubai HIE) | Outbound | Medication dispensed | Medication dispensing events, active medication list | HL7 v2.5.1 over MLLP/TLS (NABIDH pharmacy profile) | Near real-time | mTLS + OAuth 2.0 (per NABIDH) |
| INT-PIS-006 | Malaffi (Abu Dhabi HIE) | Outbound | Medication dispensed | Medication dispensing events, active medication list | HL7 v2.5.1 over MLLP/TLS (Malaffi pharmacy profile) | Near real-time | mTLS (DOH-issued cert) |
| INT-PIS-007 | UAE MOH (Controlled Substances) | Outbound | Monthly reporting cycle; discrepancy event | Controlled substance dispensing reports, inventory reconciliation, discrepancy events | Secure file transfer (SFTP over SSH) and/or MOH web portal upload (CSV/XML) | Monthly batch + event-driven | VPN + key-based SFTP / MOH portal credentials |
| INT-PIS-008 | Patient Portal | Outbound | Medication dispensed; refill available; patient views meds | Medication list, refill status, instructions | FHIR R4 REST API (MedicationRequest, MedicationDispense, MedicationStatement) |
On-demand (portal pull) + event push | OAuth 2.0 (Authorization Code) + mTLS (internal) |
INT-PIS-001: CPOE
Business Context
What flows
- Inbound to PIS (from CPOE)
- Medication orders: drug (RxNorm), dose, route, frequency, duration, indication, priority (STAT/routine), PRN details
- Patient context: patient_id, encounter_id, demographics, allergies, weight, renal/hepatic function summary
-
Ordering provider: provider_id, specialty, DEA-equivalent authority flags for controlled substances (per MOH rules)
-
Outbound from PIS (to CPOE)
- Order status updates: verified, rejected, modified, on-hold
- Pharmacist interventions: type, recommendation, prescriber response
- Dispensing status: first-dose dispensed, partial fill, backordered
When
- Inbound: immediately when a provider signs a medication order in CPOE.
- Outbound: when pharmacist verifies/rejects/modifies an order, and when dispensing events occur.
Why
- Enables pharmacist clinical verification before dispensing.
- Keeps prescribers informed of pharmacy actions and interventions.
- Supports closed-loop medication management and auditability (DOH/DHA, UAE PDPL).
How often
- High volume, real-time; every medication order and status change.
Error impact
- Inbound failure: orders not visible to pharmacy; risk of delayed therapy.
- Outbound failure: CPOE shows stale status; prescribers may duplicate orders or miss critical interventions.
- All failures must be visible in an integration dashboard and logged for ADHICS/NESA audit.
HL7 v2.5.1 Technical Detail
Message Types
- Inbound to PIS:
RDE^O11(Pharmacy/Treatment Encoded Order) – preferred for medication orders. - Outbound to CPOE:
RDE^O11with updatedORC/RXEstatus, orRDE^O11+NTEfor interventions.
Sample Inbound Order Message (CPOE → PIS)
MSH|^~\&|HIS_CPOE|DUBAIHOSP|PIS|DUBAIHOSP|20260207103015+0400||RDE^O11|PIS20260207103015001|P|2.5.1|||AL|NE||UTF-8
PID|1||2026009876^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID||AL-MAKTOUM^AHMED^HASSAN||19850315|M|||PO BOX 12345^^DUBAI^^00000^AE||+971501234567|||M||||||||||AE
PV1|1|I|4B^412^01^DUBAIHOSP||||KHAN^SARA^A^^^DR|||MED||||||||ENC2026020700456|||||||||||||||||||||||||20260207090000+0400
AL1|1|DA|70618^Penicillin^RXNORM|SV|Anaphylaxis|20230515
AL1|2|DA|763875^Sulfonamide^RXNORM|MO|Rash|20210110
ORC|NW|ORD-20260207-000123^HIS_CPOE|ORD-20260207-000123^PIS||SC|||^^^20260207110000+0400^^R|20260207103015+0400|||KHAN^SARA^A^^^DR^MD^^^^^PRC|+971504445555^WP^PH^^^+971^504445555|PO BOX 56789^^DUBAI^^00000^AE||PHARM^Inpatient Pharmacy^DUBAIHOSP
RXE|1|10|mg^milligram^UCUM|314076^Lisinopril 10 MG Oral Tablet^RXNORM|PO^Oral^HL70162|QD^Once daily^HL70335|||90|TAB^Tablet^UCUM|20260207103015+0400|||R|N|||I10^Essential hypertension^ICD10AM|||||||
RXR|PO^Oral^HL70162
OBX|1|NM|29463-7^Body weight^LN||78|kg^kilogram^UCUM|60-100|N|||F|||20260207080000+0400
OBX|2|NM|2160-0^Creatinine^LN||1.3|mg/dL^milligram/deciliter^UCUM|0.7-1.3|N|||F|||20260207080000+0400
NTE|1||Take once daily in the morning. Monitor blood pressure.
Key Segment Notes
PID-3: MRN + Emirates ID (EID) – required for UAE HIE alignment.PV1-19:ENC2026020700456maps toencounters.encounter_id.ORC-1:NW(new order); later updates useXO(change) orCA(cancel).ORC-2: CPOE order ID; primary key for idempotency.RXE: Encoded order – dose, units, route, frequency, quantity, indication.OBX: Optional clinical context (weight, creatinine) to support dose checking.
Sample Outbound Status/Intervention Message (PIS → CPOE)
MSH|^~\&|PIS|DUBAIHOSP|HIS_CPOE|DUBAIHOSP|20260207104030+0400||RDE^O11|PIS20260207104030002|P|2.5.1|||AL|NE||UTF-8
PID|1||2026009876^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID
PV1|1|I|4B^412^01^DUBAIHOSP||||KHAN^SARA^A^^^DR|||MED||||||||ENC2026020700456
ORC|OK|ORD-20260207-000123^HIS_CPOE|ORD-20260207-000123^PIS||CM|||^^^20260207110000+0400^^R|20260207104000+0400|||ALI^FATIMA^OMAR^^^PHARM^RPh||||PHARM^Inpatient Pharmacy^DUBAIHOSP
RXE|1|10|mg^milligram^UCUM|314076^Lisinopril 10 MG Oral Tablet^RXNORM|PO^Oral^HL70162|QD^Once daily^HL70335|||90|TAB^Tablet^UCUM|20260207104000+0400|||R|N|||I10^Essential hypertension^ICD10AM
NTE|1||Pharmacist intervention: Confirmed indication and renal function. Dose appropriate. No changes required.
Field Mapping to PIS Tables (Inbound)
| HL7 Field | PIS Table.Column |
|---|---|
PID-3(1).ID (MRN) |
(via patient master) patients.patient_id |
PID-3(2).ID (EID) |
patient_identifiers.identifier_value (type=EID) |
PV1-19 |
pharmacy_orders.encounter_id |
ORC-2 |
pharmacy_orders.order_id |
ORC-9 (Date/Time of Transaction) |
pharmacy_orders.order_received_datetime |
ORC-12 (Ordering Provider) |
pharmacy_orders.ordering_provider_id |
RXE-5.1 (RxNorm code) |
pharmacy_orders.drug_code_rxnorm |
RXE-5.2 |
pharmacy_orders.drug_name |
RXE-3 + RXE-4 |
pharmacy_orders.dose, pharmacy_orders.dose_unit |
RXE-6 |
pharmacy_orders.route |
RXE-7 |
pharmacy_orders.frequency |
RXE-10 |
pharmacy_orders.duration_days |
RXE-15 |
pharmacy_orders.order_status (e.g., R=requested) |
RXE-19 (Diagnosis) |
link to diagnosis table; optional in PIS |
NTE-3 |
pharmacy_orders.special_instructions (additional column) |
Field Mapping to PIS Tables (Outbound)
| HL7 Field | Source Table.Column |
|---|---|
ORC-1 |
derived from pharmacy_orders.order_status (OK, CA, etc.) |
ORC-9 |
pharmacy_orders.verified_datetime |
ORC-12 |
pharmacy_orders.verified_by (pharmacist) |
NTE-3 |
pharmacy_interventions.description / recommendation |
FHIR R4 Technical Detail
Resources
- Inbound:
MedicationRequest(CPOE → PIS). - Outbound:
MedicationRequest(status updates)MedicationDispense(dispensing status)DetectedIssue(CDS alerts / pharmacist interventions, optional).
Sample Inbound MedicationRequest (CPOE → PIS)
{
"resourceType": "MedicationRequest",
"id": "ORD-20260207-000123",
"status": "active",
"intent": "order",
"priority": "routine",
"medicationCodeableConcept": {
"coding": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"code": "314076",
"display": "Lisinopril 10 MG Oral Tablet"
}
],
"text": "Lisinopril 10mg Tablet"
},
"subject": {
"reference": "Patient/2026009876",
"display": "Ahmed Hassan Al-Maktoum"
},
"encounter": {
"reference": "Encounter/ENC2026020700456"
},
"authoredOn": "2026-02-07T10:30:15+04:00",
"requester": {
"reference": "Practitioner/KHAN-SARA",
"display": "Dr. Sara Khan"
},
"reasonCode": [
{
"coding": [
{
"system": "http://hl7.org/fhir/sid/icd-10-am",
"code": "I10",
"display": "Essential hypertension"
}
]
}
],
"dosageInstruction": [
{
"text": "Take 10mg by mouth once daily in the morning",
"timing": {
"repeat": {
"frequency": 1,
"period": 1,
"periodUnit": "d"
},
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-GTSAbbreviation",
"code": "QD",
"display": "Once daily"
}
]
}
},
"route": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "26643006",
"display": "Oral route"
}
]
},
"doseAndRate": [
{
"doseQuantity": {
"value": 10,
"unit": "mg",
"system": "http://unitsofmeasure.org",
"code": "mg"
}
}
]
}
],
"dispenseRequest": {
"quantity": {
"value": 90,
"unit": "tablet"
},
"expectedSupplyDuration": {
"value": 90,
"unit": "days",
"system": "http://unitsofmeasure.org",
"code": "d"
}
},
"note": [
{
"text": "Take once daily in the morning. Monitor blood pressure."
}
]
}
Key Element Mapping
| FHIR Element | PIS Table.Column |
|---|---|
id |
pharmacy_orders.order_id |
status |
pharmacy_orders.order_status |
subject.reference |
pharmacy_orders.patient_id |
encounter.reference |
pharmacy_orders.encounter_id |
requester.reference |
pharmacy_orders.ordering_provider_id |
medicationCodeableConcept.coding[rxnorm].code |
pharmacy_orders.drug_code_rxnorm |
medicationCodeableConcept.text |
pharmacy_orders.drug_name |
dosageInstruction[0].doseAndRate[0].doseQuantity.value |
pharmacy_orders.dose |
dosageInstruction[0].doseAndRate[0].doseQuantity.code |
pharmacy_orders.dose_unit |
dosageInstruction[0].route.coding[0].code |
pharmacy_orders.route (mapped) |
dosageInstruction[0].timing.repeat |
pharmacy_orders.frequency (coded) |
dispenseRequest.expectedSupplyDuration.value |
pharmacy_orders.duration_days |
Sample Outbound MedicationDispense (PIS → CPOE)
{
"resourceType": "MedicationDispense",
"id": "DISP-20260207-000789",
"status": "completed",
"medicationCodeableConcept": {
"coding": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"code": "314076",
"display": "Lisinopril 10 MG Oral Tablet"
}
]
},
"subject": {
"reference": "Patient/2026009876"
},
"context": {
"reference": "Encounter/ENC2026020700456"
},
"authorizingPrescription": [
{
"reference": "MedicationRequest/ORD-20260207-000123"
}
],
"quantity": {
"value": 90,
"unit": "tablet"
},
"whenHandedOver": "2026-02-07T11:05:00+04:00",
"performer": [
{
"actor": {
"reference": "Practitioner/ALI-FATIMA",
"display": "Fatima Omar Ali, RPh"
}
}
]
}
Search Parameters (PIS as FHIR server for CPOE)
GET /MedicationRequest?patient={id}&status=active– active orders for a patient.GET /MedicationDispense?authorizingPrescription={order-id}– dispensing history for an order.GET /DetectedIssue?implicated=MedicationRequest/{id}– pharmacist interventions for an order.
Error Handling (INT-PIS-001)
| Scenario | Handling | Retry / Alert |
|---|---|---|
| Network timeout (HL7 or FHIR) | Message persisted in integration_message_log with status pending; not acknowledged to source |
Exponential backoff: 30s, 1m, 2m, 5m, 10m; after 5 failures, raise alert to integration support and pharmacy supervisor |
HL7 negative ACK (AE/AR) from PIS or CPOE |
Log full message + ACK; mark as error; no auto-retry |
Manual review via integration console; corrected order can be re-sent with same order_id |
| FHIR 4xx from either side | Validation error; parse OperationOutcome and store |
No auto-retry; show error in UI (if synchronous) or integration dashboard |
| FHIR 5xx | Temporary remote failure | Same exponential backoff as above; after 15 minutes continuous failure, send email/SMS to on-call |
Duplicate order (same order_id) |
Idempotent processing: ignore if already processed with same payload hash | Logged as duplicate for audit |
| Message parsing error | Store raw payload; mark as parse_error |
No retry; manual fix required |
Manual recovery: integration admin can requeue failed messages from integration_message_log by ID; all replays must be audit-logged (user, timestamp, reason) for ADHICS compliance.
Retry and Recovery
Retry Strategy
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| HL7 MLLP timeout (no ACK) | 30s, 1m, 2m, 5m, 10m | 5 | Exponential with jitter | Move to DLQ; alert pharmacy supervisor + integration support |
| FHIR 5xx (server error) | 30s, 1m, 2m, 5m, 10m | 5 | Exponential with jitter | Move to DLQ; alert on-call support |
| FHIR 429 (rate limited) | Respect Retry-After header; default 60s |
10 | Per server directive | Move to DLQ; review rate limits with CPOE team |
HL7 negative ACK (AE/AR) |
No auto-retry | 0 | N/A | Log error; manual review in integration console |
| FHIR 4xx (validation error) | No auto-retry | 0 | N/A | Log OperationOutcome; manual correction required |
| Message parse error | No auto-retry | 0 | N/A | Store raw payload; alert integration team |
Dead Letter Queue
Failed messages are written to the integration_dlq table:
| Column | Value |
|---|---|
source_system |
CPOE or PIS (depending on direction) |
message_type |
RDE^O11, MedicationRequest, MedicationDispense, DetectedIssue |
failure_reason |
Timeout, negative ACK code, HTTP status, parse error description |
retry_count |
Number of attempts before DLQ entry |
raw_payload |
Full message content (HL7 or FHIR JSON) |
created_at |
Timestamp of DLQ entry |
resolved_at |
NULL until manually resolved |
resolved_by |
User ID of admin who resolved |
DLQ review cadence: every 4 hours during pharmacy operating hours; critical items (STAT orders, interventions) reviewed within 30 minutes.
Idempotency
- Inbound (CPOE to PIS): Deduplication key =
ORC-2(placer order number) +ORC-1(order control) +MSH-10(message control ID). If a message with the sameORC-2and matching payload hash already exists inpharmacy_orders, the duplicate is logged and discarded. - Outbound (PIS to CPOE): Deduplication key =
[dispensing_id]_[message_type]_[event_datetime]. CPOE must ignore duplicate status updates with the same composite key.
Reconciliation
- Hourly: Automated count comparison — orders received in CPOE (
ORC-1 = NW) vs. orders present inpharmacy_ordersfor the same hour window. - Daily: Full reconciliation report comparing CPOE order IDs with PIS verification/dispensing status; unmatched orders flagged for investigation.
- Post-outage: PIS requests a FHIR
MedicationRequest?_lastUpdated=gt[outage_start]query to CPOE to retrieve any orders missed during downtime.
INT-PIS-002: EHR (Patient Chart)
Business Context
What flows
- Active and historical medication list (orders + dispenses).
- eMAR records (actual administrations, holds, refusals, PRN responses).
- Pharmacy notes/interventions relevant to the patient chart.
When
- On each dispense, administration, reconciliation, or order status change.
- On-demand when EHR requests latest medication timeline.
Why
- Provides clinicians a consolidated view of medications in the EHR.
- Supports clinical decision-making and continuity of care.
- Required for NABIDH/Malaffi-aligned longitudinal medication history.
How often
- Real-time event push + on-demand queries.
Error impact
- If updates fail, EHR medication list may be stale; risk of duplicate therapy or missed doses.
- Must be clearly indicated in EHR UI if medication data is not current.
Technical Detail (Internal API + FHIR)
No HL7 v2 here; internal REST/FHIR.
Primary Resources
MedicationRequest– order-level view.MedicationDispense– dispensing events.MedicationAdministration– eMAR.MedicationStatement– reconciled/home meds.Annotation– pharmacy notes (embedded).
Sample MedicationAdministration (PIS → EHR)
{
"resourceType": "MedicationAdministration",
"id": "ADMIN-20260207-001234",
"status": "completed",
"medicationCodeableConcept": {
"coding": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"code": "314076",
"display": "Lisinopril 10 MG Oral Tablet"
}
]
},
"subject": {
"reference": "Patient/2026009876",
"display": "Ahmed Hassan Al-Maktoum"
},
"context": {
"reference": "Encounter/ENC2026020700456"
},
"effectiveDateTime": "2026-02-07T09:00:00+04:00",
"performer": [
{
"actor": {
"reference": "Practitioner/NURSE-001",
"display": "Nurse Aisha Al-Nahyan"
}
}
],
"dosage": {
"route": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "26643006",
"display": "Oral route"
}
]
},
"dose": {
"value": 10,
"unit": "mg",
"system": "http://unitsofmeasure.org",
"code": "mg"
}
},
"request": {
"reference": "MedicationRequest/ORD-20260207-000123"
},
"note": [
{
"text": "Barcode verified; patient tolerated well."
}
]
}
Mapping to PIS Tables
| FHIR Element | PIS Table.Column |
|---|---|
id |
medication_administration.admin_id |
status |
medication_administration.status |
subject.reference |
medication_administration.patient_id |
context.reference |
medication_administration.encounter_id |
effectiveDateTime |
medication_administration.actual_datetime |
dosage.dose.value |
medication_administration.dose_given |
dosage.route |
medication_administration.route |
performer.actor |
medication_administration.administered_by |
note[0].text |
medication_administration.notes (additional column) |
Search Parameters (EHR → PIS)
GET /MedicationAdministration?patient={id}&date=ge2026-02-01GET /MedicationRequest?patient={id}&status=activeGET /MedicationStatement?patient={id}– reconciled/home meds.
Error Handling (INT-PIS-002)
- Internal API calls are synchronous; if PIS is unavailable, EHR shows an inline error and may retry after 5–10 seconds.
- Event pushes (webhooks or message bus) use the same retry/backoff pattern as INT-PIS-001.
- Dead-letter queue for events that fail >5 times; visible in integration console.
- Manual reconciliation: EHR can request a full medication sync for a patient (
/MedicationAdministration?patient=...&_since=...) after outages.
Retry and Recovery
Retry Strategy
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| Synchronous API timeout (EHR → PIS query) | 5s, 10s | 2 | Linear | Show inline error in EHR UI; user can retry manually |
| Event push failure (PIS → EHR webhook/bus) | 30s, 1m, 2m, 5m, 10m | 5 | Exponential with jitter | Move to DLQ; alert integration support |
| Event push 5xx from EHR | 30s, 1m, 2m, 5m, 10m | 5 | Exponential with jitter | Move to DLQ |
| Event push 4xx (validation) | No auto-retry | 0 | N/A | Log; manual correction; alert integration team |
Dead Letter Queue
Failed event pushes are written to integration_dlq:
| Column | Value |
|---|---|
source_system |
PIS |
target_system |
EHR |
message_type |
MedicationDispense, MedicationAdministration, MedicationStatement |
failure_reason |
Timeout, HTTP error code, validation error |
raw_payload |
FHIR resource JSON |
DLQ review cadence: every 4 hours; critical medication administration events reviewed within 1 hour.
Idempotency
- Event push deduplication key =
[resource_type]_[resource_id]_[lastUpdated]. EHR discards events where the resource version is older than or equal to the currently stored version. - Synchronous queries are inherently idempotent (read-only GET requests).
Reconciliation
- Post-outage: EHR triggers a full medication sync per patient using
GET /MedicationAdministration?patient={id}&_since={outage_start}andGET /MedicationDispense?patient={id}&_since={outage_start}. - Daily: Automated comparison of
pharmacy_dispensingrecords vs. EHRMedicationDispenseresources for the past 24 hours; discrepancies flagged in integration dashboard.
INT-PIS-003: LIS (Antimicrobial Stewardship)
Business Context
What flows
- Inbound from LIS: culture and sensitivity results, organism, MIC, susceptibility (S/I/R).
- Outbound from PIS: antimicrobial orders, stewardship review linkage, recommendations.
When
- Inbound: when LIS finalizes culture/sensitivity results.
- Outbound: when antimicrobial orders are placed or stewardship reviews are recorded.
Why
- Supports antimicrobial stewardship pharmacists in optimizing therapy, reducing resistance, and meeting facility and MOH quality expectations.
How often
- Real-time; moderate volume.
Error impact
- Missing culture data → delayed de-escalation, prolonged broad-spectrum use.
- Missing outbound stewardship data → incomplete audit trail and metrics.
Technical Detail (Internal API)
Typical pattern: JSON over HTTPS between PIS and LIS/stewardship engine.
Example Inbound Culture Result (LIS → PIS)
{
"cultureResultId": "CULT-20260207-00045",
"patientId": "2026009876",
"encounterId": "ENC2026020700456",
"specimen": "Blood",
"collectionDateTime": "2026-02-06T22:15:00+04:00",
"organisms": [
{
"code": "112283007",
"system": "http://snomed.info/sct",
"display": "Escherichia coli",
"susceptibilities": [
{
"antibioticRxNorm": "197361",
"antibioticName": "Ceftriaxone",
"mic": "0.5",
"interpretation": "S"
},
{
"antibioticRxNorm": "36567",
"antibioticName": "Ciprofloxacin",
"mic": "4",
"interpretation": "R"
}
]
}
],
"status": "final"
}
Mapping
cultureResultId→antimicrobial_stewardship_reviews.culture_result_idpatientId→antimicrobial_stewardship_reviews.patient_id- Organism/susceptibility stored in a LIS-owned schema or a shared stewardship schema (not in PIS core tables).
Example Outbound Stewardship Review (PIS → LIS / Analytics)
{
"reviewId": "AST-20260207-00012",
"orderId": "ORD-20260207-000555",
"patientId": "2026009876",
"antibioticRxNorm": "197361",
"reviewType": "de-escalation",
"indication": "Urosepsis",
"cultureResultId": "CULT-20260207-00045",
"recommendation": "De-escalate from meropenem to ceftriaxone based on susceptibility.",
"accepted": true,
"reviewedBy": "PHARM-AST-001",
"reviewedDateTime": "2026-02-07T11:30:00+04:00",
"prescriberResponse": "Accepted; order changed to ceftriaxone."
}
Maps directly to antimicrobial_stewardship_reviews table.
Error Handling (INT-PIS-003)
- If LIS push fails, LIS queues and retries; PIS logs inbound failures.
- If PIS push of stewardship review fails, messages are queued with backoff; stewardship dashboard shows “pending export” status.
- No data loss allowed; all culture IDs and review IDs must be idempotent.
Retry and Recovery
Retry Strategy
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| LIS → PIS push failure (culture result) | 30s, 1m, 2m, 5m | 5 | Exponential with jitter | Move to DLQ on LIS side; alert LIS integration support + stewardship pharmacist |
| PIS → LIS push failure (stewardship review) | 30s, 1m, 2m, 5m | 5 | Exponential with jitter | Move to DLQ on PIS side; stewardship dashboard shows "pending export" |
| REST API timeout (either direction) | 10s, 20s, 40s | 3 | Exponential | Move to DLQ; alert integration team |
| 4xx validation error | No auto-retry | 0 | N/A | Log error; manual review; alert integration team |
Dead Letter Queue
| Column | Value |
|---|---|
source_system |
LIS (for inbound culture results) or PIS (for outbound stewardship reviews) |
message_type |
DiagnosticReport (culture), stewardship_review_notification |
failure_reason |
Timeout, HTTP error, validation failure |
raw_payload |
FHIR JSON or internal API payload |
DLQ review cadence: every 2 hours (culture results are clinically time-sensitive for antimicrobial stewardship decisions).
Idempotency
- Inbound culture results: Deduplication key =
[diagnostic_report_id]_[result_status]_[last_updated]. Duplicate results with same report ID and version are discarded; updated results (amended/final) replace prior preliminary data. - Outbound stewardship reviews: Deduplication key =
[stewardship_review_id]_[review_status]. LIS ignores duplicate notifications for the same review at the same status.
Reconciliation
- Every 6 hours: PIS queries LIS for finalized culture reports for patients with active antimicrobial orders (
GET /DiagnosticReport?category=microbiology&status=final&date=gt{6h_ago}); any missing reports are flagged. - Daily: Cross-reference
antimicrobial_stewardship_reviewswith LIS culture result log to ensure all positive cultures with active antimicrobial orders have been reviewed.
INT-PIS-004: Billing & Claims
Business Context
What flows
- Chargeable dispensing events with: patient, encounter, payer, drug (RxNorm + NDC if available), quantity, unit cost, total cost, charge code (CPT/HCPCS or internal), and flags for controlled substances.
When
- Each time a medication is dispensed (inpatient or outpatient).
Why
- Enables accurate pharmacy revenue capture and integration with eClaimLink (DHA) / DOH eClaims via the billing module.
- Supports cost analytics and stock valuation.
How often
- Real-time; high volume.
Error impact
- Failed charges → revenue leakage, manual reconciliation.
- Duplicate charges → claim rejections, patient complaints.
HL7 v2.5.1 Technical Detail
Message Type: DFT^P03 (Detailed Financial Transaction)
Sample DFT^P03 (PIS → Billing)
MSH|^~\&|PIS|DUBAIHOSP|BILLING|DUBAIHOSP|20260207111530+0400||DFT^P03|DFT20260207111530001|P|2.5.1|||AL|NE||UTF-8
EVN|P03|20260207111530+0400
PID|1||2026009876^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID||AL-MAKTOUM^AHMED^HASSAN||19850315|M
PV1|1|I|4B^412^01^DUBAIHOSP||||KHAN^SARA^A^^^DR|||MED||||||||ENC2026020700456
FT1|1|20260207111000+0400|20260207111000+0400|CG|RX^Pharmacy charge^C4|DISP-20260207-000321|314076^Lisinopril 10 MG Oral Tablet^RXNORM|2|TAB^Tablet^UCUM|5.00|10.00|AED^UAE Dirham^ISO4217|||PHARM-TECH-001^HASSAN^OMAR^^^TECH|PHARM^Inpatient Pharmacy^DUBAIHOSP|||NDC12345678
ZPH|DISP-20260207-000321|ORD-20260207-000123|10.00|5.00|unit_cost
Key Segment Notes
FT1-6: Transaction typeCG(charge).FT1-7: Transaction ID =pharmacy_dispensing.dispensing_id.FT1-8: RxNorm-coded drug.FT1-9: Quantity dispensed.FT1-11/FT1-12: Unit price and total amount.FT1-13: Currency (AED).- Custom
ZPHsegment carries additional pharmacy-specific data (order_id, unit_cost).
Mapping
| HL7 Field | PIS Table.Column |
|---|---|
FT1-7 |
pharmacy_dispensing.dispensing_id |
FT1-8.1 |
pharmacy_dispensing.drug_code_rxnorm |
FT1-9 |
pharmacy_dispensing.quantity_dispensed |
FT1-11 |
pharmacy_dispensing.unit_cost |
FT1-12 |
computed total cost |
FT1-16 |
pharmacy_dispensing.dispensed_by |
ZPH-2 |
pharmacy_orders.order_id |
Error Handling (INT-PIS-004)
- If billing system is down, DFT messages are queued; no user-facing error in pharmacy UI.
- Duplicate detection by
FT1-7(dispensing_id) on billing side. - Reconciliation report compares
pharmacy_dispensingvs. accepted charges daily.
Retry and Recovery
Retry Strategy
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| HL7 MLLP timeout (DFT) | 30s, 1m, 2m, 5m, 10m | 5 | Exponential with jitter | Move to DLQ; alert revenue cycle team |
HL7 negative ACK (AE/AR) |
No auto-retry | 0 | N/A | Log; manual review in integration console |
| Internal API timeout | 10s, 20s | 2 | Linear | Move to DLQ; alert integration support |
| Billing system unavailable (planned maintenance) | Queue all DFT messages; resume on recovery | N/A | N/A | Drain queue in FIFO order on recovery; alert if queue > 1000 messages |
Dead Letter Queue
| Column | Value |
|---|---|
source_system |
PIS |
target_system |
BILLING |
message_type |
DFT^P03 |
failure_reason |
Timeout, negative ACK code, billing validation error |
raw_payload |
Full HL7 DFT message |
DLQ review cadence: every 4 hours during business hours. Revenue integrity team reviews daily for completeness.
Idempotency
- Deduplication key =
FT1-7(dispensing_id). Billing system rejects duplicate charges with the same dispensing_id; returnsAEwith duplicate indicator. - Credit/reversal messages use
FT1-6 = CRwith the originalFT1-7to reverse prior charges.
Reconciliation
- Daily: Automated reconciliation report compares
pharmacy_dispensing(all records withstatus = DISPENSEDfor the day) against accepted charges in billing. Unmatched dispensing records are flagged for resubmission. - Monthly: Revenue integrity review compares total drug cost from
pharmacy_dispensingagainst total pharmacy charges posted in billing for the month; variance > 1% triggers investigation. - Post-outage: PIS replays all queued DFT messages in chronological order; billing system deduplicates using
FT1-7.
INT-PIS-005: NABIDH (Dubai HIE)
Business Context
What flows
- Outbound reporting of medication dispensing events and current medication list for Dubai-licensed facilities, per NABIDH pharmacy profile.
When
- Each time a medication is dispensed for a patient whose encounter is in a NABIDH-participating Dubai facility.
Why
- Supports cross-facility medication reconciliation and safety.
- Required by DHA NABIDH policies for connected providers.
How often
- Near real-time; messages buffered and sent within minutes.
Error impact
- Failed submissions reduce HIE completeness; KPI “NABIDH/Malaffi Dispensing Submission Rate” must remain ≥ 99.5%.
- Facility must be able to demonstrate retry and error management to DHA.
HL7 v2.5.1 Technical Detail (NABIDH Profile)
Message Type: Typically RDE^O11 or RDS^O13-like profile for dispenses; exact profile per NABIDH spec. Here we model as RDE^O11 with dispense context.
Sample Message (PIS → NABIDH)
MSH|^~\&|PIS|DUBAIHOSP|NABIDH|DHA|20260207113000+0400||RDE^O11|NABIDH20260207113000001|P|2.5.1|||AL|NE||UTF-8
PID|1||2026009876^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID||AL-MAKTOUM^AHMED^HASSAN||19850315|M|||PO BOX 12345^^DUBAI^^00000^AE||+971501234567
PV1|1|O|OPD^PHARM^01^DUBAIHOSP||||KHAN^SARA^A^^^DR|||OPD||||||||ENC2026020700789
ORC|RE|ORD-20260207-000789^HIS_CPOE|ORD-20260207-000789^PIS||CM|||^^^20260207112500+0400^^R|20260207112500+0400|||ALI^FATIMA^OMAR^^^PHARM^RPh
RXE|1|500|mg^milligram^UCUM|202531^Amoxicillin 500 MG Oral Capsule^RXNORM|PO^Oral^HL70162|TID^Three times daily^HL70335|||21|CAP^Capsule^UCUM|20260207112500+0400|||A|N|||J02.9^Acute pharyngitis^ICD10AM
RXD|1|20260207112500+0400|202531^Amoxicillin 500 MG Oral Capsule^RXNORM|21|CAP^Capsule^UCUM||ALI^FATIMA^OMAR^^^PHARM^RPh||LOT12345|20270201|DUBAIHOSP^Main Pharmacy^DUBAIHOSP
NABIDH Requirements (Conceptual)
- Emirates ID in
PID-3orPID-18as per NABIDH profile. - Facility and provider identifiers aligned with DHA master codes.
- Use RxNorm for medications; ICD-10-AM for indications.
- TLS 1.2+ with DHA-issued mTLS certificates.
- HL7 ACK handling: PIS must process
ACKand updateintegration_message_log.hie_submission_status.
Mapping
- Same as internal RDE, plus:
RXDsegment fields map topharmacy_dispensing(lot, expiry, location).integration_message_logtracksmessage_control_id,hie_submission_status,hie_submission_datetime.
Error Handling (INT-PIS-005)
- If NABIDH connection fails, messages remain in an outbound queue with status
pending_hie. - Retry schedule: every 5 minutes for 1 hour, then hourly for 24 hours.
- After 24 hours, mark as
failed_hieand alert IT + compliance. - Negative ACKs (
AE/AR) logged with reason; no auto-retry unless error is transient (e.g.,ARdue to temporary validation service outage). - KPI “NABIDH/Malaffi Dispensing Submission Rate” computed from
integration_message_log.
Retry and Recovery
Retry Strategy
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| MLLP connection timeout | 5m, 5m, 5m, 5m, 5m, 5m, 5m, 5m, 5m, 5m, 5m, 5m | 12 (1 hour) | Fixed 5-min interval | Switch to hourly retry for 24 hours |
| Hourly retry (post-1-hour failure) | 1h intervals | 24 | Fixed 1-hour interval | Mark as failed_hie; alert IT + compliance team |
HL7 negative ACK (AE) — transient |
5m, 10m, 15m | 3 | Linear | Move to DLQ; manual review |
HL7 negative ACK (AR) — permanent rejection |
No auto-retry | 0 | N/A | Log rejection reason; manual correction required |
| TLS/certificate error | No auto-retry | 0 | N/A | Alert IT security; certificate renewal required |
Dead Letter Queue
| Column | Value |
|---|---|
source_system |
PIS |
target_system |
NABIDH |
message_type |
HL7 pharmacy dispensing message (NABIDH profile) |
failure_reason |
Connection timeout, negative ACK code/reason, TLS error |
raw_payload |
Full HL7 message |
nabidh_submission_id |
NABIDH-assigned submission ID (if received before failure) |
DLQ review cadence: every 2 hours. Compliance team notified if any messages remain in DLQ > 24 hours (regulatory SLA risk).
Idempotency
- Deduplication key =
[dispensing_id]_[message_type]_[event_datetime]. NABIDH gateway processes each unique dispensing event once; duplicate submissions return an ACK with duplicate indicator. - Resubmissions after correction use a new
MSH-10(message control ID) but retain the originaldispensing_idfor NABIDH to match and update.
Reconciliation
- Daily: Compare
pharmacy_dispensingrecords for the day againstintegration_message_logentries withtarget_system = NABIDHandstatus = acknowledged. Any dispensing records without a corresponding acknowledged NABIDH submission are requeued. - Weekly: NABIDH submission rate KPI reviewed by compliance team; target > 99% within 24 hours.
- Post-outage: Bulk resubmission of all
pending_hieandfailed_hiemessages in chronological order with rate limiting to avoid overwhelming NABIDH gateway.
INT-PIS-006: Malaffi (Abu Dhabi HIE)
Business Context
Similar to NABIDH but for DOH Abu Dhabi’s Malaffi HIE, with DOH-specific profiles and facility/provider codes.
What flows
- Medication dispensing events and medication list for Abu Dhabi encounters.
When
- On each dispense in an Abu Dhabi DOH-licensed facility.
Why
- DOH Malaffi participation requirement; supports cross-facility care.
How often
- Near real-time.
Error impact
- Same as NABIDH; monitored jointly via the shared KPI.
HL7 v2.5.1 Technical Detail (Malaffi Profile)
Message Type: RDE^O11 or Malaffi-specific pharmacy profile.
Sample Message (PIS → Malaffi)
MSH|^~\&|PIS|ABUDHABIHOSP|MALAFFI|DOH|20260207114500+0400||RDE^O11|MALAFFI20260207114500001|P|2.5.1|||AL|NE||UTF-8
PID|1||2026012345^^^ABUDHABIHOSP^MR~784-1990-7654321-3^^^AE^EID||AL-NAHYAN^FATIMA^MOHAMMED||19900320|F|||PO BOX 67890^^ABU DHABI^^00000^AE||+971502223344
PV1|1|O|OPD^PHARM^01^ABUDHABIHOSP||||OMAR^KHALID^Y^^^DR|||OPD||||||||ENC2026020700999
ORC|RE|ORD-20260207-001234^HIS_CPOE|ORD-20260207-001234^PIS||CM|||^^^20260207114000+0400^^R|20260207114000+0400|||ALI^FATIMA^OMAR^^^PHARM^RPh
RXE|1|20|mg^milligram^UCUM|617314^Omeprazole 20 MG Delayed Release Capsule^RXNORM|PO^Oral^HL70162|QD^Once daily^HL70335|||30|CAP^Capsule^UCUM|20260207114000+0400|||A|N|||K21.9^Gastro-oesophageal reflux disease^ICD10AM
RXD|1|20260207114000+0400|617314^Omeprazole 20 MG Delayed Release Capsule^RXNORM|30|CAP^Capsule^UCUM||TECH-002^YOUSEF^ALI^^^TECH||LOT67890|20280131|ABUDHABIHOSP^Main Pharmacy^ABUDHABIHOSP
Malaffi Requirements (Conceptual)
- DOH facility and provider codes in
MSH-4,PV1-7. - ADHICS-compliant logging and encryption.
- mTLS with DOH-issued certificates; IP whitelisting.
Error handling mirrors NABIDH.
Retry and Recovery
Retry Strategy
Mirrors INT-PIS-005 (NABIDH) with Malaffi-specific parameters:
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| MLLP connection timeout | 5m intervals | 12 (1 hour) | Fixed 5-min interval | Switch to hourly retry for 24 hours |
| Hourly retry (post-1-hour failure) | 1h intervals | 24 | Fixed 1-hour interval | Mark as failed_hie; alert IT + compliance team |
HL7 negative ACK (AE) — transient |
5m, 10m, 15m | 3 | Linear | Move to DLQ; manual review |
HL7 negative ACK (AR) — permanent rejection |
No auto-retry | 0 | N/A | Log rejection reason; manual correction required |
| TLS/certificate error (DOH-issued cert) | No auto-retry | 0 | N/A | Alert IT security; coordinate with DOH for certificate renewal |
Dead Letter Queue
| Column | Value |
|---|---|
source_system |
PIS |
target_system |
MALAFFI |
message_type |
HL7 pharmacy dispensing message (Malaffi profile) |
failure_reason |
Connection timeout, negative ACK code/reason, TLS/cert error |
raw_payload |
Full HL7 message |
DLQ review cadence: every 2 hours. Compliance team notified if messages remain in DLQ > 24 hours. All DLQ operations logged per ADHICS requirements.
Idempotency
- Deduplication key =
[dispensing_id]_[message_type]_[event_datetime]. Malaffi gateway deduplicates on the same basis as NABIDH. - DOH facility code and provider code in
MSH-4andPV1-7must match registered values; mismatches causeARrejection (not retryable without correction).
Reconciliation
- Daily: Compare
pharmacy_dispensingrecords againstintegration_message_logentries withtarget_system = MALAFFIandstatus = acknowledged. Requeue any unsubmitted records. - Weekly: Malaffi submission rate KPI reviewed by compliance team; target > 99% within 24 hours.
- Post-outage: Bulk resubmission with rate limiting; all replay operations ADHICS-logged (user, timestamp, reason, message count).
INT-PIS-007: UAE MOH (Controlled Substances)
Business Context
What flows
- Monthly batch reports of all controlled substance transactions (dispense, return, waste, adjustment) with chain-of-custody.
- Event-driven discrepancy reports (loss, suspected diversion).
When
- Monthly, on a configured schedule (e.g., 3rd of month for prior month).
- Immediately when a discrepancy is finalized in
controlled_substance_log.
Why
- Compliance with UAE MOH controlled substance regulations (Federal Law No. 14 of 1995 and amendments).
- Supports audits and investigations.
How often
- Monthly batch + low-volume event-driven.
Error impact
- Failed submissions may put facility at regulatory risk; must be detected and corrected before MOH deadlines.
Technical Detail (File-Based / Portal)
Batch File Content (CSV Example)
Each row corresponds to a controlled substance transaction.
log_id,facility_code,drug_rxnorm,drug_name,controlled_schedule,transaction_type,quantity,balance_after,from_user,to_user,witness_id,patient_mrn,patient_eid,waste_amount,location,transaction_datetime,discrepancy_flag,discrepancy_reason
CS-202602-000001,DH-DUBAIHOSP,865098,Tramadol 50 MG Oral Capsule,III,DISPENSE,10,90,PHARM-VAULT,NURSE-001,NURSE-002,2026009876,784-1985-1234567-1,0,4B-412,2026-02-01T10:15:00+04:00,N,
CS-202602-000250,DH-DUBAIHOSP,865098,Tramadol 50 MG Oral Capsule,III,WASTE,2,88,NURSE-001,PHARM-VAULT,NURSE-003,2026009876,784-1985-1234567-1,2,4B-412,2026-02-05T09:00:00+04:00,N,
CS-202602-000400,DH-DUBAIHOSP,865098,Tramadol 50 MG Oral Capsule,III,ADJUSTMENT,-5,83,PHARM-VAULT,,SUP-001,,,0,VAULT-01,2026-02-10T18:30:00+04:00,Y,Stock count discrepancy
Mapping
| CSV Column | PIS Table.Column |
|---|---|
log_id |
controlled_substance_log.log_id |
drug_rxnorm |
controlled_substance_log.drug_code_rxnorm |
controlled_schedule |
controlled_substance_log.controlled_schedule |
transaction_type |
controlled_substance_log.transaction_type |
quantity |
controlled_substance_log.quantity |
balance_after |
controlled_substance_log.balance_after |
from_user |
controlled_substance_log.from_user |
to_user |
controlled_substance_log.to_user |
witness_id |
controlled_substance_log.witness_id |
patient_mrn/patient_eid |
controlled_substance_log.patient_id (via patient master) |
waste_amount |
controlled_substance_log.waste_amount |
location |
controlled_substance_log.location |
transaction_datetime |
controlled_substance_log.transaction_datetime |
discrepancy_flag |
derived from transaction_type and reconciliation logic |
Files are transferred via SFTP over VPN to MOH or uploaded via MOH portal; exact format will follow MOH specification.
Error Handling (INT-PIS-007)
- Batch generation failures logged and alerted to pharmacy supervisor and compliance.
- SFTP transfer failures retried every 30 minutes until success or until MOH deadline minus 24 hours, then escalated.
- Portal upload failures require manual retry; system logs export file hash and timestamp for audit.
- Discrepancy events that fail to send are queued and retried every 10 minutes; if still failing after 2 hours, on-call pharmacist notified.
Retry and Recovery
Retry Strategy
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| SFTP connection failure (monthly batch) | 30m, 30m, 30m, 30m | 4 (2 hours) | Fixed 30-min interval | Alert pharmacy supervisor + compliance; switch to manual MOH portal upload |
| SFTP authentication failure | No auto-retry | 0 | N/A | Alert IT security; key/credential renewal required |
| SFTP transfer interrupted (partial upload) | Restart from beginning (new SFTP session) | 3 | 15m intervals | Alert IT; manual upload via MOH portal |
| MOH portal upload failure | Manual retry by pharmacist | N/A | N/A | Log attempt; escalate to compliance if deadline approaching |
| Discrepancy event push failure | 10m intervals | 12 (2 hours) | Fixed 10-min interval | Alert on-call pharmacist + pharmacy director; log for manual follow-up |
| Batch report generation failure | Immediate re-run | 2 | 5m interval | Alert pharmacy supervisor; manual data extraction if system issue persists |
Dead Letter Queue
| Column | Value |
|---|---|
source_system |
PIS |
target_system |
MOH_CONTROLLED |
message_type |
monthly_batch_report or discrepancy_event |
failure_reason |
SFTP error, generation failure, portal upload error |
raw_payload |
Report file content (CSV/XML) or discrepancy event data |
file_hash |
SHA-256 hash of the report file for integrity verification |
DLQ review cadence: immediately for discrepancy events; daily for batch reports. Compliance team notified of any unresolved items.
Idempotency
- Monthly batch reports: Each report is identified by
[report_period]_[facility_id]_[generation_datetime]. Resubmission of the same report period replaces the prior submission at the MOH level. - Discrepancy events: Deduplication key =
[discrepancy_id]_[event_type]_[event_datetime]. MOH system accepts updates to existing discrepancy IDs. - File hash (
SHA-256) is computed before transmission and stored inintegration_message_log; retransmitted files must match the original hash.
Reconciliation
- Monthly: After successful batch transmission, PIS compares the count of controlled substance transactions in
controlled_substance_logfor the reporting period against the row count in the transmitted CSV/XML file. Any mismatch triggers a re-generation and resubmission. - Post-failure: If SFTP fails and manual portal upload is used, pharmacist uploads the system-generated file (same hash) and logs the manual submission with timestamp and confirmation number in
integration_message_log. - Annual audit: Full year reconciliation of
controlled_substance_logagainst MOH-acknowledged submissions; discrepancies documented and resolved before regulatory review.
INT-PIS-008: Patient Portal
Business Context
What flows
- Patient-facing medication list (current and recent).
- Refill status and eligibility for outpatient prescriptions.
- Patient-friendly instructions (English/Arabic).
When
- On-demand when patient opens medication section in portal.
- Event-driven updates when a new dispense occurs or refill becomes available.
Why
- Supports patient engagement, adherence, and PDPL-compliant access to personal data.
- Reduces calls to pharmacy for routine queries.
How often
- On-demand + low-volume event push.
Error impact
- If unavailable, portal should clearly indicate that medication data is temporarily unavailable; no clinical risk but impacts patient experience.
FHIR R4 Technical Detail
Portal acts as FHIR client; PIS (or EHR) exposes FHIR server.
Resources
MedicationRequest– prescriptions.MedicationDispense– fills and refills.MedicationStatement– reconciled/home meds.
Sample MedicationRequest for Portal
{
"resourceType": "MedicationRequest",
"id": "RX-20260207-000999",
"status": "active",
"intent": "order",
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/medicationrequest-category",
"code": "outpatient"
}
]
}
],
"medicationCodeableConcept": {
"coding": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"code": "617314",
"display": "Omeprazole 20 MG Delayed Release Capsule"
}
],
"text": "Omeprazole 20mg Capsule"
},
"subject": {
"reference": "Patient/2026012345",
"display": "Fatima Mohammed Al-Nahyan"
},
"authoredOn": "2026-02-07",
"dosageInstruction": [
{
"text": "Take one capsule by mouth once daily before breakfast",
"patientInstruction": "تناول كبسولة واحدة عن طريق الفم مرة يومياً قبل الإفطار"
}
],
"dispenseRequest": {
"numberOfRepeatsAllowed": 2,
"quantity": {
"value": 30,
"unit": "capsule"
},
"expectedSupplyDuration": {
"value": 30,
"unit": "days",
"system": "http://unitsofmeasure.org",
"code": "d"
}
}
}
Sample MedicationDispense (Refill Status)
{
"resourceType": "MedicationDispense",
"id": "DISP-20260207-001000",
"status": "completed",
"medicationCodeableConcept": {
"coding": [
{
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
"code": "617314",
"display": "Omeprazole 20 MG Delayed Release Capsule"
}
]
},
"subject": {
"reference": "Patient/2026012345"
},
"authorizingPrescription": [
{
"reference": "MedicationRequest/RX-20260207-000999"
}
],
"quantity": {
"value": 30,
"unit": "capsule"
},
"whenHandedOver": "2026-02-07T12:00:00+04:00"
}
Search Parameters (Portal → PIS/EHR)
GET /MedicationRequest?patient={id}&status=activeGET /MedicationDispense?patient={id}&_sort=-whenHandedOverGET /MedicationStatement?patient={id}
Error Handling (INT-PIS-008)
- Portal uses OAuth 2.0; if token invalid, returns 401/403; no PHI leakage.
- If FHIR server unavailable, portal shows “Medication data temporarily unavailable” and logs error.
- No retries on user-initiated GET; user can refresh manually.
- Event push failures (if used) follow the standard backoff/queue pattern.
Retry and Recovery
Retry Strategy
| Failure Type | Retry Interval | Max Attempts | Backoff | Final Action |
|---|---|---|---|---|
| Patient-initiated GET timeout (FHIR server) | No auto-retry | 0 | N/A | Portal displays "Medication data temporarily unavailable"; user can refresh |
| OAuth 2.0 token expired (401) | Automatic token refresh via refresh_token | 1 | Immediate | If refresh fails, redirect to login; log session expiry |
| OAuth 2.0 forbidden (403) | No retry | 0 | N/A | Display "Access denied"; log for security review |
| Event push failure (PIS → Portal notification) | 30s, 1m, 2m, 5m | 4 | Exponential | Move to DLQ; notification delivered on next patient login |
| FHIR server 5xx | Circuit breaker: open after 5 failures in 60s; half-open after 30s | Per circuit breaker | N/A | Portal shows cached data (if available) or graceful error |
Circuit Breaker (FHIR Server Availability)
| State | Condition | Behavior |
|---|---|---|
| CLOSED | < 5 failures in 60-second window | Normal operation; all requests pass through |
| OPEN | >= 5 failures in 60-second window | All requests immediately return cached response or "temporarily unavailable" |
| HALF-OPEN | 30 seconds after circuit opened | Allow 1 probe request; if successful, close circuit; if failed, reopen |
Dead Letter Queue (Event Push Only)
| Column | Value |
|---|---|
source_system |
PIS |
target_system |
PATIENT_PORTAL |
message_type |
medication_dispensed_notification, refill_available_notification |
failure_reason |
Push timeout, portal webhook error |
raw_payload |
Notification payload (non-PHI summary; full data retrieved on-demand) |
DLQ review cadence: daily. Non-critical notifications; patients retrieve full data on next portal login regardless.
Idempotency
- Patient GET requests are inherently idempotent (read-only FHIR queries).
- Event push notifications: Deduplication key =
[patient_id]_[event_type]_[event_datetime]. Portal discards duplicate notifications. - Portal caches the last-known medication list per patient; cache invalidated on new dispensing event or after 15-minute TTL.
Reconciliation
- No formal reconciliation required for on-demand pull model — patient always receives current data from PIS on each portal query.
- For event push notifications: weekly review of DLQ to clear stale notifications older than 7 days (events are informational; data is always available on-demand).
Authentication & Security
Across all PIS integrations:
- mTLS Certificates
- Used for all HL7 v2.5.1 over MLLP/TLS (CPOE, NABIDH, Malaffi, Billing).
- Certificates issued by internal CA for intra-hospital; DHA/DOH CAs for HIE endpoints.
-
Certificate rotation and revocation managed per TDRA/NESA and ADHICS guidelines.
-
OAuth 2.0
- Authorization Code flow for patient portal access to FHIR APIs.
- Client Credentials flow for system-to-system FHIR calls (CPOE ↔ PIS, EHR ↔ PIS).
-
Scopes limited to least privilege (e.g.,
medications.read,medications.write). -
API Keys / Internal Tokens
-
For internal REST integrations where OAuth overhead is not required; keys stored in secure vault, rotated regularly.
-
Encryption
- In transit: TLS 1.2+ for all HTTP(S) and SFTP; MLLP wrapped in TLS.
-
At rest: database and message logs encrypted per facility policy and UAE PDPL requirements.
-
Audit & Logging
- All integration calls logged with timestamp, user/system identity, patient_id, and outcome.
- Logs retained per MOH/DOH/DHA and PDPL retention policies.
-
Access to logs restricted and monitored.
-
Data Minimization & PDPL
- Only necessary fields included in external integrations (NABIDH, Malaffi, MOH).
- Patient identifiers limited to MRN + Emirates ID where required by regulation.
- Cross-border transfers (if any) require explicit PDPL-compliant assessment and approvals.
This specification provides the developer-ready integration details for the Pharmacy Information System within the UAE regulatory context.