Skip to main content

Electronic Prescription Service - FHIR API

Access the Electronic Prescription Service (EPS) - the national service used to send electronic prescriptions from GP surgeries to pharmacies.

Overview

Use this API to access the Electronic Prescription Service (EPS) - the national service used to send electronic prescription messages between prescribers and community dispensers.

As a prescriber

You can:

  • encode prescription data
  • create a secondary care (outpatient) prescription
  • cancel a secondary care (outpatient) prescription

You cannot currently use this API to:

  • create a primary care prescription
  • create a secondary care (other than outpatient) prescription
  • create a tertiary care prescription
  • track prescriptions or check a prescription's status

As a dispenser

You can:

  • download a prescription (int/sandbox implementations only)
  • return a prescription (sandbox implementation only)
  • submit a dispense notification to EPS (sandbox implementation only)
  • withdraw a dispense notification (sandbox implementation only)
  • submit a dispense claim (sandbox implementation only)

You cannot currently use this API to:

  • claim for a dispensed prescription
  • track prescriptions or check a prescription's status

Who can use this API

This API can only be used where there is a legal basis to do so. Make sure you have a valid use case before you go too far with your development.

You must do this before you can go live (see ‘Onboarding’ below).

The following APIs also give access to the Electronic Prescription Service:

The following APIs may be required when accessing the Electronic Prescription Service:

API status and roadmap

To see our roadmap, or to suggest, comment or vote on features for this API, see our interactive product backlog.

If you have any other queries, please contact us.

Prescribing API

Prescribing flows for EPS FHIR API are now in a state of technical go-live awaiting our first of type integration.

The API is currently available for sandbox testing and integration testing, but not for production use.

Dispensing API

Download and the mark as dispensed dispensing flows for the EPS FHIR API are in the sandbox environment only, withdraw and return are currently only referenced in this spec.

Technology

This API conforms to the FHIR global standard for health care data exchange. Specifically, it is aligned with FHIR UK Core, which is built on FHIR Release 4.

You don’t need to know much about FHIR to use this API - FHIR APIs are just RESTful APIs that follow specific rules. In particular:

  • array names are singular, for example line not lines for address lines
  • data items that are country-specific and thus not included in the FHIR global base resources are usually wrapped in an extension object

Network access

This API is available on the internet and, indirectly, on the Health and Social Care Network (HSCN). To use this API with NHS smartcards (see below) you do need an HSCN connection, although internet-facing alternatives are available.

For more details see Network access for APIs.

Security and authorisation

Application-restricted access

This access mode is application-restricted, meaning we authenticate the calling application but not the end user.

You can use this access mode as follows:

  • unattended (end user not present), for example as part of a back end process to send prsecriptions to the API
  • attended (end user present) - in which case, you must ensure the end user is authenticated and suitably authorised locally by the calling application

For further details on attended access, see user-restricted access.

To use this access mode, use the following security pattern:

Environment and testing

Purpose URL
Sandbox https://sandbox.api.service.nhs.uk/electronic-prescriptions
Integration test https://int.api.service.nhs.uk/electronic-prescriptions
Production Not yet available

Sandbox testing

Our sandbox environment:

  • is for early developer testing
  • only covers a limited set of scenarios
  • is stateless, so it does not actually persist any updates
  • is open access, so does not allow you to test authorisation

For more details on sandbox testing, or to try out the sandbox using our "Try this API" feature, see the documentation for each endpoint.

Integration testing

Our integration test environment:

  • is for formal integration testing
  • is stateful, so persists updates
  • includes authorisation, with smartcard and non-smartcard options

For more details see integration testing with our RESTful APIs.

Onboarding

You need to get your software approved by us before it can go live with this API. We call this onboarding. We are hoping to make the onboarding process as lightweight and as self-service as possible however it can sometimes be quite long, so it’s worth planning well ahead.

To begin the onboarding process please contact us and request the 'EPS use case form'.

Resources

