Skip to main content

Signing Service API

Generate an electronic signature using your smartcard.

Overview

Use this API to digitally sign a prescription from an application that cannot communicate directly with an NHS smartcard reader.

You can make a request to create a signature and retrieve the signature created in response to your request

You cannot currently use this API to:

  • produce signatures using an algorithm other than RS1 (RSASSA-PKCS1-v1_5 with SHA-1)

End users of this API must be authenticated with an NHS smartcard, using the NHS Identity hub.

Using this API

Use this API exclusively for browser-based applications.

To use this API, you must:

  1. Create an RSA key pair with a key length of 4096 bits or greater
  2. Contact us, and provide the following:
  • your public key, which we store in our JSON Web Key Set (JWKS) and give you a Key ID
  • a callback URL which our service can use to notify your system when the signing process is complete

To retrieve the signature:

  1. Run the NHS Identity hub, on the same machine as the web browser used to access the Signing Service Client. In production environment, the NHS Identity hub supports Windows only. In non-production environments, a mock implementation is available for all operating systems. This creates a fake signature which must not be used in production.
  2. Create a JSON Web Token (JWT) containing the Key ID and the data to be signed by using the POST /$prepare endpoint of the Electronic Prescription Service - FHIR API.
  3. Sign the JWT with the RS512 algorithm using your private key.
  4. Send the JWT to the Signing Service using the POST /signaturerequest endpoint. The service responds with a token representing your signature request and a redirect URL.
  5. Redirect the user’s browser to this URL in order to access the Signing Service Client. The Signing Service Client communicates with the NHS Identity hub to generate a signature using an NHS smartcard. Append &mock=true to the redirect URL to access a mock implementation of the NHS Identity hub integration. The Signing Service calls your registered callback URL when the signing process is complete, including the token for the payload.
  6. Send the token received by the callback URL to the GET /signatureresponse endpoint to obtain the signature.

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).

Electronic Prescription Service (FHIR) API - use this if you want to send prescriptions electronically, once they are signed with the Signing Service API.

API status and roadmap

All endpoints are in beta - expect further breaking changes.

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

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.

Technology

This API is RESTful.

End-users of the API require the NHS Identity hub to be installed and running on their local machine.

Network access

This API is available on the internet, although access using NHS smartcards (see below) currently requires a connection to the Health and Social Care Network (HSCN).

Interactions are heavily influenced by the OAuth flow for user authentication:

  • Application flow is controlled predominantly by HTTP redirects issued to the browser
  • The client receives a token representing their signature. This can be exchanged for the actual signature data

Security and authorisation

This API is user-restricted, meaning an end user must be present and authenticated to use it.

The end user must be:

  • a healthcare professional
  • strongly authenticated using an NHS smartcard

The API uses Open ID Connect to authenticate the end user and OAuth 2.0 to authorise the calling system. It supports the following security patterns:

Environments and testing

Purpose URL
Sandbox https://sandbox.api.service.nhs.uk/signing-service
Integration test (smartcard authentication) https://int.api.service.nhs.uk/signing-service
Integration test (simulated authentication) https://int.api.service.nhs.uk/signing-service-no-smartcard
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 store data
  • 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 it does persist data
  • includes authorisation, with smartcard and non-smartcard options

For more details see integration testing with our RESTful APIs.

Onboarding

We are hoping to make the assurance process as lightweight and as self-service as possible.

Endpoints: SignatureRequest

Request a signature

post
/signaturerequest

Overview

Request a signature for an electronic prescription and receive a token in exchange.

Request

