Dev Reference

eRx & EPCS

Electronic prescribing, EPCS two-factor controlled-substance signing, Surescripts NCPDP SCRIPT routing, RTPB formulary checks, and PDMP gateway integration.

Data Classification: Mixed scoping. Prescription is global (partitioned by SourceOrganizationID) because a prescription may be visible across organizations in a TEFCA network. ControlledSubstanceAuth, PdmpQuery, and FormularyCheck are org-scoped (partitioned by OrganizationID). See Data Model for ownership rules and IC Reference for isolation constraints.

Prescription

Global entity. Partition key: SourceOrganizationID. Trust Tier: T1 (PHI + controlled-substance data).

Schema

FieldTypeRequiredPKFKNotes
PrescriptionIDUUIDYesYesPrimary key
PatientIDUUIDYesPatient
PrescriberIDUUIDYesProvider
MedicationNameString(100)YesDisplay name
MedicationCodeString(50)YesRxNorm or NDC
DoseString(50)Yes
SIGTextYesDirections for use
QuantityDecimalYes
QuantityUnitString(50)Yese.g. tablets, mL
RefillsIntYes0 = no refills
DaysSupplyIntYes
PharmacyNcpdpIdString(50)NoNCPDP pharmacy ID
PharmacyNameString(100)No
IsDispenseAsWrittenBoolYesDAW flag
IsControlledBoolYes
ScheduleString(50)NoII, III, IV, V, or null
RxMessageTypeString(50)YesNewRx / RxRenewal / RxChange / CancelRx / Compound
SurescriptsMessageIdString(50)NoSurescripts tracking ID
EpaidString(50)NoElectronic prior-auth ID
StatusString(50)YesDraft / Sent / Received / Completed / Cancelled / Error
SentDateTimeDateTime (UTC)No
CompletedDateTimeDateTime (UTC)No
SourceOrganizationIDUUIDYesOrganizationGlobal partition key
CreatedByUserIDUUIDYesUserAudit
CreatedDateTimeDateTime (UTC)YesAudit
UpdatedByUserIDUUIDYesUserAudit
UpdatedDateTimeDateTime (UTC)YesAudit

RBAC

RoleTierPermissions
Patient (10)T1Read own prescriptions via portal
Front Desk (30)T1Read prescription status
MA / RN (40)T1Read + process non-controlled RxRenewal
Clinician (60)T1Read / Write / Sign (EPCS requires DEA enrollment)
Practice Manager (70)T1Read + override mandate
EditAMI (90)T1Schema administration

ControlledSubstanceAuth

Org-scoped. Trust Tier: T1 (identity proofing + DEA credentials).

Schema

FieldTypeRequiredPKFKNotes
ControlledSubstanceAuthIDUUIDYesYesPrimary key
ProviderIDUUIDYesProvider
DeaNumberString(50)YesDEA registration number
ScheduleAuthorityString(50)YesAuthorized schedules
IdentityProofingProviderString(50)Yese.g. ID.me
IdentityProofingStatusString(50)YesPending / Verified / Expired / Revoked
IdentityProofingVerifiedDateTimeDateTime (UTC)No
TokenTypeString(50)YesHardToken / SoftToken
TokenSerialNumberString(50)Yes
TokenActivationDateTimeDateTime (UTC)Yes
TokenExpirationDateTimeDateTime (UTC)Yes
SigningCertificateRefString(200)YesFIPS 140-2 HSM reference
DrummondCertifiedBoolYesDrummond Group certification
IsActiveBoolYes
OrganizationIDUUIDYesOrganizationTenant partition key
CreatedByUserIDUUIDYesUserAudit
CreatedDateTimeDateTime (UTC)YesAudit
UpdatedByUserIDUUIDYesUserAudit
UpdatedDateTimeDateTime (UTC)YesAudit

RBAC

RoleTierPermissions
Clinician (60)T1Read own auth record; initiate identity proofing
Practice Manager (70)T1Read all; manage token lifecycle
EditAMI (90)T1Schema administration

PdmpQuery

Org-scoped. Trust Tier: T2 (controlled-substance check logs).

Schema

