A prescription can pass every schema check and still be wrong. The message is valid, the code exists, and the pharmacy system quietly reads it as something the prescriber did not intend. In medicines data the failure is almost never the transport. It is the level of specificity. This article covers how the Dictionary of Medicines and Devices (dm+d) identifies a medicine, how that maps into FHIR, and the build decisions that keep a prescription meaning the same thing from the prescriber to the pharmacy shelf to the claim.
What dm+d is, and where EPS and FHIR fit
dm+d is the national standard for identifying medicinal products and packs in England. Its identifiers are SNOMED CT concepts, and they are governed nationally, so the same code means the same product in every care setting. That stability is why it sits underneath electronic prescribing, dispensing, and medicines analytics.
The Electronic Prescription Service (EPS) is the service that moves prescriptions from prescribers to community pharmacies. It has its own business rules for nomination, tokens, claims, and cancellations. Your product has to respect those rules, and it has to send or receive the medicinal product at the right dm+d level for the job.
FHIR is the modelling layer. The UK Core profiles constrain the international resources to the English context and bind medication concepts to dm+d. A simple way to hold the three together is that dm+d says what the product is, EPS governs how a prescription moves, and FHIR describes it to the system on the other side.
One caution on versions. The UK Core profiles are built on FHIR R4, and some material online still describes STU3 behaviour. Check any example against R4 before you copy it. We come back to one place where this matters below.
The dm+d concept classes
A medicine can be described from the abstract to the concrete, and dm+d has a class for each level.
The Virtual Therapeutic Moiety (VTM) is the active substance with no strength or form. It suits decision support, such as flagging that a patient is on an ACE inhibitor, and it is rarely the right level for a prescription.
The Virtual Medicinal Product (VMP) is a generic product with a strength and a dose form. It is the usual choice for generic prescribing.
The Actual Medicinal Product (AMP) is the branded equivalent, with a named supplier product, strength, and form.
The Virtual and Actual Medicinal Product Packs (VMPP and AMPP) add a specific pack size, generic or branded.
The practical rule is short. If the prescriber cares about what and how strong but not about brand or pack, use the VMP. If a brand matters, use the AMP. If the pack itself matters, for example with inhalers, devices, or count-sensitive packs, use a pack-level concept. Write that rule down once for the whole team, so two engineers do not make different choices for the same scenario.
What the level decides downstream
The concept you choose is a clinical and legal statement, not a formatting choice.
A VMP leaves the pharmacy free to supply an equivalent brand and to pick an appropriate pack. That supports formulary compliance and cost control, and it puts the choice of AMP or AMPP in the dispensing system.
An AMP restricts supply to the named brand. That is correct for narrow therapeutic index drugs and some devices, and it affects stock availability and reimbursement.
A pack-level concept fixes the pack size, and for an AMPP it fixes the brand as well. Ambiguity goes down, and so does the pharmacist's flexibility.
Check the exact levels EPS accepts for each message type against the current NHS England specification for your route. Do not assume every class is valid in every flow.
Mapping dm+d into FHIR resources
Use the resource that matches the job. Medication describes the product. MedicationRequest is the prescription or instruction to supply. MedicationDispense records what was supplied, MedicationAdministration records what was given, and MedicationStatement records reported use. MedicationKnowledge can carry formulary and pack information.
Bind the product to a dm+d SNOMED CT code at the chosen level. Carry the correct SNOMED CT system URI and the numeric dm+d identifier, and populate the code text with the official dm+d term, so a clinician reads what they expect.
A FHIR R4 detail that source material often gets wrong is the brand flag. The R4 Medication resource has no isBrand element. That element existed in STU3. In R4, the VMP or AMP distinction travels in the dm+d concept itself, so do not build logic around a flag that the profile does not carry. For the same reason, do not rely on packaging elements on Medication. Carry pack information through the pack-level dm+d concept and the amount, and use MedicationKnowledge where you need richer pack detail.
There are two ways to connect a request to a product. A reference to a Medication resource gives you reuse, validation, and richer attributes. An inline code is simpler for small messages but makes later decision support harder. Pick one pattern and use it everywhere. Whichever you choose, carry a stable identifier so the product can be reconciled across systems.
Dosage, supply, and repeats
The dose travels with the product, so treat it with the same care.
Use the structured Dosage elements where you can, for dose, timing, route, and additional instructions. Keep a full free-text version alongside them, because real prescriptions contain nuance that codes do not hold. Generate that text from the structured fields where possible, so what a person reads is what the system believes.
For a regimen that changes over time, such as a taper or a titration, use several dosage instructions in sequence, each with its own timing and dose and a clear transition. For a single instruction that varies, such as one or two tablets as required, use a dose range with the as-needed flag and clear text.
Supply details belong in the dispense request. Align quantity with the product. If you prescribe a VMP for 28 days, the quantity should match the intended use, or the system should make clear that the pharmacist will round to a pack. If a prescriber selects a pack-level concept, express quantity as whole packs.
Repeat dispensing needs particular care. The repeat count, validity windows, and grouping must follow EPS business rules, and subsequent issues need to tie back to the original. Confirm the exact representation against the current EPS specification, rather than inferring it from the generic FHIR model. When therapy changes mid-batch, cancel the outstanding issues cleanly and raise a new request with a fresh identifier.
Identifiers, substitution, and safety checks
Identifiers are safety equipment. Give each prescription a stable, unique identifier that survives retries, and use the group identifier to bind its items. Give each line its own identifier and carry both through dispense and claim records, so an item can be traced from authoring to reimbursement. Include organisation identifiers and practitioner identifiers on the referenced resources.
Substitution is a clinical and legal concept, and FHIR gives you an element to express it. A generic VMP normally allows an equivalent brand. A brand-specific AMP where substitution is not appropriate should say so, with the reason recorded. Validate the combination, so a request cannot carry a product class and a substitution flag that contradict each other.
Allergies and intolerances need to be computable against the medicine. Because dm+d sits within SNOMED CT, a VMP can be related to an allergy recorded against a VTM or a specific AMP, which lets software block an unsafe choice and still allow a safe alternative. Carry ingredients and routes on the Medication where they matter.
Plan for the awkward categories before they find you. Specials and extemporaneous preparations can lack the rich attributes of licensed packs. Devices bundled with medicines, such as insulin pens, blur the line between product and device. Controlled drugs have additional legal rules for content and validity. Give each its own branch in the logic and its own test data.
Keeping a medicines build correct over time
dm+d changes. Products are added, discontinued, and inactivated, so a build that was correct at launch drifts without maintenance.
Keep a canonical product catalogue keyed by dm+d code, with the official term, strength, form, ingredients, and pack details, and keep the history of inactivations and replacements. Ingest dm+d updates on a predictable cadence and run an impact check each time, asking which products were inactivated and what replaced them. When a product is inactivated, offer a guided path to the replacement and record the reason for the change on the new request.
Validate incoming codes against current content, and handle an inactive concept gracefully rather than rejecting the whole message. If you hold terminology in your own service, the NHS England Terminology Server is the natural source for validation and expansion, which we cover in a separate article.
Validate payloads against the UK Core profiles in your pipeline, and add your own checks for the rules the profiles cannot express, such as a quantity that does not match the pack, an invalid repeat count, or a substitution flag that conflicts with the product class. Make the error messages usable by a clinician.
Separate the authoring model from the exchange model. Clinicians work in a rich interface, and the payload carries the minimum safe set. Test with realistic data, from simple generics to complex regimens, specials, devices, and controlled drugs. If a case cannot run end to end in a test environment, it is not ready for production.
Where this connects to build work
The closest work we have delivered is an AI prescription intake pipeline on Azure for a UK clinical homecare and specialist pharmacy provider. It reads incoming prescriptions, splits bundled uploads, classifies each by confidence, extracts patient identifiers, and matches each to the right record. A confident match is filed and written back automatically. A low-confidence match goes to a person. At one fulfilment site it handled roughly 700 prescriptions a day, and it cut the route from submission to the pharmacy queue from up to two days by post to minutes.
That is adjacent to this topic, not identical. The pipeline works on prescription documents and patient matching, not on dm+d coding or EPS messaging. The discipline carries across, which is to be explicit about confidence, keep a human in the loop where the system is unsure, and keep an audit trail behind every decision.
If you are building a product that prescribes, dispenses, or reconciles medicines, and you want the dm+d binding, the FHIR modelling, and the clinical safety evidence built together, we build it so it passes assurance, not just the demo.
Get in touch