Body
Required
Content type: text/plain
Example
Valid JWT
eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0xIn0.eyJwYXlsb2FkIjoiUEZOcFoyNWxaRWx1Wm04K1BFTmhibTl1YVdOaGJHbDZZWFJwYjI1TlpYUm9iMlFnUVd4bmIzSnBkR2h0UFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eU1EQXhMekV3TDNodGJDMWxlR010WXpFMGJpTWlQand2UTJGdWIyNXBZMkZzYVhwaGRHbHZiazFsZEdodlpENDhVMmxuYm1GMGRYSmxUV1YwYUc5a0lFRnNaMjl5YVhSb2JUMGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM4d09TOTRiV3hrYzJsbkkzSnpZUzF6YUdFeElqNDhMMU5wWjI1aGRIVnlaVTFsZEdodlpENDhVbVZtWlhKbGJtTmxQanhVY21GdWMyWnZjbTF6UGp4VWNtRnVjMlp2Y20wZ1FXeG5iM0pwZEdodFBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHlNREF4THpFd0wzaHRiQzFsZUdNdFl6RTBiaU1pUGp3dlZISmhibk5tYjNKdFBqd3ZWSEpoYm5ObWIzSnRjejQ4UkdsblpYTjBUV1YwYUc5a0lFRnNaMjl5YVhSb2JUMGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM4d09TOTRiV3hrYzJsbkkzTm9ZVEVpUGp3dlJHbG5aWE4wVFdWMGFHOWtQanhFYVdkbGMzUldZV3gxWlQ0NVVVaDZVV0ZHYVRKdEwycG5OakZZYTNSRVF6ZE1hM1ZvUkZVOVBDOUVhV2RsYzNSV1lXeDFaVDQ4TDFKbFptVnlaVzVqWlQ0OEwxTnBaMjVsWkVsdVptOCsiLCJhbGdvcml0aG0iOiJSUzEiLCJpYXQiOjE2MTQyNzQwODIsImV4cCI6MTYxNDI3NDY4MiwiYXVkIjoiaHR0cHM6Ly9pbnRlcm5hbC1kZXYuYXBpLnNlcnZpY2UubmhzLnVrL3NpZ25pbmctc2VydmljZSIsImlzcyI6InF2UDlOb1FjT1ZxS3JYRWR0THY4QjBqN3A1Vm1qUERkIiwic3ViIjoiNTU1MDg2Njg5MTA2In0.NvjBUOg6AlkIGnH63m8gjsC-i15GwSgwI09IJUpgvms2YLi5Ny2iDEPNwWu7ST98z29YQN30xDQXtBPPUjMmi6zDhdSqJCPGOD639TYJ_Laj7Xk29J9Dq3e1vRAp4qf1_TCg8dcswlN2TdELIVNZ3WYpfhQbGGgIyRKJ9n9yEb0k4av3peQpfXUfG_BwX21C1j8QV6xjR5szlvTwWZZtvo2KbELXQfHwHjkhJ7HA2gItrkHTxsvszK3T9Pr24-kyREpoID9EQ8lLSPjVaamUUc1dQnET8kdwOndsnJ4jERg1j50GRoNjXfq5LNtNCZ2_OZVbWJuV7WkkJVNM4Oj97s5WbrXzQGZiaaJ0iRHH9Wx0zcJT85vyaWFLk_k7hOFaMbH5SyW4SwAf8WA6zibeUeGgY5AZIZsbg0PW09v3TWB0Vk0ul9hK6Ao0xQIXZdDdbO-nvlOLzO7p_9os1En0fESoNaOUjf1JuJEVumSRO76YxLHGz77DxH-c9Cg0v68M2O_h0J7DRIStYkxMJ9NkcEULEycGOd7O6SaO7egYsE_MEbMsqyv91Zu_GXeS_ZtblB3Nt1P0VkN1xlRu9-2F2RYzebA9nAOlTDW6U2JnpRCavGnILKQheaD9gqbjmmqSXeNweOV6UtsjyqxDeZ4Na34DkHZ51A_VEu6VhiR8r3g
Schema
Name Description
string
A signed JWT containing the data to be signed by the service.

The JWT header must include the following fields:

  • typ - the type of the token. This must be JWT.
  • alg - the algorithm used to sign the token. This must be RS512.
  • kid - the ID of the key which the service uses to verify the JWT signature.

The JWT payload must include the following fields:

  • iss - the issuer of the token. This must be the client ID of your Apigee app.
  • sub - the subject of the token. This must be the SDS user ID or the person requesting the signature.
  • aud - the intended audience of the token. This must be the URL of the Signing Service.
  • exp - the expiry time of the token. This must be at most 10 minutes in the future.
  • iat - the time the token was issued.
  • algorithm - the algorithm which is used to sign the prescription itself (not the JWT). Values are defined in JSON Web Signature and Encryption Algorithms. At present, only RS1 is supported.
  • payload - the payload to be signed, encoded in base64.

The JWT signature must be present, and must use the RS512 algorithm.

Pattern: ^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?$

Response

HTTP status: 200
Successful upload
Body
Content type: application/json
Example
{
  "token" : "ZDk1YjE0NmEtZWQwMi00N2QzLWE3ZjctNWEwMGY2YzI4NTBj",
  "redirectUri" : "https://int.api.service.nhs.uk/signing-service/client?token=ZDk1YjE0NmEtZWQwMi00N2QzLWE3ZjctNWEwMGY2YzI4NTBj"
}
Schema
Name Description
HTTP status: 4XX
Unsuccessful operation
Body
Content type: application/json
Examples
{
  "statusCode" : 404,
  "error" : "Not Found",
  "message" : "No signature request for specified token"
}
{
  "resourceType" : "OperationOutcome",
  "issue" : [ {
    "severity" : "error",
    "code" : "forbidden",
    "details" : {
      "coding" : [ {
        "system" : "https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode",
        "version" : "1",
        "code" : "ACCESS_DENIED",
        "display" : "Invalid Access Token"
      } ]
    }
  } ]
}