FieldTypeRequiredPKFKNotes
PdmpQueryIDUUIDYesYesPrimary key
PatientIDUUIDYesPatient
ProviderIDUUIDYesProvider
StateCodeString(50)YesState PDMP queried
PdmpGatewayString(50)YesBambooHealth / LogiCoy / DirectAPI
QuerySentDateTimeDateTime (UTC)Yes
ResponseReceivedDateTimeDateTime (UTC)No
IsMandatedBoolYesState mandate requires check
MandateSatisfiedBoolYes
ControlledSubstanceFillCountIntNo
NarxScoreIntNoNarxCare risk score
AlertTriggeredBoolYes
SummaryTextNoDisplayable summary
RawResponseTextNoEncrypted at rest
OrganizationIDUUIDYesOrganizationTenant partition key
CreatedByUserIDUUIDYesUserAudit
CreatedDateTimeDateTime (UTC)YesAudit
UpdatedByUserIDUUIDYesUserAudit
UpdatedDateTimeDateTime (UTC)YesAudit

RBAC

RoleTierPermissions
Clinician (60)T2Read / Initiate PDMP query
Practice Manager (70)T2Read all; override mandate flag
EditAMI (90)T2Schema administration

FormularyCheck

Org-scoped. Trust Tier: T2 (payer benefit data, no direct PHI).

Schema

FieldTypeRequiredPKFKNotes
FormularyCheckIDUUIDYesYesPrimary key
PrescriptionIDUUIDYesPrescription
PatientIDUUIDYesPatient
MedicationCodeString(50)YesRxNorm code
FormularyTierString(50)NoPayer formulary tier
IsPreferredBoolNo
PatientCopayAmountMoneyNo
PatientCopayCurrencyCodeString(3)NoISO 4217
PatientCostAmountMoneyNo
PatientCostCurrencyCodeString(3)NoISO 4217
RequiresPriorAuthBoolYes
StepTherapyRequiredBoolYes
QuantityLimitBoolYes
AlternativesTextNoJSON array of alternative medications
RtpbTransactionIdString(50)NoRTPB transaction tracking
CheckDateTimeDateTime (UTC)Yes
OrganizationIDUUIDYesOrganizationTenant partition key
CreatedByUserIDUUIDYesUserAudit
CreatedDateTimeDateTime (UTC)YesAudit
UpdatedByUserIDUUIDYesUserAudit
UpdatedDateTimeDateTime (UTC)YesAudit

RBAC

RoleTierPermissions
Patient (10)T2Read own formulary results via portal
MA / RN (40)T2Read formulary check results
Clinician (60)T2Read / Initiate formulary check
Practice Manager (70)T2Read all
EditAMI (90)T2Schema administration

NCPDP SCRIPT 2017071 Message Model

Message TypeDirectionDescription
NewRxPrescriber → PharmacyNew prescription order
RxRenewalPharmacy → PrescriberRefill/renewal request from pharmacy
RxChangePharmacy → PrescriberTherapeutic substitution or formulary change request
CancelRxPrescriber → PharmacyCancel previously sent prescription
CompoundPrescriber → PharmacyCompound medication order with ingredient list
RxFillPharmacy → PrescriberFill status notification (dispensed, partial, not filled)
VerifyPrescriber ↔ PharmacyMessage receipt verification
ErrorEitherError response for unprocessable messages

Trust tier roll-up

EntityTierSource of truth
Prescription1 — Internal canonicalAuthored by a credentialed prescriber in this system; Surescripts delivery confirms transmission
ControlledSubstanceAuth1 — Internal canonicalID.me IAL2 proofing result + DEA registration verification + token enrollment record
PdmpQuery2 — External inboundResponse payload originates with the state PDMP database via Bamboo Health / LogiCoy gateway
FormularyCheck2 — External inboundFormulary and benefit data from Surescripts RTPB response

RBAC matrix (IC 0–100 scale)