Use the Digital Medicines Implementation Guide to assist with your integration. This is the FHIR specification for Digital Medicines starting with the assets required for an electronic prescription sent to the EPS.

Errors

API wide errors

HTTP Status Error Code Description
400 MISSING_FIELD A required field is missing within the request, see display field in response.
400 INVALID_VALUE Invalid value in message.
400 INCORRECT_RESOURCETYPE FHIR resource has incorrect resourceType.
404 NOT_FOUND Route not found.

Platform wide errors

HTTP Status Error Code Description
401 ACCESS_DENIED User does not have permission for a particular request.
403 FORBIDDEN Insufficient authorization.
404 NOT_FOUND Resource not found.

For further details on common HTTP status codes, see 5xx status codes

Endpoint overview

Prescribing endpoints

To encode prescription data

POST a prescription-order message to the /FHIR/R4/$prepare endpoint and get the encoded prescription data that requires a signature.

To create a prescription:

  1. Sign the encoded prescription data using the Signing Service API or your existing local signing solution to get the prescription data signed.
  2. Generate a XML-DSig using the signed prescription data (see below).
  3. Put the XML-DSig in a Provenance resource.
  4. Add the Provenance to the prescription-order message.
  5. POST the signed prescription-order message to the /FHIR/R4/$process-message endpoint.

To generate an XML-DSig:

  1. Get the encoded prescription data from the /FHIR/R4/$prepare endpoint of the EPS API.
  2. Get the signature and certificate from the /SignatureResponse endpoint of the Signing Service API.
  3. Assemble the XML-DSig (see the javascript example code below).

Example code to generate an XML-DSig:

To cancel a prescription:

POST a prescription-order-update message to the /FHIR/R4/$process-message endpoint.

Dispensing endpoints

To download a prescription:

POST a Task-release-message to the /FHIR/R4/Task/$release endpoint.

To submit a dispense notification to EPS:

POST a prescription-dispense-notification message to the /FHIR/R4/$process-message endpoint to inform EPS of a partial/successful dispense.

To return a prescription:

POST a Task-dispense-proposal-return message to the /FHIR/R4/Task endpoint.

To withdraw a dispense notification:

POST a Task-dispense-notification-amend message to the /FHIR/R4/Task endpoint.

To make a dispense claim:

POST a dispense-claim message to the /FHIR/R4/$process-message endpoint.


Endpoints: Prescribing

Encode prescription data

post
/FHIR/R4/$prepare

Overview

Use this endpoint to convert a FHIR prescription-order message into HL7 V3 signature fragments which can then be signed by the prescriber.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Body
Required

Content type: application/fhir+json

Example

A valid secondary care prepare request.

Schema

Name Description
object

Response

HTTP status: 200

Successful conversion.

Body

Content type: application/fhir+json

Example

A successful response to a prepare request.

Schema

Name Description
object

A response from the /$prepare endpoint.

resourceType
string
Allowed values: Parameters
parameter
array
oneOf
object
name
string
Allowed values: digest
valueString
string

The Prescription Information that requires signing.

Example: PFNpZ25lZEluZm8geG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L0Nhbm9uaWNhbGl6YXRpb25NZXRob2Q+PFNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSI+PC9TaWduYXR1cmVNZXRob2Q+PFJlZmVyZW5jZT48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L1RyYW5zZm9ybT48L1RyYW5zZm9ybXM+PERpZ2VzdE1ldGhvZCBBbGdv
object
name
string
Allowed values: timestamp
valueString
string date-time
Example: 2021-05-07T14:47:47Z
object
name
string
Allowed values: algorithm
valueString
string
Allowed values: RS1
HTTP status: 4XX

Invalid request.

Body

Content type: application/fhir+json

Example

An error response to a prepare request.

Schema

Name Description
object

Outcome of an operation that does not result in a resource or bundle being returned (for example, error, async/batch submission).

resourceType
string

FHIR Resource Type.

Allowed values: OperationOutcome
Example: OperationOutcome
issue
array

List of issues that have occurred.

Min items: 1
object
severity
string
required

Severity of the error.

