Written by Technical Team | Last updated 15.08.2025 | 22 minute read
Electronic prescribing is one of the quiet workhorses of modern healthcare. It looks simple from the outside—enter a prescription, send it, dispense it—but under the bonnet is a tightly governed ecosystem of standards, assurance processes and security controls. EPS-FHIR sits at the centre of that world. It brings the Electronic Prescription Service together with the HL7® FHIR® standard so prescribing and dispensing systems can exchange prescription information in a structured, machine-readable way while meeting the high bar set for patient safety and data protection across the NHS.
The “FHIR” part defines how data is structured and exchanged: resources such as MedicationRequest, MedicationDispense, Patient, Practitioner, and Organization are represented with consistent fields, codes and relationships. The “EPS” part defines the business rules and workflows—who is allowed to do what, when a prescription is considered legally valid, how cancellations and replacements are handled, the obligations on both prescriber and dispenser, and the auditing required to demonstrate that everything happened correctly. EPS-FHIR marries those two pieces so that systems can speak the same language and also follow the same choreography.
If you are onboarding to EPS-FHIR, you are not only adopting a vocabulary; you are adopting a contract. That contract covers security (how the calling system proves its identity), behaviour (what operations are allowed and under what conditions), non-functional expectations (throughput, latency, error handling) and operational hygiene (monitoring, incident response and change control). Treating onboarding as a one-off technical integration almost always underestimates the depth of the obligation. The organisations that move fastest and suffer the fewest surprises are those that plan for Security and Information Governance from day one, model the workload realistically, and invest early in robust automated tests built directly from the OpenAPI specification.
A final framing point before we dive into the mechanics: FHIR is deliberately flexible; EPS is deliberately specific. You will have freedom in how you design your internal data model and surrounding services, but very little freedom in how you implement EPS’s externally observable behaviour. That’s a good thing; it reduces ambiguity and gives every patient, prescriber and dispenser a more predictable, safer experience.
At the heart of EPS-FHIR onboarding is proving who you are—both as an organisation and as a piece of software. In UK healthcare contexts this typically involves a combination of organisation identifiers (for example, ODS codes for NHS organisations), software identity (the client you register during onboarding), and end-user identity where a person is in the loop. The pattern you will encounter is OAuth 2.0 with OpenID Connect for authorisation, fortified by mutual TLS to bind the token to your client and to protect the transport channel. Tokens advertise scopes that are tightly constrained to the operations your application is approved to perform. Expect to use JWTs signed by a trusted authority, short lifetimes, explicit refresh mechanics and event logging that ties every API call to both a client and a user where relevant.
Where EPS needs to attribute actions to a specific health professional—think signing a prescription or cancelling one—your workflow will include an interactive authentication step for that person. This is not optional decoration: it’s a regulatory requirement and the basis on which accountability is determined. For machine-to-machine operations where no end user is present (for example, a pharmacy system reconciling messages overnight), a separate non-interactive credential is typical, provisioned with narrower scopes and locked to your registered client. In both cases, plan for certificate lifecycle management: rotating keys on a schedule, storing private keys in a Hardware Security Module or equivalent, and automating renewals so they don’t expire at the worst possible time.
A common early onboarding pitfall is conflating “I can get a token” with “I’m authorised to do everything I need.” Tokens are only as useful as the scopes they carry and the access policies behind them. The onboarding checklists usually ask you to declare the precise EPS interactions your system will perform: creating or updating prescription resources, querying status, acknowledging dispensations, or issuing cancellations. If you request broad scopes “just in case,” you will slow down assurance; if you request scopes that are too narrow, your build will stall later. The best route is to model your complete user journeys and map every API call to a specific scope well before you open a ticket with the onboarding team.
Finally, plan for strong correlation and auditing. Every API call should carry a correlation ID that your system logs end-to-end alongside the user identity (if present), the client identity, the token identifier and the operation performed. When incidents happen—and in complex, distributed systems they do—the ability to reconstruct events precisely is what turns a multi-day outage investigation into a ten-minute log query.
Design your security model early:
Anticipate real-world authentication flows:
The OpenAPI Specification (OAS) is more than documentation; it’s the living blueprint of your integration. A high-quality EPS-FHIR OAS file will describe the RESTful surface area in concrete terms: paths (e.g., /MedicationRequest or operation-specific endpoints), methods, expected parameters, authentication requirements, response schemas and standard error payloads. Consuming that specification in your build pipeline accelerates development and raises quality simultaneously. Code generation tools can produce type-safe clients and server stubs that already enforce the right shapes; contract tests can validate that your implementation returns the exact status codes, headers and bodies the contract demands. When the specification is versioned and published reliably, you can also automate breaking-change detection to avoid “silent” drift.
There is a second specification living alongside OAS: the FHIR Implementation Guide, which defines the profiles, value sets and invariants that constrain the base FHIR resources for EPS use. For example, a generic MedicationRequest becomes an EPS prescription with additional required elements, fixed bindings to coding systems, and narrative rules about when certain fields must or must not be present. Treat these profiles as executable rules. Many teams integrate FHIR validation libraries into their API gateways or application services so that requests and responses are checked against the relevant profile before they leave the system. That gives you immediate feedback if a deployment introduced a regression.
The most successful onboarding teams maintain an internal “API contract kit”: a repository that bundles the authoritative OAS file, the FHIR profiles and value sets, example payloads, conformance test fixtures, and a minimal client that exercises each operation. They wire this kit into continuous integration so that every change to their codebase runs contract tests, profile validation and example-driven scenario tests. Over time, the kit becomes the lantern you carry through change—the thing that tells you what changed and whether it’s safe to deploy.
When you read the OAS closely, pay attention to pagination, conditional operations and idempotency. Prescription workflows are sensitive to duplicated requests, race conditions and partial failure. If the API supports conditional If-Match or If-None-Match headers, use them to keep updates safe. If operations are idempotent with a request identifier (for example, a Idempotency-Key or a FHIR Provenance link), implement that consistently across your client and be disciplined about retries: exponential backoff, jitter, and strict upper bounds prevent thundering herds when a service blips.
Build from the spec, not from memory:
Engineer for resilience and clarity:
Every onboarding story is a journey through environments. It usually starts in a local or sandbox space where authentication can be faked or simplified and where you can iterate quickly on payload shape and error handling. The aim at this stage is to become fluent: you want your team to read and write FHIR comfortably, to understand the lifecycle of a prescription, and to get your internal abstractions right. Don’t skip design documentation here; future you will thank present you for a clean resource model and sequence diagrams that match reality.
Next comes a controlled test environment with proper identity, realistic data and representative performance characteristics. This is where you integrate with real authentication flows, receive real tokens with the exact scopes, and discover what your network stack does to mTLS when a proxy sits between your service and the outside world. It’s also where data governance starts to bite: even in test, prescription information is sensitive and your handling of it is subject to audit. Build your retention and redaction rules now. If you need production-like volume to validate cache policies, thread pools and database indices, generate synthetic prescriptions in statistically realistic numbers and shapes rather than cloning production.
Assurance artefacts start to accumulate as you move into formal testing. Expect to provide evidence of secure coding practices, dependency management, penetration testing and vulnerability remediation timelines. You will be asked to show that your business logic follows EPS rules exactly, that you can handle cancellations, substitutions and repeats correctly, and that you don’t degrade the legal intent of the prescriber. The best way to pass these gates smoothly is to treat the assurance body as a partner: they are there to keep patients safe, and your documentation should make that easy to verify. Keep diagrams current, keep your threat model live, and supply test runs that are reproducible by anyone following the readme.
Go-live readiness is partly technical and partly organisational. On the technical side you will finalise endpoints, DNS, certificates and monitoring. On the organisational side you will lock down who is allowed to deploy, who will be paged when the red dashboard lights up at 3 a.m., and how incidents are escalated both internally and to the wider health ecosystem. Run a pre-production exercise where you deliberately cause failure—expire a token, block a certificate, simulate a partial network drop—so your team knows what the alarms look like and how to respond. If you operate in multiple regions or have high availability requirements, practise failover in anger; passive DR is not enough for a service that underpins critical medication.
Once you are live, capacity planning and change control become the rhythm of your operations. Prescriptions are bursty around clinic hours, and the system’s reputation depends on snappy performance during those peaks. Autoscaling works, but only if your statelessness is honest and your cold-start times are short. Cache smartly—especially for reference data and tokens—but never cache prescription states in a way that can make you answer incorrectly after a cancellation or dispense event elsewhere. Releases should be small, reversible, and feature-flagged; dark-launch protocol changes behind negotiation so one deployment does not force everyone else to deploy on the same day.
The human side often determines success. Pharmacists and prescribers have lived reality, and the edge cases they surface will be the ones no test suite imagined. Build fast feedback loops: capture user-reported errors with embedded correlation IDs and the exact OperationOutcome you returned, then reproduce within hours. Publish a humble, plain-English changelog that tells integrators what you changed and why. Nothing builds trust like being predictable, transparent and quick to correct your own mistakes.
Gaining access to EPS-FHIR is inseparable from meeting governance obligations. Information Governance frameworks require you to handle patient data lawfully, fairly and transparently; to minimise data collected and retained; to protect it at rest and in transit; and to ensure availability and integrity. That sounds abstract until your service is the link between a prescription and a life-saving medicine. Put governance into code. Encrypt everything at rest with managed keys. Segment networks so that compromise in your analytics cluster cannot reach production. Use role-based access controls inside your organisation so developers do not routinely see live patient data. Train people and run tabletop exercises; the best time to discover your process gap is Wednesday morning in a white-board session, not Sunday evening when a regulator is on the call.
Operationally, you will live inside an ecosystem. Upstream and downstream systems have their own maintenance windows, incident processes and cultural norms. Publish and subscribe to the right channels, keep your contact lists current, and be a good citizen when something goes wrong. If you must degrade service, degrade safely—fail closed on authorisation, avoid lossy queues for clinical messages, and make your status page meaningful to non-engineers. The measure of a well-onboarded EPS-FHIR integration is not perfect uptime; it is measured by how quickly it detects problems, how gracefully it fails, and how thoroughly it learns.
Credentials underpin everything you can and cannot do in EPS-FHIR. For human-in-the-loop actions, your application will prompt the user to authenticate with a mechanism that binds the real person to the session. In many NHS contexts this is a modern web-based flow using OpenID Connect layered on top of OAuth 2.0, returning an ID token and an access token. Your front end must treat these as sensitive artefacts: store only in secure, HTTP-only cookies or memory, never in local storage, and refresh in the background with short lifetimes. If your UI is native, use the system browser rather than an embedded web view to keep credentials out of your process memory.
Machine-to-machine flows look simpler but carry their own risks. They typically exchange a client assertion (a JWT signed by your private key) for an access token with strictly bounded scopes. That private key must be guarded like the crown jewels: use a hardware-backed keystore where possible, restrict its use to the single service account that owns it, and monitor requests so any anomaly trips an alarm within minutes. Because mTLS is usually required, your platform should support certificate pinning—or at least certificate transparency checks—and rotate certificates on a cadence you can sustain without heroics. Keep a spare certificate pre-registered and test hot swaps so a revocation or a mis-issued certificate is a non-event.
Auditing closes the loop between identity and action. Your audit trail should tell a complete story: who initiated the action, what they attempted, what data they saw, which patient was involved, the exact API endpoint and verb, the request and response identifiers, and the time stamps down to milliseconds with a consistent time source. Don’t forget failures. Unsuccessful authorisation attempts are gold for detecting misuse; validation failures are early warning signs of drifting clients; rate-limit exceedances tell you where your caching or batching strategy is wrong. Store audit logs in a write-once, tamper-evident store and set a retention period that satisfies regulatory expectations without holding data longer than necessary.
A frequent question in onboarding workshops is how to reconcile the legal act of “signing” a prescription with the digital mechanics of sending a MedicationRequest. The answer is that the system must prove that an appropriately authorised prescriber took a deliberate action at a specific time, having seen the relevant clinical context, and that the message received by EPS is bound to that action. In practice, that means the token used to create the resource is linked to the prescriber, your system captured an explicit confirmation step, and the payload contains the required elements (including the prescriber’s identity) in the right shape. Digital signatures at the message level may also be in scope depending on the exact integration pattern; where they are, make sure the keys used for signing are clearly separated from the keys used for transport security.
The very last mile of authentication is the user experience. If your clinicians are forced to re-authenticate too often, they will find workarounds; if they can stay authenticated forever, you will eventually leak a session. Use session timeouts that reflect the sensitivity of the operation and the context of use—shorter for signing and cancellation, longer for read-only lookup—and give clear, respectful prompts that explain why re-authentication is required. The best security is invisible when it can be, obvious when it must be, and always understandable.
One of the simplest ways to make your integration robust is to make the specification executable. Treat the OAS as code. Keep it under version control in your own repository, pinned to an exact upstream version with a cryptographic checksum so you can prove which contract you built against. Write a small gate in your CI that refuses to build if the checksum of the spec has changed without an explicit acknowledgement commit from a human. That guarding step prevents accidental upgrades when an upstream ref is moved and preserves your ability to roll back to known-good combinations of code and contract.
Next, build contract-first tests. For each operation you intend to call or implement, write a test that loads the OAS, constructs an example request from your library of fixtures, runs it against your development instance, and validates the response against the schema in the spec. Keep examples complete and realistic; include edge cases like prescriptions with multiple line items, special dosage instructions, or a cancellation that references a prescription issued by another system. For the FHIR layer, use a validator that understands the EPS profiles and their value sets so you are checking not just shape but clinical semantics: that codes exist in the required system, that mandatory elements are present, and that mutually exclusive fields are respected.
Error handling is the quiet killer of integrations. EPS-aligned FHIR APIs will surface errors using OperationOutcome resources with machine-readable codes and human-readable messages. Parse and propagate both. Your application should show clinicians a clear explanation of what went wrong and what they can do about it, but the logs should record the full OperationOutcome for later analysis. When you discover an error pattern that confuses users—“You cannot cancel a prescription that has already been dispensed,” for example—work with product and clinical safety leads to give targeted guidance in the UI and to create non-blocking guardrails that prevent the action from being attempted in the first place.
Versioning deserves specific attention. FHIR itself has major versions (R4, R5) and EPS will profile a specific base version. At the same time, the OAS for an EPS-aligned API will evolve independently to add endpoints, fields or clarifications. Adopt semantic versioning on your side and set a clear policy: you will accept non-breaking minor updates automatically after passing contract tests, but major updates trigger a project with dedicated time for remediation. Where the API publishes deprecation timelines, build watchers that alert you months in advance so you can schedule the work rather than drop everything later.
Finally, think about observability as a spec-driven concern. If the contract says that successful MedicationDispense acknowledgements are 201 Created with a Location header, add a metric that counts those responses and a monitor that alerts if the rate deviates materially from your traffic profile. If the spec says that certain validation failures must return 422 Unprocessable Entity, expose a dashboard that shows you which ones are rising, which clients are causing them, and which example payloads demonstrate the problem best. The specification did not just tell you how to talk to the API; it told you what to measure.
Onboarding starts before the first line of code is written. Your organisation will need the right registrations and assurances in place to hold and process prescription data. That often means a named senior responsible owner for clinical safety, documented standard operating procedures, and a risk management approach that references recognised standards. If you are a supplier to NHS organisations, expect to complete due-diligence questionnaires and provide evidence of certifications. Get these ducks in a row early; technical progress cannot compensate for missing governance.
With organisational prerequisites in hand, the access journey typically follows a repeatable sequence. You register your application as a client, supply technical contacts, present the outcomes of your threat model and your intended scopes, and receive initial credentials for a non-production environment. You integrate with the authentication flow, confirm that your token carries the expected scopes, and begin to exercise the endpoints behind feature flags. At this stage, stand up a shared “integration journal” where engineers and testers from both sides can see what you attempted, what payloads you sent, and what came back. Nothing accelerates onboarding like clear, asynchronous communication that preserves context.
As confidence grows, you submit evidence for formal assurance. This includes security artefacts (pen-test results and patch timelines), clinical safety artefacts (hazard logs and safety case), and technical conformance (test results demonstrating that your implementation matches the OAS and FHIR profile constraints). You may also be asked to prove non-functional characteristics: that your service responds within a target latency, does not exceed rate limits, and stays within reasonable error budgets under load. Run these load tests with a realistic mix of read and write operations and with failure injected at known weak points—DNS resolution, TLS termination, database connection pools—so your results reflect the world you will actually run in.
The last step before live traffic is often a controlled pilot. Choose sites that are motivated, technically competent and able to provide quick feedback. Keep the pilot narrow in scope—perhaps a subset of prescription types or a limited set of pharmacies—and instrument the path so you can spot anomalies early. Daily stand-ups during the pilot keep everyone honest about what is working and what is not; short feedback loops mean you can correct course before issues grow legs.
After general availability, your obligations do not shrink; they change shape. You must maintain compatibility with evolving specs, rotate keys on agreed schedules, and participate in incident coordination when the wider ecosystem experiences a wobble. Treat your integration as a product with its own roadmap. Publish deprecation notices clearly, provide migration guides with code examples, and give integrators a sandbox where they can test new behaviours months in advance. When you do this well, you reduce the total cost of ownership not just for yourself but for every other system that depends on you.
EPS integrations fail in predictable ways. The first is “spec drift”—assuming the behaviour you saw last year remains accurate today. Guard against it with pinned specs, automated breaking-change detection, and explicit human approval before upgrading. The second is “environment mirage”—tests pass in a permissive sandbox but fail in a hardened pre-production because TLS, mTLS or token binding is different. Make your development environment stricter than production, not looser, so you catch security misconfigurations early.
A third pitfall is insufficient idempotency. Prescription workflows are not friendly to duplicate writes, and network failures can multiply requests. If the API provides request identifiers or supports conditional updates, use them; if it does not, build deduplication into your own service by hashing payloads and keeping a short-lived cache of recent operations keyed by a stable identifier. The fourth pitfall is a brittle user experience around errors. Clinicians will inevitably run into edge cases; if your UI collapses into opaque messages, they will escalate to support and your credibility will suffer. Build copy with clinical input, map known OperationOutcome codes to helpful advice, and provide next-step links to retry or correct data.
The last pitfall is treating security and governance as a hurdle to clear rather than an ongoing discipline. Rotating keys on a Friday afternoon because they expire on Saturday is not a strategy; it is an incident in waiting. Maintain a calendar of certificate and secret expiries, monitor for clock skew across your fleet, and keep a rehearsal playbook for emergency revocations. When you practise these things in daylight, they take minutes; when you improvise them at night, they take hours.
EPS-FHIR onboarding is demanding because what it connects is important. Medication safety is unforgiving of ambiguity, and that is why the process pushes you to be precise: in who you are (authentication), in what you do (authorisation and scopes), in how you talk (OAS and FHIR profiles), and in how you operate (governance and incident response). The good news is that the same disciplines that make onboarding smoother also make your system better. Contract-driven development gives you fewer defects. Strong authentication gives you fewer incidents. Observability tied to the spec gives you faster recovery when something breaks. And respectful, clear communication with the clinical and integration communities gives you the insight you need to improve.
If you are starting today, start with the map. Gather the authoritative OAS and FHIR profiles, write down the user journeys you will support, and list the scopes and operations you will need. Build a minimal client that can authenticate properly, send a well-formed request, and parse a well-formed response. Wrap it in tests that fail loudly if anything deviates from the contract. Then add real-world concerns deliberately: idempotency, pagination, backoff, logging, metrics, dashboards, alarms, and playbooks. When you move into formal assurance, keep your artefacts short, current and reproducible. And when you go live, be the kind of operator everyone wants to depend on: predictable, transparent and, when necessary, humbly swift to put things right.
The result is not only compliance with EPS expectations; it is an integration your clinicians will trust and your patients will never need to think about. That is the point. The best API is the one that turns a complicated world into a dependable click.
Is your team looking for help with EPS integration? Click the button below.
Get in touch