RoleLevelPrescriptionControlledSubstanceAuthPdmpQueryFormularyCheck
Patient (self)10Read own (via Patient Portal)No accessNo accessRead own cost/tier
Front desk (Jordan)30Read statusNo accessNo accessRead cost/tier
MA / RN (Tasha)40Read; process RxRenewal under standing orderNo accessReadRead
Clinician (Dr. M / Maria)60Read / Write / Sign (EPCS requires DEA authority)Read own; enroll own tokenRead / Write (trigger query)Read / Write (trigger check)
Practice manager (Sam)70Read; override mandate blocksRead all; enroll/revoke tokensRead; override mandateRead
EditAMI90Required for any AMI schema break (per IC hard rule #5)

EPCS RBAC hard rule: Only DEA-registered prescribers (level ≥ 60 with a valid ControlledSubstanceAuth row that has IsActiveBool = true and ScheduleAuthorityString covering the Rx schedule) can sign Schedule II–V prescriptions. MA/RN (level 40) cannot sign controlled Rx even under standing order; they can process RxRenewal for non-controlled medications only.

FK Relationship Diagram

erDiagram
    Patient ||--o{ Prescription : "has"
    Provider ||--o{ Prescription : "prescribes"
    Organization ||--o{ Prescription : "SourceOrganizationID"
    Provider ||--o| ControlledSubstanceAuth : "holds"
    Patient ||--o{ PdmpQuery : "subject"
    Provider ||--o{ PdmpQuery : "queries"
    Prescription ||--o{ FormularyCheck : "checked"
    Patient ||--o{ FormularyCheck : "beneficiary"
    

EPCS Authentication Flow

flowchart TD
    A[Clinician initiates EPCS enrollment] --> B[Identity proofing via ID.me]
    B --> C{Identity verified?}
    C -- No --> D[Reject — retry or escalate]
    C -- Yes --> E[Issue hard/soft token]
    E --> F[Bind token to DEA number]
    F --> G[Store signing cert ref in FIPS 140-2 HSM]
    G --> H[Drummond certification check]
    H --> I{Certified?}
    I -- No --> J[Block EPCS — manual review]
    I -- Yes --> K[ControlledSubstanceAuth.IsActive = true]
    K --> L[Clinician signs Rx with two-factor]
    L --> M[Token challenge + biometric/PIN]
    M --> N[Digital signature applied]
    N --> O[Prescription.Status = Sent via Surescripts]
    

Functional Requirements

  1. P0 The system SHALL transmit NewRx messages via Surescripts using NCPDP SCRIPT 2017071 and receive Verify/Error responses.
  2. P0 The system SHALL enforce EPCS two-factor authentication (token + biometric/PIN) before signing any Schedule II-V prescription.
  3. P0 The system SHALL store EPCS signing certificate references in a FIPS 140-2 Level 2 (or higher) HSM and never expose private keys.
  4. P0 The system SHALL perform PDMP queries before dispensing controlled substances when the patient's state mandates it, and block signing if the mandate is not satisfied (unless overridden by Practice Manager).
  5. P0 The system SHALL support identity proofing via ID.me (or equivalent NIST IAL-2 provider) and track proofing status on ControlledSubstanceAuth.
  6. P1 The system SHALL process inbound RxRenewal requests and route them to the prescribing clinician (or delegate MA/RN for non-controlled).
  7. P1 The system SHALL perform real-time RTPB formulary checks and display formulary tier, copay, alternatives, and prior-auth requirements before the clinician signs.
  8. P1 The system SHALL support CancelRx messages and update Prescription.Status accordingly.
  9. P1 The system SHALL display NarxScore and alert indicators from PDMP responses when the score exceeds the configured threshold.
  10. P1 The system SHALL support Compound prescription messages with ingredient-level detail.
  11. P2 The system SHALL support RxChange responses (therapeutic substitution acceptance/rejection) from pharmacies.
  12. P2 The system SHALL log all PDMP raw responses encrypted at rest and retain them per state-specific retention requirements.

Non-Functional Requirements

icApplication Overrides

How the four eRx & EPCS AMI schemas turn into a live application: module-specific stack additions, the Surescripts certification pipeline, override component bindings, EPCS hard/soft-token bindings, PDMP component integration, a versioning worked example, environment cascade, and RBAC enforcement.

Shared generation map. The IC platform code-gen flow, default bindings, environment cascade, RBAC model, and CLI commands are identical across all modules. See the IC Reference for the canonical shared reference. This section covers only eRx & EPCS-specific content.

Technology stack P0

The shared platform stack (Cosmos DB, Redis, IC-generated API, Angular 21, SQS+SNS, OpenTelemetry, etc.) is documented in the IC Reference. Module-specific additions:

LayerTechnologyNotes
eRx networkSurescripts (direct certification)NCPDP SCRIPT 2017071: NewRx, RxRenewal, RxChange, CancelRx, MHX, RTPB, ePA. Per Integration Ecosystem decision (BUILD — direct cert, DrFirst as standby).
EPCS signingFIPS 140-2 HSM + ID.me IAL2Hard token (SAV-Littleton, Episerver) or DEA-accepted soft token. Signing certificate managed in HSM. Drummond EPCS app certification required.
PDMP gatewayBamboo Health PMP Gateway + LogiCoy (IL)Covers >46 states via Bamboo; Illinois via LogiCoy. State-by-state API integration per mandate requirements.
DUR engineCoding / CDS moduleDDI, drug-allergy, drug-condition, dose-range checks invoked via CDS Hooks at prescribing time.
FHIR resource profilesMedicationRequest, MedicationDispense, Task (ePA)R4 baseline; USCDI v3 alignment for CY 2026; HTI-4 eRx criteria.

Surescripts certification pipeline P0

Surescripts certification is a 9–12 month process from kickoff to production activation. It is a gating dependency for any eRx functionality. The pipeline runs in parallel with platform development:

flowchart LR
  KICKOFF[Cert kickoff
+ NDA + fees] TEST[Test environment
Surescripts sandbox] CERT[Certification testing
Drummond + Surescripts] PROD[Production activation
live trading partners] KICKOFF --> TEST TEST --> CERT CERT --> PROD
StageDurationWhat happensEnvironment
Cert kickoffMonth 0Sign NDA, pay fees, receive sandbox credentials, submit prescriber directory entriesn/a
Test environmentMonths 1–6Build and validate SCRIPT 2017071 message construction; test NewRx, RxRenewal, RxChange, CancelRx, MHX, RTPB against Surescripts sandboxSurescripts sandbox (cert-test.rev.health)
Certification testingMonths 6–10Drummond EPCS app certification; Surescripts interoperability test; EPCS two-factor signing verification; all SCRIPT transaction types validatedSurescripts staging + Drummond lab
Production activationMonths 10–12Go-live with live trading partners; prescriber directory published; production Surescripts routing enabledSurescripts production
Critical-path dependency. Surescripts certification takes 9–12 months from scratch. This must start in Month 1 of the project, not Month 12, or launch slips. DrFirst is maintained as a standby eRx provider in case Surescripts cert is delayed.

eRx-specific override bindings P0

These overrides are declared in rules/*.rules.json and replace the default for the matching field name pattern.

FieldDefault would renderOverride componentWhy
Prescription.MedicationCodeString50plain text inputic-ng21-erx-1-medication-searchRxNorm-aware medication search with auto-complete, NDC expansion, and SIG templates; prevents free-text drug entry.
Prescription.PharmacyNcpdpIdString50plain text inputic-ng21-erx-1-pharmacy-pickerNCPDP directory search; shows patient’s preferred pharmacy; validates NCPDP ID against Surescripts directory.
Prescription.SIGTextplain textareaic-ng21-erx-1-prescription-writerStructured SIG builder: verb + dose + route + frequency + duration + PRN reason; produces both human-readable and coded SIG.
Prescription.StatusString50plain text displayic-ng21-erx-1-rx-status-pillColor-coded dark status pill (Draft / Sent / Received / Completed / Cancelled / Error).
(synthetic) EPCS signing gaten/aic-ng21-erx-1-epcs-signerTwo-factor signing modal: biometric + token challenge + digital signature application. Only rendered for controlled Rx.
(synthetic) PDMP result paneln/aic-ng21-erx-1-pdmp-queryControlled-substance fill history display with NarxCare score, mandate badge, and prescriber acknowledgment gate.
(synthetic) RTPB cost paneln/aic-ng21-erx-1-formulary-checkerPatient-specific cost + tier + PA flag + alternatives; rendered before Rx signing.
(synthetic) DUR alert paneln/aic-ng21-erx-1-dur-alert-panelDDI / allergy / condition / dose-range alerts with override + reason. Sourced from Coding / CDS.
(synthetic) RTPB cost displayn/aic-ng21-erx-1-rtpb-cost-displayPatient copay and total cost inline in the prescription writer; pulls from FormularyCheck.
(synthetic) RxRenewal inbasketn/aic-ng21-erx-1-renewal-inbasketInbound RxRenewal/RxChange card with approve/deny/modify actions; routes through Task Management.
(synthetic) ePA formn/aic-ng21-erx-1-epa-formPharmacy-benefit PA request form; submits via Surescripts ePA network.

EPCS hard-token and soft-token bindings P0

Per DEA 21 CFR 1311, EPCS two-factor authentication requires an AAL2-compliant token. The system supports both hard tokens and soft tokens; the binding is per-org per-provider in ControlledSubstanceAuth.

Token typeBindingDEA complianceWhen to use
Hard token (FIPS 140-2 Level 3)Physical OTP token (e.g., SAV-Littleton, Episerver); serial number recorded in TokenSerialNumberString50Meets DEA hard-token requirement directlyP1; highest assurance; required for practices that prefer hardware tokens
Soft token (DEA-accepted authenticator app)Mobile authenticator app (TOTP); enrollment tracked in TokenTypeString50 = "SoftToken"DEA-accepted per 2015 interim final rule; requires Drummond-certified EPCS applicationP2; reduces hardware overhead for small practices

Both token types require IAL2 identity proofing (via ID.me) before enrollment. The ControlledSubstanceAuth row records which token type is active, when it was activated, and when it expires. The system blocks EPCS signing when the token is expired or revoked.

PDMP component — state-by-state API integration P0

PDMP queries are routed through two gateways based on state coverage:

GatewayStates coveredIntegration methodComponent binding
Bamboo Health PMP Gateway>46 states (all except IL and a few holdouts)REST API via bamboo-pdmp.ts adapter; PMIX/NABP standard query formatic-ng21-erx-1-pdmp-query
LogiCoyIllinois onlyREST API via logicoy-pdmp.ts adapter; IL-specific formatic-ng21-erx-1-pdmp-query (same component; adapter routing is backend)

The state mandate table is maintained in rules/pdmp-query.rules.json and encodes: (1) whether the state mandates a PDMP check before a controlled-substance Rx, (2) the mandate window (how recent the query must be to satisfy the mandate), and (3) the applicable schedule range. When the prescriber attempts a controlled-substance Rx, the mandate enforcer job checks this table and blocks the Rx if a mandated query has not been completed and acknowledged within the window.

Versioning — worked example P0

All eRx artifacts are versioned break.feature.bug.buildtimestamp per IC hard rule #9. The example below traces a feature bump on Prescription.

Prescription 1.0.0.20260301T120000Z — Initial schema. 20 business fields plus global audit columns. Component ic-ng21-erx-1-prescription-writer and ic-ng21-erx-1-epcs-signer bind to prescription@1.0.0.* via the DI manifest.

Prescription 1.1.0.20260515T093000Z — feature bump — Adds a single optional field, RxTransmissionIdString50, to capture the Surescripts transmission tracking ID separately from the message ID (for delivery-receipt correlation). Per the IC change matrix:

ChangeVersion impactApproval neededMin permission
Add optional field RxTransmissionIdString50feature bump (1.0.0 → 1.1.0)NoWrite (60)

Because the change is backward-compatible, the component tag stays ic-ng21-erx-1-prescription-writer. Existing UI consumers continue to bind prescription@1.x.* and ignore the new field. New UI surfaces that need delivery-receipt correlation bind prescription@^1.1.0. No new database is required (IC rule #13 only applies to break bumps).

Prescription 2.0.0.20280101T120000Z — break bump (illustrative) — An illustrative future break bump: SIGText is split into separate coded fields (SIGVerbString50, SIGDoseString50, SIGRouteString50, SIGFrequencyString50, SIGDurationString50, SIGPRNReasonString50). Per the IC change matrix this is change field type + add required fields — break bump, EditAMI (90) approval, and per IC rule #13 a new database is provisioned with ETL from the old one. The component tag becomes ic-ng21-erx-2-prescription-writer; consumers must re-bind. The old database stays live for the configured grace period (default 90 days) for rollback.

Illustrative. The 2.0.0 example is illustrative of the change matrix and IC rule #13; it is not a committed roadmap item.

eRx & EPCS environment details

EnvSurescriptsPDMP gatewayEPCS signing
DevSurescripts sandbox (test trading partners)Bamboo Health sandboxSoft-token only (Dev HSM)
QASurescripts sandbox (expanded test partner set)Bamboo Health sandbox + LogiCoy sandboxSoft-token only (QA HSM)
UATSurescripts staging (Drummond cert testing)Bamboo Health staging (test patients)Hard token (UAT HSM)
ProdSurescripts production (live trading partners)Bamboo Health prod + LogiCoy prodHard token + soft token (Prod HSM)

eRx & EPCS RBAC notes

Cross-Module Dependencies

See also: eRx & EPCS walkthrough · IC Reference