Allowed values: fatal, error, warning, information
Example: error
code
string
required

FHIR error code.

Allowed values: invalid, structure, required, value, invariant, security, login, unknown, expired, forbidden, suppressed, processing, not-supported, duplicate, multiple-matches, not-found, deleted, too-long, code-invalid, extension, too-costly, business-rule, conflict, transient, lock-error, no-store, exception, timeout, incomplete, throttled, informational
Example: invalid
details
object

Internal error code.

coding
array
object
read-only
system
string

URI of the coding system specification.

Example: https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode
version
string

Version of the coding system in use.

Example: 1
code
string

Symbol in syntax defined by the system.

Example: INVALID_VALUE
display
string

Representation defined by the system.

Example: Provided value is invalid
expression
string

FHIRPath of element(s) related to the error.

Example: Patient.name.given

Create a new prescription

post
/FHIR/R4/$process-message#prescription-order

Overview

Use this endpoint to send a prescription-order message to EPS.

The effect of calling this endpoint depends on the type of the message, which is determined by the MessageHeader resource. To create a prescription, send a prescription-order message. The message must include a digital signature.

Note that the #prescription-order in the URL has been added to distinguish this from the other operations which can be performed using the $process-message endpoint. It is not required in requests to the API.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Body
Required

Content type: application/fhir+json

Example

A valid secondary care prescription-order message.

Schema

Name Description
object

Response

HTTP status: 200

Successfully submitted.

Body

Content type: application/fhir+json

Example

A successful response to a prescription-order, dispense-notification or dispense-claim request.

Schema

Name Description
object
HTTP status: 4XX

An error occurred as follows:

HTTP status Error code Description
400 BAD_REQUEST Invalid request.
Body

Content type: application/fhir+json

Example

An error response.

Schema

Name Description
object

Cancel a prescription

post
/FHIR/R4/$process-message#prescription-order-update

Overview

Use this endpoint to send a prescription-order-update message to EPS.

The effect of calling this endpoint depends on the type of the message, which is determined by the MessageHeader resource. To cancel a prescription, send a prescription-order-update message.

Note that the #prescription-order-update in the URL has been added to distinguish this from the other operations which can be performed using the $process-message endpoint. It is not required in requests to the API.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Body
Required

Content type: application/fhir+json

Example

A valid secondary care prescription-order-update message.

Schema

Name Description
object

Response

HTTP status: 200

Successfully submitted.

Body

Content type: application/fhir+json

Example

A successful response to a prescription-order-update request.

Schema

Name Description
object
HTTP status: 4XX

An error occurred as follows:

HTTP status Error code Description FHIR type
400 BAD_REQUEST Invalid request. OperationOutcome
400 BAD_REQUEST Invalid request (with additional details). Bundle
Body

Content type: application/fhir+json

Examples

An error response.

An error response with additional details provided.

Schema

Name Description
object

Endpoints: Dispensing

Download prescriptions

post
/FHIR/R4/Task/$release

Overview

Use this endpoint to download prescriptions from Spine prior to being dispensed to a patient. To do this, send a Task-release-message to this endpoint.

The endpoint will return a set of (up to 25) prescriptions associated with the pharmacy that sends the request.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Body
Required

Content type: application/fhir+json

Example

A valid release request.

Schema

Name Description
object

Response

HTTP status: 200

Successfully downloaded a prescription for dispensing.

Body

Content type: application/fhir+json

Example

A successful response to a release request.

Schema

Name Description
object
HTTP status: 4XX

An error occurred as follows:

HTTP status Error code Description
400 BAD_REQUEST Invalid request.
Body

Content type: application/fhir+json

Example

An error response to a release request.

Schema

Name Description
object

Return a downloaded prescription

post
/FHIR/R4/Task#return

Overview

Use this endpoint to return a downloaded prescription to Spine, so that another dispensing system can download it.

The effect of calling this endpoint depends on the Task status. To return a downloaded prescription to EPS, send a Task with a status of rejected. For more information on how to create these messages, see NHSDigital-Task.