Endpoints: SignatureResponse

Retrieve a signature

get
/signatureresponse/{token}

Overview

Retrieve a signature for a given payload token.

Request

Path parameters
Name Description
token
UUID (uuid)
The payload token returned in response to the signature creation request
Required

Response

HTTP status: 200
Successful retrieval
Body
Content type: application/json
Example
{
  "signature" : "XpjsKXPfUW708rGPuOAphlr4/UA23f3bhdBOocEJ17BXV0Jruz1E1KLFQwq37EJfnVo/WCLTSjgkkp0BWj5bG3JjEfj78ZjI1yVSRbfbVXXQX0GLZmiSGJrhWnFZt8cFrxO1MFAtSLmKfyXKzbuHsLTmsHQKpXCRdZnFmKBojLmp7NBr0lLE8Phttu8F2Eaeu2wPQ84p1iNW91fo1H+SFVxC+BRoPI1polXg42ceTjoJ7+FqYPDHfC7nNFIgTYJZlQdboMNbndv6BPDuFq0wusQjDQ4zMZ+8ClpRdt3iKmylXNmKkJA15W0pFbGq0Xnf3S1MXWElkaCIUCdGK2WsPA==",
  "certificate" : "MIIEJDCCAwygAwIBAgIUK3xkEUlRhXPJKNVwryqLZRoNTQQwDQYJKoZIhvcNAQELBQAwRDEOMAwGA1UEChMFSFNDSUMxETAPBgNVBAsTCE9wZW50ZXN0MR8wHQYDVQQDExZFUFMgTm9uLXJlcHVkaWF0aW9uIENBMB4XDTIwMDIyNzEzMDcyMloXDTIyMDIyNjEzMDcyMlowOzEOMAwGA1UEChMFSFNDSUMxGzAZBgNVBAsTElNvbHV0aW9uIEFzc3VyYW5jZTEMMAoGA1UEAxMDRU1VMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0G4Gac7S0mqlHY/sW+EFZZL8AU+FMRrSFIefISocA6DsHePgHpg0tJcdmj3N45VR6FHDrKx5Dg/005R/t8gbuIHF+iI1puTcV9jWPmakkurlVPARmiAy767WPk9mpUolfoHdILKqfIWMzQzW7C4L8vFK55BIeV4/lIDvEpxZ+LHWbkmk/h1dWexupjOTfqTn/Uix+Lat2TpqzYSrM0bep8p8ucndN5sqcm6UkPothsxNEi2Hjkd8aoH1H4KIVwgcBwWe+XrLXK5WarMW0Y9qgQKxMsnvW8oyHa83mkHY+e8OeN/SnqYjkag0I4pvbBTclrGfIScIfTZorVn2WvCIQIDAQABo4IBFTCCAREwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBaAwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMDYGCWCGSAGG+EIBDQQpFidPcGVudGVzdDogT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFAH4ptckOhsUzBfVjt/m05GiO8XRMHsGA1UdIwR0MHKAFNIRvX9omrl7ZXSqEINy6w2rPQduoU+kTTBLMRQwEgYDVQQKEwtOSFMgRGlnaXRhbDERMA8GA1UECxMIT3BlbnRlc3QxIDAeBgNVBAMTF09wZW50ZXN0IFJvb3QgQXV0aG9yaXR5ggkA6u0cXbLqKoQwDQYJKoZIhvcNAQELBQADggEBAEDcrPcdrIC5ufVHra62oGBP/lz5oJq3Ql93Phgw9BDbumPU74P+XgQoO9vw8xO2Yb4+PL7M2BuJo3fDqcDsW+4B4t9mdhWW7lRjN3WcujoLslPz23cfyxCgZnYMMDbOhBrJxVCzYeC6nx6OhkL1V3Yoe+OIyrReUzpzeBwsUX5q802dNaV1yrb6ai2icgxqpY+fOZYFLRefPIqutBK73hnDuxDjI+7ehyFpapfOXVBmLTacLxLF1Dy/7+GIXbdIwbedet4p2IcEaRX0eWT0U//ZJSeBqnOOpXo64DfZtS9Vl2exHbHHqYc0RVNpKImaWVrMydC1qOexjUZSVBVd+Zo="
}
Schema
Name Description
HTTP status: 4XX
Unsuccessful operation
Body
Content type: application/json
Examples
{
  "$ref" : "#/paths/~1signaturerequest/post/responses/4XX/content/application~1json/examples/validationError/value"
}
{
  "$ref" : "#/paths/~1signaturerequest/post/responses/4XX/content/application~1json/examples/authError/value"
}