Why am I getting this error when trying to auth?


I have an NHS Developer account, and have Enabled access to the Hello World and Personal Demographics Service APIs (both application-restricted and healthcare worker). I have uploaded a valid JWKS JSON and a callback URL.

I have also created a signed JWT, using the API Key value from my application in, using my .PEM which I created via BASH.

However, when I try now to use the signed JWT in a POST API to get an access token to https://dev.api.service.nhs.uk/oauth2/token

I have been following this

I am receiving ALWAYS the below in Postman. Am I doing something wrong or missing something claring?


Below are my scripts in Python:

import datetime
import jwt
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
import uuid

# Your header and payload
header = {
    "alg": "RS512",
    "typ": "JWT",
    "kid": "test1"

payload = {
    "iss": "REDACTED",
    "sub": "REDACTED",
    "aud": "https://dev.api.service.nhs.uk/oauth2/token",
    "jti": str(uuid.uuid4()),
    "exp": datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=5)

# Load your RSA private key
with open("C:\\Users\\PhilGlew\\test1.pem", "rb") as key_file:
    private_key = serialization.load_pem_private_key(

# Generate the JWT token
encoded_jwt = jwt.encode(payload, private_key, algorithm="RS512", headers=header)

    encoded_jwt = jwt.encode(payload, private_key, algorithm="RS512", headers=header)
    print("JWT Token:", encoded_jwt)  # To verify the token is generated

    # Save the JWT token to a file
    with open("C:\\Users\\PhilGlew\\jwtToken.txt", "w") as token_file:
        token_file.write(encoded_jwt)  # No need to decode
        print("Token written to jwtToken.txt")  # Confirmation message

except Exception as e:
    print("An error occurred:", e)


import uuid
from time import time
import jwt  # https://github.com/jpadilla/pyjwt

with open("C:\\Users\\PhilGlew\\test1.pem", "r") as f:
  private_key = f.read()

claims = {
  "sub": "REDACTED",
  "iss": "REDACTED",
  "jti": str(uuid.uuid4()),
  "aud": "https://dev.api.service.nhs.uk/oauth2/token",
  "exp": int(time()) + 300, # 5mins in the future

additional_headers = {"kid": "test1"}

j = jwt.encode(
  claims, private_key, algorithm="RS512", headers=additional_headers

can you double check your sub and iss, it should be the api key not the application id

in portal

Security details

Active API keys - and then

Active keys


to rule out code issues I would firstly create the jwt via something like this

and then run your tests against int environment in postman

@NHS england

can we make this clear in the API documentation, it trips alot of people up

the naming convention isnt in line with industry standards imo

Hi @hameed

Thanks for the feedback. We will raise a ticket to investigate improving the documentation.


1 Like