EHR & Patient Management Integration Specifications
Integration Summary
| ID | Target System | Direction | Trigger Event | Data Exchanged | Protocol | Frequency | Auth |
|---|---|---|---|---|---|---|---|
| INT-EHR-001 | NABIDH (Dubai HIE) | Bidirectional | Patient registration/update; encounter open/close; clinical note signed | ADT A01/A04/A08/A40, patient demographics, encounter notifications, CDA clinical documents | HL7 v2.5.1 over MLLP/TLS | Real-time | mTLS + NABIDH OAuth 2.0 |
| INT-EHR-002 | Malaffi (Abu Dhabi HIE) | Bidirectional | Same as NABIDH, emirate-based routing | ADT A01/A04/A08/A40, patient demographics, encounter notifications, CDA clinical documents | HL7 v2.5.1 over MLLP/TLS | Real-time | mTLS (DOH-issued) |
| INT-EHR-003 | Scheduling | Bidirectional | New registration; demographic update; appointment booking | Patient demographics (view/create/update), encounter shell creation, visit status notifications | Internal REST API + HL7 ADT (optional) | Real-time | Internal mTLS / JWT |
| INT-EHR-004 | Billing & Claims | Outbound | Registration; insurance update; encounter status change | Patient demographics, identifiers, insurance info, encounter data for claim creation | Internal REST API + HL7 ADT | Real-time | Internal mTLS / JWT |
| INT-EHR-005 | CPOE | Outbound | Allergy/problem list update; chart open | Patient allergies, problem list, core demographics for order context | Internal REST API / DB views | Real-time | Internal network + RBAC |
| INT-EHR-006 | Patient Portal | Bidirectional | Patient login; data view; demographic update; document upload; consent change | Patient demographics, clinical summaries, consents, documents; patient-initiated updates | FHIR R4 REST API | On-demand | OAuth 2.0 + PKCE |
| INT-EHR-007 | Insurance Eligibility (eClaimLink / DOH) | Bidirectional | Patient registration; insurance update; pre-encounter eligibility check | Member validation, eligibility response, policy coverage details | REST API (payer-specific) | Real-time | mTLS and/or OAuth 2.0 / keys |
INT-EHR-001: NABIDH (Dubai HIE)
Business Context
What flows
- Outbound from HIS to NABIDH:
- Patient demographics and identifiers (MRN, Emirates ID, passport, mobile, address).
- Encounter notifications (inpatient/outpatient registration, discharge).
- Clinical documents (e.g., discharge summaries, outpatient visit summaries) as CDA.
- Inbound from NABIDH to HIS:
- External clinical documents for the patient (CDA).
- Updated demographics if NABIDH is configured as a reference source (optional, usually view-only).
When
- ADT A01/A04: New registration or admission in Dubai-licensed facilities.
- ADT A08: Demographic updates (e.g., mobile, address, name corrections).
- ADT A40: Patient merge / MPI resolution.
- CDA: When a clinical note of a configured type (e.g., discharge summary) is signed.
Why
- Meet DHA/NABIDH requirements for HIE participation.
- Provide longitudinal patient record across Dubai providers.
- Reduce duplicate testing and improve care coordination.
How often
- Real-time: messages sent within seconds of the triggering event.
Error impact
- Outbound failure: NABIDH may not have up-to-date demographics or encounters; could impact downstream providers’ view but does not block local care.
- Inbound failure: External documents may not be visible; clinicians may miss outside history.
- All failures must be logged and monitored to maintain NABIDH submission success KPI (≥ 99.5%).
HL7 v2.5.1 Technical Detail (NABIDH)
Primary Message Types
ADT^A04– Outpatient registration.ADT^A01– Inpatient admission.ADT^A08– Demographic update.ADT^A40– Patient merge.- CDA documents are typically transported via separate document-sharing mechanisms (XDS.b) referenced from HL7 (if required by NABIDH profile); here we focus on ADT.
Sample: ADT^A04 – Outpatient Registration (Dubai)
MSH|^~\&|HIS_EHR|DUBAIHOSP|NABIDH|DHA|20260207101530+0400||ADT^A04^ADT_A01|MSG20260207101530001|P|2.5.1|||AL|NE||UTF-8
EVN|A04|20260207101525+0400|||RC001^ALI^HASSAN^^^MR
PID|1||MRN202600987^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID||AL-MAKTOUM^AHMED^MOHAMMED^^MR||19850315|M|||PO BOX 12345^^DUBAI^^00000^AE||+971501234567^PRN^PH^^^971^50^1234567|+97143211234^WPN^PH^^^971^4^3211234||M|||784-1985-1234567-1^^^AE^EID|||||||||||AE
PD1|||DUBCLINIC^^^DUBAIHOSP^^^^^DHA|PRV001^KHAN^SARA^AHMED^^DR^^^DHA
NK1|1|AL-MAKTOUM^FATIMA^ALI|SPO^Spouse|PO BOX 12345^^DUBAI^^00000^AE|+971505551111^PRN^PH
PV1|1|O|OPD^CARD^01^DUBAIHOSP^^BED01||||PRV001^KHAN^SARA^AHMED^^DR^^^DHA|||||||||ENC20260207000123^^^DUBAIHOSP^VN|||||||||||||||||||||||||20260207101000+0400
ZID|1|EID|784-1985-1234567-1|Verified
ZEM|1|Nationality|AE|United Arab Emirates
Key Segment Notes
MSH-3/4: Sending application/facility must match NABIDH registration.PID-3: Multiple identifiers:- MRN:
MRN202600987^^^DUBAIHOSP^MR - Emirates ID:
784-1985-1234567-1^^^AE^EID PID-11: UAE address with PO Box and emirate.PID-13/14: UAE-format phone numbers.PV1-2:Ofor outpatient,Ifor inpatient.PV1-19: Visit/encounter number, mapped fromencounters.encounter_id.ZID,ZEM: Example custom Z-segments for Emirates ID verification and nationality (exact structure to follow NABIDH profile).
Sample: ADT^A08 – Demographic Update (Dubai)
MSH|^~\&|HIS_EHR|DUBAIHOSP|NABIDH|DHA|20260207113010+0400||ADT^A08^ADT_A08|MSG20260207113010001|P|2.5.1|||AL|NE||UTF-8
EVN|A08|20260207113005+0400|||RC002^SALEH^OMAR^^^MR
PID|1||MRN202600987^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID||AL-MAKTOUM^AHMED^MOHAMMED^^MR||19850315|M|||PO BOX 67890^^DUBAI^^00000^AE||+971509998888^PRN^PH^^^971^50^9998888
PV1|1|O|OPD^CARD^01^DUBAIHOSP^^BED01||||PRV001^KHAN^SARA^AHMED^^DR^^^DHA|||||||||ENC20260207000123^^^DUBAIHOSP^VN
Sample: ADT^A40 – Patient Merge (Dubai)
MSH|^~\&|HIS_EHR|DUBAIHOSP|NABIDH|DHA|20260207120000+0400||ADT^A40^ADT_A39|MSG20260207120000001|P|2.5.1|||AL|NE||UTF-8
EVN|A40|20260207115955+0400|||MRO001^YOUSEF^LAILA^^^MS
PID|1||MRN202600987^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID||AL-MAKTOUM^AHMED^MOHAMMED^^MR||19850315|M
MRG|MRN202600654^^^DUBAIHOSP^MR~784-1985-1234567-1^^^AE^EID|MRN202600987^^^DUBAIHOSP^MR
PID-3: Surviving (primary) identifiers.MRG-1: Prior (merged) identifiers.MRG-2: Surviving identifiers (may repeat).
Field Mapping to EHR Tables
| HL7 Field | Table/Column |
|---|---|
| PID-3 (MRN) | patients.mrn |
| PID-3 (EID) | patient_identifiers.identifier_value (type = EID) |
| PID-5 (names) | patients.first_name_en, last_name_en, etc. |
| PID-7 | patients.date_of_birth |
| PID-8 | patients.gender |
| PID-11 | patient_demographics.address_line1_en, city, emirate, po_box |
| PID-13/14 | patient_demographics.mobile_phone, home_phone |
| NK1 | patient_demographics.emergency_contacts (JSON or child table) |
| PV1-19 | encounters.encounter_id (FK) |
| PV1-3 | locations (facility/department/bed) |
| EVN-2 | Event timestamp (audit) |
| MRG-1/2 | duplicate_suspects, merge logic in MPI |
NABIDH-Specific Requirements
- Use NABIDH-defined value sets for:
- Gender, marital status, nationality, encounter type.
- Emirates ID is mandatory where available and must be validated (format
784-YYYY-NNNNNNN-C). - All messages must be sent over MLLP within a TLS tunnel (mTLS).
- Acknowledgement:
- Expect
ACK^A01/ACK^A08withMSA-1=AA(accept),AE(error), orAR(reject). - Store
MSA-2(message control ID) and status inintegration_message_log.
Error Handling (INT-EHR-001)
| Condition | Handling | Retry / Recovery |
|---|---|---|
| TCP/MLLP connection failure | Queue message in integration_message_log with status queued; do not block registration UI |
Exponential backoff: 30s, 1m, 2m, 5m, 10m; after 10 attempts mark as failed and alert IT |
| No ACK within 30 seconds | Treat as timeout; keep message in pending state |
Retry send up to 3 times; if still no ACK, mark suspect and alert interface team |
ACK with AE (application error) |
Log error text; mark message error; do not auto-resend |
MRO/HIM correct data (e.g., invalid code) and trigger manual resend via admin UI |
ACK with AR (application reject) |
Log as rejected; store reason; may indicate configuration issue |
Interface team investigates; resend only after root cause fixed |
| Invalid Emirates ID format | Block outbound message; show validation error to registration clerk | User corrects ID; message generated only after valid data |
| CDA document packaging error | Do not send CDA; still send ADT | Queue CDA for re-generation; alert HIS technical team |
- Dead-letter queue: messages with status
failedorrejectedolder than 24 hours appear in an “Integration Exceptions” dashboard for HIM/IT. - All failures must be auditable for DHA/NABIDH compliance.
Retry and Recovery
Retry Strategy
| Attempt | Delay | Max Elapsed | Action on Final Failure |
|---|---|---|---|
| 1 | 30 seconds | 30s | — |
| 2 | 1 minute | 1m 30s | — |
| 3 | 2 minutes | 3m 30s | — |
| 4 | 5 minutes | 8m 30s | — |
| 5 | 10 minutes | 18m 30s | — |
| 6–10 | 10 minutes each | 68m 30s | Mark failed; move to DLQ; alert Integration Admin |
- Trigger: TCP/MLLP connection failure or no ACK within 30 seconds.
- Non-retryable: ACK with
AE(application error) orAR(application reject) — route directly to DLQ for manual investigation.
Dead Letter Queue
- Storage:
integration_message_logrows withstatus IN ('failed', 'rejected')andendpoint = 'NABIDH'. - Visibility: “Integration Exceptions” dashboard filtered by endpoint, status, and age.
- Retention: DLQ entries retained for 90 days (configurable); older entries archived per facility policy.
- Resolution workflow: HIM/IT reviews DLQ entry → corrects root cause (data, configuration, or connectivity) → triggers manual resend via admin UI → system updates status to
resentand logs new attempt. - Alerting: Email + dashboard alert to Integration Admin if DLQ depth > 10 messages or any message aged > 24 hours unresolved.
Idempotency
- Deduplication key:
MSH-10(Message Control ID), unique per message. - NABIDH-side: NABIDH is expected to deduplicate by
MSH-10; resending the same message should not create duplicate records. - HIS-side: On ACK receipt, system matches
MSA-2(acknowledging message control ID) tointegration_message_log.message_control_idto update status; duplicate ACKs are ignored.
Reconciliation
- Frequency: Daily at 03:00 (configurable).
- Process: Batch job compares
integration_message_logentries (status =sent,acked) for the previous 24 hours against expected events (registrations, updates, merges fromaudit_log). Any events without corresponding successful messages are flagged for re-transmission. - Report: Reconciliation discrepancies appear on the Integration Exceptions dashboard and in the daily integration health report sent to HIM Supervisor.
- KPI: NABIDH submission success rate target >= 99.5%.
INT-EHR-002: Malaffi (Abu Dhabi HIE)
Business Context
What flows
- Same categories as NABIDH:
- Patient demographics and identifiers.
- Encounter notifications.
- CDA clinical documents.
- Emirate-specific routing: only encounters at Abu Dhabi–licensed facilities are sent to Malaffi.
When
- ADT A01/A04/A08/A40 on events occurring in facilities where
facilities.emirate IN ('Abu Dhabi', 'Al Ain', 'Al Dhafra').
Why
- Meet DOH/Malaffi participation requirements.
- Support cross-provider care in Abu Dhabi.
How often
- Real-time.
Error impact
- Similar to NABIDH: HIE may be out-of-date; local care continues but external providers may lack latest data.
HL7 v2.5.1 Technical Detail (Malaffi)
Malaffi uses DOH-specific profiles; structure is similar to NABIDH but with DOH code sets and ADHICS security requirements.
Sample: ADT^A01 – Inpatient Admission (Abu Dhabi)
MSH|^~\&|HIS_EHR|ADHOSP|MALAFFI|DOH|20260207104500+0400||ADT^A01^ADT_A01|MSG20260207104500001|P|2.5.1|||AL|NE||UTF-8
EVN|A01|20260207104455+0400|||RC010^OMAR^KHALID^^^MR
PID|1||MRNAD202600321^^^ADHOSP^MR~784-1990-7654321-3^^^AE^EID||AL-NAHYAN^FATIMA^SAEED^^MRS||19900620|F|||PO BOX 54321^^ABU DHABI^^00000^AE||+971502223344^PRN^PH^^^971^50^2223344|||M|||784-1990-7654321-3^^^AE^EID|||||||||||AE
PD1|||ADCLINIC^^^ADHOSP^^^^^DOH|PRV010^HASSAN^ALI^MOHAMMED^^DR^^^DOH
NK1|1|AL-NAHYAN^SAEED^ALI|HUS^Husband|PO BOX 54321^^ABU DHABI^^00000^AE|+971505556666^PRN^PH
PV1|1|I|WARD3^301^02^ADHOSP^^BED05||||PRV010^HASSAN^ALI^MOHAMMED^^DR^^^DOH|||||||||ENCAD2026020700456^^^ADHOSP^VN|||||||||||||||||||||||||20260207104000+0400
- Same mapping as NABIDH; use DOH facility and provider codes.
Sample: ADT^A08 – Demographic Update (Abu Dhabi)
MSH|^~\&|HIS_EHR|ADHOSP|MALAFFI|DOH|20260207130000+0400||ADT^A08^ADT_A08|MSG20260207130000001|P|2.5.1|||AL|NE||UTF-8
EVN|A08|20260207125955+0400|||RC011^SALEH^LAILA^^^MR
PID|1||MRNAD202600321^^^ADHOSP^MR~784-1990-7654321-3^^^AE^EID||AL-NAHYAN^FATIMA^SAEED^^MRS||19900620|F|||PO BOX 77777^^ABU DHABI^^00000^AE||+971507778888^PRN^PH^^^971^50^7778888
PV1|1|I|WARD3^301^02^ADHOSP^^BED05||||PRV010^HASSAN^ALI^MOHAMMED^^DR^^^DOH|||||||||ENCAD2026020700456^^^ADHOSP^VN
Field Mapping
Same as INT-EHR-001, but:
facilities.licensing_authority = 'DOH'.- Provider codes from DOH registry.
Malaffi-Specific Requirements
- ADHICS-aligned security controls (network segmentation, logging).
- DOH-specific value sets for:
- Facility codes, provider identifiers, encounter types.
- mTLS with DOH-issued certificates.
- Acknowledgement handling identical to NABIDH (ACK with
AA/AE/AR).
Error Handling (INT-EHR-002)
Same pattern as NABIDH, but separate queues and monitoring:
- Separate
integration_endpointidentifier for Malaffi. - Alerting rules may differ (e.g., DOH requires notification if downtime > defined threshold).
- Messages failing due to DOH code-set issues must be flagged for master data correction (facility/provider codes).
Retry and Recovery
Retry Strategy
| Attempt | Delay | Max Elapsed | Action on Final Failure |
|---|---|---|---|
| 1 | 30 seconds | 30s | — |
| 2 | 1 minute | 1m 30s | — |
| 3 | 2 minutes | 3m 30s | — |
| 4 | 5 minutes | 8m 30s | — |
| 5 | 10 minutes | 18m 30s | — |
| 6–10 | 10 minutes each | 68m 30s | Mark failed; move to DLQ; alert Integration Admin |
- Trigger: TCP/MLLP connection failure or no ACK within 30 seconds.
- Non-retryable: ACK with
AEorAR— route to DLQ for manual investigation. DOH code-set errors specifically flagged for master data correction.
Dead Letter Queue
- Storage:
integration_message_logrows withstatus IN ('failed', 'rejected')andendpoint = 'MALAFFI'. - Visibility: "Integration Exceptions" dashboard filtered by endpoint; separate from NABIDH queue for independent monitoring.
- Retention: 90 days; archived per facility policy.
- Resolution workflow: HIM/IT reviews DLQ entry → corrects root cause (DOH facility/provider codes, data quality, or connectivity) → triggers manual resend → system updates status.
- Alerting: Email + dashboard alert to Integration Admin if DLQ depth > 10 messages or any message aged > 24 hours unresolved. DOH may require notification if outbound downtime exceeds a defined threshold.
Idempotency
- Deduplication key:
MSH-10(Message Control ID), unique per message. - Malaffi-side: Malaffi deduplicates by
MSH-10. - HIS-side: ACK matching via
MSA-2tointegration_message_log.message_control_id.
Reconciliation
- Frequency: Daily at 03:00 (configurable), separate from NABIDH reconciliation.
- Process: Batch job compares
integration_message_logentries for Malaffi endpoint against expected events for Abu Dhabi–licensed facilities (facilities.emirate IN ('Abu Dhabi', 'Al Ain', 'Al Dhafra')). Missing messages flagged for re-transmission. - Report: Discrepancies on Integration Exceptions dashboard and daily health report.
- KPI: Malaffi submission success rate target >= 99.5%.
INT-EHR-003: Scheduling
Business Context
What flows
- EHR → Scheduling:
- New patient demographics for appointment booking.
- Demographic updates (phone, address, insurance).
- Scheduling → EHR:
- Creation of encounter shell when appointment is confirmed/checked-in.
- Updates to encounter status (scheduled, arrived, in-progress, completed, no-show).
When
- On patient registration or demographic update (EHR pushes to Scheduling).
- On appointment creation/check-in (Scheduling calls EHR to create/update encounter).
Why
- Ensure a single source of truth for patient data.
- Avoid duplicate patient creation in Scheduling.
- Link appointments to encounters for clinical and billing workflows.
How often
- Real-time, synchronous for APIs; optional HL7 ADT feed for legacy scheduling engines.
Error impact
- If EHR → Scheduling fails: appointment staff may not see the latest demographics; manual re-entry risk.
- If Scheduling → EHR fails: encounters may not be created; downstream modules (CPOE, billing) may lack encounter context.
HL7 v2.5.1 Technical Detail (Optional ADT Feed)
Some deployments may use HL7 ADT from EHR to a legacy scheduling system.
Sample: ADT^A04 – New Registration to Scheduling
MSH|^~\&|HIS_EHR|MAINHOSP|SCHEDSYS|MAINHOSP|20260207111000+0400||ADT^A04^ADT_A01|MSG20260207111000001|P|2.5.1|||AL|NE||UTF-8
EVN|A04|20260207110955+0400|||RC020^AHMED^NOUR^^^MR
PID|1||MRN202601111^^^MAINHOSP^MR~784-1988-2223334-5^^^AE^EID||AL-SUWAIDI^OMAR^KHALID^^MR||19881201|M|||PO BOX 22222^^DUBAI^^00000^AE||+971501112233^PRN^PH
PV1|1|O|OPD^GEN^01^MAINHOSP^^BED01||||PRV020^ALI^HANA^MOHAMMED^^DR
- Scheduling system uses PID/PV1 to create or update its own patient and visit records.
REST API Technical Detail (Primary)
1. EHR → Scheduling: Push/Sync Patient
Endpoint (Scheduling)
POST /api/v1/patients/sync
Request (from EHR)
{
"externalId": "MRN202601111",
"emiratesId": "784-1988-2223334-5",
"firstNameEn": "Omar",
"lastNameEn": "Al-Suwaidi",
"firstNameAr": "عمر",
"lastNameAr": "السويدي",
"dateOfBirth": "1988-12-01",
"gender": "M",
"mobile": "+971501112233",
"email": "[email protected]",
"address": {
"line1": "PO BOX 22222",
"city": "Dubai",
"emirate": "Dubai",
"country": "AE"
},
"insurance": {
"payerCode": "DAMAN",
"memberId": "DAM123456789",
"planId": "PLN-DAMAN-ENHANCED"
}
}
Key Mappings
| JSON Field | Table/Column |
|---|---|
| externalId | patients.mrn |
| emiratesId | patient_identifiers (type = EID) |
| firstNameEn/Ar | patients.first_name_en/ar |
| lastNameEn/Ar | patients.last_name_en/ar |
| dateOfBirth | patients.date_of_birth |
| gender | patients.gender |
| mobile | patient_demographics.mobile_phone |
| insurance.* | insurance_plans, patient_identifiers (member ID) |
2. Scheduling → EHR: Create Encounter Shell
Endpoint (EHR)
POST /api/v1/encounters
Request
{
"patientMrn": "MRN202601111",
"appointmentId": "APT-20260207-0001",
"visitType": "OPD",
"departmentCode": "CARD",
"providerId": "PRV020",
"scheduledStart": "2026-02-07T11:30:00+04:00",
"facilityId": "MAINHOSP"
}
Response
{
"encounterId": "ENC2026020700789",
"status": "planned"
}
Error Handling (INT-EHR-003)
| Condition | Handling | Retry / Recovery |
|---|---|---|
| Scheduling API unreachable | Log failure; queue message in integration_message_log with target scheduling |
Exponential backoff: 15s, 30s, 1m, 2m, 5m; after 10 attempts mark as failed |
| 4xx from Scheduling (validation) | Do not retry; mark as rejected; store response body |
Registration supervisor corrects data and triggers manual re-sync |
| 5xx from Scheduling | Treat as transient; retry as above | If > 30 minutes cumulative, alert IT |
| Encounter creation failure | Appointment remains without encounter; Scheduling shows warning | Staff can manually create encounter via EHR UI and re-link appointment |
| Duplicate patient detected in Sched. | Scheduling returns conflict with existing externalId/emiratesId | EHR logs and flags for MPI review; no auto-merge |
- Dead-letter queue:
integration_message_logentries withstatus in ('failed','rejected')older than 24h.
Retry and Recovery
Retry Strategy
| Attempt | Delay | Max Elapsed | Action on Final Failure |
|---|---|---|---|
| 1 | 15 seconds | 15s | — |
| 2 | 30 seconds | 45s | — |
| 3 | 1 minute | 1m 45s | — |
| 4 | 2 minutes | 3m 45s | — |
| 5 | 5 minutes | 8m 45s | — |
| 6–10 | 5 minutes each | 33m 45s | Mark failed; move to DLQ; alert IT |
- Trigger: 5xx server errors or network timeouts from Scheduling API.
- Non-retryable: 4xx validation errors — route directly to DLQ for data correction by Registration Supervisor.
- Timeout: 10 seconds per request; requests exceeding timeout are treated as failures.
Circuit Breaker
- Threshold: 5 consecutive failures within 2 minutes → circuit opens.
- Open state: All requests to Scheduling are queued locally (not sent) for 60 seconds.
- Half-open: After 60 seconds, one probe request is sent; if successful, circuit closes and queued messages are drained. If probe fails, circuit remains open for another 60 seconds.
- Alert: Dashboard + email alert to IT when circuit opens; auto-close notification when circuit recovers.
Dead Letter Queue
- Storage:
integration_message_logrows withstatus IN ('failed', 'rejected')andendpoint = 'SCHEDULING'. - Visibility: "Integration Exceptions" dashboard.
- Retention: 30 days; older entries archived.
- Resolution workflow: IT/Registration Supervisor reviews → corrects data or resolves connectivity → triggers manual re-sync via admin UI.
Idempotency
- Deduplication key:
patient_id+message_type+timestamp(truncated to second). - Scheduling-side: Patient sync endpoint uses
externalId(MRN) as natural key; duplicate syncs perform upsert rather than insert, preventing duplicate patient records. - Encounter creation:
appointmentIdserves as idempotency key; duplicate encounter creation requests return existing encounter rather than creating a new one.
Reconciliation
- Frequency: Nightly at 02:00.
- Process: Batch job compares
patientsrecords (created/updated in last 24 hours) with Scheduling's patient table via reconciliation API (GET /api/v1/patients/reconcile?since={timestamp}). Mismatches (missing or stale records) are queued for re-sync. - Report: Reconciliation results logged in
integration_message_logand visible on dashboard.
INT-EHR-004: Billing & Claims
Business Context
What flows
- EHR → Billing:
- Patient demographics and identifiers.
- Insurance coverage details.
- Encounter data (type, dates, attending provider, location) to support claim generation.
When
- On registration (new patient or new encounter).
- On insurance update.
- On encounter status change (e.g., discharge, visit completion).
Why
- Ensure billing has accurate data for claim submission to payers (eClaimLink, DOH eClaims).
- Avoid claim rejections due to demographic/insurance mismatches.
How often
- Real-time.
Error impact
- If integration fails, claims may be delayed or rejected; manual re-entry may be required.
HL7 v2.5.1 Technical Detail (ADT to Billing)
Sample: ADT^A04 – Outpatient Registration to Billing
MSH|^~\&|HIS_EHR|MAINHOSP|BILLING|MAINHOSP|20260207114500+0400||ADT^A04^ADT_A01|MSG20260207114500001|P|2.5.1|||AL|NE||UTF-8
EVN|A04|20260207114455+0400|||RC030^ALI^HASSAN^^^MR
PID|1||MRN202601222^^^MAINHOSP^MR~784-1982-5556667-9^^^AE^EID||AL-MAZROUI^HIND^AHMED^^MRS||19820510|F|||PO BOX 99999^^DUBAI^^00000^AE||+971501234890^PRN^PH
PV1|1|O|OPD^DERM^02^MAINHOSP^^BED03||||PRV030^YOUSEF^LAILA^OMAR^^DR|||||||||ENC2026020700999^^^MAINHOSP^VN
IN1|1|DAMAN|DAMAN^^^DHA|Daman Insurance||PO BOX 128888^^ABU DHABI^^00000^AE|+97126000000^WPN^PH||||AL-MAZROUI^HIND^AHMED||19820510|F|||||THIQA123456789|PLN-DAMAN-ENHANCED
IN2|1|784-1982-5556667-9^^^AE^EID
Key Segment Notes
IN1-3: Payer code (aligned with DHA/DOH payer registry).IN1-36: Policy number / member ID.IN2: Additional info (e.g., Emirates ID).
REST API Technical Detail
Endpoint (Billing)
POST /api/v1/patients-and-encounters
Request
{
"patient": {
"mrn": "MRN202601222",
"emiratesId": "784-1982-5556667-9",
"firstNameEn": "Hind",
"lastNameEn": "Al-Mazroui",
"firstNameAr": "هند",
"lastNameAr": "المزروعي",
"dateOfBirth": "1982-05-10",
"gender": "F",
"mobile": "+971501234890",
"address": {
"line1": "PO BOX 99999",
"city": "Dubai",
"emirate": "Dubai",
"country": "AE"
}
},
"encounter": {
"encounterId": "ENC2026020700999",
"visitType": "OPD",
"departmentCode": "DERM",
"facilityId": "MAINHOSP",
"attendingProviderId": "PRV030",
"start": "2026-02-07T11:30:00+04:00",
"status": "in-progress"
},
"insurance": {
"payerCode": "DAMAN",
"planCode": "PLN-DAMAN-ENHANCED",
"memberId": "THIQA123456789",
"validFrom": "2026-01-01",
"validTo": "2026-12-31"
}
}
Error Handling (INT-EHR-004)
| Condition | Handling | Retry / Recovery |
|---|---|---|
| Billing API unreachable | Queue payload; do not block registration | Exponential backoff: 30s, 1m, 2m, 5m, 10m; after 10 attempts mark failed |
| 4xx validation error | Mark as rejected; show notification to Registration Supervisor |
Correct data in EHR (e.g., missing payer code) and trigger manual re-send |
| 5xx server error | Treat as transient; retry | If > 1 hour cumulative, alert RCM and IT |
| Insurance segment rejected | Billing returns specific error code (e.g., invalid plan) | Registration clerk prompted to correct insurance; new message sent on update |
Retry and Recovery
Retry Strategy
| Attempt | Delay | Max Elapsed | Action on Final Failure |
|---|---|---|---|
| 1 | 30 seconds | 30s | — |
| 2 | 1 minute | 1m 30s | — |
| 3 | 2 minutes | 3m 30s | — |
| 4 | 5 minutes | 8m 30s | — |
| 5 | 10 minutes | 18m 30s | — |
| 6–10 | 10 minutes each | 68m 30s | Mark failed; move to DLQ; alert RCM + IT |
- Trigger: 5xx server errors or network timeouts from Billing API.
- Non-retryable: 4xx validation errors (e.g., invalid payer code, missing insurance) — route to DLQ for data correction.
- Timeout: 15 seconds per request.
Circuit Breaker
- Threshold: 5 consecutive failures within 2 minutes → circuit opens.
- Open state: All outbound billing messages queued locally for 60 seconds.
- Half-open: Probe request after 60 seconds; success closes circuit and drains queue.
- Alert: Dashboard + email to RCM and IT when circuit opens.
Dead Letter Queue
- Storage:
integration_message_logrows withstatus IN ('failed', 'rejected')andendpoint = 'BILLING'. - Visibility: "Integration Exceptions" dashboard with RCM-specific filter view.
- Retention: 60 days (billing data has longer audit requirements).
- Resolution workflow: RCM reviews rejected messages → coordinates with Registration to correct data (insurance, payer codes) → triggers manual resend → billing module processes corrected payload.
- Alerting: Email + dashboard alert if DLQ depth > 5 messages or cumulative failure > 1 hour.
Idempotency
- Deduplication key:
encounter_id+message_type(registration, insurance_update, status_change). - Billing-side: Billing uses
encounter_idas natural key for encounter-related data; duplicate pushes perform upsert. Insurance updates are versioned byeffective_date.
Reconciliation
- Frequency: Nightly at 01:00.
- Process: Batch job compares encounters with status changes in the last 24 hours (
audit_logevents for encounter registration, insurance update, discharge) against Billing's encounter records via reconciliation API. Missing or stale records are queued for re-push. - Report: Discrepancies flagged on dashboard and included in daily RCM operations report.
- KPI: Billing data sync success rate target >= 99.9% (to minimize claim rejections).
INT-EHR-005: CPOE
Business Context
What flows
- EHR → CPOE:
- Patient demographics (read-only).
- Allergy list.
- Problem list.
- CPOE uses this context for:
- Clinical decision support (drug-allergy, drug-diagnosis checks).
- Displaying patient context in order entry.
When
- On chart open in CPOE.
- On allergy or problem list update in EHR.
Why
- Maintain a single source of truth for allergies and problems.
- Avoid duplicate maintenance of clinical lists.
How often
- Real-time, internal.
Error impact
- If unavailable, CPOE may operate with stale or missing allergy/problem data; risk to patient safety.
- CPOE must clearly indicate when allergy/problem data is unavailable.
Technical Detail (Internal API / DB Views)
Preferred approach is read-only DB views or internal REST.
Option A: Shared Database Views
vw_patient_allergies(in CPOE DB, view over EHR schema):
CREATE VIEW cpoe.vw_patient_allergies AS
SELECT
pa.allergy_id,
pa.patient_id,
pa.allergen_code,
pa.allergen_system,
pa.allergen_display,
pa.reaction_type,
pa.severity,
pa.manifestation_code,
pa.manifestation_display,
pa.onset_date,
pa.status,
pa.verified_by,
pa.verified_date
FROM ehr.patient_allergies pa
WHERE pa.status IN ('active', 'historical');
vw_patient_problemssimilarly mapped frompatient_problems.
Option B: REST API
Endpoint
GET /internal/cpoe/patients/{patientId}/context
Response
{
"patient": {
"id": "P202600987",
"mrn": "MRN202600987",
"emiratesId": "784-1985-1234567-1",
"nameEn": "Ahmed Mohammed Al-Maktoum",
"gender": "M",
"dateOfBirth": "1985-03-15"
},
"allergies": [
{
"allergyId": "ALG-1001",
"allergenCode": "70618",
"allergenSystem": "RXNORM",
"allergenDisplay": "Penicillin",
"reactionType": "allergy",
"severity": "severe",
"manifestationCode": "39579001",
"manifestationDisplay": "Anaphylaxis",
"status": "active",
"onsetDate": "2023-05-15"
}
],
"problems": [
{
"problemId": "PRB-2001",
"icd10Code": "I10",
"snomedCode": "38341003",
"description": "Essential (primary) hypertension",
"status": "active",
"onsetDate": "2020-01-10",
"priority": "chronic"
}
]
}
Error Handling (INT-EHR-005)
| Condition | Handling | Retry / Recovery |
|---|---|---|
| DB view unavailable | CPOE detects DB error; show banner “Allergy/problem data unavailable” | IT investigates DB connectivity; no automatic retry at app level |
| REST API timeout | CPOE uses cached context (if available) and flags as “stale” | Retry once; if still failing, log and alert application support |
| Partial data (e.g., allergies OK, problems fail) | Display what is available; clearly indicate missing sections | Log error; nightly job to reconcile discrepancies |
- No dead-letter queue required; internal integration, but errors must be logged in
audit_logand application logs.
Retry and Recovery
Timeout and Circuit Breaker (synchronous internal integration)
| Parameter | Value | Notes |
|---|---|---|
| Request timeout (REST API) | 5 seconds | CPOE displays cached data if timeout exceeded |
| DB view query timeout | 3 seconds | Query cancelled; CPOE shows "data unavailable" banner |
| Circuit breaker threshold | 3 consecutive failures in 1 minute | Circuit opens; CPOE operates on cached context |
| Circuit open duration | 30 seconds | Half-open probe after 30s; auto-close on success |
| Cache TTL | 5 minutes | CPOE caches patient context per session; refreshes on explicit reload |
- No DLQ required: This is a read-only, synchronous integration. CPOE pulls data from EHR; there are no queued outbound messages.
- Degraded mode: When EHR data is unavailable, CPOE must clearly display "Allergy data unavailable — verify with patient" and "Problem list unavailable" banners. Ordering is not blocked but CDS alerts may be incomplete.
- Alert: Application log entry + dashboard alert if CPOE-EHR circuit opens; IT investigates DB connectivity or REST API health.
Idempotency
- Not applicable — read-only integration with no state-changing operations.
Reconciliation
- Frequency: Nightly at 04:00.
- Process: Batch job compares allergy and problem list counts per patient (EHR source vs CPOE cache, if persistent cache exists). Discrepancies are logged and CPOE cache invalidated for affected patients.
- Report: Discrepancies logged in application monitoring; included in daily system health report.
INT-EHR-006: Patient Portal (FHIR R4)
Business Context
What flows
- Patient Portal → EHR:
- Demographic updates (contact info).
- Document uploads (e.g., external reports).
- Consent preferences (e.g., data sharing).
- EHR → Patient Portal:
- Patient demographics.
- Clinical summaries (problems, allergies, notes).
- Documents and consents.
When
- On patient login and navigation in portal.
- On patient-submitted updates.
Why
- Enable patient engagement and UAE PDPL-compliant consent management.
- Reduce front-desk workload for demographic updates.
How often
- On-demand (per API call).
Error impact
- If read fails: patient may not see latest data.
- If write fails: patient updates not applied; must be clearly communicated to patient.
FHIR R4 Technical Detail
1. Patient Resource (Read from EHR)
Endpoint
GET /fhir/Patient/{id}
Sample JSON
{
"resourceType": "Patient",
"id": "MRN202600987",
"identifier": [
{
"use": "usual",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR",
"display": "Medical Record Number"
}
]
},
"system": "http://ehr.gatesgroup.ae/mrn",
"value": "MRN202600987"
},
{
"use": "official",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "NI",
"display": "National unique individual identifier"
}
]
},
"system": "http://u.ae/emirates-id",
"value": "784-1985-1234567-1"
}
],
"active": true,
"name": [
{
"use": "official",
"family": "Al-Maktoum",
"given": ["Ahmed", "Mohammed"]
},
{
"use": "official",
"text": "أحمد محمد المكتوم"
}
],
"telecom": [
{
"system": "phone",
"value": "+971501234567",
"use": "mobile"
},
{
"system": "email",
"value": "[email protected]",
"use": "home"
}
],
"gender": "male",
"birthDate": "1985-03-15",
"address": [
{
"use": "home",
"line": ["PO BOX 12345"],
"city": "Dubai",
"district": "Dubai",
"country": "AE"
}
],
"communication": [
{
"language": {
"coding": [
{
"system": "urn:ietf:bcp:47",
"code": "ar",
"display": "Arabic"
}
]
},
"preferred": true
}
],
"managingOrganization": {
"reference": "Organization/DUBAIHOSP",
"display": "Dubai General Hospital"
}
}
Key Mappings
| FHIR Element | Table/Column |
|---|---|
| identifier[MR] | patients.mrn |
| identifier[NI] | patient_identifiers (type = EID) |
| name (EN/AR) | patients.first_name_en/ar, last_name_en/ar |
| telecom | patient_demographics.mobile_phone, email |
| address | patient_demographics.address_line1_en, city, emirate, country |
| communication.language | patient_demographics.preferred_language |
Search Parameters
GET /fhir/Patient?identifier=http://u.ae/emirates-id|784-1985-1234567-1GET /fhir/Patient?name=Al-MaktoumGET /fhir/Patient?birthdate=1985-03-15
2. Patient Demographic Update (Portal → EHR)
Endpoint
PATCH /fhir/Patient/{id} (JSON Patch or FHIR Patch)
Example (simplified PUT)
{
"resourceType": "Patient",
"id": "MRN202600987",
"telecom": [
{
"system": "phone",
"value": "+971509999000",
"use": "mobile"
},
{
"system": "email",
"value": "[email protected]",
"use": "home"
}
],
"address": [
{
"use": "home",
"line": ["PO BOX 77777"],
"city": "Dubai",
"district": "Dubai",
"country": "AE"
}
]
}
- EHR writes changes to
patient_demographicsand creates an approval task if configured (e.g., for name or Emirates ID changes).
3. Consent (Patient → EHR)
Resource: Consent
{
"resourceType": "Consent",
"id": "CONS-20260207-001",
"status": "active",
"scope": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/consentscope",
"code": "patient-privacy"
}
]
},
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/consentcategorycodes",
"code": "INFA",
"display": "Information access"
}
]
}
],
"patient": {
"reference": "Patient/MRN202600987"
},
"dateTime": "2026-02-07T10:20:00+04:00",
"performer": [
{
"reference": "Patient/MRN202600987"
}
],
"provision": {
"type": "permit",
"period": {
"start": "2026-02-07T10:20:00+04:00"
}
}
}
Mapping
Consent.id→patient_consents.consent_id.status→patient_consents.status.provision.period.start/end→granted_datetime/expiry_datetime.
Error Handling (INT-EHR-006)
| Condition | Handling | Retry / Recovery |
|---|---|---|
| Auth failure (invalid token) | Return HTTP 401/403; no data returned | Portal prompts re-login; no retry from EHR side |
| Validation error on update | Return HTTP 400 with OperationOutcome |
Portal displays error; patient can correct and resubmit |
| EHR FHIR server unavailable | Portal shows “Service temporarily unavailable” | Portal may retry once; EHR logs outage and alerts IT |
| Consent write failure | Log error; do not assume consent granted | Portal informs patient that consent change failed; retry after issue resolved |
- All FHIR calls logged in
audit_logwithresource_type=Patient,Consent, etc., andis_btg = false.
Retry and Recovery
Timeout and Circuit Breaker (synchronous FHIR API)
| Parameter | Value | Notes |
|---|---|---|
| Request timeout | 10 seconds | Portal displays "Service temporarily unavailable" on timeout |
| Circuit breaker threshold | 5 consecutive failures in 2 minutes | Circuit opens; portal enters read-only cached mode |
| Circuit open duration | 60 seconds | Half-open probe after 60s |
| Portal-side retry | 1 automatic retry on timeout | No further automatic retries; patient informed to try again |
- Read failures (EHR → Portal): Portal may display cached data (if available) with "Data may not be current" notice. No DLQ needed for read operations.
- Write failures (Portal → EHR): Patient-submitted updates (demographics, consents, documents) are stored in the portal's pending queue if EHR is unavailable.
Dead Letter Queue (Write Operations Only)
- Storage: Portal-side pending queue for failed write operations (demographic updates, consent changes, document uploads).
- Visibility: Portal admin dashboard shows pending submissions; patient sees "Update pending — we'll process it shortly" status.
- Retention: 7 days; if unresolved, patient is notified to resubmit or contact the facility.
- Resolution workflow: When EHR connectivity is restored, portal drains pending queue automatically. Failed items after retry are escalated to portal admin for manual processing.
- Alerting: Portal admin alerted if pending queue depth > 20 items or any item aged > 4 hours.
Idempotency
- Deduplication key: FHIR resource
id+meta.versionIdfor reads; portal-generatedtransactionIdfor writes. - EHR-side: FHIR server uses
If-Matchheaders (optimistic locking) to prevent stale updates; duplicate PATCH requests with sametransactionIdreturn success without re-applying changes.
Reconciliation
- Frequency: Nightly at 05:00.
- Process: Batch job compares portal's pending queue (any items not confirmed by EHR) and verifies that all processed updates are reflected in EHR data. Discrepancies are flagged for portal admin review.
- Report: Reconciliation results on portal admin dashboard and in daily operations report.
INT-EHR-007: Insurance Eligibility (eClaimLink / DOH eClaims)
Business Context
What flows
- EHR → Payer gateway:
- Patient demographics and insurance policy details.
- Payer gateway → EHR:
- Eligibility response (active/inactive, coverage details, co-pay).
When
- On insurance capture during registration.
- On explicit “Check Eligibility” action by registration clerk.
- Optionally, nightly batch re-check for future scheduled encounters.
Why
- Reduce claim denials due to inactive coverage.
- Provide accurate co-pay information at point of service.
How often
- Real-time for interactive checks.
- Optional batch for scheduled appointments.
Error impact
- If eligibility check fails, registration proceeds but flagged as “eligibility unknown”; billing risk increases.
REST API Technical Detail
Actual endpoints vary by payer; below is a generic pattern aligned with eClaimLink/DOH eClaims concepts.
Endpoint
POST /eligibility/check
Request
{
"transactionId": "ELIG-20260207-0001",
"payerCode": "DAMAN",
"facilityId": "MAINHOSP",
"patient": {
"emiratesId": "784-1982-5556667-9",
"firstNameEn": "Hind",
"lastNameEn": "Al-Mazroui",
"dateOfBirth": "1982-05-10",
"gender": "F"
},
"insurance": {
"memberId": "THIQA123456789",
"policyNumber": "PLN-DAMAN-ENHANCED"
},
"serviceDate": "2026-02-07"
}
Response
{
"transactionId": "ELIG-20260207-0001",
"status": "eligible",
"coverage": {
"planName": "Daman Enhanced",
"startDate": "2026-01-01",
"endDate": "2026-12-31",
"coPayPercent": 20,
"networkStatus": "in-network"
},
"payerReference": "DAM-ELIG-99887766"
}
Mapping
status→patients.insurance_eligibility_status(if such column exists) or stored in a dedicated eligibility table.coverage.*→ used by Billing & Claims for claim generation and patient estimates.
Error Handling (INT-EHR-007)
| Condition | Handling | Retry / Recovery |
|---|---|---|
| Network / gateway timeout | Mark eligibility as unknown; show warning to clerk |
Retry once automatically; further retries only on manual request |
| 4xx error (invalid payload) | Show error to clerk; do not retry | Clerk corrects insurance/member ID and re-initiates check |
| 5xx error (payer system down) | Mark as unknown; log error |
Optionally schedule background retry; alert RCM if persistent |
Eligibility status = ineligible |
Store response; flag encounter for RCM review | Clerk may verify with payer via phone; update insurance details if needed |
- All eligibility requests/responses stored for audit and dispute resolution.
Retry and Recovery
Timeout and Circuit Breaker (synchronous external API)
| Parameter | Value | Notes |
|---|---|---|
| Request timeout | 15 seconds | Payer gateways may be slow; generous timeout |
| Automatic retry | 1 retry on timeout or 5xx | No further automatic retries; clerk can manually re-check |
| Circuit breaker threshold | 5 consecutive failures in 5 minutes (per payer) | Circuit opens per payer; other payers unaffected |
| Circuit open duration | 120 seconds | Longer duration for external payer systems; half-open probe after 120s |
- Per-payer isolation: Circuit breakers are maintained per payer endpoint. A Daman outage does not affect ADNIC or other payer eligibility checks.
- Degraded mode: When eligibility check fails, registration proceeds with
eligibility_status = 'unknown'; encounter is flagged for RCM review. Clerk can retry manually later.
Dead Letter Queue
- Storage:
integration_message_logrows withstatus = 'failed'andendpoint = 'ELIGIBILITY_{payerCode}'. - Visibility: "Integration Exceptions" dashboard filtered by payer.
- Retention: 30 days.
- Resolution workflow: Failed interactive checks are not automatically retried (real-time context is lost). However, the nightly batch re-check (if configured) will automatically re-attempt eligibility for future scheduled encounters with
unknownstatus. - Alerting: Dashboard alert if any payer's circuit breaker opens; email to RCM if > 10 eligibility failures in a day for a single payer.
Idempotency
- Deduplication key:
transactionId(generated per request, e.g.,ELIG-{date}-{sequence}). - Payer-side: Most payer gateways are stateless for eligibility queries; duplicate requests simply return current eligibility status without side effects.
- HIS-side: Eligibility responses are stored with
transactionId; duplicate responses (from retries) update the same record rather than creating new entries.
Reconciliation
- Frequency: Nightly at 00:30 (optional batch re-check).
- Process: For all encounters scheduled in the next 48 hours with
eligibility_status IN ('unknown', 'pending'), system re-runs eligibility check against the appropriate payer. Successful checks update status; persistent failures are flagged for manual follow-up by RCM. - Report: Batch eligibility results included in daily RCM operations report.
- KPI: Eligibility verification rate at registration >= 95%.
Authentication & Security
Transport Security
- All external integrations (NABIDH, Malaffi, payer APIs, portal) must use HTTPS/TLS 1.2+.
- HL7 v2.5.1 over MLLP must be encapsulated in TLS tunnels with mutual TLS (mTLS).
Mutual TLS (mTLS)
- NABIDH / Malaffi:
- Client certificates issued by DHA/DOH or trusted CA.
- Certificate rotation managed by IT security; downtime windows coordinated with HIE.
- Payer APIs:
- Some require mTLS; certificates managed per payer.
OAuth 2.0
- Patient Portal:
- Authorization Code + PKCE flow.
- Access tokens scoped (e.g.,
patient/*.read,patient/*.write). - NABIDH:
- Where required, use OAuth 2.0 client credentials for HIE API endpoints in addition to mTLS.
- Internal APIs (Scheduling, Billing):
- Use JWT-based service-to-service tokens with short lifetimes and audience restrictions.
API Key Management
- For payer APIs that use API keys:
- Keys stored in secure secrets vault.
- Never hard-coded in application code.
- Rotation procedures defined with minimal downtime.
Message Encryption & Data Protection
- No PHI in logs beyond what is necessary for troubleshooting; Emirates ID and names should be masked where possible.
- At-rest encryption for integration queues and logs per UAE PDPL and ADHICS/TDRA guidance.
- Access to integration monitoring tools restricted to authorized roles (e.g., HIM Supervisor, System Administrator, Privacy Officer).
Audit & Privacy
- All external data exchanges recorded in
audit_log: resource_type(e.g.,HL7_ADT,FHIR_Patient,Eligibility).action(send,receive,view).user_idor system account.timestamp,ip_address.- Break-the-glass (BTG) events that trigger external queries (e.g., HIE document retrieval) must be flagged with
is_btg = trueand reviewed by Privacy Officer. - Consent checks:
- Before sending data to NABIDH/Malaffi or portal, verify
patient_consentsfor relevant consent type (e.g., HIE sharing). - If consent withdrawn, suppress outbound messages except where UAE law mandates reporting (e.g., public health).