Note that the #return in the URL has been added to distinguish this from the other operations which can be performed using the Task endpoint. It is not required in requests to the API.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Response

HTTP status: 200

Action completed successfully.

Body

Content type: application/fhir+json

Example

A successful response to a return request.

Schema

Name Description

A successful response.

HTTP status: 4XX

An error occurred as follows:

HTTP status Error code Description
400 BAD_REQUEST Invalid request.
Body

Content type: application/fhir+json

Example

An error response to a return request.

Claim for a dispensed prescription

post
/FHIR/R4/$process-message#dispense-claim

Overview

Use this endpoint to send a dispense-claim message to EPS.

The effect of calling this endpoint depends on the type of the message, which is determined by the MessageHeader resource. To submit a claim for a dispensed prescription, send a dispense-claim message.

Note that the #dispense-claim in the URL has been added to distinguish this from the other operations which can be performed using the $process-message endpoint. It is not required in requests to the API.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Body
Required

Content type: application/fhir+json

Example

A valid secondary care dispense-claim message.

Schema

Name Description
object

Response

HTTP status: 200

Successfully submitted.

Body

Content type: application/fhir+json

Example

A successful response to a dispense-claim request.

Schema

Name Description
object
HTTP status: 4XX

An error occurred as follows:

HTTP status Error code Description
400 BAD_REQUEST Invalid request.
Body

Content type: application/fhir+json

Example

An error response.

Schema

Name Description
object

Mark a prescription as dispensed

post
/FHIR/R4/$process-message#dispense-notification

Overview

Use this endpoint to send a dispense-notification message to EPS.

The effect of calling this endpoint depends on the type of the message, which is determined by the MessageHeader resource. To mark a prescription as partially or fully dispensed, send a dispense-notification message.

Note that the #dispense-notification in the URL has been added to distinguish this from the other operations which can be performed using the $process-message endpoint. It is not required in requests to the API.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Body
Required

Content type: application/fhir+json

Example

A valid secondary care dispense-notification message.

Schema

Name Description
object

Response

HTTP status: 200

Successfully submitted.

Body

Content type: application/fhir+json

Example

A successful response to a dispense-notification.

Schema

Name Description
object
HTTP status: 4XX

An error occurred as follows:

HTTP status Error code Description
400 BAD_REQUEST Invalid request.
Body

Content type: application/fhir+json

Example

An error response.

Schema

Name Description
object

Withdraw a dispense notification

post
/FHIR/R4/Task#withdraw

Overview

Use this endpoint to withdraw a dispense-notification message, for example in the case that a prescription was marked as dispensed erroneously.

The effect of calling this endpoint depends on the Task status. To withdraw a dispense-notification message from EPS, send a Task with a status of in-progress. For more information on how to create these messages, see NHSDigital-Task.

Note that the #withdraw in the URL has been added to distinguish this from the other operations which can be performed using the Task endpoint. It is not required in requests to the API.

This interaction is only available in the sandbox environment.

Request

Headers
Name Description
Authorization

String (^Bearer\ [[:ascii:]]+$)

An OAuth 2.0 bearer token. Required in all environments except sandbox.

Example: Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM

X-Request-ID

String

A globally unique identifier (GUID) for the request, which we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.

Must be a universally unique identifier (UUID) (ideally version 4). Mirrored back in a response header. If you re-send a failed request, use the same value in this header. Required in all environments except sandbox.

Pattern: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Example: 60E0B220-8136-4CA5-AE46-1D97EF59D068

Required
X-Correlation-ID

String

An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding . characters.

Mirrored back in a response header.

Example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA

Response

HTTP status: 200

Action completed successfully.

Body

Content type: application/fhir+json

Example

A successful response to a withdraw request.

Schema

Name Description

A successful response.

HTTP status: 4XX

An error occurred as follows:

HTTP status Error code Description
400 BAD_REQUEST Invalid request.
Body

Content type: application/fhir+json

Example

An error response to a withdraw request.