diff --git a/.gitignore b/.gitignore index 6af55f9..fd96800 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ target/ src/main/resources/validation.json src/main/resources/nhs-validation.json src/main/resources/implementationGuides/*.tgz +src/main/resources/static/web/*.* +src/main/resources/static/app/*.* src/uk.nhs.digital.fhir.fwoa.main/resources/*.tgz !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ @@ -38,3 +40,5 @@ build/ ### VS Code ### .vscode/ +/interoperability-standards-tools-skunkworks/.angular/cache/17.1.3/angular-webpack/a1dba4dffcba8d84d9c03b2ef4d54bb9f8f40d2d/0.pack +/interoperability-standards-tools-skunkworks/.angular/cache/17.1.3/angular-webpack/a1dba4dffcba8d84d9c03b2ef4d54bb9f8f40d2d/index.pack diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..793022a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,5 @@ +[submodule "interoperability-standards-tools-skunkworks"] + path = interoperability-standards-tools-skunkworks + url = https://github.com/NHSDigital/interoperability-standards-tools-skunkworks + + diff --git a/Dockerfile b/Dockerfile index 52407bb..8d83b65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,11 @@ -FROM eclipse-temurin:18.0.2 +FROM openjdk:23 VOLUME /tmp -ENV JAVA_OPTS="-Xms128m -Xmx2048m" +ENV JAVA_OPTS="-Xms128m -Xmx8192m" ADD target/fhir-validator.jar fhir-validator.jar +EXPOSE 9001 ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/fhir-validator.jar"] diff --git a/aws-repo-notes.txt b/aws-repo-notes.txt deleted file mode 100644 index 40c0ad7..0000000 --- a/aws-repo-notes.txt +++ /dev/null @@ -1,39 +0,0 @@ -Initial user Setup - -https://nhsd-confluence.digital.nhs.uk/display/AWS/001+-+Use+AWS+CLI+with+MFA - -Logon using MFA - MFA needs replacing in the following - -aws --profile kevin.mayfield1 sts get-session-token --serial-number arn:aws:iam::347250048819:mfa/kevin.mayfield1 --duration-seconds 129600 --token-code MFA - -aws configure --profile default set aws_access_key_id {from above} -aws configure --profile default set aws_secret_access_key {from above} -aws configure --profile default set aws_session_token - -Then run - -aws sts assume-role --role-arn arn:aws:iam::365027538941:role/NHSDAdminRole --role-session-name bob - -And repeat configure step? - -aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin 365027538941.dkr.ecr.eu-west-2.amazonaws.com - -mvn clean install - -docker build -t fhir-validator-r4 . - -docker tag fhir-validator-r4:latest 365027538941.dkr.ecr.eu-west-2.amazonaws.com/fhir-validator-r4:latest -docker tag fhir-validator-r4:latest 365027538941.dkr.ecr.eu-west-2.amazonaws.com/fhir-validator-r4:6.8.0 - -docker push 365027538941.dkr.ecr.eu-west-2.amazonaws.com/fhir-validator-r4:latest - -docker push 365027538941.dkr.ecr.eu-west-2.amazonaws.com/fhir-validator-r4:6.8.0 - - - -### Cloud Formation Notes - -Command is - -aws cloudformation deploy --template-file C:\Development\NHSDigital\validation-service-fhir-r4\cloudfront\IOPSValidation.yaml --stack-name test-stack - diff --git a/cloudformation/IOPSValidation.yaml b/cloudformation/IOPSValidation.yaml index 5027d95..b10f72c 100644 --- a/cloudformation/IOPSValidation.yaml +++ b/cloudformation/IOPSValidation.yaml @@ -1,5 +1,5 @@ AWSTemplateFormatVersion: "2010-09-09" -Description: NHS Digital IOPS FHIR Services +Description: NHS England Interoperability Standards FHIR Services Parameters: OntoClientId: diff --git a/deploy-notes.md b/deploy-notes.md new file mode 100644 index 0000000..af6e0a6 --- /dev/null +++ b/deploy-notes.md @@ -0,0 +1,27 @@ +## General + +Do this first if app has changed or app code is not present in the static folder +(may need to run `git submodule update` (maybe `git submodule foreach git pull`) and `npm install`) + +Run these separately as the angular has different location for the swagger pages + +### docker + +`mvn clean install -P dockerBuild,dockerRelease` + +### AWS ECR + +`aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin 365027538941.dkr.ecr.eu-west-2.amazonaws.com` + +`mvn clean install -P dockerBuild,awsRelease` + +Run + +`mvn spring-boot:run` and check correct app is working on http://localhost:9001 + +### Cloud Formation Notes + +Do not use + +aws cloudformation deploy --template-file C:\Development\NHSDigital\validation-service-fhir-r4\cloudfront\IOPSValidation.yaml --stack-name test-stack + diff --git a/interoperability-standards-tools-skunkworks b/interoperability-standards-tools-skunkworks new file mode 160000 index 0000000..14adf87 --- /dev/null +++ b/interoperability-standards-tools-skunkworks @@ -0,0 +1 @@ +Subproject commit 14adf87e737aade3004b1826b72346d1d7ba2f49 diff --git a/pom.xml b/pom.xml index 5459d1f..190f611 100644 --- a/pom.xml +++ b/pom.xml @@ -1,209 +1,549 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.7.12 - - - - uk.nhs.england - IOPS-FHIR-Validation-Service - 6.8.0 - IOPS-FHIR-Validation-Service - HAPI FHIR Validator using Spring Boot - - 1.8 - 1.6.21 - 6.8.0 - 2.1.12 - 2.0.30 - 2.15.2 - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-oauth2-client - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.jetbrains.kotlin - kotlin-reflect - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - com.fasterxml.jackson.module - jackson-module-kotlin - ${jackson_databind_version} - - - - com.fasterxml.jackson.core - jackson-core - ${jackson_databind_version} - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - com.vaadin.external.google - android-json - - - - - ca.uhn.hapi.fhir - hapi-fhir-base - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-client - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-server - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-structures-r4b - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-structures-r4 - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-structures-dstu3 - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-validation - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-validation-resources-r4 - ${fhir.version} - - - ca.uhn.hapi.fhir - hapi-fhir-validation-resources-dstu3 - ${fhir.version} - - - io.github.microutils - kotlin-logging - 1.8.0.1 - - - - org.json - json - 20231013 - - - - io.swagger.core.v3 - swagger-models - ${swagger_version} - - - io.swagger.core.v3 - swagger-core - ${swagger_version} - - - - io.swagger.parser.v3 - swagger-parser - ${parser_version} - - - org.springdoc - springdoc-openapi-ui - 1.6.4 - - - com.github.ben-manes.caffeine - caffeine - 2.5.5 - - - - com.amazonaws - aws-java-sdk-cognitoidp - 1.12.225 - - - com.amazonaws - aws-java-sdk-sqs - 1.12.252 - - - - fhir-validator - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/test/kotlin - - - org.springframework.boot - spring-boot-maven-plugin - - - org.jetbrains.kotlin - kotlin-maven-plugin - - - -Xjsr305=strict - - - spring - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 9 - 9 - - - - + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.2 + + + uk.nhs.england + IOPS-FHIR-Validation-Service + 7.0.3 + IOPS-FHIR-Validation-Service + HAPI FHIR Validator using Spring Boot + + + 20 + 1.9.22 + 7.0.2 + 2.2.20 + 2.1.20 + 2.16.1 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + com.fasterxml.jackson.module + jackson-module-kotlin + ${jackson_databind_version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson_databind_version} + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + com.vaadin.external.google + android-json + + + + + + jakarta.activation + jakarta.activation-api + 2.1.2 + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + + + jakarta.ejb + jakarta.ejb-api + 4.0.1 + + + jakarta.interceptor + jakarta.interceptor-api + 2.1.0 + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + + + jakarta.transaction + jakarta.transaction-api + 2.0.1 + + + jakarta.websocket + jakarta.websocket-client-api + 2.1.1 + + + jakarta.ws.rs + jakarta.ws.rs-api + 3.1.0 + + + jakarta.xml.bind + jakarta.xml.bind-api + 4.0.1 + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + javax.json + javax.json-api + 1.1.4 + + + javax.xml.bind + jaxb-api + 2.3.1 + + + + ca.uhn.hapi.fhir + hapi-fhir-base + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-client + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-server + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-r4b + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-r4 + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu3 + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-r4 + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-dstu3 + ${fhir.version} + + + ca.uhn.hapi.fhir + hapi-fhir-caching-caffeine + ${fhir.version} + + + io.github.microutils + kotlin-logging + 1.8.0.1 + + + + org.json + json + 20230227 + + + + + io.swagger.core.v3 + swagger-models + ${swagger_version} + + + io.swagger.core.v3 + swagger-core + ${swagger_version} + + + + + io.swagger.parser.v3 + swagger-parser + ${parser_version} + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.3.0 + + + + com.github.ben-manes.caffeine + caffeine + 2.5.5 + + + + + com.amazonaws + aws-java-sdk-cognitoidp + 1.12.225 + + + com.amazonaws + aws-java-sdk-sqs + 1.12.252 + + + + + xalan + xalan + 2.7.3 + + + xalan + serializer + 2.7.2 + + + + net.sf.saxon + Saxon-HE + 12.4 + + + + + + org.xhtmlrenderer + flying-saucer-pdf + 9.1.22 + + + + + + fhir-validator + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + org.springframework.boot + spring-boot-maven-plugin + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + -Xjsr305=strict + + + spring + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + + + + + + + dockerBuild + + + + + maven-resources-plugin + + + copy-resources + validate + + copy-resources + + + ${basedir}/target + + + src/main/docker + true + + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.6 + + + prepare-package + package + false + + + + + + + + + + + + run + + + + + + + + true + + + + + dockerRelease + + + + maven-clean-plugin + 3.0.0 + + + + src/main/resources/static + false + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + running ng build docker + generate-sources + + exec + + + interoperability-standards-tools-skunkworks + ng + + build + --configuration + docker + --output-path + ../src/main/resources/static + --base-href + ./ + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.6 + + + install + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + + + + awsRelease + + + + maven-clean-plugin + 3.0.0 + + + + src/main/resources/static + false + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + running ng build production + generate-sources + + exec + + + interoperability-standards-tools-skunkworks + ng + + build + --configuration + production + --output-path + ../src/main/resources/static + --base-href + ./ + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.6 + + + install + false + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + + + diff --git a/readme.md b/readme.md index 19e37c8..bfffa68 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,6 @@ -### IOPS FHIR Validator +# FHIR Development and Testing (FHIR Validation) Skunkworks + +This project is classed as **skunkworks** it is not built for operational use. [Demonstration Server](http://lb-fhir-validator-924628614.eu-west-2.elb.amazonaws.com/) @@ -12,10 +14,95 @@ It has several configuration options: a. To validate against a supplied set of FHIR Implementation Guides (NPM packages are supplied). b. To validate against a configured FHIR Implementation Guide (NPM package are retrieved by the service and configured via environment variables) -c. Optionally validate using the NHS Digital Ontology Service (configured via environment variables). +c. Optionally validate using the NHS England Ontology Service (configured via environment variables). The configuration is aimed at supporting different use cases. For example the lambda version with no ontology support is aimed at performing basic FHIR validation checks. This may just be FHIR core and schema validation but can also test against UKCore profiles. +## Docker Image + +**Experimental** + +https://hub.docker.com/repository/docker/thorlogic/fhir-validator-r4/general +This should work without the configuration below +Port is expected to be 9001 + +`docker run --env=fhir.igs=fhir.r4.ukcore.stu3.currentbuild#0.0.8-pre-release --env=fhir.server.baseUrl=http://localhost -p 80:9001 --runtime=runc thorlogic/fhir-validator-r4:latest` + +Using an ontology service + +`docker run --env=fhir.igs=fhir.r4.ukcore.stu3.currentbuild#0.0.8-pre-release --env=fhir.server.baseUrl=http://localhost --env=terminology.authorization.clientId=REPLACE_ME_CLIENT_ID --env=terminology.authorization.clientSecret=REPLACE_ME_CLIENT_SECRET --env=terminology.authorization.tokenUrl=https://ontology.nhs.uk/authorisation/auth/realms/nhs-digital-terminology/protocol/openid-connect/token --env=terminology.url=https://ontology.nhs.uk/authoring/fhir/ -p 80:9001 --runtime=runc thorlogic/fhir-validator-r4:latest` + + + +## Environmental Variables + + +#### fhir.server.baseUrl + +This controls the url used in the OAS/Swagger page. This needs to be altered when hosted on AWS (for example the base url of the ELB service). + +`http://localhost:9001` + +### fhir.igs + +Optional - Use to override the default packages. Package id and version can be found from FHIR Implementation Guides. + +`fhir.r4.ukcore.stu3.currentbuild#0.0.3-pre-release,uk.nhsengland.r4#0.0.0-prerelease` + +### Ontology Server Configuration + +Optional, if Ontoserver is to be used then all parameters are required. +Configuation details are found by requesting a [System-to-system account] from NHS England Ontology Server + +#### terminology.authorization.clientId + +#### terminology.authorization.clientSecret + +#### terminology.authorization.tokenUrl + +`https://ontology.nhs.uk/authorisation/auth/realms/nhs-digital-terminology/protocol/openid-connect/token` + +#### terminology.url + +'https://ontology.nhs.uk/authoring/fhir/; + +#### terminology.loincUrl + +Experimental - do not use + +'https://r4.ontoserver.csiro.au/fhir' + +### AWS FHIRWorks Configuration + +Can be obtained from NHS England Interoperability Standards + +#### aws.apiKey + +AWS FHIRWorks API Gateway Key + +#### aws.clientId + +AWS Cognito token clientId + +#### aws.pass + +AWS FHIR Works password + +#### aws.tokenUrl + +AWS Cognito token url + +#### aws.user + +AWS FHIR Works username + +#### cdr.fhirServer + +Url of AWS FHIRWorks in API Gateway +https://cnuc9zdola.execute-api.eu-west-2.amazonaws.com/dev + + + diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRLOINCServer.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRLOINCServer.kt new file mode 100644 index 0000000..d6985b7 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRLOINCServer.kt @@ -0,0 +1,57 @@ +package uk.nhs.england.fhirvalidator + +import ca.uhn.fhir.context.FhirContext +import ca.uhn.fhir.rest.api.EncodingEnum +import ca.uhn.fhir.rest.server.RestfulServer +import com.amazonaws.services.sqs.AmazonSQS +import com.fasterxml.jackson.databind.ObjectMapper +import jakarta.servlet.annotation.WebServlet +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import uk.nhs.england.fhirvalidator.configuration.FHIRServerProperties +import uk.nhs.england.fhirvalidator.configuration.MessageProperties +import uk.nhs.england.fhirvalidator.interceptor.AWSAuditEventLoggingInterceptor +import uk.nhs.england.fhirvalidator.interceptor.ValidationInterceptor +import uk.nhs.england.fhirvalidator.providerLOINC.CodeSystemLOINCProvider +import uk.nhs.england.fhirvalidator.providerLOINC.QuestionnaireProvider +import uk.nhs.england.fhirvalidator.providerLOINC.ValueSetLOINCProvider +import java.util.* + + +@ConditionalOnProperty(prefix = "services", name = ["LOINC"]) +@WebServlet("/LOINC/R4/*", loadOnStartup = 1) +class FHIRLOINCServer( + @Qualifier("R4") fhirContext: FhirContext, + @Autowired(required = false) val sqs : AmazonSQS?, + val questionnaireProvider: QuestionnaireProvider, + val codeSystemLOINCProvider: CodeSystemLOINCProvider, + val valueSetLOINCProvider: ValueSetLOINCProvider, + val fhirServerProperties: FHIRServerProperties, + private val messageProperties: MessageProperties +) : RestfulServer(fhirContext) { + + override fun initialize() { + super.initialize() + + TimeZone.setDefault(TimeZone.getTimeZone("UTC")) + registerProvider(questionnaireProvider) + registerProvider(codeSystemLOINCProvider) + registerProvider(valueSetLOINCProvider) + + val awsAuditEventLoggingInterceptor = + AWSAuditEventLoggingInterceptor( + this.fhirContext, + fhirServerProperties, + messageProperties, + sqs + ) + interceptorService.registerInterceptor(awsAuditEventLoggingInterceptor) + + val validationInterceptor = ValidationInterceptor(fhirContext,messageProperties) + interceptorService.registerInterceptor(validationInterceptor) + + isDefaultPrettyPrint = true + defaultResponseEncoding = EncodingEnum.JSON + } +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4BRestfulServer.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4BRestfulServer.kt index 7726e2a..ceaad0a 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4BRestfulServer.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4BRestfulServer.kt @@ -3,13 +3,16 @@ package uk.nhs.england.fhirvalidator import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.rest.api.EncodingEnum import ca.uhn.fhir.rest.server.RestfulServer +import jakarta.servlet.annotation.WebServlet import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import uk.nhs.england.fhirvalidator.providerR4B.CapabilityStatementInterceptorR4B import uk.nhs.england.fhirvalidator.providerR4B.MedicinalProductDefinitionProviderR4B import uk.nhs.england.fhirvalidator.providerR4B.PackagedProductDefinitionProviderR4B import java.util.* -import javax.servlet.annotation.WebServlet + +@ConditionalOnProperty(prefix = "services", name = ["R4B"]) @WebServlet("/FHIR/R4B/*", loadOnStartup = 1) class FHIRR4BRestfulServer( @Qualifier("R4B") fhirContext: FhirContext, diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4RestfulServer.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4RestfulServer.kt index 385d7eb..5721cba 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4RestfulServer.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRR4RestfulServer.kt @@ -6,23 +6,29 @@ import ca.uhn.fhir.rest.api.EncodingEnum import ca.uhn.fhir.rest.server.RestfulServer import com.amazonaws.services.sqs.AmazonSQS import com.fasterxml.jackson.databind.ObjectMapper +import jakarta.servlet.annotation.WebServlet import org.hl7.fhir.utilities.npm.NpmPackage import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import uk.nhs.england.fhirvalidator.configuration.FHIRServerProperties import uk.nhs.england.fhirvalidator.configuration.MessageProperties import uk.nhs.england.fhirvalidator.interceptor.AWSAuditEventLoggingInterceptor import uk.nhs.england.fhirvalidator.interceptor.CapabilityStatementInterceptor import uk.nhs.england.fhirvalidator.interceptor.ValidationInterceptor +import uk.nhs.england.fhirvalidator.model.FHIRPackage import uk.nhs.england.fhirvalidator.provider.* import java.util.* -import javax.servlet.annotation.WebServlet -@WebServlet("/FHIR/R4/*", loadOnStartup = 1) + + +@ConditionalOnProperty(prefix = "services", name = ["R4"]) +@WebServlet + ("/FHIR/R4/*", loadOnStartup = 1) class FHIRR4RestfulServer( @Qualifier("R4") fhirContext: FhirContext, @Autowired(required = false) val sqs : AmazonSQS?, - val objectMapper: ObjectMapper, + val fhirPackage: List, private val validateR4Provider: ValidateR4Provider, private val openAPIProvider: OpenAPIProvider, private val markdownProvider: MarkdownProvider, @@ -36,8 +42,7 @@ class FHIRR4RestfulServer( private val namingSystemProvider: NamingSystemProvider, private val valueSetProvider: ValueSetProvider, private val codeSystemProvider: CodeSystemProvider, - - private val npmPackages: List, + private val compostionProvider: CompostionProvider, @Qualifier("SupportChain") private val supportChain: IValidationSupport, val fhirServerProperties: FHIRServerProperties, private val messageProperties: MessageProperties @@ -61,10 +66,11 @@ class FHIRR4RestfulServer( registerProvider(namingSystemProvider) registerProvider(valueSetProvider) registerProvider(codeSystemProvider) + registerProvider(compostionProvider) - registerInterceptor(CapabilityStatementInterceptor(this.fhirContext, objectMapper, supportChain, fhirServerProperties)) + registerInterceptor(CapabilityStatementInterceptor(this.fhirContext, fhirPackage, supportChain, fhirServerProperties)) val awsAuditEventLoggingInterceptor = diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRSTU3RestfulServer.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRSTU3RestfulServer.kt index 5201edc..7f4de6f 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRSTU3RestfulServer.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/FHIRSTU3RestfulServer.kt @@ -5,11 +5,13 @@ import ca.uhn.fhir.context.support.IValidationSupport import ca.uhn.fhir.rest.api.EncodingEnum import ca.uhn.fhir.rest.server.RestfulServer import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import uk.nhs.england.fhirvalidator.providerSTU3.ConversionProviderSTU3 import uk.nhs.england.fhirvalidator.providerSTU3.ValidateProviderSTU3 import java.util.* -import javax.servlet.annotation.WebServlet +import jakarta.servlet.annotation.WebServlet +@ConditionalOnProperty(prefix = "services", name = ["STU3"]) @WebServlet("/FHIR/STU3/*", loadOnStartup = 1) class FHIRSTU3RestfulServer( @Qualifier("STU3") fhirContext: FhirContext, diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/FhirValidatorApplication.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/FhirValidatorApplication.kt index 0a1399b..414d860 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/FhirValidatorApplication.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/FhirValidatorApplication.kt @@ -12,7 +12,7 @@ import uk.nhs.england.fhirvalidator.configuration.* @SpringBootApplication @ServletComponentScan -@EnableConfigurationProperties(TerminologyValidationProperties::class,FHIRServerProperties::class) +@EnableConfigurationProperties(TerminologyValidationProperties::class,FHIRServerProperties::class, ServicesProperties::class) open class FhirValidatorApplication : ApplicationRunner { companion object : KLogging() diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ApplicationConfiguration.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ApplicationConfiguration.kt index cee3857..4f0abac 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ApplicationConfiguration.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ApplicationConfiguration.kt @@ -9,15 +9,16 @@ import com.amazonaws.services.sqs.model.AmazonSQSException import com.amazonaws.services.sqs.model.CreateQueueRequest import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Qualifier -import org.springframework.boot.web.servlet.FilterRegistrationBean import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.web.client.RestTemplate import org.springframework.web.cors.CorsConfiguration +import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource +import uk.nhs.england.fhirvalidator.interceptor.BasicAuthInterceptor import uk.nhs.england.fhirvalidator.interceptor.CognitoAuthInterceptor -import uk.nhs.england.fhirvalidator.util.CorsFilter -import javax.servlet.Filter +import java.util.* + @Configuration open class ApplicationConfiguration( @@ -25,6 +26,7 @@ open class ApplicationConfiguration( ) { private val logger = LoggerFactory.getLogger(MessageProperties::class.java) + @Bean("R4") open fun fhirR4Context(): FhirContext { val fhirContext = FhirContext.forR4Cached() @@ -51,27 +53,27 @@ open class ApplicationConfiguration( return RestTemplate() } - @Bean - open fun corsFilter(): FilterRegistrationBean<*>? { - val source = UrlBasedCorsConfigurationSource() - val config = CorsConfiguration() - config.allowCredentials = true - config.addAllowedOrigin("*") - config.addAllowedHeader("*") - config.addAllowedMethod("*") - source.registerCorsConfiguration("/**", config) - val bean: FilterRegistrationBean<*> = FilterRegistrationBean(CorsFilter()) - bean.order = 0 - return bean - } @Bean - fun getAWSclient(cognitoIdpInterceptor: CognitoAuthInterceptor?, messageProperties: MessageProperties, @Qualifier("R4") ctx : FhirContext): IGenericClient? { + fun getAWSclient( + cognitoIdpInterceptor: CognitoAuthInterceptor?, + messageProperties: MessageProperties, + @Qualifier("R4") ctx: FhirContext + ): IGenericClient? { val client: IGenericClient = ctx.newRestfulGenericClient(messageProperties.getCdrFhirServer()) client.registerInterceptor(cognitoIdpInterceptor) return client } + @Bean + fun getBasicAuth( + messageProperties: MessageProperties, + fhirServerProperties: FHIRServerProperties, + @Qualifier("R4") ctx: FhirContext + ): BasicAuthInterceptor { + return BasicAuthInterceptor(messageProperties, fhirServerProperties, ctx) + } + @Bean fun getSQS(): AmazonSQS? { @@ -100,4 +102,6 @@ open class ApplicationConfiguration( } + + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/FHIRServerProperties.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/FHIRServerProperties.kt index 09d9831..792c5a5 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/FHIRServerProperties.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/FHIRServerProperties.kt @@ -1,21 +1,24 @@ package uk.nhs.england.fhirvalidator.configuration import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.boot.context.properties.ConstructorBinding -@ConstructorBinding + @ConfigurationProperties(prefix = "fhir") data class FHIRServerProperties( var server: Server, - var ig: Package? + //var ig: Package?, + var igs: String? ) { data class Server( var baseUrl: String, var name: String, var version: String ) + /* data class Package( var name: String, var version: String ) + + */ } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/MessageProperties.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/MessageProperties.kt index 55067e7..cba6e66 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/MessageProperties.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/MessageProperties.kt @@ -34,6 +34,7 @@ open class MessageProperties { val AWS_QUEUE_ENABLED = "aws.queueEnabled" val AWS_VALIDATION_SUPPORT = "aws.validationSupport" val CDR_FHIR_SERVER = "cdr.fhirServer" + val LOINC_FHIR_SERVER = "loinc.fhirServer" val NPM_FHIR_SERVER = "npm.fhirServer" val VALIDATION_FHIR_SERVER = "validation.fhirServer" @@ -133,10 +134,6 @@ open class MessageProperties { } else value.toInt() } - private fun ?> getPropertyEnum(thePropertyName: String, theEnumType: Class, theDefaultValue: T): T { - val value = getProperty(thePropertyName, theDefaultValue!!.name) - return java.lang.Enum.valueOf(theEnumType, value) as T - } fun getEmailEnabled(): Boolean? { @@ -241,6 +238,9 @@ open class MessageProperties { fun getCdrFhirServer(): String? { return getProperty(CDR_FHIR_SERVER) } + fun getLOINCFhirServer(): String? { + return getProperty(LOINC_FHIR_SERVER) + } fun getNPMFhirServer(): String? { return getProperty(NPM_FHIR_SERVER) } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OAuth2ClientConfiguration.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OAuth2ClientConfiguration.kt index 484a03f..c34be37 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OAuth2ClientConfiguration.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OAuth2ClientConfiguration.kt @@ -21,7 +21,7 @@ open class OAuth2ClientConfiguration(private val terminologyValidationProperties return ClientRegistration.withRegistrationId(REGISTRATION_ID) .clientId(authorization.clientId) .clientSecret(authorization.clientSecret) - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .tokenUri(authorization.tokenUrl) .build() diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OpenApiConfig.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OpenApiConfig.kt index 6854cdb..de6b7b3 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OpenApiConfig.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/OpenApiConfig.kt @@ -2,7 +2,7 @@ package uk.nhs.england.fhirvalidator.configuration import ca.uhn.fhir.context.FhirContext -import io.swagger.v3.oas.models.ExternalDocumentation +import com.fasterxml.jackson.databind.ObjectMapper import io.swagger.v3.oas.models.OpenAPI import io.swagger.v3.oas.models.Operation import io.swagger.v3.oas.models.PathItem @@ -22,20 +22,26 @@ import io.swagger.v3.oas.models.servers.Server import org.springframework.beans.factory.annotation.Qualifier import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import uk.nhs.england.fhirvalidator.util.FHIRExamples +import org.springframework.core.io.ClassPathResource +import uk.nhs.england.fhirvalidator.model.SimplifierPackage +import uk.nhs.england.fhirvalidator.util.OASExamples @Configuration -open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { +open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext, + val objectMapper: ObjectMapper, + val servicesProperties: ServicesProperties, + val fhirServerProperties: FHIRServerProperties, + val terminologyValidationProperties: TerminologyValidationProperties + ) { var VALIDATION = "Validation" var UTILITY = "Utility" - var EXPANSION = "ValueSet Expansion (inc. Filtering)" + var CONFORMANCE = "FHIR Package Queries" - val SVCM_98 = "Lookup Code" var MEDICATION_DEFINITION = "Experimental - FHIR R4B Medication Definition" var EXPERIMENTAL = "Experimental" - var TERMINOLOGY = "Terminology" + var ONTOLOGY = "Terminology Services" @Bean open fun customOpenAPI( @@ -46,13 +52,26 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { val oas = OpenAPI() .info( Info() - .title("Conformance Support (R4)") + .title(fhirServerProperties.server.name) .version(fhirServerProperties.server.version) - .description(fhirServerProperties.server.name - + "\n " - + "\n [UK Core Implementation Guide (fhir.r4.ukcore.stu3.currentbuild)](https://simplifier.net/guide/ukcoreversionhistory?version=current)" - + "\n\n [NHS Digital Implementation Guide](https://simplifier.net/guide/nhsdigital)" - ) + .description( + "This server is a **proof of concept**, it contains experimental features and so not is recommended for live use. \n It is used internally by NHS England Interoperability Standards to support delivery of HL7 FHIR. \n" + + "\n For official HL7 FHIR Validators, see:" + + "\n - [HL7 FHIR Validator](https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Validator) A command line utilty" + + "\n - [Validator GUI](https://validator.fhir.org/) A web based application " + + "\n\n This server is preconfigured with the following FHIR Implementation Packages: \n\n" + + " | Package | Version | Implementation Guide | \n" + + " |---|---|---| \n" + + getPackages() + + "\n\n This is an implementation of FHIR Validation [Asking a FHIR Server](https://hl7.org/fhir/R4/validation.html#op) and is built using [HAPI FHIR Validation](https://hapifhir.io/hapi-fhir/docs/validation/introduction.html). This is the same code base as the [official HL7 Validator](https://github.com/hapifhir/org.hl7.fhir.validator-wrapper), the main differences are: \n" + + "\n - Configuration and code to support code validation using NHS England Terminology Server." + + "\n - Support for validating **FHIR Messages** against definitions held in **FHIR MessageDefinition**" + + "\n - Default profile support configured via **FHIR CapabilityStatement**" + + "\n\n ### Terminology Testing (Coding)\n" + + "\n\n This server uses services from [NHS England Termonology Server](https://digital.nhs.uk/services/terminology-server) to perform terminology verification. The UK SNOMED CT version used for FHIR Validation is set by this ontology service. \n" + + "\n\n ### Open Source" + + "\n\n Source code [GitHub](https://github.com/NHSDigital/IOPS-FHIR-Validation-Service)" + ) .termsOfService("http://swagger.io/terms/") .license(License().name("Apache 2.0").url("http://springdoc.org")) ) @@ -67,29 +86,28 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { .description("[Validation](https://www.hl7.org/fhir/R4/validation.html)") ) - oas.addTagsItem(io.swagger.v3.oas.models.tags.Tag() - .name(EXPANSION) - .description("[expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html)") - ) - oas.addTagsItem(io.swagger.v3.oas.models.tags.Tag() - .name(SVCM_98) - .description("[lookup](https://www.hl7.org/fhir/R4/operation-codesystem-lookup.html)") - ) - - oas.addTagsItem( - io.swagger.v3.oas.models.tags.Tag() - .name(TERMINOLOGY) - ) + if (terminologyValidationProperties.url !== null ) { + oas.addTagsItem( + io.swagger.v3.oas.models.tags.Tag() + .name(ONTOLOGY) + ) + } val examples = LinkedHashMap() examples.put("Patient PDS", - Example().value(FHIRExamples().loadExample("Patient-PDS.json",ctx)) + Example().value(OASExamples().loadFHIRExample("Patient-PDS.json",ctx)) + ) + examples.put("FHIR Message - Diagnostics Report (Unsolicited Observations)", + Example().value(OASExamples().loadFHIRExample("Bundle-message-Diagnostics-unsolicited-observations.json",ctx)) + ) + examples.put("FHIR Message - Diagnostics Request (Laboratory Order)", + Example().value(OASExamples().loadFHIRExample("Bundle-message-Diagnostics-laboratory-order.json",ctx)) ) - examples.put("Encounter converted from HL7 v2", - Example().value(FHIRExamples().loadExample("Encounter-ADTA03.json",ctx)) + examples.put("FHIR Message - Medications Request (Prescription Order)", + Example().value(OASExamples().loadFHIRExample("Bundle-message-Medications-prescription-order.json",ctx)) ) - examples.put("Bundle - FHIR Messge example", - Example().value(FHIRExamples().loadExample("Bundle-message.json",ctx)) + examples.put("FHIR Message - Medications Event (Dispense Notification)", + Example().value(OASExamples().loadFHIRExample("Bundle-message-Medications-dispense-notification.json",ctx)) ) val validateItem = PathItem() .post( @@ -97,29 +115,23 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { .addTagsItem(VALIDATION) .summary( "The validate operation checks whether the attached content would be acceptable either generally, as a create, an update or as a delete to an existing resource.") - .description("Validating a resource means, checking that the following aspects of the resource are valid: \n" - + " - **Structure:** Check that all the content in the resource is described by the specification, and nothing extra is present \n" - + " - **Cardinality:** Check that the cardinality of all properties is correct (min & max) \n" - + " - **Value Domains:** Check that the values of all properties conform to the rules for the specified types (including checking that enumerated codes are valid) \n" - + " - **Coding/CodeableConcept bindings:** Check that codes/displays provided in the Coding/CodeableConcept types are valid \n" - + " - **Invariants:** Check that the invariants (co-occurrence rules, etc.) have been followed correctly \n" - + " - **Profiles:** Check that any rules in profiles have been followed (including those listed in the Resource.meta.profile, or in CapabilityStatement, or in an ImplementationGuide, or otherwise required by context) \n" - + " - **Questionnaires:** Check that a QuestionnaireResponse is valid against its matching Questionnaire \n" - + " \n \n" - + "The validate operation checks whether the attached content would be acceptable either generally, as a create, an update or as a delete to an existing resource. \n" - + "Note that this operation is not the only way to validate resources - see [Validating Resources](https://www.hl7.org/fhir/R4/validation.html) for further information. \n" - + "\n" - + "The official URL for this operation definition is \n" - + " **http://hl7.org/fhir/OperationDefinition/Resource-validate** ") .responses(getApiResponsesXMLJSON_JSONDefault()) .addParametersItem(Parameter() .name("profile") .`in`("query") .required(false) .style(Parameter.StyleEnum.SIMPLE) - .description("The uri that identifies the profile. If no profile uri is supplied, NHS Digital defaults will be used.") - .schema(StringSchema().format("token")) - .example("https://fhir.hl7.org.uk/StructureDefinition/UKCore-Patient")) + .description("The uri that identifies the profile (e.g. https://fhir.hl7.org.uk/StructureDefinition/UKCore-Patient). If no profile uri is supplied, NHS England defaults will be used.") + // Removed example profile + .schema(StringSchema().format("token"))) + .addParametersItem(Parameter() + .name("imposeProfile") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("`true | false`. Selected true will also validate the resource against the imposeProfile listed in this servers CapabilityStatement") + // Removed example profile + .schema(StringSchema().format("token"))) .requestBody(RequestBody().content(Content() .addMediaType("application/fhir+json", MediaType() .examples(examples) @@ -207,202 +219,256 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { oas.path("/FHIR/R4/MessageDefinition",getPathItem(CONFORMANCE,"MessageDefinition", "Message Definition", "url" , "https://fhir.nhs.uk/MessageDefinition/prescription-order", "")) - // SVCM - - // ITI-95 Query Value Set - var pathItem = getPathItem(getTerminologyTagName(TERMINOLOGY),"ValueSet", "Value Set", "url" , "https://fhir.nhs.uk/ValueSet/NHSDigital-MedicationRequest-Code", - "This transaction is used by the Terminology Consumer to find value sets based on criteria it\n" + - "provides in the query parameters of the request message, or to retrieve a specific value set. The\n" + - "request is received by the Terminology Repository. The Terminology Repository processes the\n" + - "request and returns a response of the matching value sets.") - oas.path("/FHIR/R4/ValueSet",pathItem) - - // ITI 96 Query Code System - - pathItem = getPathItem(getTerminologyTagName(TERMINOLOGY),"CodeSystem", "Code System", "url", "https://fhir.nhs.uk/CodeSystem/NHSD-API-ErrorOrWarningCode", - "This transaction is used by the Terminology Consumer to solicit information about code systems " + - "whose data match data provided in the query parameters on the request message. The request is " + - "received by the Terminology Repository. The Terminology Repository processes the request and " + - "returns a response of the matching code systems.") - oas.path("/FHIR/R4/CodeSystem",pathItem) - - // ITI 97 Expand Value Set [ - oas.path("/FHIR/R4/ValueSet/\$expand",PathItem() - .get( - Operation() - .addTagsItem(getTerminologyTagName(EXPANSION)) - .summary("Expand a Value Set") - .description("This transaction is used by the Terminology Consumer to expand a given ValueSet to return the\n" + - "full list of concepts available in that ValueSet. The request is received by the Terminology\n" + - "Repository. The Terminology Repository processes the request and returns a response of the\n" + - "expanded ValueSet. \n\n" + - "FHIR Definition [expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html) " - ) - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("url") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("A canonical reference to a value set. The server must know the value set (e.g. it is defined explicitly in the server's value sets, or it is defined implicitly by some code system known to the server") - .schema(StringSchema().format("uri")) - .example("https://fhir.hl7.org.uk/ValueSet/UKCore-MedicationPrecondition")) - .addParametersItem(Parameter() - .name("filter") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("(EXPERIMENTAL - ValueSet must be in UKCore or NHSDigital IG) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") - .schema(StringSchema()) - .example("Otalgia")) + if (terminologyValidationProperties.url !== null) { + // SVCM + + // ITI-95 Query Value Set + var pathItem = getPathItem( + getTerminologyTagName(ONTOLOGY), + "ValueSet", + "Value Set", + "url", + "https://fhir.nhs.uk/ValueSet/NHSDigital-MedicationRequest-Code", + "This transaction is used by the Terminology Consumer to find value sets based on criteria it\n" + + "provides in the query parameters of the request message, or to retrieve a specific value set. The\n" + + "request is received by the Terminology Repository. The Terminology Repository processes the\n" + + "request and returns a response of the matching value sets." ) - .post( - Operation() - .addTagsItem(getTerminologyTagName(EXPANSION)) - .summary("The definition of a value set is used to create a simple collection of codes suitable for use for data entry or validation. Body should be a FHIR ValueSet").responses(getApiResponses()) - .description("[expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html)") - .responses(getApiResponsesXMLJSON_JSONDefault()) - .requestBody(RequestBody().content(Content() - .addMediaType("application/fhir+json",MediaType().schema(StringSchema()._default("{}"))) - .addMediaType("application/fhir+xml",MediaType().schema(StringSchema())) - )) + oas.path("/FHIR/R4/ValueSet", pathItem) + + // ITI 96 Query Code System + + pathItem = getPathItem( + getTerminologyTagName(ONTOLOGY), + "CodeSystem", + "Code System", + "url", + "https://fhir.nhs.uk/CodeSystem/NHSD-API-ErrorOrWarningCode", + "This transaction is used by the Terminology Consumer to solicit information about code systems " + + "whose data match data provided in the query parameters on the request message. The request is " + + "received by the Terminology Repository. The Terminology Repository processes the request and " + + "returns a response of the matching code systems." ) - ) - val eclItem = PathItem() - .get( - Operation() - .addTagsItem(getTerminologyTagName(EXPANSION)) - .summary("Expand a SNOMED CT ecl statement.") - .description("This internally uses ValueSet [expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html) operation.") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("ecl") - .`in`("query") - .required(true) - .style(Parameter.StyleEnum.SIMPLE) - .description("A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") - .schema(StringSchema()) - .example("< 19829001 |Disorder of lung| AND < 301867009 |Edema of trunk|")) - .addParametersItem(Parameter() - .name("count") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") - .schema(StringSchema()) - .example("10")) - .addParametersItem(Parameter() - .name("filter") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("(EXPERIMENTAL - ValueSet must be in UKCore or NHSDigital IG) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") - .schema(StringSchema())) - + oas.path("/FHIR/R4/CodeSystem", pathItem) + + // ITI 97 Expand Value Set [ + oas.path( + "/FHIR/R4/ValueSet/\$expand", PathItem() + .get( + Operation() + .addTagsItem(getTerminologyTagName(ONTOLOGY)) + .summary("Expand a Value Set") + .description( + "This transaction is used by the Terminology Consumer to expand a given ValueSet to return the\n" + + "full list of concepts available in that ValueSet. The request is received by the Terminology\n" + + "Repository. The Terminology Repository processes the request and returns a response of the\n" + + "expanded ValueSet. \n\n" + + "FHIR Definition [expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html) " + ) + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("url") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("A canonical reference to a value set. The server must know the value set (e.g. it is defined explicitly in the server's value sets, or it is defined implicitly by some code system known to the server") + .schema(StringSchema().format("uri")) + .example("https://fhir.hl7.org.uk/ValueSet/UKCore-MedicationPrecondition") + ) + .addParametersItem( + Parameter() + .name("filter") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("(EXPERIMENTAL - ValueSet must be in UKCore or NHSDigital IG) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") + .schema(StringSchema()) + .example("Otalgia") + ) + ) + .post( + Operation() + .addTagsItem(getTerminologyTagName(ONTOLOGY)) + .summary("The definition of a value set is used to create a simple collection of codes suitable for use for data entry or validation. Body should be a FHIR ValueSet") + .responses(getApiResponses()) + .description("[expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html)") + .responses(getApiResponsesXMLJSON_JSONDefault()) + .requestBody( + RequestBody().content( + Content() + .addMediaType( + "application/fhir+json", + MediaType().schema(StringSchema()._default("{}")) + ) + .addMediaType("application/fhir+xml", MediaType().schema(StringSchema())) + ) + ) + ) ) + val eclItem = PathItem() + .get( + Operation() + .addTagsItem(getTerminologyTagName(ONTOLOGY)) + .summary("Expand a SNOMED CT ecl statement.") + .description("This internally uses ValueSet [expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html) operation.") + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("ecl") + .`in`("query") + .required(true) + .style(Parameter.StyleEnum.SIMPLE) + .description("A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") + .schema(StringSchema()) + .example("< 19829001 |Disorder of lung| AND < 301867009 |Edema of trunk|") + ) + .addParametersItem( + Parameter() + .name("count") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") + .schema(StringSchema()) + .example("10") + ) + .addParametersItem( + Parameter() + .name("filter") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("(EXPERIMENTAL - ValueSet must be in UKCore or NHSDigital IG) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") + .schema(StringSchema()) + ) - oas.path("/FHIR/R4/ValueSet/\$expandEcl",eclItem) - - val searchItem = PathItem() - .get( - Operation() - .addTagsItem(getTerminologyTagName(EXPANSION)) - .summary("Search SNOMED CT for a term.") - .description("This internally uses ValueSet [expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html) operation.") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("filter") - .`in`("query") - .required(true) - .style(Parameter.StyleEnum.SIMPLE) - .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") - .schema(StringSchema()) - .example("Otalgia")) - .addParametersItem(Parameter() - .name("count") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") - .schema(StringSchema()) - .example("10")) - .addParametersItem(Parameter() - .name("includeDesignations") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") - .schema(BooleanSchema()) - .example("true")) - .addParametersItem(Parameter() - .name("property") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("(EXPERIMENTAL) Properties to return.") - .schema(StringSchema()) - .example("sufficientlyDefined,inactive,parent")) + ) - ) + oas.path("/FHIR/R4/ValueSet/\$expandEcl", eclItem) + + val searchItem = PathItem() + .get( + Operation() + .addTagsItem(getTerminologyTagName(ONTOLOGY)) + .summary("Search SNOMED CT for a term.") + .description("This internally uses ValueSet [expand](https://www.hl7.org/fhir/R4/operation-valueset-expand.html) operation.") + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("filter") + .`in`("query") + .required(true) + .style(Parameter.StyleEnum.SIMPLE) + .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") + .schema(StringSchema()) + .example("Otalgia") + ) + .addParametersItem( + Parameter() + .name("count") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") + .schema(StringSchema()) + .example("10") + ) + .addParametersItem( + Parameter() + .name("includeDesignations") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("(EXPERIMENTAL) A text filter that is applied to restrict the codes that are returned (this is useful in a UI context).") + .schema(BooleanSchema()) + .example("true") + ) + .addParametersItem( + Parameter() + .name("property") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("(EXPERIMENTAL) Properties to return.") + .schema(StringSchema()) + .example("sufficientlyDefined,inactive,parent") + ) - oas.path("/FHIR/R4/ValueSet/\$expandSCT",searchItem) + ) - // Lookup Code [ITI-98] - val lookupItem = PathItem() - .get( - Operation() - .addTagsItem(getTerminologyTagName(SVCM_98)) - .summary("Lookup a Code in a Value Set") - .description("This transaction is used by the Terminology Consumer to lookup a given code to return the full " + - "details. The request is received by the Terminology Repository. The Terminology Repository " + - "processes the request and returns a response of the code details as a Parameters Resource." + - "\n\nFHIR Definition [lookup](https://www.hl7.org/fhir/R4/operation-codesystem-lookup.html)") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("code") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The code that is to be located. If a code is provided, a system must be provided") - .schema(StringSchema().format("code")) - .example("15517911000001104")) - .addParametersItem(Parameter() - .name("system") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The system for the code that is to be located") - .schema(StringSchema().format("url")) - .example("http://snomed.info/sct")) - .addParametersItem(Parameter() - .name("version") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The version of the system, if one was provided in the source data") - .schema(StringSchema())) - .addParametersItem(Parameter() - .name("coding") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The system for the code that is to be located") - .schema(StringSchema().format("Coding"))) - .addParametersItem(Parameter() - .name("date") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The date for which the information should be returned.") - .schema(StringSchema().format("dateTime"))) - .addParametersItem(Parameter() - .name("displayLanguage") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The requested language for display (see \$expand.displayLanguage)") - .schema(StringSchema().format("code"))) - /* .addParametersItem(Parameter() + oas.path("/FHIR/R4/ValueSet/\$expandSCT", searchItem) + + // Lookup Code [ITI-98] + val lookupItem = PathItem() + .get( + Operation() + .addTagsItem(getTerminologyTagName(ONTOLOGY)) + .summary("Lookup a Code in a Value Set") + .description( + "This transaction is used by the Terminology Consumer to lookup a given code to return the full " + + "details. The request is received by the Terminology Repository. The Terminology Repository " + + "processes the request and returns a response of the code details as a Parameters Resource." + + "\n\nFHIR Definition [lookup](https://www.hl7.org/fhir/R4/operation-codesystem-lookup.html)" + ) + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("code") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The code that is to be located. If a code is provided, a system must be provided") + .schema(StringSchema().format("code")) + .example("15517911000001104") + ) + .addParametersItem( + Parameter() + .name("system") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The system for the code that is to be located") + .schema(StringSchema().format("url")) + .example("http://snomed.info/sct") + ) + .addParametersItem( + Parameter() + .name("version") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The version of the system, if one was provided in the source data") + .schema(StringSchema()) + ) + .addParametersItem( + Parameter() + .name("coding") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The system for the code that is to be located") + .schema(StringSchema().format("Coding")) + ) + .addParametersItem( + Parameter() + .name("date") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The date for which the information should be returned.") + .schema(StringSchema().format("dateTime")) + ) + .addParametersItem( + Parameter() + .name("displayLanguage") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The requested language for display (see \$expand.displayLanguage)") + .schema(StringSchema().format("code")) + ) + /* .addParametersItem(Parameter() .name("property") .`in`("query") .required(false) @@ -411,182 +477,214 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { .description("A property that the client wishes to be returned in the output. If no properties are specified, the server chooses what to return.") .schema(StringSchema().format("code").maxItems(10)) .example("code display property fullySpecifiedName")) */ - ) - - oas.path("/FHIR/R4/CodeSystem/\$lookup",lookupItem) - - // Validate Code [ITI-99] - - val validateCodeItem = PathItem() - .get( - Operation() - .addTagsItem(getTerminologyTagName(VALIDATION)) - .summary("Validate that a coded value is in the set of codes allowed by a value set.") - .description("This transaction is used by the Terminology Consumer to validate the existence of a given code " + - "in a value set or code system. The request is received by the Terminology Repository. The " + - "Terminology Repository processes the request and returns a response as a Parameters Resource." + - "\n\nFHIR Definition [validate-code](https://www.hl7.org/fhir/R4/operation-valueset-validate-code.html)") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("url") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("Value set Canonical URL. The server must know the value set (e.g. it is defined explicitly in the server's value sets, or it is defined implicitly by some code system known to the server") - .schema(StringSchema().format("uri")) - //.example("https://fhir.nhs.uk/ValueSet/NHSDigital-MedicationRequest-Code") - ) - .addParametersItem(Parameter() - .name("code") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The code that is to be validated. If a code is provided, a system or a context must be provided.") - .schema(StringSchema().format("code")) - .example("15517911000001104")) - .addParametersItem(Parameter() - .name("system") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The system for the code that is to be validated") - .schema(StringSchema().format("uri")) - .example("http://snomed.info/sct")) - .addParametersItem(Parameter() - .name("display") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The display associated with the code, if provided. If a display is provided a code must be provided. If no display is provided, the server cannot validate the display value, but may choose to return a recommended display name using the display parameter in the outcome. Whether displays are case sensitive is code system dependent") - .schema(StringSchema()) - .example("Methotrexate 10mg/0.2ml solution for injection pre-filled syringes")) - ) - oas.path("/FHIR/R4/ValueSet/\$validate-code",validateCodeItem) - - // Query Concept Map [ITI-100] - - oas.path("/FHIR/R4/ConceptMap",getPathItem(getTerminologyTagName(TERMINOLOGY),"ConceptMap", "Concept Map", "url" , "https://fhir.nhs.uk/ConceptMap/eps-issue-code-to-fhir-issue-type", - "This transaction is used by the Terminology Consumer that supports the Translate Option to " + - "solicit information about concept maps whose data match data provided in the query parameters " + - "on the request message. The request is received by the Terminology Repository that supports the " + - "Translate Option. The Terminology Repository processes the request and returns a response of " + - "the matching concept maps.")) - - - // Terminology Misc - - val subsumesItem = PathItem() - .get( - Operation() - .addTagsItem(EXPERIMENTAL) - .summary("Test the subsumption relationship between code A and code B given the semantics of subsumption in the underlying code system ") - .description("[subsumes](https://hl7.org/fhir/R4/codesystem-operation-subsumes.html)") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("codeA") - .`in`("query") - .required(true) - .style(Parameter.StyleEnum.SIMPLE) - .description("The \"A\" code that is to be tested.") - .schema(StringSchema().format("code")) - .example("15517911000001104")) - .addParametersItem(Parameter() - .name("codeB") - .`in`("query") - .required(true) - .style(Parameter.StyleEnum.SIMPLE) - .description("The \"B\" code that is to be tested.") - .schema(StringSchema().format("code")) - .example("15513411000001100")) - .addParametersItem(Parameter() - .name("system") - .`in`("query") - .required(true) - .style(Parameter.StyleEnum.SIMPLE) - .description("The code system in which subsumption testing is to be performed. This must be provided unless the operation is invoked on a code system instance") - .schema(StringSchema()) - .example("http://snomed.info/sct")) - - ) - - oas.path("/FHIR/R4/CodeSystem/\$subsumes",subsumesItem) - - + ) - // MEDICATION DEFINITION + oas.path("/FHIR/R4/CodeSystem/\$lookup", lookupItem) - val medicineItem = PathItem() - .get( - Operation() - .addTagsItem(MEDICATION_DEFINITION) - .summary("EXPERIMENTAL A medicinal product, being a substance or combination of substances that is intended to treat, prevent or diagnose a disease, or to restore, correct or modify physiological functions by exerting a pharmacological, immunological or metabolic action.") - .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("name") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The full product name") - .schema(StringSchema()) - .example("Methotrexate 5mg")) - ) - oas.path("/FHIR/R4B/MedicinalProductDefinition",medicineItem) + // Validate Code [ITI-99] - val medicineReadItem = PathItem() - .get( - Operation() - .addTagsItem(MEDICATION_DEFINITION) - .summary("EXPERIMENTAL A medicinal product, being a substance or combination of substances that is intended to treat, prevent or diagnose a disease, or to restore, correct or modify physiological functions by exerting a pharmacological, immunological or metabolic action.") - .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("id") - .`in`("path") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The product dm+d/SNOMED CT code") - .schema(StringSchema()) - .example("39720311000001101")) + val validateCodeItem = PathItem() + .get( + Operation() + .addTagsItem(getTerminologyTagName(ONTOLOGY)) + .summary("Validate that a coded value is in the set of codes allowed by a value set.") + .description( + "This transaction is used by the Terminology Consumer to validate the existence of a given code " + + "in a value set or code system. The request is received by the Terminology Repository. The " + + "Terminology Repository processes the request and returns a response as a Parameters Resource." + + "\n\nFHIR Definition [validate-code](https://www.hl7.org/fhir/R4/operation-valueset-validate-code.html)" + ) + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("url") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("Value set Canonical URL. The server must know the value set (e.g. it is defined explicitly in the server's value sets, or it is defined implicitly by some code system known to the server") + .schema(StringSchema().format("uri")) + //.example("https://fhir.nhs.uk/ValueSet/NHSDigital-MedicationRequest-Code") + ) + .addParametersItem( + Parameter() + .name("code") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The code that is to be validated. If a code is provided, a system or a context must be provided.") + .schema(StringSchema().format("code")) + .example("15517911000001104") + ) + .addParametersItem( + Parameter() + .name("system") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The system for the code that is to be validated") + .schema(StringSchema().format("uri")) + .example("http://snomed.info/sct") + ) + .addParametersItem( + Parameter() + .name("display") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The display associated with the code, if provided. If a display is provided a code must be provided. If no display is provided, the server cannot validate the display value, but may choose to return a recommended display name using the display parameter in the outcome. Whether displays are case sensitive is code system dependent") + .schema(StringSchema()) + .example("Methotrexate 10mg/0.2ml solution for injection pre-filled syringes") + ) + ) + oas.path("/FHIR/R4/ValueSet/\$validate-code", validateCodeItem) + + // Query Concept Map [ITI-100] + + oas.path( + "/FHIR/R4/ConceptMap", getPathItem( + getTerminologyTagName(ONTOLOGY), + "ConceptMap", + "Concept Map", + "url", + "https://fhir.nhs.uk/ConceptMap/eps-issue-code-to-fhir-issue-type", + "This transaction is used by the Terminology Consumer that supports the Translate Option to " + + "solicit information about concept maps whose data match data provided in the query parameters " + + "on the request message. The request is received by the Terminology Repository that supports the " + + "Translate Option. The Terminology Repository processes the request and returns a response of " + + "the matching concept maps." + ) ) - oas.path("/FHIR/R4B/MedicinalProductDefinition/{id}",medicineReadItem) - val medicinePackItem = PathItem() - .get( - Operation() - .addTagsItem(MEDICATION_DEFINITION) - .summary("A medically related item or items, in a container or package..") - .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("name") - .`in`("query") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("A name for this package.") - .schema(StringSchema()) - .example("Methotrexate 5mg")) - ) - oas.path("/FHIR/R4B/PackagedProductDefinition",medicinePackItem) - val medicinePackReadItem = PathItem() - .get( - Operation() - .addTagsItem(MEDICATION_DEFINITION) - .summary("EXPERIMENTAL A medically related item or items, in a container or package..") - .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") - .responses(getApiResponses()) - .addParametersItem(Parameter() - .name("id") - .`in`("path") - .required(false) - .style(Parameter.StyleEnum.SIMPLE) - .description("The product pack dm+d/SNOMED CT code") - .schema(StringSchema()) - .example("1029811000001106")) - ) - oas.path("/FHIR/R4B/PackagedProductDefinition/{id}",medicinePackReadItem) + // Terminology Misc + + val subsumesItem = PathItem() + .get( + Operation() + .addTagsItem(EXPERIMENTAL) + .summary("Test the subsumption relationship between code A and code B given the semantics of subsumption in the underlying code system ") + .description("[subsumes](https://hl7.org/fhir/R4/codesystem-operation-subsumes.html)") + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("codeA") + .`in`("query") + .required(true) + .style(Parameter.StyleEnum.SIMPLE) + .description("The \"A\" code that is to be tested.") + .schema(StringSchema().format("code")) + .example("15517911000001104") + ) + .addParametersItem( + Parameter() + .name("codeB") + .`in`("query") + .required(true) + .style(Parameter.StyleEnum.SIMPLE) + .description("The \"B\" code that is to be tested.") + .schema(StringSchema().format("code")) + .example("15513411000001100") + ) + .addParametersItem( + Parameter() + .name("system") + .`in`("query") + .required(true) + .style(Parameter.StyleEnum.SIMPLE) + .description("The code system in which subsumption testing is to be performed. This must be provided unless the operation is invoked on a code system instance") + .schema(StringSchema()) + .example("http://snomed.info/sct") + ) + ) + oas.path("/FHIR/R4/CodeSystem/\$subsumes",subsumesItem) + } + + + if (servicesProperties.R4B) { + + // MEDICATION DEFINITION + + val medicineItem = PathItem() + .get( + Operation() + .addTagsItem(MEDICATION_DEFINITION) + .summary("EXPERIMENTAL A medicinal product, being a substance or combination of substances that is intended to treat, prevent or diagnose a disease, or to restore, correct or modify physiological functions by exerting a pharmacological, immunological or metabolic action.") + .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("name") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The full product name") + .schema(StringSchema()) + .example("Methotrexate 5mg") + ) + ) + oas.path("/FHIR/R4B/MedicinalProductDefinition", medicineItem) + + val medicineReadItem = PathItem() + .get( + Operation() + .addTagsItem(MEDICATION_DEFINITION) + .summary("EXPERIMENTAL A medicinal product, being a substance or combination of substances that is intended to treat, prevent or diagnose a disease, or to restore, correct or modify physiological functions by exerting a pharmacological, immunological or metabolic action.") + .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("id") + .`in`("path") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The product dm+d/SNOMED CT code") + .schema(StringSchema()) + .example("39720311000001101") + ) + ) + oas.path("/FHIR/R4B/MedicinalProductDefinition/{id}", medicineReadItem) + + val medicinePackItem = PathItem() + .get( + Operation() + .addTagsItem(MEDICATION_DEFINITION) + .summary("A medically related item or items, in a container or package..") + .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("name") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("A name for this package.") + .schema(StringSchema()) + .example("Methotrexate 5mg") + ) + ) + oas.path("/FHIR/R4B/PackagedProductDefinition", medicinePackItem) + + val medicinePackReadItem = PathItem() + .get( + Operation() + .addTagsItem(MEDICATION_DEFINITION) + .summary("EXPERIMENTAL A medically related item or items, in a container or package..") + .description("[Medication Definition Module](https://www.hl7.org/fhir/medication-definition-module.html)") + .responses(getApiResponses()) + .addParametersItem( + Parameter() + .name("id") + .`in`("path") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("The product pack dm+d/SNOMED CT code") + .schema(StringSchema()) + .example("1029811000001106") + ) + ) + oas.path("/FHIR/R4B/PackagedProductDefinition/{id}", medicinePackReadItem) + } // Hidden oas.path("/FHIR/R4/metadata",PathItem() @@ -622,6 +720,13 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { oas.path("/FHIR/R4/StructureMap",getPathItem(CONFORMANCE, "StructureMap", "Structure Map", "url" , "http://fhir.nhs.uk/StructureMap/MedicationRepeatInformation-Extension-3to4", "")) + val examplesOAS = LinkedHashMap() + examplesOAS.put("Imaging API", + Example().value(OASExamples().loadOASExample("Imaging.json",ctx)) + ) + examplesOAS.put("PDS API", + Example().value(OASExamples().loadOASExample("PDS.json",ctx)) + ) val verifyOASItem = PathItem() .post( Operation() @@ -629,11 +734,48 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { .summary("Verifies a self contained OAS file for FHIR Conformance. Response format is the same as the FHIR \$validate operation") .description("This is a proof of concept.") .responses(getApiResponsesRAWJSON()) + .requestBody(RequestBody().content(Content() + .addMediaType("application/json",MediaType().examples(examplesOAS) + .schema(StringSchema())) + .addMediaType("application/x-yaml",MediaType().schema(StringSchema()))) + ) + ) + oas.path("/FHIR/R4/\$verifyOAS",verifyOASItem) + + val convertOASItem = PathItem() + .post( + Operation() + .addTagsItem(EXPERIMENTAL) + .summary("Converts OAS in YAML to JSON format") + .description("This is a proof of concept.") + .responses(getApiResponsesRAWJSON()) .requestBody(RequestBody().content(Content() .addMediaType("application/x-yaml",MediaType().schema(StringSchema())) - .addMediaType("application/json",MediaType().schema(StringSchema())))) + .addMediaType("application/json",MediaType().examples(examplesOAS) + .schema(StringSchema())) + ) + ) + ) + oas.path("/FHIR/R4/\$convertOAS",convertOASItem) + + val convertOAStoFHIRItem = PathItem() + .post( + Operation() + .addTagsItem(EXPERIMENTAL) + .summary("Converts OAS in YAML/JSON format to FHIR CapabilityStatement") + .description("This is a proof of concept.") + .responses(getApiResponsesRAWJSON()) + .requestBody(RequestBody().content(Content() + .addMediaType("application/x-yaml",MediaType().schema(StringSchema())) + .addMediaType("application/json",MediaType().examples(examplesOAS) + .schema(StringSchema())) + ) + ) ) - oas.path("/\$verifyOAS",verifyOASItem) + oas.path("/FHIR/R4/\$convertOAStoFHIR",convertOAStoFHIRItem) + + + val convertToTextItem = PathItem() .post( @@ -688,16 +830,27 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { .addMediaType("application/fhir+xml",MediaType().schema(StringSchema())) ))) oas.path("/FHIR/STU3/\$convertR4",convertR4Item) - + val examplesCS = LinkedHashMap() + examplesCS.put("UK Core Access Patient Provider", + Example().value(OASExamples().loadFHIRExample("UKCore-Access-Patient-Provider.json",ctx)) + ) val capabilityStatementItem = PathItem() .post( Operation() - .addTagsItem(EXPERIMENTAL) + .addTagsItem(UTILITY) .summary("Converts a FHIR CapabilityStatement to openapi v3 format") + .addParametersItem(Parameter() + .name("enhance") + .`in`("query") + .required(false) + .style(Parameter.StyleEnum.SIMPLE) + .description("`true | false`. Adds markdown documentation from FHIR Specification (do not rerun once it has been added)") + // Removed example profile + .schema(StringSchema().format("token"))) .responses(getApiResponsesMarkdown()) - .requestBody(RequestBody().content(Content().addMediaType("application/fhir+json",MediaType().schema(StringSchema()._default("{\"resourceType\":\"CapabilityStatement\"}"))))) + .requestBody(RequestBody().content(Content().addMediaType("application/fhir+json",MediaType().examples(examplesCS).schema(StringSchema())))) ) - oas.path("/FHIR/R4/\$openapi",capabilityStatementItem) + oas.path("/FHIR/R4/CapabilityStatement/\$openapi",capabilityStatementItem) return oas @@ -762,6 +915,8 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { return apiResponses } + + fun getApiResponsesRAWJSON() : ApiResponses { val response200 = ApiResponse() @@ -791,4 +946,41 @@ open class OpenApiConfig(@Qualifier("R4") val ctx : FhirContext) { .example(example))) return pathItem } + + fun getPackages() : String { + var packages = "" + var manifest : Array? = null + if (fhirServerProperties.igs != null && !fhirServerProperties.igs!!.isEmpty() ) { + val packages= fhirServerProperties.igs!!.split(",") + val manifest2 = arrayListOf() + packages.forEachIndexed{ index, pkg -> + manifest2.add(SimplifierPackage(pkg.substringBefore("#"),pkg.substringAfter("#"))) + } + manifest = manifest2.toTypedArray() + } else { + val configurationInputStream = ClassPathResource("manifest.json").inputStream + manifest = objectMapper.readValue(configurationInputStream, Array::class.java) + } + + manifest!!.forEach { + packages += " | "+ it.packageName + " | " + it.version + " | " + if (it.packageName.contains("ukcore")) { + packages += "[UK Core Implementation Guide](https://simplifier.net/guide/ukcoreversionhistory?version=current)" + } else if (it.packageName.contains("diagnostics")) { + packages += "[NHS England Pathology Implementation Guide](https://simplifier.net/guide/pathology-fhir-implementation-guide)" + } else if (it.packageName.contains("eu.laboratory")) { + packages += "[HL7 Europe Laboratory Report](https://build.fhir.org/ig/hl7-eu/laboratory/)" + } else if (it.packageName.contains("hl7.fhir.uv.ips")) { + packages += "[International Patient Summary Implementation Guide](https://build.fhir.org/ig/HL7/fhir-ips/)" + } else if (it.packageName.contains("hl7.fhir.uv.sdc")) { + packages += "[Structured Data Capture](https://build.fhir.org/ig/HL7/sdc/)" + } else if (it.packageName.contains("fhir.r4.nhsengland")) { + packages += "[NHS England Pathology Implementation Guide](https://simplifier.net/guide/nhs-england-implementation-guide-version-history)" + } else if (it.packageName.contains("hl7.fhir.uv.ipa")) { + packages += "[International Patient Access](https://build.fhir.org/ig/HL7/fhir-ipa/index.html)" + } + packages += " | \n" + } + return packages + } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/PackageConfiguration.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/PackageConfiguration.kt index c077600..b524080 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/PackageConfiguration.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/PackageConfiguration.kt @@ -21,7 +21,7 @@ import java.util.* @Configuration open class PackageConfiguration( - + val terminologyValidationProperties: TerminologyValidationProperties ) { companion object : KLogging() @@ -29,6 +29,7 @@ open class PackageConfiguration( @Bean open fun getCoreSearchParamters(@Qualifier("R4") ctx: FhirContext) : Bundle? { + // TODO could maybe get this from packages val u = URL("http://hl7.org/fhir/R4/search-parameters.json") try { diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/SecurityConfiguration.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/SecurityConfiguration.kt index 58b4d45..ad40131 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/SecurityConfiguration.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/SecurityConfiguration.kt @@ -1,14 +1,56 @@ package uk.nhs.england.fhirvalidator.configuration +import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter +import org.springframework.security.web.SecurityFilterChain +import org.springframework.http.HttpHeaders +import org.springframework.security.web.header.writers.StaticHeadersWriter +import org.springframework.web.cors.CorsConfiguration +import org.springframework.web.cors.CorsConfigurationSource +import org.springframework.web.cors.UrlBasedCorsConfigurationSource +import java.util.* + @Configuration @EnableWebSecurity -open class SecurityConfiguration : WebSecurityConfigurerAdapter() { - override fun configure(http: HttpSecurity) { - http.authorizeRequests().anyRequest().permitAll().and().csrf().disable() +open class SecurityConfiguration { + @Bean + public fun configure(http: HttpSecurity): SecurityFilterChain { + http + .authorizeHttpRequests { authorize -> + authorize + .anyRequest().permitAll() + } + .csrf { csrf -> + csrf + .disable() + } + .cors{ cors -> corsConfigurationSource()} + .headers{ + headers -> + headers.addHeaderWriter(StaticHeadersWriter("Access-Control-Allow-Origin", "*")) + headers.addHeaderWriter(StaticHeadersWriter("Access-Control-Allow-Headers", "Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token")) + headers.addHeaderWriter(StaticHeadersWriter("Access-Control-Allow-Methods", "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT")) + } + return http.build() + } + + @Bean + fun corsConfigurationSource(): CorsConfigurationSource { + val configuration = CorsConfiguration() + configuration.addAllowedMethod("GET") + configuration.addAllowedMethod("PUT") + configuration.addAllowedMethod("PUT") + configuration.addAllowedMethod("POST") + configuration.addAllowedMethod("OPTIONS") + configuration.allowedOrigins = Arrays.asList("*") + configuration.allowedHeaders = Arrays.asList("*") + configuration.maxAge = 3600 + configuration.exposedHeaders = Arrays.asList("Access-Control-Request-Method", "Access-Control-Request-Headers") + val source = UrlBasedCorsConfigurationSource() + source.registerCorsConfiguration("/**", configuration) + return source } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ServicesProperties.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ServicesProperties.kt new file mode 100644 index 0000000..0ab5902 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ServicesProperties.kt @@ -0,0 +1,14 @@ +package uk.nhs.england.fhirvalidator.configuration + +import org.springframework.boot.context.properties.ConfigurationProperties + + +@ConfigurationProperties(prefix = "services") +data class ServicesProperties( + var STU3: Boolean, + var R4: Boolean, + var LOINC: Boolean, + var R4B: Boolean +) { + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/TerminologyValidationProperties.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/TerminologyValidationProperties.kt index 857efd6..931ddb0 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/TerminologyValidationProperties.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/TerminologyValidationProperties.kt @@ -1,9 +1,7 @@ package uk.nhs.england.fhirvalidator.configuration import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.boot.context.properties.ConstructorBinding -@ConstructorBinding @ConfigurationProperties(prefix = "terminology") data class TerminologyValidationProperties( var url: String?, diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ValidationConfiguration.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ValidationConfiguration.kt index 03a409e..6dacf6f 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ValidationConfiguration.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/configuration/ValidationConfiguration.kt @@ -7,9 +7,12 @@ import ca.uhn.fhir.context.support.ValidationSupportContext import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException import ca.uhn.fhir.validation.FhirValidator import com.fasterxml.jackson.databind.ObjectMapper +import io.swagger.v3.oas.models.examples.Example import mu.KLogging import org.hl7.fhir.common.hapi.validation.support.* import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator +import org.hl7.fhir.r4.model.CapabilityStatement +import org.hl7.fhir.r4.model.ImplementationGuide import org.hl7.fhir.r4.model.StructureDefinition import org.hl7.fhir.utilities.json.model.JsonProperty import org.hl7.fhir.utilities.npm.NpmPackage @@ -20,6 +23,8 @@ import org.springframework.context.annotation.Configuration import org.springframework.core.io.ClassPathResource import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager import uk.nhs.england.fhirvalidator.awsProvider.* +import uk.nhs.england.fhirvalidator.model.DependsOn +import uk.nhs.england.fhirvalidator.model.FHIRPackage import uk.nhs.england.fhirvalidator.model.SimplifierPackage import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser import uk.nhs.england.fhirvalidator.util.AccessTokenInterceptor @@ -34,6 +39,7 @@ import java.time.Duration import java.time.Instant import java.util.* import java.util.function.Predicate +import kotlin.collections.ArrayList @Configuration @@ -46,8 +52,13 @@ open class ValidationConfiguration( ) { companion object : KLogging() - var npmPackages: List? = null + var npmPackages: List = emptyList() + var fhirPackage = mutableListOf() + @Bean + open fun fhirPackages() : List { + return this.fhirPackage + } @Bean open fun validator(@Qualifier("R4") fhirContext: FhirContext, instanceValidator: FhirInstanceValidator): FhirValidator { return fhirContext.newValidator().registerValidatorModule(instanceValidator) @@ -81,17 +92,69 @@ open class ValidationConfiguration( switchedTerminologyServiceValidationSupport ) if (messageProperties.getAWSValidationSupport()) supportChain.addValidationSupport( AWSValidationSupport(fhirContext, awsQuestionnaire,awsCodeSystem,awsValueSet, awsConceptMap)) - getPackages() + val manifest = getPackages() if (npmPackages != null) { + /* npmPackages!! .filter { !it.name().equals("hl7.fhir.r4.examples") } .map(implementationGuideParser::createPrePopulatedValidationSupport) .forEach(supportChain::addValidationSupport) + */ + val npms = npmPackages!!.filter { !it.name().equals("hl7.fhir.r4.examples") } + for (pckg in npms) { + val support = implementationGuideParser.createPrePopulatedValidationSupport(pckg) + supportChain.addValidationSupport(support) + var description = pckg.description() + if (description == null) description = "" + var derived = true + if (manifest !==null) { + manifest.forEach { + if (it.packageName.equals(pckg.name())) derived = false + } + } + val dependsOn = ArrayList() + for (dependency in pckg.dependencies()) { + val pckgStrs = dependency.split("#") + if (pckgStrs.size>1) { + // dummy value for now + var uri = "https://example.fhir.org/ImplementationGuide/" + pckgStrs[0] + "|" + pckgStrs[1] + if (pckgStrs[0].contains("hl7.fhir.r4.core")) uri = "https://hl7.org/fhir/R4/" + if (pckgStrs[0].contains("ukcore")) uri = "https://simplifier.net/guide/ukcoreversionhistory" + if (pckgStrs[0].contains("nhsengland")) uri = "https://simplifier.net/guide/nhs-england-implementation-guide-version-history" + val depends = DependsOn( + pckgStrs[0], + pckgStrs[1], + uri + ) + dependsOn.add(depends) + } + } + var packUrl = pckg.url() + if (pckg.name().contains("hl7.fhir.r4.core")) packUrl = "https://hl7.org/fhir/R4/" + if (pckg.name().contains("ukcore")) packUrl = "https://simplifier.net/guide/ukcoreversionhistory" + if (pckg.name().contains("nhsengland")) packUrl = "https://simplifier.net/guide/nhs-england-implementation-guide-version-history" + var newPckg = FHIRPackage(pckg.name(),pckg.version(),description,packUrl,derived,dependsOn) + this.fhirPackage.add(newPckg) + } //Initialise now instead of when the first message arrives generateSnapshots(supportChain) supportChain.fetchCodeSystem("http://snomed.info/sct") + // Correct dependencies canonical urls + for (pkg in this.fhirPackage) { + if (pkg.canonicalUri !== null && pkg.derived) { + for (otherPkg in this.fhirPackage) { + if (!otherPkg.packageName.equals(pkg.packageName) && !otherPkg.version.equals(pkg.version) && otherPkg.dependencies !== null) { + for (depencyPkg in otherPkg.dependencies) { + if (depencyPkg.packageName.equals(pkg.packageName) && depencyPkg.version.equals(pkg.version)) { + depencyPkg.canonicalUri = pkg.canonicalUri + } + } + } + } + } + } // packages have been processed so remove them npmPackages = emptyList() return supportChain @@ -208,15 +271,21 @@ open class ValidationConfiguration( } - open fun getPackages() { + open fun getPackages() :Array? { var manifest : Array? = null - if (fhirServerProperties.ig != null ) { - manifest = arrayOf(SimplifierPackage(fhirServerProperties.ig!!.name, fhirServerProperties.ig!!.version)) + if (fhirServerProperties.igs != null && !fhirServerProperties.igs!!.isEmpty() ) { + val packages= fhirServerProperties.igs!!.split(",") + val manifest2 = arrayListOf() + packages.forEachIndexed{ index, pkg -> + manifest2.add(SimplifierPackage(pkg.substringBefore("#"),pkg.substringAfter("#"))) + } + manifest = manifest2.toTypedArray() } else { val configurationInputStream = ClassPathResource("manifest.json").inputStream manifest = objectMapper.readValue(configurationInputStream, Array::class.java) } - val packages = arrayListOf() + + val packages = HashMap() if (manifest == null) throw UnprocessableEntityException("Error processing IG manifest") for (packageNpm in manifest ) { val packageName = packageNpm.packageName + "-" + packageNpm.version+ ".tgz" @@ -229,13 +298,26 @@ open class ValidationConfiguration( } if (inputStream == null) { val downloadedPackages = downloadPackage(packageNpm.packageName,packageNpm.version) - packages.addAll(downloadedPackages) + for (downloadpackage in downloadedPackages) { + val name = downloadpackage.name()+'#'+downloadpackage.version() + if (packages.get(name) == null) { + packages.put(name,downloadpackage) + } else { + logger.info("package "+name + " already present") + } + } } else { logger.info("Using local cache for {} - {}",packageNpm.packageName, packageNpm.version) - packages.add(NpmPackage.fromPackage(inputStream)) + val downloadpackage = NpmPackage.fromPackage(inputStream) + val name = downloadpackage.name()+'#'+downloadpackage.version() + if (packages.get(name) == null) { + packages.put(name,downloadpackage) + } else { + logger.info("package "+name + " already present") + } } } - this.npmPackages = packages + this.npmPackages = packages.values.toList() /* if (fhirServerProperties.ig != null && !fhirServerProperties.ig!!.isEmpty()) { return downloadPackage(fhirServerProperties.ig!!) @@ -247,6 +329,7 @@ open class ValidationConfiguration( .toList() */ + return manifest } open fun downloadPackage(name : String, version : String) : List { @@ -334,8 +417,13 @@ open class ValidationConfiguration( } private fun getBase(profile : String,supportChain: IValidationSupport): String? { - val structureDefinition : StructureDefinition= - supportChain.fetchStructureDefinition(profile) as StructureDefinition; + val structureDefinitionResource = supportChain.fetchStructureDefinition(profile) + if (structureDefinitionResource === null) { + logger.error("Issue retrieving " + profile) + return null; + } + val structureDefinition = structureDefinitionResource as StructureDefinition; + if (structureDefinition.hasBaseDefinition()) { var baseProfile = structureDefinition.baseDefinition if (baseProfile.contains(".uk")) baseProfile = getBase(baseProfile, supportChain) diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/ErrorController.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/ErrorController.kt new file mode 100644 index 0000000..0a3f7fd --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/ErrorController.kt @@ -0,0 +1,28 @@ +package uk.nhs.england.fhirvalidator.controller + +import mu.KLogging +import org.springframework.boot.web.servlet.error.ErrorController +import org.springframework.stereotype.Controller +import org.springframework.web.bind.annotation.RequestMapping +import jakarta.servlet.RequestDispatcher +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse + + +@Controller +class ErrorController : ErrorController { + companion object : KLogging() + @RequestMapping("/error") + fun handleError(request : HttpServletRequest, response: HttpServletResponse): String { + val status: Any = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE) + + val statusCode = status.toString().toInt() + + if (statusCode.equals(404)) { + response.sendRedirect("/") + return "error-404" + + } + return "error" + } +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/StatusController.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/StatusController.kt index 1e9bde1..d0e7a37 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/StatusController.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/StatusController.kt @@ -1,14 +1,26 @@ package uk.nhs.england.fhirvalidator.controller import io.swagger.v3.oas.annotations.Hidden +import mu.KLogging +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController +import kotlin.math.log @RestController @Hidden class StatusController { + companion object : KLogging() @GetMapping("_status") fun validate(): String { return "Validator is alive" } + @ExceptionHandler + @ResponseStatus(value= HttpStatus.NOT_FOUND) + fun conflict() { + // Nothing to do + logger.info("not found") + } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/VerifyController.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/VerifyController.kt deleted file mode 100644 index ec91978..0000000 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/controller/VerifyController.kt +++ /dev/null @@ -1,71 +0,0 @@ -package uk.nhs.england.fhirvalidator.controller - -import ca.uhn.fhir.context.FhirContext -import io.swagger.v3.core.util.Json -import io.swagger.v3.oas.annotations.Hidden -import uk.nhs.england.fhirvalidator.service.VerifyOAS -import uk.nhs.england.fhirvalidator.util.createOperationOutcome -import io.swagger.v3.oas.models.OpenAPI -import io.swagger.v3.parser.OpenAPIV3Parser -import io.swagger.v3.parser.core.models.ParseOptions -import mu.KLogging -import org.hl7.fhir.r4.model.OperationOutcome -import org.springframework.beans.factory.annotation.Qualifier -import org.springframework.web.bind.annotation.* -import uk.nhs.england.fhirvalidator.service.OpenAPIParser -import java.util.* - - -@RestController -@Hidden -class VerifyController( - @Qualifier("R4") private val fhirContext: FhirContext, - private val verifyOAS:VerifyOAS, - private val oasParser : OpenAPIParser - -) { - companion object : KLogging() - - - @PostMapping("convertOAS",produces = ["application/json"]) - fun convert( - @RequestBody input: Optional, - @RequestParam(required = false) url: String? - ): String { - var openAPI : OpenAPI? = null - openAPI = OpenAPIV3Parser().readContents(input.get()).openAPI - return Json.pretty(openAPI) - } - @PostMapping("/\$verifyOAS", produces = ["application/json", "application/x-yaml"]) - fun validate( - @RequestBody input: Optional, - @RequestParam(required = false) url: String? - ): String { - var openAPI : OpenAPI? = null - if (url != null) { - val parseOptions = ParseOptions() - parseOptions.isResolve = true // implicit - // parseOptions.isResolveFully = true - openAPI = OpenAPIV3Parser().readLocation(url,null,parseOptions).openAPI - } - else { - if (input.isPresent) { - openAPI = OpenAPIV3Parser().readContents(input.get()).openAPI - } else { - return fhirContext.newJsonParser().encodeResourceToString(OperationOutcome() - .addIssue(OperationOutcome.OperationOutcomeIssueComponent() - .setSeverity(OperationOutcome.IssueSeverity.FATAL) - .setDiagnostics("If url is not provided, the OAS must be present in the payload"))) - } - } - - if (openAPI !=null) { - val results = verifyOAS.validate(openAPI) - return fhirContext.newJsonParser().encodeResourceToString(createOperationOutcome(results)) - } - - return fhirContext.newJsonParser().encodeResourceToString(OperationOutcome().addIssue(OperationOutcome.OperationOutcomeIssueComponent() - .setSeverity(OperationOutcome.IssueSeverity.FATAL).setDiagnostics("Unable to process OAS"))) - } - -} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/AWSAuditEventLoggingInterceptor.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/AWSAuditEventLoggingInterceptor.kt index 8ba4aa4..395c289 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/AWSAuditEventLoggingInterceptor.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/AWSAuditEventLoggingInterceptor.kt @@ -20,9 +20,9 @@ import uk.nhs.england.fhirvalidator.configuration.FHIRServerProperties import uk.nhs.england.fhirvalidator.configuration.MessageProperties import java.io.IOException import java.util.* -import javax.servlet.ServletException -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse +import jakarta.servlet.ServletException +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse @Interceptor class AWSAuditEventLoggingInterceptor( @@ -83,10 +83,13 @@ class AWSAuditEventLoggingInterceptor( } } } catch (io: InvalidRequestException) { - System.out.println("Issue Processing - " + theRequestDetails.requestPath) + System.out.println("InvalidRequestException Issue Processing - " + theRequestDetails.requestPath) } catch (io: IOException) { - System.out.println("Issue Processing - " + theRequestDetails.requestPath) + System.out.println("IOException Issue Processing - " + theRequestDetails.requestPath) + } + catch (io: IllegalStateException) { + System.out.println("IllegalStateException Issue Processing - " + theRequestDetails.requestPath) } } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/BasicAuthInterceptor.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/BasicAuthInterceptor.kt new file mode 100644 index 0000000..02f0bd5 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/BasicAuthInterceptor.kt @@ -0,0 +1,375 @@ +package uk.nhs.england.fhirvalidator.interceptor + +import ca.uhn.fhir.context.FhirContext + +import ca.uhn.fhir.rest.api.MethodOutcome +import ca.uhn.fhir.rest.client.api.IClientInterceptor +import ca.uhn.fhir.rest.client.api.IHttpRequest +import ca.uhn.fhir.rest.client.api.IHttpResponse +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException +import com.amazonaws.services.cognitoidp.model.AuthenticationResultType +import org.apache.commons.io.IOUtils +import org.hl7.fhir.dstu3.model.OperationOutcome +import org.hl7.fhir.r4.model.Binary +import org.hl7.fhir.r4.model.Bundle +import org.hl7.fhir.r4.model.Resource +import org.json.JSONObject +import org.json.JSONTokener +import org.springframework.beans.factory.annotation.Qualifier +import uk.nhs.england.fhirvalidator.configuration.FHIRServerProperties +import uk.nhs.england.fhirvalidator.configuration.MessageProperties +import uk.nhs.england.fhirvalidator.model.ResponseObject +import java.io.BufferedReader +import java.io.FileNotFoundException +import java.io.IOException +import java.io.InputStreamReader +import java.net.HttpURLConnection +import java.net.URL +import jakarta.servlet.http.HttpServletRequest + + +class BasicAuthInterceptor(val messageProperties: MessageProperties, + val fhirServerProperties: FHIRServerProperties, + @Qualifier("R4") val ctx : FhirContext +) : IClientInterceptor { + + var authenticationToken = "a2V2aW5tYXlmaWVsZDpxd2VydHk0OSY=" + + + + override fun interceptRequest(iHttpRequest: IHttpRequest) { + // 10th Oct 2022 use id token instead of access token + iHttpRequest.addHeader("Authorization", "Basic " + authenticationToken) + + } + + override fun interceptResponse(p0: IHttpResponse?) { + + } + + + @Throws(Exception::class) + fun readFromUrl(path: String, queryParams: String?, resourceName: String?): Resource? { + val url = messageProperties.getLOINCFhirServer() + return readFromUrl(url,path, queryParams, resourceName) + } + + @Throws(Exception::class) + fun readFromUrl(url: String?, path: String, queryParams: String?, resourceName: String?): Resource? { + val responseObject = ResponseObject() + var myUrl: URL? = null + myUrl = if (queryParams != null) { + URL("$url$path?$queryParams") + } else { + URL(url + path) + } + var retry = 2 + while (retry > 0) { + val conn = myUrl.openConnection() as HttpURLConnection + + val basicAuth = "Basic "+authenticationToken + conn.setRequestProperty("Authorization", basicAuth) + conn.setRequestProperty("Content-Type", "application/fhir+json") + conn.setRequestProperty("Accept", "application/fhir+json") + + conn.requestMethod = "GET" + + try { + conn.connect() + val `is` = InputStreamReader(conn.inputStream) + try { + val rd = BufferedReader(`is`) + responseObject.responseCode = 200 + var res = IOUtils.toString(rd) + val resource = ctx.newJsonParser().parseResource(res) as Resource + + if (resource is Bundle) { + for (entry in resource.entry) { + entry.fullUrl = fhirServerProperties.server.baseUrl + "/FHIR/R4/"+entry.resource.javaClass.simpleName + "/"+entry.resource.idElement.idPart + } + for (link in resource.link) { + if (link.hasUrl() && resourceName!=null) { + var str : MutableList = link.url.split(resourceName).toMutableList() + if (str.size>1) { + str.removeAt(0) + link.url = fhirServerProperties.server.baseUrl + "/FHIR/R4/" + resourceName + str.joinToString(resourceName) + } else { + link.url = fhirServerProperties.server.baseUrl + "/FHIR/R4/" + resourceName + } + } + } + } + return resource + } finally { + `is`.close() + } + } catch (ex: FileNotFoundException) { + throw ResourceNotFoundException(getErrorStreamMessage(conn, ex)) + } catch (ex: Exception) { + retry-- + if (ex.message != null) { + if (ex.message!!.contains("401") || ex.message!!.contains("403")) { + + + } + } + if (retry == 0) { + throw ResourceNotFoundException(getErrorStreamMessage(conn, ex)) + } + } + } + throw UnprocessableEntityException("Number of retries exhausted") + } + + + @Throws(Exception::class) + fun updatePost(httpRequest : HttpServletRequest, resource : Resource): MethodOutcome { + + val method = MethodOutcome() + method.created = true + val opOutcome = OperationOutcome() + + method.operationOutcome = opOutcome + + val url = messageProperties.getCdrFhirServer() + var myUrl: URL? = null + val queryParams = httpRequest.queryString + val path = httpRequest.pathInfo + myUrl = if (queryParams != null) { + URL("$url$path?$queryParams") + } else { + URL(url + path) + } + var retry = 2 + while (retry > 0) { + val conn = myUrl.openConnection() as HttpURLConnection + + val basicAuth = "Basic " + authenticationToken + conn.setRequestProperty("Authorization", basicAuth) + conn.setRequestProperty("x-api-key", messageProperties.getAwsApiKey()) + conn.setRequestProperty("Content-Type", "application/fhir+json") + conn.setRequestProperty("Accept", "application/fhir+json") + conn.requestMethod = httpRequest.method + conn.setDoOutput(true) + val jsonInputString = ctx.newJsonParser().encodeResourceToString(resource) + try { + conn.getOutputStream().use { os -> + val input = jsonInputString.toByteArray(charset("utf-8")) + os.write(input, 0, input.size) + } + //conn.connect() + val `is` = InputStreamReader(conn.inputStream) + try { + val rd = BufferedReader(`is`) + val postedResource = ctx.newJsonParser().parseResource(IOUtils.toString(rd)) as Resource + if (postedResource != null && postedResource is Resource) { + method.resource = postedResource + } + return method + } finally { + `is`.close() + } + } catch (ex: FileNotFoundException) { + throw ResourceNotFoundException(ex.message) + } catch (ex: Exception) { + retry-- + if (ex.message != null) { + if (ex.message!!.contains("401") || ex.message!!.contains("403")) { + + + } + } + if (retry == 0) { + throw ResourceNotFoundException(getErrorStreamMessage(conn, ex)) + } + } + } + throw UnprocessableEntityException("Number of retries exhausted") + } + + @Throws(Exception::class) + fun postBinaryLocation(resource : Binary): JSONObject { + + var myUrl: URL? = URL(messageProperties.getCdrFhirServer() + "/Binary") + + var retry = 2 + while (retry > 0) { + + val conn = myUrl?.openConnection() as HttpURLConnection + + val basicAuth = "Basic "+authenticationToken + conn.setRequestProperty("Authorization", basicAuth) + conn.setRequestProperty("x-api-key",messageProperties.getAwsApiKey()) + conn.setRequestProperty("Content-Type", "application/fhir+json") + conn.setRequestProperty("Accept", "application/fhir+json") + conn.requestMethod = "POST" + conn.setDoOutput(true) + val jsonInputString = ctx.newJsonParser().encodeResourceToString(resource) + + try { + conn.getOutputStream().use { os -> + val input = jsonInputString.toByteArray(charset("utf-8")) + os.write(input, 0, input.size) + } + //conn.connect() + val `is` = InputStreamReader(conn.inputStream) + try { + val rd = BufferedReader(`is`) + val tokener = JSONTokener(rd) + return JSONObject(tokener) + // json.getString("presignedPutUrl") + } finally { + `is`.close() + } + } catch (ex: Exception) { + retry-- + if (ex.message != null) { + if (ex.message!!.contains("401") || ex.message!!.contains("403")) { + + + } + } + if (retry == 0) { + throw ResourceNotFoundException(getErrorStreamMessage(conn, ex)) + } + } + } + throw UnprocessableEntityException("Number of retries exhausted") + } + + @Throws(Exception::class) + fun getBinaryLocation(path: String): JSONObject { + + val url = messageProperties.getCdrFhirServer() + var myUrl: URL= URL(url + path) + var retry = 2 + while (retry > 0) { + val conn = myUrl.openConnection() as HttpURLConnection + + val basicAuth = "Basic "+authenticationToken + conn.setRequestProperty("Authorization", basicAuth) + conn.setRequestProperty("x-api-key",messageProperties.getAwsApiKey()) + conn.setRequestProperty("Content-Type", "application/fhir+json") + conn.setRequestProperty("Accept", "application/fhir+json") + conn.requestMethod = "GET" + conn.setDoOutput(true) + try { + conn.connect() + val `is` = InputStreamReader(conn.inputStream) + try { + val rd = BufferedReader(`is`) + val tokener = JSONTokener(rd) + return JSONObject(tokener) + } finally { + `is`.close() + } + } catch (ex: Exception) { + retry-- + if (ex.message != null) { + if (ex.message!!.contains("401") || ex.message!!.contains("403")) { + + + } + } + if (retry == 0) { + throw ResourceNotFoundException(getErrorStreamMessage(conn, ex)) + } + } + } + throw UnprocessableEntityException("Number of retries exhausted") + } + + @Throws(Exception::class) + fun postBinary(presignedUrl : String,fileArray : ByteArray) { + + var myUrl: URL? = URL(presignedUrl) + + val conn = myUrl?.openConnection() as HttpURLConnection + + conn.requestMethod = "PUT" + conn.setDoOutput(true) + + return try { + conn.getOutputStream().use { os -> + os.write(fileArray, 0, fileArray.size) + } + //conn.connect() + val `is` = InputStreamReader(conn.inputStream) + try { + val rd = BufferedReader(`is`) + return + } finally { + `is`.close() + } + } catch (ex: FileNotFoundException) { + throw UnprocessableEntityException(ex.message) + } catch (ex: IOException) { + throw UnprocessableEntityException(ex.message) + } + } + + @Throws(Exception::class) + fun getBinary(presignedUrl : String) : HttpURLConnection { + + var myUrl: URL? = URL(presignedUrl) + + val conn = myUrl?.openConnection() as HttpURLConnection + + conn.requestMethod = "GET" + conn.setDoOutput(true) + + return try { + conn.connect() + conn + /* + val inputStream = InputStreamReader(conn.inputStream, "utf-8") + try { + val binary = Binary() + BufferedReader( + inputStream + ).use { br -> + val response = StringBuilder() + var responseLine: String? = null + while (br.readLine().also { responseLine = it } != null) { + response.append(responseLine!!.trim { it <= ' ' }) + } + binary.setData(response.toString().toByteArray()) + } + binary.contentType = conn.getHeaderField("Content-Type"); + return binary + + } finally { + + inputStream.close() + } + */ + } catch (ex: FileNotFoundException) { + throw UnprocessableEntityException(ex.message) + } catch (ex: IOException) { + throw UnprocessableEntityException(ex.message) + } + } + + private fun getErrorStreamMessage(conn: HttpURLConnection, ex: Exception) : String? { + if (conn.errorStream == null) { + if (ex.message == null) return "Unknown Error" + return ex.message + } + val `is` = InputStreamReader(conn.errorStream) + try { + val rd = BufferedReader(`is`) + val resource: Resource = ctx.newJsonParser().parseResource(IOUtils.toString(rd)) as Resource + if (resource != null && resource is org.hl7.fhir.r4.model.OperationOutcome) { + return resource.issueFirstRep.diagnostics + } + } + catch (exOther: Exception) { + throw ex + } finally { + `is`.close() + } + return ex.message + } + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/CapabilityStatementApplier.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/CapabilityStatementApplier.kt new file mode 100644 index 0000000..1ab3df9 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/CapabilityStatementApplier.kt @@ -0,0 +1,60 @@ +package uk.nhs.england.fhirvalidator.interceptor + +import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain +import uk.nhs.england.fhirvalidator.util.applyProfile +import uk.nhs.england.fhirvalidator.util.getResourcesOfType +import org.hl7.fhir.instance.model.api.IBaseResource +import org.hl7.fhir.r4.model.CanonicalType +import org.hl7.fhir.r4.model.CapabilityStatement +import org.springframework.stereotype.Service + +@Service +class CapabilityStatementApplier( + val supportChain: ValidationSupportChain +) { + private val restResources = supportChain.fetchAllConformanceResources()?.filterIsInstance(CapabilityStatement::class.java)?.filterNot { it.url == null + || it.url.contains("sdc") + || it.url.contains("ips") + || it.url.contains("ipa") + || (!it.url.contains(".uk") && !it.url.contains(".wales") ) + || it.url.contains("us.core")} + ?.flatMap { it.rest } + ?.flatMap { it.resource } + + fun applyCapabilityStatementProfiles(resource: IBaseResource, importProfile: Boolean?) { + restResources?.forEach { applyRestResource(resource, it, importProfile) } + } + + fun getProfile(resourceType: String): String? { + var profile: String? = null + restResources?.forEach { + if (it.type !== null && it.type.equals(resourceType) && it.hasProfile()) { + profile = it.profile + } + + } + return profile + } + private fun applyRestResource( + resource: IBaseResource, + restResource: CapabilityStatement.CapabilityStatementRestResourceComponent, + importProfile: Boolean? + ) { + val matchingResources = getResourcesOfType(resource, restResource.type) + if (restResource.hasProfile()) { + applyProfile(matchingResources, restResource.profile) + } + if (importProfile !== null && importProfile && restResource.hasExtension()) { + restResource.extension.forEach{ + if (it.hasUrl() + && it.url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-imposeProfile") + && it.hasValue() && it.value is CanonicalType) { + val canonicalType = it.value as CanonicalType + applyProfile(matchingResources, canonicalType.value) + } + } + + } + } + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/CapabilityStatementInterceptor.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/CapabilityStatementInterceptor.kt index 7fc2ccd..f540bcb 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/CapabilityStatementInterceptor.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/CapabilityStatementInterceptor.kt @@ -12,13 +12,14 @@ import org.hl7.fhir.r4.model.* import org.hl7.fhir.utilities.npm.NpmPackage import org.springframework.core.io.ClassPathResource import uk.nhs.england.fhirvalidator.configuration.FHIRServerProperties +import uk.nhs.england.fhirvalidator.model.FHIRPackage import uk.nhs.england.fhirvalidator.model.SimplifierPackage import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser @Interceptor class CapabilityStatementInterceptor( fhirContext: FhirContext, - val objectMapper: ObjectMapper, + private val fhirPackage: List, private val supportChain: IValidationSupport, private val fhirServerProperties: FHIRServerProperties ) { @@ -32,34 +33,63 @@ class CapabilityStatementInterceptor( val cs: CapabilityStatement = theCapabilityStatement as CapabilityStatement // Customize the CapabilityStatement as desired - val apiextension = Extension(); - apiextension.url = "https://fhir.nhs.uk/StructureDefinition/Extension-NHSDigital-CapabilityStatement-Package" - var manifest : Array? = null - if (fhirServerProperties.ig != null ) { - manifest = arrayOf(SimplifierPackage(fhirServerProperties.ig!!.name, fhirServerProperties.ig!!.version)) - } else { - val configurationInputStream = ClassPathResource("manifest.json").inputStream - manifest = objectMapper.readValue(configurationInputStream, Array::class.java) - } - if (manifest != null) { - manifest.forEach { - val packageExtension = Extension(); - packageExtension.url="FHIRPackage" - packageExtension.extension.add(Extension().setUrl("name").setValue(StringType(it.packageName))) - packageExtension.extension.add(Extension().setUrl("version").setValue(StringType(it.version))) - apiextension.extension.add(packageExtension) + // val apiextension = Extension(); + // apiextension.url = "https://fhir.nhs.uk/StructureDefinition/Extension-NHSDigital-CapabilityStatement-Package" + /* + if (enhance && fhirPackage !== null && fhirPackage.size > 0) { + var igDescription = "\n\n | FHIR Implementation Guide | Version |\n |-----|-----|\n" + + fhirPackage.forEach { + if (!it.derived) { + val name = it.url + val version = it.version + val pckg = it.name + val url = getDocumentationPath(it.url) + if (name == null) igDescription += " ||$pckg#$version|\n" + else igDescription += " |[$name]($url)|$pckg#$version|\n" + } + } + openApi.info.description += "\n\n" + igDescription + } + + */ + + + fhirPackage.forEach { + if (!it.derived) { + var implementationGuide = ImplementationGuide() + implementationGuide.packageId = it.packageName + implementationGuide.version = it.version + implementationGuide.status = Enumerations.PublicationStatus.UNKNOWN + implementationGuide.name = it.packageName + implementationGuide.url = it.canonicalUri + implementationGuide.id = it.packageName + if (it.dependencies !== null) { + for (dependency in it.dependencies) { + implementationGuide.dependsOn.add( + ImplementationGuide.ImplementationGuideDependsOnComponent() + .setPackageId(dependency.packageName) + .setVersion(dependency.version) + .setUri(dependency.canonicalUri) + ) + } + } + cs.implementationGuide.add(CanonicalType("#" + it.packageName)) + cs.contained.add(implementationGuide) + } } - } + + /* val packageExtension = Extension(); packageExtension.url="openApi" packageExtension.extension.add(Extension().setUrl("documentation").setValue(UriType("https://simplifier.net/guide/NHSDigital/Home"))) - packageExtension.extension.add(Extension().setUrl("description").setValue(StringType("NHS Digital FHIR Implementation Guide"))) + packageExtension.extension.add(Extension().setUrl("description").setValue(StringType("NHS England FHIR Implementation Guide"))) apiextension.extension.add(packageExtension) cs.extension.add(apiextension) - +*/ for (resourceIG in supportChain.fetchAllConformanceResources()?.filterIsInstance()!!) { - if (!resourceIG.url.contains("sdc") && !resourceIG.url.contains("us.core")) { + if (resourceIG.url.contains(".uk")) { for (restComponent in resourceIG.rest) { for (component in restComponent.resource) { @@ -70,12 +100,33 @@ class CapabilityStatementInterceptor( resourceComponent.profile = component.profile } else { // add this to CapabilityStatement to indicate profile being valiated against - cs.restFirstRep.resource.add( - CapabilityStatement.CapabilityStatementRestResourceComponent().setType(component.type) - .setProfile(component.profile) - ) + resourceComponent = CapabilityStatement.CapabilityStatementRestResourceComponent().setType(component.type) + .setProfile(component.profile) + cs.restFirstRep.resource.add(resourceComponent) + } + if (component.hasExtension()) { + component.extension.forEach{ + if (it.url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-imposeProfile")) { + var found = false + if (resourceComponent !== null) { + if (resourceComponent.hasExtension()) { + for (extension in resourceComponent.extension) { + if (extension.url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-imposeProfile")) { + if (extension.hasValue() && it.hasValue() && it.value is CanonicalType && extension.value is CanonicalType) { + if ((extension.value as CanonicalType).value.equals((it.value as CanonicalType).value)) { + found = true + } + } + } + } + } + if (!found) { + resourceComponent.extension.add(it) + } + } + } + } } - } } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/ValidationInterceptor.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/ValidationInterceptor.kt index 10ee054..23a2ed3 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/ValidationInterceptor.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/interceptor/ValidationInterceptor.kt @@ -21,7 +21,7 @@ import java.io.IOException import java.io.InputStreamReader import java.net.HttpURLConnection import java.net.URL -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest @Interceptor @@ -37,7 +37,8 @@ class ValidationInterceptor(val ctx : FhirContext, val messageProperties: Messag fun incomingRequest(request: HttpServletRequest, requestDetails: RequestDetails?, resource: IBaseResource?) :Boolean { // Don't validate validate! - if ((request.method.equals("POST") || request.method.equals("PUT")) && !request.pathInfo.startsWith("/$") ) { + if ((request.method.equals("POST") || request.method.equals("PUT")) + && !request.pathInfo.contains("/$") ) { val encoding = RestfulServerUtils.determineRequestEncodingNoDefault(requestDetails) if (encoding == null) { log.trace("Incoming request does not appear to be FHIR, not going to validate") @@ -56,10 +57,10 @@ class ValidationInterceptor(val ctx : FhirContext, val messageProperties: Messag for (issue in validationResult.issue) { if (issue.hasSeverity() && ( issue.severity.equals(OperationOutcome.IssueSeverity.ERROR) || - issue.severity.equals(OperationOutcome.IssueSeverity.FATAL) || - issue.severity.equals(OperationOutcome.IssueSeverity.WARNING) + issue.severity.equals(OperationOutcome.IssueSeverity.FATAL) )) { log.debug(issue.diagnostics) + if (issue.diagnostics.contains("Validation failed for")) continue fail(validationResult) } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/model/FHIRPackage.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/model/FHIRPackage.kt new file mode 100644 index 0000000..ddf11a8 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/model/FHIRPackage.kt @@ -0,0 +1,15 @@ +package uk.nhs.england.fhirvalidator.model + +data class DependsOn( + val packageName: String, + val version: String, + var canonicalUri: String? +) +data class FHIRPackage( + val packageName: String, + val version: String, + val description: String, + var canonicalUri: String?, + val derived: Boolean, + val dependencies: List? +) diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CapabilityStatementProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CapabilityStatementProvider.kt index e647574..cb1bbc0 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CapabilityStatementProvider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CapabilityStatementProvider.kt @@ -1,20 +1,27 @@ package uk.nhs.england.fhirvalidator.provider import ca.uhn.fhir.context.FhirContext -import ca.uhn.fhir.rest.annotation.RequiredParam -import ca.uhn.fhir.rest.annotation.Search +import ca.uhn.fhir.rest.annotation.* import ca.uhn.fhir.rest.param.TokenParam import ca.uhn.fhir.rest.server.IResourceProvider +import io.swagger.util.Yaml +import io.swagger.v3.core.util.Json import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain +import org.hl7.fhir.instance.model.api.IBaseResource +import org.hl7.fhir.r4.model.BooleanType import org.hl7.fhir.r4.model.CapabilityStatement - import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser +import uk.nhs.england.fhirvalidator.service.oas.CapabilityStatementToOpenAPIConversion import java.nio.charset.StandardCharsets +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse + @Component class CapabilityStatementProvider(@Qualifier("R4") private val fhirContext: FhirContext, + private val oasParser : CapabilityStatementToOpenAPIConversion, private val supportChain: ValidationSupportChain) : IResourceProvider { /** * The getResourceType method comes from IResourceProvider, and must @@ -29,11 +36,60 @@ class CapabilityStatementProvider(@Qualifier("R4") private val fhirContext: Fhir @Search - fun search(@RequiredParam(name = CapabilityStatement.SP_URL) url: TokenParam): List { - val list = mutableListOf() - var decodeUri = java.net.URLDecoder.decode(url.value, StandardCharsets.UTF_8.name()); - val resource = supportChain.fetchResource(CapabilityStatement::class.java,decodeUri) - if (resource != null) list.add(resource) - return list + fun search(@OptionalParam(name = CapabilityStatement.SP_URL) url: TokenParam?): List { + val list = HashMap() + if (url !== null) { + val decodeUri = java.net.URLDecoder.decode(url.value, StandardCharsets.UTF_8.name()) + val resource = supportChain.fetchResource(CapabilityStatement::class.java,decodeUri) + if (resource != null) list.put(resource.url, resource) + return list.values.toList() + }; + for (resource in supportChain.fetchAllConformanceResources()!!) { + if (resource is CapabilityStatement) { + val cs = resource as CapabilityStatement + if (list.get(cs.url) === null) { + list.put(resource.url,resource) + } + } + } + return list.values.toList() + } + + @Operation(name = "openapi", idempotent = true,manualResponse=true, manualRequest=true) + fun convertOpenAPI( + servletRequest: HttpServletRequest, + servletResponse: HttpServletResponse, + @ResourceParam inputResource: IBaseResource, + @OperationParam(name = "enhance") abstract: BooleanType?, + ) { + + // var input = IOUtils.toString(servletRequest.getReader()); + // var inputResource : IBaseResource + servletResponse.setContentType("application/json") + servletResponse.setCharacterEncoding("UTF-8") + /* + try { + inputResource = fhirContext.newJsonParser().parseResource(input) + } catch (ex : Exception) { + inputResource = fhirContext.newXmlParser().parseResource(input) + } + + */ + if (inputResource is CapabilityStatement) { + val cs : CapabilityStatement = inputResource + + var boilerPlate = true + if (abstract !== null && !abstract.booleanValue()) boilerPlate = false + val os = oasParser.generateOpenApi(cs, boilerPlate); + val yaml = Yaml.pretty().writeValueAsString(os); + // System.out.println(yaml); + servletResponse.writer.write(Json.pretty(os)) + servletResponse.writer.flush() + return + } + servletResponse.writer.write("{}") + servletResponse.writer.flush() + return } + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CodeSystemProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CodeSystemProvider.kt index 801fdbe..be78a4a 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CodeSystemProvider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CodeSystemProvider.kt @@ -20,7 +20,7 @@ import uk.nhs.england.fhirvalidator.service.CodingSupport import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser import uk.nhs.england.fhirvalidator.shared.LookupCodeResultUK import java.nio.charset.StandardCharsets -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest @Component class CodeSystemProvider (@Qualifier("R4") private val fhirContext: FhirContext, @@ -88,7 +88,7 @@ class CodeSystemProvider (@Qualifier("R4") private val fhirContext: FhirContext, @Operation(name = "\$lookup", idempotent = true) - fun validateCode ( + fun lookup ( @OperationParam(name = "code") code: String?, @OperationParam(name = "system") system: String?, diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CompostionProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CompostionProvider.kt new file mode 100644 index 0000000..a813307 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/CompostionProvider.kt @@ -0,0 +1,98 @@ +package uk.nhs.england.fhirvalidator.provider + +import ca.uhn.fhir.context.FhirContext +import ca.uhn.fhir.rest.annotation.* +import ca.uhn.fhir.rest.server.IResourceProvider +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException +import org.apache.commons.io.output.ByteArrayOutputStream +import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain +import org.hl7.fhir.r4.model.BooleanType +import org.hl7.fhir.r4.model.Bundle +import org.hl7.fhir.r4.model.Composition +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.stereotype.Component +import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser +import uk.nhs.england.fhirvalidator.util.MyUriResolver +import java.io.ByteArrayInputStream +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import javax.xml.transform.Transformer +import javax.xml.transform.TransformerFactory +import javax.xml.transform.stream.StreamResult +import javax.xml.transform.stream.StreamSource + + +@Component +class CompostionProvider(@Qualifier("R4") private val fhirContext: FhirContext, + private val supportChain: ValidationSupportChain) : IResourceProvider { + /** + * The getResourceType method comes from IResourceProvider, and must + * be overridden to indicate what type of resource this provider + * supplies. + */ + override fun getResourceType(): Class { + return Composition::class.java + } + var implementationGuideParser: ImplementationGuideParser? = ImplementationGuideParser(fhirContext) + + private val log = LoggerFactory.getLogger("FHIRAudit") + + + @Operation(name = "\$convert", idempotent = true,manualResponse=true, manualRequest=false) + fun convertOpenAPI( + servletRequest: HttpServletRequest, + servletResponse: HttpServletResponse, + @ResourceParam document: Bundle, + @OperationParam(name = "enhance") abstract: BooleanType?, + ) { + if (document.type !== Bundle.BundleType.DOCUMENT) { + throw UnprocessableEntityException("Not a FHIR Document") + } + // Set the property to use saxon processor + System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.BasicTransformerFactory") + + // Saxon is hanging at the moment so using xalan + System.setProperty( + "javax.xml.transform.TransformerFactory", + "org.apache.xalan.processor.TransformerFactoryImpl" + ) + val xml = this.fhirContext.newXmlParser().encodeResourceToString(document) + + val xmlSource = StreamSource(xml.byteInputStream()) + val classLoader = javaClass.classLoader + + val inputStream = classLoader.getResourceAsStream("xslt/DocumentToHTML.xslt") + val xsltSource = StreamSource(inputStream) + + val transformerFactory = TransformerFactory.newInstance() + //val transformerFactory = net.sf.saxon.TransformerFactoryImpl() + transformerFactory.setURIResolver(MyUriResolver()) + + val transformer: Transformer = transformerFactory.newTransformer(xsltSource) + + val os = ByteArrayOutputStream() + val result: StreamResult = StreamResult(os) + try { + transformer.transform(xmlSource, result) + println("XSLT transformation completed successfully.") + } catch (ex : Exception) { + log.error(ex.message) + } + val output = ByteArrayInputStream(os.toByteArray()) + + servletResponse.setContentType("text/html") + servletResponse.setCharacterEncoding("UTF-8") + + val buffer = ByteArray(1024*8) + + var j = -1 + while (output.read(buffer).also { j = it } > 0) { + servletResponse.writer.write(buffer.decodeToString(0,j)) + } + + servletResponse.writer.flush() + return + } + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/FHIRtoTextProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/FHIRtoTextProvider.kt index 12d639c..b910c07 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/FHIRtoTextProvider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/FHIRtoTextProvider.kt @@ -6,23 +6,25 @@ import ca.uhn.fhir.context.support.ValidationSupportContext import ca.uhn.fhir.model.api.IElement import ca.uhn.fhir.rest.annotation.Operation import ca.uhn.fhir.rest.annotation.ResourceParam -import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain import org.hl7.fhir.instance.model.api.IBaseResource import org.hl7.fhir.r4.model.* import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component import uk.nhs.england.fhirvalidator.service.CodingSupport -import uk.nhs.england.fhirvalidator.service.OpenAPIParser import java.net.URI import java.nio.charset.StandardCharsets import java.text.SimpleDateFormat -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse import kotlin.reflect.KClass import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.isAccessible +/* + +DO NOT USE + */ @Component class FHIRtoTextProvider(@Qualifier("R4") private val fhirContext: FhirContext, diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/MarkdownProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/MarkdownProvider.kt index c2085b0..ba79db4 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/MarkdownProvider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/MarkdownProvider.kt @@ -1,23 +1,22 @@ package uk.nhs.england.fhirvalidator.provider -import ca.uhn.fhir.context.FhirContext +import ca.uhn.fhir.context.support.IValidationSupport import ca.uhn.fhir.rest.annotation.Operation import ca.uhn.fhir.rest.annotation.OperationParam import ca.uhn.fhir.rest.param.StringParam -import ca.uhn.fhir.validation.FhirValidator import mu.KLogging +import org.hl7.fhir.r4.model.* +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component -import uk.nhs.england.fhirvalidator.service.CapabilityStatementApplier -import uk.nhs.england.fhirvalidator.service.MessageDefinitionApplier -import uk.nhs.england.fhirvalidator.service.OpenAPIParser -import uk.nhs.england.fhirvalidator.service.VerifyOAS +import uk.nhs.england.fhirvalidator.service.oas.CapabilityStatementToOpenAPIConversion import java.nio.charset.StandardCharsets -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse @Component class MarkdownProvider ( - private val oasParser : OpenAPIParser + private val oasParser : CapabilityStatementToOpenAPIConversion, + @Qualifier("SupportChain") private val supportChain: IValidationSupport, ) { companion object : KLogging() @@ -31,10 +30,213 @@ class MarkdownProvider ( servletResponse.setContentType("text/markdown") servletResponse.setCharacterEncoding("UTF-8") if (profile != null) { - servletResponse.writer.write(oasParser.generateMarkdown(java.net.URLDecoder.decode(profile.value, StandardCharsets.UTF_8.name()))) + servletResponse.writer.write(generateMarkdown(java.net.URLDecoder.decode(profile.value, StandardCharsets.UTF_8.name()))) } servletResponse.writer.flush() return } + private fun getElementDescription(element : ElementDefinition) : String { + + var table = "\n\n| | |\n|----|----|" + // header body + /* + if (element.hasMustSupport() && element.mustSupport) { + description += "\n `mustSupport`" + } +*/ + table += "\n|Element Id|"+element.id+"|" + table += "\n|[Cardinality](https://www.hl7.org/fhir/conformance-rules.html#cardinality)|"+element.min+".."+element.max+"|" + + + if (element.hasFixed()) { + if (element.fixed is UriType) { + table += "\n|Fixed Value|"+(element.fixed as UriType).value+"|" + } + if (element.fixed is CodeType) { + table += "\n|Fixed Value|"+(element.fixed as CodeType).value+"|" + } + } + + if (element.hasBinding()) { + if (element.binding.hasValueSet()) + { + val valueSet = supportChain.fetchValueSet(element.binding.valueSet) + if (valueSet !== null) { + var description = + "[" + (valueSet as ValueSet).name + "](" + oasParser.getDocumentationPath(element.binding.valueSet) + ")" + if (element.binding.hasStrength()) description += " (" + element.binding.strength.display + ")" + if (element.binding.hasDescription()) { + var elementDescription = element.binding.description + elementDescription = "
" + elementDescription.replace("\\n", "\n") + description += elementDescription + " " + } + table += "\n|[Terminology Binding](https://www.hl7.org/fhir/terminologies.html)|" + description + "|" + } + } + } + + if (element.hasSliceName()) { + table += "\n|[Slice Name](https://www.hl7.org/fhir/profiling.html#slicing)|"+element.sliceName+"|" + } + if (element.hasSlicing()) { + var description = "" + if (element.slicing.hasRules()) { + description += " *"+element.slicing.rules.name + "*" + } + if (element.slicing.hasDiscriminator()) { + for (discrimninator in element.slicing.discriminator) { + description += " discriminator - " + if (discrimninator.hasType()) { + description += " *"+discrimninator.type.name + "*" + } + if (discrimninator.hasPath()) { + description += " *"+discrimninator.path + "*" + } + } + } + if (element.slicing.hasDescription()) { + description += "
"+element.slicing.description + } + table += "\n|[Slicing](https://www.hl7.org/fhir/profiling.html#slicing)|"+description+"|" + } + + // Data type + if (element.hasType()) { + var description = "" + for (type in element.type) { + + description += "["+type.code+"](https://www.hl7.org/fhir/datatypes.html#"+type.code+")" + var itemDescription="" + var first = true + for (target in type.targetProfile) { + if (itemDescription.isEmpty()) description+= "(" + val profile = supportChain.fetchStructureDefinition(target.value) + if (!first) { + itemDescription += " " + } else { + first = false + } + itemDescription += "["+(profile as StructureDefinition).name + "]("+ oasParser.getDocumentationPath(target.value) +")" + + } + first = true + for (target in type.profile) { + if (itemDescription.isEmpty()) description+= "(" + val profile = supportChain.fetchStructureDefinition(target.value) + if (!first) { + itemDescription += " " + } else { + first = false + } + itemDescription += "["+(profile as StructureDefinition).name+ "](" + oasParser.getDocumentationPath(target.value) +")" + } + + if (itemDescription.isNotEmpty()) description+= itemDescription + ")" + if (type.hasAggregation()) { + for (aggregation in type.aggregation) { + description += "
Aggregation - [" + aggregation.code+"](http://www.hl7.org/fhir/valueset-resource-aggregation-mode.html)" + } + } + } + table += "\n|[type](https://www.hl7.org/fhir/datatypes.html)|"+description+"|" + } + var description = table + "\n\n
" + // Documentation section + /* + if (element.hasShort()) { + + description += "\n\n " + element.short + } + */ + + if (element.hasDefinition()) { + description += "\n\n #### Definition" + description += "\n\n " + element.definition.replace("\\n","\n") + } + + if (element.hasRequirements()) { + description += "\n\n #### Requirements" + description += "\n\n " + element.requirements.replace("\\n","\n") + } + + if (element.hasComment()) { + description += "\n\n #### Comment" + description += "\n\n " + element.comment.replace("\\n","\n") + } + + if (element.hasConstraint()) { + var displayConstraints = false + for (constraint in element.constraint) { + if (doDisplay(constraint.key)) displayConstraints = true + } + + if (displayConstraints) { + description += "\n\n #### Constraints \n" + for (constraint in element.constraint) { + if (doDisplay(constraint.key)) description += "\n- **" + constraint.key + "** (*" + constraint.severity + "*) " + constraint.human.replace( + "\\n", + "\n" + ) + } + } + } + + return description + } + + fun generateMarkdown(profile :String) : String { + var mainDescription = "" + var subDescription = "" + var index = "" + + + if (profile != null) { + val structureDefinition = oasParser.getProfile(profile) + if (structureDefinition is StructureDefinition) { + + if (structureDefinition.hasDescription()) { + mainDescription += "\n\n " + structureDefinition.description + } + if (structureDefinition.hasPurpose()) { + mainDescription += "\n\n " + structureDefinition.purpose + } + + for (element in structureDefinition.snapshot.element) { + val paths = element.path.split(".") + if ( + element.hasMustSupport() || element.hasFixed() || (element.hasSliceName() && !paths[paths.size-1].equals("extension")) + || element.id.split(".").size == 1) { + val paths = element.id.split(".") + var title = "" + + + if (paths.size>1){ + for (i in 2..paths.size) { + if (title.isNotEmpty()) title += "." + title += paths[i-1] + } + index += "\n- "+title+"" + subDescription += "\n\n\n ## "+title + subDescription += getElementDescription(element) + } else { + mainDescription += getElementDescription(element) + } + + + + } + } + } + } + return mainDescription + "\n\n" + index + subDescription + } + + private fun doDisplay(key : String) : Boolean { + if (key.startsWith("ext")) return false + if (key.startsWith("ele")) return false + if (key.startsWith("dom")) return false + return true + } + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/OpenAPIProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/OpenAPIProvider.kt index c41a0c0..192ef95 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/OpenAPIProvider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/OpenAPIProvider.kt @@ -2,51 +2,120 @@ package uk.nhs.england.fhirvalidator.provider import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.rest.annotation.Operation -import io.swagger.util.Yaml import io.swagger.v3.core.util.Json +import io.swagger.v3.oas.models.OpenAPI +import io.swagger.v3.parser.OpenAPIV3Parser +import io.swagger.v3.parser.core.models.ParseOptions +import io.swagger.v3.parser.core.models.SwaggerParseResult import org.apache.commons.io.IOUtils -import org.hl7.fhir.instance.model.api.IBaseResource import org.hl7.fhir.r4.model.CapabilityStatement +import org.hl7.fhir.r4.model.OperationOutcome import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component -import uk.nhs.england.fhirvalidator.service.OpenAPIParser -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse +import uk.nhs.england.fhirvalidator.service.oas.OpenAPItoCapabilityStatementConversion +import uk.nhs.england.fhirvalidator.util.createOperationOutcome +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse @Component class OpenAPIProvider(@Qualifier("R4") private val fhirContext: FhirContext, - private val oasParser : OpenAPIParser + + private val openAPItoCapabilityStatementConversion: OpenAPItoCapabilityStatementConversion ) { - @Operation(name = "openapi", idempotent = true,manualResponse=true, manualRequest=true) - fun convertOpenAPI( + + @Operation(name = "convertOAS", idempotent = true,manualResponse=true, manualRequest=true) + fun convertOAS( servletRequest: HttpServletRequest, servletResponse: HttpServletResponse ) { + var input = IOUtils.toString(servletRequest.getReader()); + var openAPI : OpenAPI? = null + openAPI = OpenAPIV3Parser().readContents(input).openAPI + servletResponse.writer.write(Json.pretty(openAPI)) + servletResponse.writer.flush() + return + } + + @Operation(name = "convertOAStoFHIR", idempotent = true, manualRequest=true) + fun convertOAStoFHIR( + servletRequest: HttpServletRequest, + servletResponse: HttpServletResponse + ) : CapabilityStatement { + var input = IOUtils.toString(servletRequest.getReader()); + var openAPI : OpenAPI? = null + openAPI = OpenAPIV3Parser().readContents(input).openAPI + var capabilityStatement = openAPItoCapabilityStatementConversion.convert(openAPI) + return capabilityStatement + } + + + @Operation(name = "verifyOAS", idempotent = true,manualResponse=true, manualRequest=true) + fun verifyOAS( + servletRequest: HttpServletRequest, + servletResponse: HttpServletResponse + ) { + var openAPI : OpenAPI? = null + val parseOptions = ParseOptions() + parseOptions.isResolve = false // implicit var input = IOUtils.toString(servletRequest.getReader()); - var inputResource : IBaseResource + /* + if (url != null) { + + + // parseOptions.isResolveFully = true + openAPI = OpenAPIV3Parser().readLocation(url,null,parseOptions).openAPI + } + else { + + */ servletResponse.setContentType("application/json") servletResponse.setCharacterEncoding("UTF-8") - try { - inputResource = fhirContext.newJsonParser().parseResource(input) - } catch (ex : Exception) { - inputResource = fhirContext.newXmlParser().parseResource(input) + val oasResult: SwaggerParseResult; + if (input !== null && !input.isEmpty()) { + oasResult = io.swagger.parser.OpenAPIParser().readContents(input, null, parseOptions) + + openAPI = oasResult.openAPI + } else { + servletResponse.writer.write(fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString( + OperationOutcome() + .addIssue( + OperationOutcome.OperationOutcomeIssueComponent() + .setSeverity(OperationOutcome.IssueSeverity.FATAL) + .setDiagnostics("If url is not provided, the OAS must be present in the payload")))) + servletResponse.writer.flush() + return } - if (inputResource is CapabilityStatement) { - val cs : CapabilityStatement = inputResource - val os = oasParser.generateOpenApi(cs); - val yaml = Yaml.pretty().writeValueAsString(os); - // System.out.println(yaml); - servletResponse.writer.write(Json.pretty(os)) + + if (openAPI !=null) { + val results = openAPItoCapabilityStatementConversion.validate(openAPI) + var outcome = createOperationOutcome(results) + if (oasResult !== null && oasResult.getMessages() != null) { + oasResult.getMessages().forEach({ + var issue = outcome.addIssue() + issue.setSeverity(OperationOutcome.IssueSeverity.WARNING) + .setDiagnostics("OAS Issues: "+it) + issue.code = OperationOutcome.IssueType.CODEINVALID + } + ) + }; // validation errors and warnings + + + servletResponse.writer.write(fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome)) servletResponse.writer.flush() return } - servletResponse.writer.write("{}") + + servletResponse.writer.write(fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString( + OperationOutcome().addIssue( + OperationOutcome.OperationOutcomeIssueComponent() + .setSeverity(OperationOutcome.IssueSeverity.FATAL).setDiagnostics("Unable to process OAS")))) servletResponse.writer.flush() return } + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/StructureDefinitionProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/StructureDefinitionProvider.kt index d91f67f..ded07b9 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/StructureDefinitionProvider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/StructureDefinitionProvider.kt @@ -19,7 +19,7 @@ import org.springframework.stereotype.Component import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser import java.net.URLDecoder import java.nio.charset.StandardCharsets -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest @Component class StructureDefinitionProvider ( diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValidateR4Provider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValidateR4Provider.kt index 0b19cde..e8d669b 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValidateR4Provider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValidateR4Provider.kt @@ -13,23 +13,28 @@ import mu.KLogging import org.hl7.fhir.instance.model.api.IBaseResource import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext import org.hl7.fhir.r4.model.* +import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent import org.hl7.fhir.r4.utils.FHIRPathEngine import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component -import uk.nhs.england.fhirvalidator.service.CapabilityStatementApplier -import uk.nhs.england.fhirvalidator.service.MessageDefinitionApplier +import uk.nhs.england.fhirvalidator.interceptor.CapabilityStatementApplier +import uk.nhs.england.fhirvalidator.service.interactions.FHIRDocument +import uk.nhs.england.fhirvalidator.service.interactions.FHIRMessage +import uk.nhs.england.fhirvalidator.service.interactions.FHIRRESTful import uk.nhs.england.fhirvalidator.util.createOperationOutcome import java.net.URLDecoder import java.nio.charset.StandardCharsets -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest @Component class ValidateR4Provider ( @Qualifier("R4") private val fhirContext: FhirContext, @Qualifier("SupportChain") private val supportChain: IValidationSupport, private val validator: FhirValidator, - private val messageDefinitionApplier: MessageDefinitionApplier, - private val capabilityStatementApplier: CapabilityStatementApplier + private val fhirMessage: FHIRMessage, + private val capabilityStatementApplier: CapabilityStatementApplier, + private val fhirDocumentApplier: FHIRDocument, + private val fhirRESTful: FHIRRESTful ) { companion object : KLogging() @@ -98,15 +103,18 @@ class ValidateR4Provider ( @Validate.Profile parameterResourceProfile: String? ): MethodOutcome { var profile = parameterResourceProfile ?: servletRequest.getParameter("profile") + var importProfileParam = parameterResourceProfile ?: servletRequest.getParameter("imposeProfile") + var importProfile = false + if (importProfileParam !== null && importProfileParam.equals("true")) importProfile = true if (profile!= null) profile = URLDecoder.decode(profile, StandardCharsets.UTF_8.name()); var operationOutcome : OperationOutcome? = null if (resource == null && theRequestDetails.resource == null) throw UnprocessableEntityException("Not resource supplied to validation") if (resource == null) { // This should cope with Parameters resources being passed in - operationOutcome = parseAndValidateResource(theRequestDetails.resource, profile) + operationOutcome = parseAndValidateResource(theRequestDetails.resource, profile, importProfile) } else { - operationOutcome = parseAndValidateResource(resource, profile) + operationOutcome = parseAndValidateResource(resource, profile, importProfile) } val methodOutcome = MethodOutcome() if (operationOutcome != null ) { @@ -118,6 +126,19 @@ class ValidateR4Provider ( issue.diagnostics.contains("https://fhir.nhs.uk/CodeSystem/NHSDataModelAndDictionary-treatment-function")) { issue.severity = OperationOutcome.IssueSeverity.INFORMATION } + // This is to downgrade onto server issues to information. + if (!issue.diagnostics.contains(".uk") && (issue.diagnostics.contains("A usable code system with URL") + || issue.diagnostics.contains("LOINC is not indexed!"))) { + // This is probably ontology server issue so degrade warning to information + issue.severity = OperationOutcome.IssueSeverity.INFORMATION + } + + } + if (issue.diagnostics.contains("http://unstats.un.org/unsd/")) { + issue.severity = OperationOutcome.IssueSeverity.INFORMATION + } + if (issue.diagnostics.contains("note that the validator cannot judge what is suitable")) { + issue.severity = OperationOutcome.IssueSeverity.INFORMATION } } } else { @@ -144,10 +165,10 @@ class ValidateR4Provider ( */ - fun parseAndValidateResource(inputResource: IBaseResource, profile: String?): OperationOutcome { + fun parseAndValidateResource(inputResource: IBaseResource, profile: String?, importProfile: Boolean?): OperationOutcome { return try { val resources = getResourcesToValidate(inputResource) - val operationOutcomeList = resources.map { validateResource(it, profile) } + val operationOutcomeList = resources.map { validateResource(it, profile, importProfile) } val operationOutcomeIssues = operationOutcomeList.filterNotNull().flatMap { it.issue } return createOperationOutcome(operationOutcomeIssues) } catch (e: DataFormatException) { @@ -156,15 +177,48 @@ class ValidateR4Provider ( } } - fun validateResource(resource: IBaseResource, profile: String?): OperationOutcome? { - if (profile != null) return validator.validateWithResult(resource, ValidationOptions().addProfile(profile)) - .toOperationOutcome() as? OperationOutcome - capabilityStatementApplier.applyCapabilityStatementProfiles(resource) - val messageDefinitionErrors = messageDefinitionApplier.applyMessageDefinition(resource) - if (messageDefinitionErrors != null) { - return messageDefinitionErrors + fun validateResource(resource: IBaseResource, profile: String?, importProfile: Boolean?): OperationOutcome? { + var additionalIssues = ArrayList() + if (resource is Resource) { + if (resource.hasMeta() && resource.meta.hasProfile()) { + additionalIssues.add(OperationOutcome.OperationOutcomeIssueComponent() + .setSeverity(OperationOutcome.IssueSeverity.INFORMATION) + .setCode(OperationOutcome.IssueType.INFORMATIONAL) + .setDiagnostics("UK Core advice - population of meta.profile claims is not required for resource instances.") + ) + } + } + var result : OperationOutcome? = null + if (resource is CapabilityStatement) { + val errors = fhirRESTful.test(resource) + if (errors != null) { + errors.forEach { + additionalIssues.add(it) + } + } + } + if (profile != null) { + if (importProfile !== null && importProfile) capabilityStatementApplier.applyCapabilityStatementProfiles(resource, importProfile) + if (importProfile !== null && importProfile && resource is Bundle) fhirDocumentApplier.applyDocumentDefinition(resource) + result = validator.validateWithResult(resource, ValidationOptions().addProfile(profile)) + .toOperationOutcome() as? OperationOutcome + } else { + capabilityStatementApplier.applyCapabilityStatementProfiles(resource, importProfile) + val messageDefinitionErrors = fhirMessage.applyMessageDefinition(resource) + if (messageDefinitionErrors != null) { + messageDefinitionErrors.issue.forEach{ + additionalIssues.add(it) + } + } + if (importProfile !== null && importProfile && resource is Bundle) fhirDocumentApplier.applyDocumentDefinition(resource) + result = validator.validateWithResult(fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(resource)).toOperationOutcome() as? OperationOutcome + } + if (result !== null) { + additionalIssues.forEach{ + result.issue.add(it) + } } - return validator.validateWithResult(resource).toOperationOutcome() as? OperationOutcome + return result } fun getResourcesToValidate(inputResource: IBaseResource?): List { diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValueSetProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValueSetProvider.kt index fd19101..06b2e74 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValueSetProvider.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/provider/ValueSetProvider.kt @@ -10,6 +10,7 @@ import ca.uhn.fhir.context.support.ValueSetExpansionOptions import ca.uhn.fhir.rest.annotation.* import ca.uhn.fhir.rest.api.MethodOutcome import ca.uhn.fhir.rest.api.server.RequestDetails +import ca.uhn.fhir.rest.client.api.IGenericClient import ca.uhn.fhir.rest.param.DateParam import ca.uhn.fhir.rest.param.StringOrListParam import ca.uhn.fhir.rest.param.StringParam @@ -17,27 +18,30 @@ import ca.uhn.fhir.rest.param.TokenParam import ca.uhn.fhir.rest.server.IResourceProvider import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException import mu.KLogging -import org.apache.commons.lang3.StringUtils import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain +import org.hl7.fhir.instance.model.api.IBaseBundle import org.hl7.fhir.r4.model.* -import org.hl7.fhir.utilities.npm.NpmPackage import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager import org.springframework.stereotype.Component import uk.nhs.england.fhirvalidator.awsProvider.AWSValueSet +import uk.nhs.england.fhirvalidator.configuration.TerminologyValidationProperties import uk.nhs.england.fhirvalidator.interceptor.CognitoAuthInterceptor import uk.nhs.england.fhirvalidator.service.CodingSupport -import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser +import uk.nhs.england.fhirvalidator.util.AccessTokenInterceptor import uk.nhs.england.fhirvalidator.util.FhirSystems import java.nio.charset.StandardCharsets -import java.util.UUID -import javax.servlet.http.HttpServletRequest +import java.util.* +import jakarta.servlet.http.HttpServletRequest @Component class ValueSetProvider (@Qualifier("R4") private val fhirContext: FhirContext, private val supportChain: ValidationSupportChain, private val codingSupport: CodingSupport, private val awsValueSet: AWSValueSet, - private val cognitoAuthInterceptor: CognitoAuthInterceptor + private val cognitoAuthInterceptor: CognitoAuthInterceptor, + private val optionalAuthorizedClientManager: Optional, + private val terminologyValidationProperties: TerminologyValidationProperties ) : IResourceProvider { /** * The getResourceType method comes from IResourceProvider, and must @@ -49,8 +53,24 @@ class ValueSetProvider (@Qualifier("R4") private val fhirContext: FhirContext, } private val validationSupportContext = ValidationSupportContext(supportChain) + init { + if (optionalAuthorizedClientManager.isPresent) { + val authorizedClientManager = optionalAuthorizedClientManager.get() + val accessTokenInterceptor = AccessTokenInterceptor(authorizedClientManager) + provideClient(accessTokenInterceptor) + } + } + + private fun provideClient(accessTokenInterceptor : AccessTokenInterceptor) { + val retVal: IGenericClient = fhirContext.newRestfulGenericClient(terminologyValidationProperties.url) + retVal.registerInterceptor(accessTokenInterceptor) + terminologyClient = retVal + } + companion object : KLogging() + private var terminologyClient : IGenericClient? = null; + @Update fun update( theRequest: HttpServletRequest, @@ -117,7 +137,21 @@ class ValueSetProvider (@Qualifier("R4") private val fhirContext: FhirContext, if (resource != null) { list.add(resource) } else { val resources = awsValueSet.search(url) - if (resources.size>0) list.addAll(resources) + if (resources.size > 0) { + list.addAll(resources) + } else { + if (terminologyClient !== null) { + val results = terminologyClient!!.search().forResource("ValueSet") + .where(CodeSystem.URL.matches().value(url.value)).execute() + if (results !== null && results.hasEntry()) { + if (results.entry.size>0 && results.entry[0].hasResource() && results.entry[0].resource is ValueSet) { + val summaryValueset = results.entry[0].resource as ValueSet + val fullValueSet = terminologyClient!!.read().resource("ValueSet").withId(summaryValueset.id).execute() + if (fullValueSet is ValueSet) list.add(fullValueSet) + } + } + } + } } return list } @@ -192,7 +226,10 @@ class ValueSetProvider (@Qualifier("R4") private val fhirContext: FhirContext, @Operation(name = "\$expand", idempotent = true) fun expand(@ResourceParam valueSet: ValueSet?, @OperationParam(name = ValueSet.SP_URL) url: TokenParam?, - @OperationParam(name = "filter") filter: StringParam?): ValueSet? { + @OperationParam(name = "filter") filter: StringParam?, + @OperationParam(name = "includeDesignations") includeDesignations: BooleanType?, + @OperationParam(name = "elements") elements: StringOrListParam?, + @OperationParam(name = "property") property: StringOrListParam?): ValueSet? { if (url == null && valueSet == null) throw UnprocessableEntityException("Both resource and url can not be null") var valueSetR4: ValueSet? = null; if (url != null) { @@ -207,6 +244,7 @@ class ValueSetProvider (@Qualifier("R4") private val fhirContext: FhirContext, } if (valueSetR4 != null) { var valueSetExpansionOptions = ValueSetExpansionOptions(); + valueSetR4.expansion = null; // remove any previous expansion if (filter != null) valueSetExpansionOptions.filter = filter.value var expansion: ValueSetExpansionOutcome? = @@ -225,4 +263,5 @@ class ValueSetProvider (@Qualifier("R4") private val fhirContext: FhirContext, } } + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/CodeSystemLOINCProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/CodeSystemLOINCProvider.kt new file mode 100644 index 0000000..c2be685 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/CodeSystemLOINCProvider.kt @@ -0,0 +1,87 @@ +package uk.nhs.england.fhirvalidator.providerLOINC + +import ca.uhn.fhir.context.FhirContext +import ca.uhn.fhir.context.support.IValidationSupport +import ca.uhn.fhir.context.support.ValidationSupportContext +import ca.uhn.fhir.rest.annotation.* +import ca.uhn.fhir.rest.api.MethodOutcome +import ca.uhn.fhir.rest.api.server.RequestDetails +import ca.uhn.fhir.rest.param.DateParam +import ca.uhn.fhir.rest.param.TokenParam +import ca.uhn.fhir.rest.server.IResourceProvider +import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain +import org.hl7.fhir.r4.model.* +import org.hl7.fhir.utilities.npm.NpmPackage +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.stereotype.Component +import uk.nhs.england.fhirvalidator.awsProvider.AWSCodeSystem +import uk.nhs.england.fhirvalidator.interceptor.BasicAuthInterceptor +import uk.nhs.england.fhirvalidator.interceptor.CognitoAuthInterceptor +import uk.nhs.england.fhirvalidator.service.CodingSupport +import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser +import uk.nhs.england.fhirvalidator.shared.LookupCodeResultUK +import java.nio.charset.StandardCharsets +import jakarta.servlet.http.HttpServletRequest + +@Component +class CodeSystemLOINCProvider (@Qualifier("R4") private val fhirContext: FhirContext, + private val basicAuthInterceptor: BasicAuthInterceptor +) : IResourceProvider { + /** + * The getResourceType method comes from IResourceProvider, and must + * be overridden to indicate what type of resource this provider + * supplies. + */ + override fun getResourceType(): Class { + return CodeSystem::class.java + } + @Operation(name = "\$lookup", idempotent = true) + fun lookup ( + httpRequest : HttpServletRequest, + @OperationParam(name = "code") code: String?, + @OperationParam(name = "system") system: String? + ) : Parameters? { + val resource: Resource? = basicAuthInterceptor.readFromUrl(httpRequest.pathInfo, httpRequest.queryString, null) + return if (resource is Parameters) resource else null + } + + + @Operation(name = "\$units", idempotent = true) + open fun getUnits(@OperationParam(name = "code") code: String): Parameters { + val coding = Parameters() + val resource: Resource? = basicAuthInterceptor.readFromUrl("/CodeSystem/\$lookup", "system=http://loinc.org&code="+code, null) + if (resource is Parameters) { + val parameters = resource + for ( param in parameters.parameter) { + if (param.hasName() && param.name.equals("property")) { + if (param.hasPart()) { + var isUCUM = false + var unit = "" + for (part in param.part) { + if (part.hasValue()) { + if ((part.value is CodeType) && (part.value as CodeType).code.equals("EXAMPLE_UCUM_UNITS")) { + isUCUM = + true + } + if ((part.value is StringType)) { + unit = + (part.value as StringType).value + } + } + } + if (isUCUM) { + val units = unit.split(";") + for (ut in units) { + coding.parameter.add( + Parameters.ParametersParameterComponent().setValue(StringType().setValue(ut)) + ) + } + } + } + } + } + } + return coding + } + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/QuestionnaireProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/QuestionnaireProvider.kt new file mode 100644 index 0000000..7a4aabd --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/QuestionnaireProvider.kt @@ -0,0 +1,91 @@ +package uk.nhs.england.fhirvalidator.providerLOINC + +import ca.uhn.fhir.context.FhirContext +import ca.uhn.fhir.rest.annotation.* +import ca.uhn.fhir.rest.param.StringParam +import ca.uhn.fhir.rest.param.TokenParam +import ca.uhn.fhir.rest.server.IResourceProvider +import mu.KLogging +import org.hl7.fhir.r4.model.* +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.stereotype.Component +import uk.nhs.england.fhirvalidator.interceptor.BasicAuthInterceptor +import jakarta.servlet.http.HttpServletRequest + +@Component +class QuestionnaireProvider (@Qualifier("R4") private val fhirContext: FhirContext, + private val basicAuthInterceptor: BasicAuthInterceptor, + private val codeSystemLOINCProvider: CodeSystemLOINCProvider +) : IResourceProvider { + /** + * The getResourceType method comes from IResourceProvider, and must + * be overridden to indicate what type of resource this provider + * supplies. + */ + override fun getResourceType(): Class { + return Questionnaire::class.java + } + + + companion object : KLogging() + + @Read + fun read( httpRequest : HttpServletRequest,@IdParam internalId: IdType): Questionnaire? { + val resource: Resource? = basicAuthInterceptor.readFromUrl(httpRequest.pathInfo, null, null) + + if (resource is Questionnaire) { + var questionnaire = resource as Questionnaire + if (questionnaire.hasItem()) getUnits(questionnaire.item) + return questionnaire + } + + return null + } + + private fun getUnits(items: List) { + for (item in items) { + if (item.hasCode() && item.code.size > 0 && item.codeFirstRep.hasSystem() && item.codeFirstRep.system.equals("http://loinc.org")) { + val units = codeSystemLOINCProvider.getUnits(item.codeFirstRep.code) + if (units !== null && units.hasParameter()) { + if (item.type.equals(Questionnaire.QuestionnaireItemType.DECIMAL)) { + // if it has units it is not a decimal + item.type = Questionnaire.QuestionnaireItemType.QUANTITY + } + for (unit in units.parameter) { + if (unit.hasValue() && unit.value is StringType) { + item.initial.add( + Questionnaire.QuestionnaireItemInitialComponent() + .setValue( + Coding().setSystem("http://unitsofmeasure.org").setCode((unit.value as StringType).value)) + ) + item.extension.add( + Extension() + .setUrl("http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption") + .setValue( + Coding().setSystem("http://unitsofmeasure.org").setCode((unit.value as StringType).value)) + ) + } + } + } + } + } + } + + @Search + fun search( + httpRequest : HttpServletRequest, + @OptionalParam(name = Questionnaire.SP_URL) url: TokenParam?, + @OptionalParam(name = Questionnaire.SP_TITLE) title: StringParam?, + @OptionalParam(name = Questionnaire.SP_CODE) code: TokenParam?, + @OptionalParam(name = "_content") content: StringParam?, + @OptionalParam(name = "_count") count: StringParam? + ): Bundle? { + val resource: Resource? = + basicAuthInterceptor.readFromUrl(httpRequest.pathInfo, httpRequest.queryString, "Patient") + if (resource != null && resource is Bundle) { + return resource + } + return null + } + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/ValueSetLOINCProvider.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/ValueSetLOINCProvider.kt new file mode 100644 index 0000000..ef5861b --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerLOINC/ValueSetLOINCProvider.kt @@ -0,0 +1,81 @@ +package uk.nhs.england.fhirvalidator.providerLOINC + +import ca.uhn.fhir.context.FhirContext +import ca.uhn.fhir.context.support.ConceptValidationOptions +import ca.uhn.fhir.context.support.IValidationSupport +import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult +import ca.uhn.fhir.context.support.IValidationSupport.ValueSetExpansionOutcome +import ca.uhn.fhir.context.support.ValidationSupportContext +import ca.uhn.fhir.context.support.ValueSetExpansionOptions +import ca.uhn.fhir.rest.annotation.* +import ca.uhn.fhir.rest.api.MethodOutcome +import ca.uhn.fhir.rest.api.server.RequestDetails +import ca.uhn.fhir.rest.client.api.IGenericClient +import ca.uhn.fhir.rest.param.DateParam +import ca.uhn.fhir.rest.param.StringOrListParam +import ca.uhn.fhir.rest.param.StringParam +import ca.uhn.fhir.rest.param.TokenParam +import ca.uhn.fhir.rest.server.IResourceProvider +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException +import mu.KLogging +import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain +import org.hl7.fhir.instance.model.api.IBaseBundle +import org.hl7.fhir.r4.model.* +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager +import org.springframework.stereotype.Component +import uk.nhs.england.fhirvalidator.awsProvider.AWSValueSet +import uk.nhs.england.fhirvalidator.configuration.TerminologyValidationProperties +import uk.nhs.england.fhirvalidator.interceptor.BasicAuthInterceptor +import uk.nhs.england.fhirvalidator.interceptor.CognitoAuthInterceptor +import uk.nhs.england.fhirvalidator.service.CodingSupport +import uk.nhs.england.fhirvalidator.util.AccessTokenInterceptor +import uk.nhs.england.fhirvalidator.util.FhirSystems +import java.nio.charset.StandardCharsets +import java.util.* +import jakarta.servlet.http.HttpServletRequest + +@Component +class ValueSetLOINCProvider( @Qualifier("R4") private val fhirContext: FhirContext, +private val basicAuthInterceptor: BasicAuthInterceptor +) : IResourceProvider { + /** + * The getResourceType method comes from IResourceProvider, and must + * be overridden to indicate what type of resource this provider + * supplies. + */ + override fun getResourceType(): Class { + return ValueSet::class.java + } + companion object : KLogging() + + + + @Read + fun read(httpRequest : HttpServletRequest, @IdParam internalId: IdType): ValueSet? { + val resource: Resource? = basicAuthInterceptor.readFromUrl(httpRequest.pathInfo, null,"ValueSet") + return if (resource is ValueSet) resource else null + } + @Search + fun search(httpRequest : HttpServletRequest, + @OptionalParam(name = ValueSet.SP_URL) url: TokenParam?): Bundle? { + val resource: Resource? = basicAuthInterceptor.readFromUrl(httpRequest.pathInfo, httpRequest.queryString,null) + return if (resource is Bundle) resource else null + } + + + + @Operation(name = "\$expand", idempotent = true) + fun expand( + httpRequest : HttpServletRequest, + @ResourceParam valueSet: ValueSet?, + @OperationParam(name = ValueSet.SP_URL) url: TokenParam?, + @OperationParam(name = "filter") filter: StringParam?, + @OperationParam(name = "includeDesignations") includeDesignations: BooleanType?, + @OperationParam(name = "elements") elements: StringOrListParam?, + @OperationParam(name = "property") property: StringOrListParam?): ValueSet? { + val resource: Resource? = basicAuthInterceptor.readFromUrl(httpRequest.pathInfo, httpRequest.queryString,null) + return if (resource is ValueSet) resource else null + } + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ConversionProviderSTU3.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ConversionProviderSTU3.kt index 0aa175a..38e8e3d 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ConversionProviderSTU3.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ConversionProviderSTU3.kt @@ -17,7 +17,7 @@ import org.hl7.fhir.dstu3.model.Resource import org.hl7.fhir.dstu3.model.ResourceType import org.springframework.stereotype.Component import uk.nhs.england.fhirvalidator.util.createSTU3OperationOutcome -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest @Component class ConversionProviderSTU3 () { diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ValidateProviderSTU3.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ValidateProviderSTU3.kt index e5c4ce5..ceff260 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ValidateProviderSTU3.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/providerSTU3/ValidateProviderSTU3.kt @@ -18,7 +18,7 @@ import org.hl7.fhir.dstu3.model.ResourceType import org.springframework.stereotype.Component import uk.nhs.england.fhirvalidator.util.createSTU3OperationOutcome import uk.nhs.england.fhirvalidator.util.createSTU3OperationOutcomeR4 -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest @Component class ValidateProviderSTU3 ( diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/CapabilityStatementApplier.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/CapabilityStatementApplier.kt deleted file mode 100644 index c5a8cb1..0000000 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/CapabilityStatementApplier.kt +++ /dev/null @@ -1,34 +0,0 @@ -package uk.nhs.england.fhirvalidator.service - -import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain -import uk.nhs.england.fhirvalidator.util.applyProfile -import uk.nhs.england.fhirvalidator.util.getResourcesOfType -import org.hl7.fhir.instance.model.api.IBaseResource -import org.hl7.fhir.r4.model.CapabilityStatement -import org.hl7.fhir.r4.model.Resource -import org.hl7.fhir.utilities.npm.NpmPackage -import org.springframework.stereotype.Service - -@Service -class CapabilityStatementApplier( - val supportChain: ValidationSupportChain -) { - private val restResources = supportChain.fetchAllConformanceResources()?.filterIsInstance(CapabilityStatement::class.java)?.filterNot { it.url == null || it.url.contains("sdc") || it.url.contains("us.core")} - ?.flatMap { it.rest } - ?.flatMap { it.resource } - - fun applyCapabilityStatementProfiles(resource: IBaseResource) { - restResources?.forEach { applyRestResource(resource, it) } - } - - private fun applyRestResource( - resource: IBaseResource, - restResource: CapabilityStatement.CapabilityStatementRestResourceComponent - ) { - val matchingResources = getResourcesOfType(resource, restResource.type) - if (restResource.hasProfile()) { - applyProfile(matchingResources, restResource.profileElement) - } - } - -} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/CodingSupport.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/CodingSupport.kt index 5581bd5..7baf38c 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/CodingSupport.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/CodingSupport.kt @@ -27,7 +27,6 @@ import kotlin.collections.ArrayList @Service class CodingSupport(@Qualifier("R4") private val ctx: FhirContext?, - private val npmPackages: List?, @Qualifier("SupportChain") private val supportChain: IValidationSupport, private val terminologyValidationProperties: TerminologyValidationProperties, optionalAuthorizedClientManager: Optional, diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRDocument.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRDocument.kt new file mode 100644 index 0000000..a9e0f54 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRDocument.kt @@ -0,0 +1,42 @@ +package uk.nhs.england.fhirvalidator.service.interactions + +import org.hl7.fhir.instance.model.api.IBaseResource +import org.hl7.fhir.r4.model.* +import org.springframework.stereotype.Service +import uk.nhs.england.fhirvalidator.util.FhirSystems +import uk.nhs.england.fhirvalidator.util.createOperationOutcome + + +@Service +class FHIRDocument { + + fun applyDocumentDefinition(resource: IBaseResource): OperationOutcome? { + if (resource !is Bundle || resource.type != Bundle.BundleType.DOCUMENT) { + return null + } + + val composition = findComposition(resource) + ?: return createOperationOutcome( + "No Composition found.", + "Bundle.entry" + ) + + if (composition.hasType()) { + if (composition.type.hasCoding(FhirSystems.SNOMED_CT,"4241000179101") + || composition.type.hasCoding(FhirSystems.LOINC,"11502-2") + ) composition.meta.addProfile("http://hl7.eu/fhir/laboratory/StructureDefinition/Composition-eu-lab") + if (composition.type.hasCoding(FhirSystems.LOINC,"60591-5") + ) composition.meta.addProfile("http://hl7.org/fhir/uv/ips/StructureDefinition/Composition-uv-ips") + } + return null + } + + private fun findComposition(bundle: Bundle): Composition? { + return bundle.entry + ?.map { it.resource } + ?.filterIsInstance(Composition::class.java) + ?.singleOrNull() + } + + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/MessageDefinitionApplier.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRMessage.kt similarity index 95% rename from src/main/kotlin/uk/nhs/england/fhirvalidator/service/MessageDefinitionApplier.kt rename to src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRMessage.kt index 2d644ae..7431b5e 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/MessageDefinitionApplier.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRMessage.kt @@ -1,4 +1,4 @@ -package uk.nhs.england.fhirvalidator.service +package uk.nhs.england.fhirvalidator.service.interactions import uk.nhs.england.fhirvalidator.util.applyProfile import uk.nhs.england.fhirvalidator.util.createOperationOutcome @@ -8,9 +8,10 @@ import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain import org.hl7.fhir.instance.model.api.IBaseResource import org.hl7.fhir.r4.model.* import org.springframework.stereotype.Service +import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser @Service -class MessageDefinitionApplier( +class FHIRMessage( implementationGuideParser: ImplementationGuideParser, supportChain: ValidationSupportChain ) { @@ -87,7 +88,7 @@ class MessageDefinitionApplier( matchingResources: List ) { if (focus.hasProfile()) { - applyProfile(matchingResources, focus.profileElement) + applyProfile(matchingResources, focus.profile) } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRRESTful.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRRESTful.kt new file mode 100644 index 0000000..09e71c5 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/interactions/FHIRRESTful.kt @@ -0,0 +1,188 @@ +package uk.nhs.england.fhirvalidator.service.interactions + +import io.swagger.v3.oas.models.media.ArraySchema +import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain +import org.hl7.fhir.instance.model.api.IBaseResource +import org.hl7.fhir.r4.model.* +import org.springframework.stereotype.Service +import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser +import uk.nhs.england.fhirvalidator.service.SearchParameterSupport + +@Service +class FHIRRESTful( + implementationGuideParser: ImplementationGuideParser, + private val searchParameterSupport : SearchParameterSupport, + supportChain: ValidationSupportChain +) { + + + fun test(resource: IBaseResource): List { + val outcomes = mutableListOf() + + if (resource !is CapabilityStatement) { + return outcomes + } + val capabilityStatement = resource as CapabilityStatement + for((index,rest) in capabilityStatement.rest.withIndex()) { + for((idx,resource) in rest.resource.withIndex()) { + if (resource.hasSearchParam()) { + for(searchParameter in resource.searchParam) { + checkSearchParameter(resource.type,"CapabilityStatement.rest[$index].resource[$idx]",searchParameter,outcomes) + + } + } + } + } + + return outcomes + } + + fun checkSearchParameter( + resourceType: String, + locaton: String, + apiParameter: CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent, + outcomes: MutableList + ) { + if (apiParameter.name == null) { + val issue = addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.WARNING, + "Name must not be null for resource type = "+resourceType + ) + issue.location.add(StringType(locaton)) + } + val searchParameter = getSearchParameter(outcomes, resourceType,apiParameter.name) + if (searchParameter == null) { + val issue = addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.WARNING, + "Unable to find FHIR SearchParameter of for: " + apiParameter.name + ) + issue.location.add(StringType(locaton)) + } else { + if (searchParameter.hasName() && searchParameter.name.startsWith("_include")) { + + } + else { + if (searchParameter.hasType() && apiParameter.hasType() && !searchParameter.type.equals(apiParameter.type)) { + val issue = addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.INFORMATION, + "Parameter type for **" + resourceType + '.'+ apiParameter.name + "** should be `" + searchParameter.type.toCode() + "` but is `" + apiParameter.type.toCode()+"`." + ) + issue.location.add(StringType(locaton)) + } + if (searchParameter.hasType() && !apiParameter.hasType() && !searchParameter.type.equals(apiParameter.type)) { + val issue = addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.INFORMATION, + "Parameter type for **" + resourceType + '.'+ apiParameter.name + "** should be `" + searchParameter.type.toCode() + "` but is not present." + ) + issue.location.add(StringType(locaton)) + } + /* + when (searchParameter.type) { + Enumerations.SearchParamType.STRING -> { + if (!apiParameter.type.equals(Enumerations.SearchParamType.STRING)) { + addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.INFORMATION, + "Parameter type for :" + apiParameter.name + " should be a `" + searchParameter.type.toCode() + "`, is `" + apiParameter.type.toCode()+"`" + ) + } + } + + Enumerations.SearchParamType.REFERENCE -> { + if (!apiParameter.type.equals(Enumerations.SearchParamType.REFERENCE)) { + addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.INFORMATION, + "Parameter type for :" + apiParameter.name + " should be a `" + searchParameter.type.toCode() + "`, is `" + apiParameter.type.toCode()+"`" + ) + } + } + + Enumerations.SearchParamType.TOKEN -> { + if (!apiParameter.type.equals(Enumerations.SearchParamType.TOKEN)) { + addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.INFORMATION, + "Parameter type for :" + apiParameter.name + " should be a `" + searchParameter.type.toCode() + "`, is `" + apiParameter.type.toCode()+"`" + ) + } + } + + Enumerations.SearchParamType.DATE -> { + if (!apiParameter.type.equals(Enumerations.SearchParamType.DATE)) { + addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.INFORMATION, + "Parameter type for :" + apiParameter.name + " should be a `" + searchParameter.type.toCode() + "`, is `" + apiParameter.type.toCode()+"`" + ) + } + } + + Enumerations.SearchParamType.NUMBER -> { + addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.INFORMATION, + "Parameter type for :" + apiParameter.name + " should be a `" + searchParameter.type.toCode() + "`, is `" + apiParameter.type.toCode()+"`" + ) + } + + else -> {} + }*/ + } + } + } + +private fun addOperationIssue(outcomes: MutableList, code : OperationOutcome.IssueType, severity :OperationOutcome.IssueSeverity, message : String? ): OperationOutcome.OperationOutcomeIssueComponent { + val operation = OperationOutcome.OperationOutcomeIssueComponent() + operation.code = code + operation.severity = severity + if (message!=null) operation.diagnostics = message + outcomes.add(operation) + return operation +} + fun getSearchParameter(outcomes : MutableList , resourceType: String, name : String) : SearchParameter? { + val parameters = name.split(".") + + val searchParameter = searchParameterSupport.getSearchParameter(resourceType,name) + + if (parameters.size>1) { + if (searchParameter?.type != Enumerations.SearchParamType.REFERENCE) { + // maybe throw error? + } else { + + var resourceType: String? + + // A bit coarse + resourceType = "Resource" + if (searchParameter.hasTarget() ) { + for (resource in searchParameter.target) { + if (!resource.code.equals("Group")) resourceType=resource.code + } + } + + var newSearchParamName = parameters.get(1) + // Add back in remaining chained parameters + for (i in 3..parameters.size) { + newSearchParamName += "."+parameters.get(i) + } + + } + } + + return searchParameter + } + +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/OpenAPIParser.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/oas/CapabilityStatementToOpenAPIConversion.kt similarity index 72% rename from src/main/kotlin/uk/nhs/england/fhirvalidator/service/OpenAPIParser.kt rename to src/main/kotlin/uk/nhs/england/fhirvalidator/service/oas/CapabilityStatementToOpenAPIConversion.kt index 093527a..0ee4607 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/OpenAPIParser.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/oas/CapabilityStatementToOpenAPIConversion.kt @@ -1,4 +1,4 @@ -package uk.nhs.england.fhirvalidator.service +package uk.nhs.england.fhirvalidator.service.oas import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.context.support.IValidationSupport @@ -6,6 +6,7 @@ import ca.uhn.fhir.context.support.ValidationSupportContext import ca.uhn.fhir.context.support.ValueSetExpansionOptions import ca.uhn.fhir.rest.api.Constants import ca.uhn.fhir.util.HapiExtensions +import com.fasterxml.jackson.databind.ObjectMapper import io.swagger.v3.oas.models.* import io.swagger.v3.oas.models.examples.Example import io.swagger.v3.oas.models.info.Contact @@ -18,14 +19,22 @@ import io.swagger.v3.oas.models.responses.ApiResponses import io.swagger.v3.oas.models.servers.Server import io.swagger.v3.oas.models.tags.Tag import org.apache.commons.lang3.StringUtils +import org.apache.commons.text.StringEscapeUtils import org.hl7.fhir.instance.model.api.IBaseResource import org.hl7.fhir.instance.model.api.IPrimitiveType import org.hl7.fhir.r4.model.* -import org.hl7.fhir.utilities.npm.NpmPackage import org.json.JSONArray import org.json.JSONObject import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.core.Ordered +import org.springframework.core.annotation.Order +import org.springframework.core.io.ClassPathResource import org.springframework.stereotype.Service +import uk.nhs.england.fhirvalidator.interceptor.CapabilityStatementApplier +import uk.nhs.england.fhirvalidator.model.FHIRPackage +import uk.nhs.england.fhirvalidator.model.SimplifierPackage +import uk.nhs.england.fhirvalidator.service.ImplementationGuideParser +import uk.nhs.england.fhirvalidator.service.SearchParameterSupport import java.math.BigDecimal import java.net.URI import java.util.concurrent.atomic.AtomicReference @@ -33,10 +42,13 @@ import java.util.function.Supplier import java.util.stream.Collectors @Service -class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, - private val npmPackages: List?, - @Qualifier("SupportChain") private val supportChain: IValidationSupport, - private val searchParameterSupport : SearchParameterSupport) { +@Order(Ordered.LOWEST_PRECEDENCE) +class CapabilityStatementToOpenAPIConversion(@Qualifier("R4") private val ctx: FhirContext, + private val fhirPackage: List, + @Qualifier("SupportChain") private val supportChain: IValidationSupport, + private val searchParameterSupport : SearchParameterSupport, + private val capabilityStatementApplier: CapabilityStatementApplier +) { val PAGE_SYSTEM = "System Level Operations" @@ -52,65 +64,56 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, - fun generateOpenApi(_cs: CapabilityStatement): OpenAPI? { + fun generateOpenApi(_cs: CapabilityStatement, enhance: Boolean): OpenAPI? { cs = _cs val openApi = OpenAPI() openApi.info = Info() - openApi.info.description = cs.description + openApi.info.description = unescapeMarkdown(cs.description) if (openApi.info.description == null) openApi.info.description = "" - openApi.info.title = cs.software.name + if (cs.hasTitle()) openApi.info.title = cs.title openApi.info.version = cs.software.version - openApi.info.contact = Contact() - openApi.info.contact.name = cs.contactFirstRep.name - openApi.info.contact.email = cs.contactFirstRep.telecomFirstRep.value + if (cs.hasContact()) { + openApi.info.contact = Contact() + for (contact in cs.contact){ + if (cs.hasName()) openApi.info.contact.name = contact.name + if (contact.hasTelecom()) { + for (telecom in contact.telecom) { + if (telecom.hasSystem() && telecom.system.equals(ContactPoint.ContactPointSystem.EMAIL)) { + openApi.info.contact.email = telecom.value + } + if (telecom.hasSystem() && telecom.system.equals(ContactPoint.ContactPointSystem.URL)) { + openApi.info.contact.url = telecom.value + } + } + } + } + } for (code in cs.format) { if (code.value.contains("xml")) generateXML = true } - - if (cs.hasExtension("https://fhir.nhs.uk/StructureDefinition/Extension-NHSDigital-CapabilityStatement-Package")) { - val apiDefinition = cs.getExtensionByUrl("https://fhir.nhs.uk/StructureDefinition/Extension-NHSDigital-CapabilityStatement-Package") - // Sample table:\n\n| One | Two | Three |\n|-----|-----|-------|\n| a | b | c | - if (apiDefinition.hasExtension("openApi")) { - var docDescription = "\n\n | API Documentation |\n |-----|\n " - apiDefinition.extension.forEach{ - if (it.url.equals("openApi")) { - docDescription += " |["+(it.getExtensionByUrl("description").value as StringType).value+"]("+(it.getExtensionByUrl("documentation").value as UriType).value+")|\n" - } + /* + if (enhance && fhirPackage !== null && fhirPackage.size > 0) { + var igDescription = "\n\n | FHIR Implementation Guide | Version |\n |-----|-----|\n" + + fhirPackage.forEach { + if (!it.derived) { + val name = it.url + val version = it.version + val pckg = it.name + val url = getDocumentationPath(it.url) + if (name == null) igDescription += " ||$pckg#$version|\n" + else igDescription += " |[$name]($url)|$pckg#$version|\n" } - openApi.info.description += docDescription } - openApi.info.extensions = mutableMapOf() - val igs = mutableMapOf() - if (apiDefinition.hasExtension("FHIRPackage")) { - var igDescription = "\n\n | FHIR Implementation Guide | Version |\n |-----|-----|\n" - apiDefinition.extension.forEach{ - - if (it.url.equals("FHIRPackage")) { - - val name = it.getExtensionByUrl("name").value as StringType - var url = "https://simplifier.net/guide/NHSDigital/Home" - var version = "" - if (it.hasExtension("version")) { - version = (it.getExtensionByUrl("version").value as StringType).value - igs[(it.getExtensionByUrl("name").value as StringType).value] = (it.getExtensionByUrl("version").value as StringType).value - } else { - igs[(it.getExtensionByUrl("name").value as StringType).value] = "" - } - if (name.value.startsWith("uk.nhsdigital.medicines")) url = "https://simplifier.net/guide/nhsdigital-medicines/home" - if (name.value.startsWith("ukcore.")) url = "https://simplifier.net/guide/hl7fhirukcorer4release1/home" - igDescription += " |[$name]($url)|$version|\n" + openApi.info.description += "\n\n" + igDescription + } - } - } - openApi.info.description += igDescription - } - openApi.info.extensions["x-HL7-FHIR-NpmPackages"] = igs + */ - } openApi.externalDocs = ExternalDocumentation() - openApi.externalDocs.description = "Hl7 FHIR R4" - openApi.externalDocs.url = "https://www.hl7.org/fhir/" + if (cs.hasTitle()) openApi.externalDocs.description = cs.title + if (cs.hasUrl()) openApi.externalDocs.url = getDocumentationPath(cs.url) val server = Server() openApi.addServersItem(server) server.url = cs.implementation.url @@ -122,10 +125,18 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, serverTag.name = PAGE_SYSTEM serverTag.description = "Server-level operations" openApi.addTagsItem(serverTag) + + val capabilitiesOperation = getPathItem(paths, "/metadata", PathItem.HttpMethod.GET) capabilitiesOperation.addTagsItem(PAGE_SYSTEM) - capabilitiesOperation.summary = "server-capabilities: Fetch the server FHIR CapabilityStatement" - addFhirResourceResponse(this.ctx, openApi, capabilitiesOperation, "CapabilityStatement",null,null,null) + if (enhance) { + capabilitiesOperation.externalDocs = ExternalDocumentation() + capabilitiesOperation.externalDocs.url = "https://hl7.org/fhir/R4/http.html#capabilities" + capabilitiesOperation.externalDocs.description = "FHIR RESTful API - capabilities" + } + addFhirResourceResponse(this.ctx, openApi, capabilitiesOperation, "CapabilityStatement",null,null,null, enhance) + + val systemInteractions = cs.restFirstRep.interaction.stream().map { t: CapabilityStatement.SystemInteractionComponent -> t.code } .collect(Collectors.toSet()) @@ -138,23 +149,30 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, ) { val transaction = getPathItem(paths, "/", PathItem.HttpMethod.POST) transaction.addTagsItem(PAGE_SYSTEM) - transaction.summary = "server-transaction: Execute a FHIR Transaction (or FHIR Batch) Bundle" - addFhirResourceResponse(ctx, openApi, transaction, null, null,null,null) - addFhirResourceRequestBody(openApi, transaction, emptyList(), "Bundle",null) + if (enhance) { + transaction.externalDocs = ExternalDocumentation() + transaction.externalDocs.url = "https://hl7.org/fhir/R4/http.html#transaction" + transaction.externalDocs.description = "FHIR RESTful API - transaction" + } + addFhirResourceResponse(ctx, openApi, transaction, null, null,null,null, enhance) + addFhirResourceRequestBody(openApi, transaction, emptyList(), "Bundle",null, enhance) } // System History Operation if (systemInteractions.contains(CapabilityStatement.SystemRestfulInteraction.HISTORYSYSTEM)) { val systemHistory = getPathItem(paths, "/_history", PathItem.HttpMethod.GET) systemHistory.addTagsItem(PAGE_SYSTEM) - systemHistory.summary = - "server-history: Fetch the resource change history across all resource types on the server" - addFhirResourceResponse(ctx, openApi, systemHistory, null, null,null,null) + if (enhance) { + systemHistory.externalDocs = ExternalDocumentation() + systemHistory.externalDocs.url = "https://hl7.org/fhir/R4/http.html#history" + systemHistory.externalDocs.description = "FHIR RESTful API - history" + } + addFhirResourceResponse(ctx, openApi, systemHistory, null, null,null,null, enhance) } // System-level Operations for (nextOperation in cs.restFirstRep.operation) { - addFhirOperation(ctx, openApi, paths, null, nextOperation) + addFhirOperation(ctx, openApi, paths, null, nextOperation, enhance) } @@ -167,7 +185,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, t.codeElement.value }.collect(Collectors.toSet()) - addResoureTag(openApi,resourceType,nextResource.profile) + addResoureTag(openApi,resourceType,nextResource.profile, enhance, nextResource.documentation) for (resftfulIntraction in nextResource.interaction) { val requestExample = getRequestExample(resftfulIntraction) @@ -177,124 +195,197 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, CapabilityStatement.TypeRestfulInteraction.SEARCHTYPE -> { val operation = getPathItem(paths, "/$resourceType", PathItem.HttpMethod.GET) operation.addTagsItem(resourceType) - operation.summary = resftfulIntraction.code.display - operation.description = "[search](http://www.hl7.org/fhir/search.html) for $resourceType instances." + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - search") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#search") + } if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+ resftfulIntraction.documentation + operation.description = unescapeMarkdown(resftfulIntraction.documentation) + } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } } - if (nextResource.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination")) { - var comboDoc = "\n\n **Required Parameters** \n\n One of the following search paramter combinations is **required** \n\n" + - "| Required | Optional | \n" + if (enhance && nextResource.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination")) { + var comboDoc = "\n\n **Search Parameter Combination Conformance** \n\n " + + "| Conformance Expectation | Parameter Combination | \n" comboDoc += "|----------|---------| \n" for (extension in nextResource.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination")) { - var requiredDoc = "" - var optionalDoc = "" + var conformance = "" + var combination = "" + if (extension.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + for (required in extension.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + conformance = "**" + (required.value as CodeType).value + "**" + } + } if (extension.hasExtension("required")) { for (required in extension.getExtensionsByUrl("required")) { - if (requiredDoc != "") requiredDoc += "+" - requiredDoc += (required.value as StringType).value + if (combination != "") combination += " + " + val name = (required.value as StringType).value + combination += "[$name](https://www.hl7.org/fhir/R4/$resourceType.html#search)" + } } if (extension.hasExtension("optional")) { for (optional in extension.getExtensionsByUrl("optional")) { - optionalDoc += (optional.value as StringType).value + "
" + if (combination != "") combination += " + " + val name = (optional.value as StringType).value + combination += "[$name](https://www.hl7.org/fhir/R4/$resourceType.html#search) *optional*" } } - comboDoc += "| $requiredDoc| $optionalDoc | \n" + comboDoc += "| $conformance| $combination | \n" } + if (operation.description == null) operation.description = "" operation.description += comboDoc } - addFhirResourceResponse(ctx, openApi, operation, resourceType,resftfulIntraction, null,null) - processSearchParameter(operation,nextResource,resourceType) + addFhirResourceResponse(ctx, openApi, operation, resourceType,resftfulIntraction, null,null, enhance) + processSearchParameter(operation,nextResource,resourceType, enhance) addResourceAPIMParameter(operation) } // Instance Read CapabilityStatement.TypeRestfulInteraction.READ -> { val operation = getPathItem(paths, "/$resourceType/{id}", PathItem.HttpMethod.GET) operation.addTagsItem(resourceType) - operation.summary = resftfulIntraction.code.display - operation.description = "[read](http://www.hl7.org/fhir/http.html#read) $resourceType instance." + + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - read") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#read") + } if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+resftfulIntraction.documentation + operation.description = resftfulIntraction.documentation + } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } } addResourceIdParameter(operation) addResourceAPIMParameter(operation) - addFhirResourceResponse(ctx, openApi, operation,resourceType,resftfulIntraction,null,null) + addFhirResourceResponse(ctx, openApi, operation,resourceType,resftfulIntraction,null,null, enhance) } // Instance Update CapabilityStatement.TypeRestfulInteraction.UPDATE -> { val operation = getPathItem(paths, "/$resourceType/{id}", PathItem.HttpMethod.PUT) operation.addTagsItem(resourceType) - operation.summary = resftfulIntraction.code.display - operation.description = - "[update](http://www.hl7.org/fhir/http.html#update) an existing $resourceType instance, or create using a client-assigned ID." - if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+ resftfulIntraction.documentation + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - update") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#update") + } + if (resftfulIntraction.hasDocumentation()) { + operation.description = resftfulIntraction.documentation + } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } } addResourceIdParameter(operation) addResourceAPIMParameter(operation) - addFhirResourceRequestBody(openApi, operation, requestExample, resourceType,nextResource.profile) - addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null) + addFhirResourceRequestBody(openApi, operation, requestExample, resourceType,nextResource.profile, enhance) + addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null, enhance) } // Type Create CapabilityStatement.TypeRestfulInteraction.CREATE -> { val operation = getPathItem(paths, "/$resourceType", PathItem.HttpMethod.POST) operation.addTagsItem(resourceType) - operation.summary = resftfulIntraction.code.display - operation.description = "[create](http://www.hl7.org/fhir/http.html#create) a new $resourceType instance." + + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - create") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#create") + } if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+resftfulIntraction.documentation + operation.description = resftfulIntraction.documentation + } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } } addResourceAPIMParameter(operation) - addFhirResourceRequestBody(openApi, operation, requestExample, resourceType, nextResource.profile) - addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null) + addFhirResourceRequestBody(openApi, operation, requestExample, resourceType, nextResource.profile, enhance) + addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null, enhance) } // Instance Patch CapabilityStatement.TypeRestfulInteraction.PATCH -> { val operation = getPathItem(paths, "/$resourceType/{id}", PathItem.HttpMethod.PATCH) operation.addTagsItem(resourceType) - operation.summary = resftfulIntraction.code.display - operation.description = "[patch](http://www.hl7.org/fhir/http.html#patch) a resource instance of type $resourceType by ID." + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - patch") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#patch") + } if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+resftfulIntraction.documentation + operation.description = resftfulIntraction.documentation + } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } } addResourceIdParameter(operation) addResourceAPIMParameter(operation) addJSONSchema(openApi) addPatchResourceRequestBody(operation, patchExampleSupplier(resourceType)) - addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null) + addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null, enhance) } // Instance Delete CapabilityStatement.TypeRestfulInteraction.DELETE -> { val operation = getPathItem(paths, "/$resourceType/{id}", PathItem.HttpMethod.DELETE) operation.addTagsItem(resourceType) - operation.summary = resftfulIntraction.code.display - operation.description = "Perform a logical [delete](http://www.hl7.org/fhir/http.html#delete) on a resource instance." + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - delete") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#delete") + } if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+resftfulIntraction.documentation + operation.description = resftfulIntraction.documentation } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } + } addResourceIdParameter(operation) - addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null) + addFhirResourceResponse(ctx, openApi, operation, "OperationOutcome",resftfulIntraction,null,null, enhance) } // Type history CapabilityStatement.TypeRestfulInteraction.HISTORYTYPE -> { val operation = getPathItem(paths, "/$resourceType/_history", PathItem.HttpMethod.GET) operation.addTagsItem(resourceType) - operation.summary = "history" - operation.description = - "Fetch the resource change [history](http://www.hl7.org/fhir/http.html#history) for all resources of type $resourceType." + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - history") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#history") + } if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+resftfulIntraction.documentation + operation.description = resftfulIntraction.documentation + } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } } - processSearchParameter(operation,nextResource,resourceType) + processSearchParameter(operation,nextResource,resourceType, enhance) addResourceAPIMParameter(operation) - addFhirResourceResponse(ctx, openApi, operation, resourceType,resftfulIntraction, null,null) + addFhirResourceResponse(ctx, openApi, operation, resourceType,resftfulIntraction, null,null, enhance) } // Instance history @@ -304,16 +395,24 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, "/$resourceType/{id}/_history", PathItem.HttpMethod.GET ) operation.addTagsItem(resourceType) - operation.summary = "history" - operation.description = - "Fetch the resource change [history](http://www.hl7.org/fhir/http.html#history) for all resources of type $resourceType" - if (resftfulIntraction.hasDocumentation()) { - operation.description += "\n\n"+resftfulIntraction.documentation + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - history") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#history") + } + if (resftfulIntraction.hasDocumentation()) { + operation.description = resftfulIntraction.documentation + } + if (enhance && resftfulIntraction.hasExtension("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (operation.description == null) operation.description = "" + for (required in resftfulIntraction.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + operation.description += "\n\n Query Conformance Expectation: **" + (required.value as CodeType).value + "** be supported." + } } addResourceIdParameter(operation) - processSearchParameter(operation,nextResource,resourceType) + processSearchParameter(operation,nextResource,resourceType, enhance) addResourceAPIMParameter(operation) - addFhirResourceResponse(ctx, openApi, operation, resourceType,resftfulIntraction,null,null) + addFhirResourceResponse(ctx, openApi, operation, resourceType,resftfulIntraction,null,null, enhance) } else -> {} @@ -328,34 +427,54 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, "/$resourceType/{id}/_history/{version_id}", PathItem.HttpMethod.GET ) operation.addTagsItem(resourceType) - operation.summary = "vread" - operation.description = "[vread](http://www.hl7.org/fhir/http.html#vread) $resourceType instance with specific version." + if (enhance) { + operation.externalDocs = ExternalDocumentation() + operation.externalDocs.description("FHIR RESTful API - vread") + operation.externalDocs.url("https://hl7.org/fhir/R4/http.html#vread") + } addResourceIdParameter(operation) addResourceVersionIdParameter(operation) addResourceAPIMParameter(operation) - addFhirResourceResponse(ctx, openApi, operation, resourceType,null,null,null) + addFhirResourceResponse(ctx, openApi, operation, resourceType,null,null,null, enhance) } // Resource-level Operations for (nextOperation in nextResource.operation) { - addFhirOperation(ctx, openApi, paths, resourceType, nextOperation) + addFhirOperation(ctx, openApi, paths, resourceType, nextOperation, enhance) } } return openApi } - private fun processSearchParameter(operation : Operation, nextResource : CapabilityStatement.CapabilityStatementRestResourceComponent,resourceType: String) { + private fun processSearchParameter(operation : Operation, + nextResource : CapabilityStatement.CapabilityStatementRestResourceComponent, + resourceType: String, + addFHIRBoilerPlater: Boolean) { for (nextSearchParam in nextResource.searchParam) { val parametersItem = Parameter() operation.addParametersItem(parametersItem) parametersItem.name = nextSearchParam.name parametersItem.setIn("query") - parametersItem.description = nextSearchParam.documentation - parametersItem.description += getSearchParameterDocumentation(nextSearchParam,resourceType, parametersItem,true) + parametersItem.description = "" + if (nextSearchParam.hasDocumentation()) parametersItem.description += nextSearchParam.documentation + if (addFHIRBoilerPlater) parametersItem.description += getSearchParameterDocumentation(nextSearchParam,resourceType, parametersItem,true) + /* required is not present in CapabilityStatement ..... or not found at present + if (nextSearchParam.hasExtension()) { + nextSearchParam.extension.forEach { + if (it.hasUrl() && it.url.equals("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation")) { + if (it.hasValue() && it.value is CodeType) { + if ((it.value as CodeType).code.equals("SHALL")) { + parametersItem.required = true + } + } + } + } + } + */ // calculate style and explode parametersItem.style = Parameter.StyleEnum.FORM if (parametersItem.schema != null && parametersItem.schema.format != null) { @@ -436,6 +555,10 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, } } + fun unescapeMarkdown(markdown : String ) : String { + return StringEscapeUtils.unescapeHtml4(markdown) + } + private fun addJSONSchema(openApi: OpenAPI) { // Add schema @@ -450,30 +573,14 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, } - - private fun getBaseProfile(profile: String) :StructureDefinition? { - var profileDef = getProfile(profile) - if (profileDef != null && profileDef.hasBaseDefinition() && !profileDef.baseDefinition.contains("Resource")) { - profileDef = getBaseProfile(profileDef.baseDefinition) - } - return profileDef - } - - private fun getProfile(profile: String?) : StructureDefinition? { + fun getProfile(profile: String?) : StructureDefinition? { + if (profile == null) return null val structureDefinition = supportChain.fetchStructureDefinition(profile) if (structureDefinition is StructureDefinition) return structureDefinition return null } - private fun getDocumentationPath(profile : String) : String { - supportChain.fetchAllConformanceResources()?.filterIsInstance()?.forEach { - if (it.url == profile) { - return "https://simplifier.net/guide/nhsdigital" - /// TODO return getDocumentationPathNpm(profile,npmPackage) - } - } - return "https://simplifier.net/guide/nhsdigital/home" - } + private fun getProfileName(profile : String) : String { @@ -536,7 +643,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOpenApi: OpenAPI, thePaths: Paths, theResourceType: String?, - theOperation: CapabilityStatement.CapabilityStatementRestResourceOperationComponent + theOperation: CapabilityStatement.CapabilityStatementRestResourceOperationComponent, + enhance: Boolean ) { val operationDefinition = AtomicReference() //val definitionId = IdType(theOperation.definition) @@ -567,7 +675,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, operationDefinition.get(), operation, true, - theOperation + theOperation, + enhance ) return } @@ -587,7 +696,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, operationDefinition.get(), operation, true, - theOperation + theOperation, + enhance ) } if (operationDefinition.get()!!.instance) { @@ -603,7 +713,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, operationDefinition.get(), operation, true, - theOperation + theOperation, + enhance ) } } else { @@ -613,7 +724,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, .code, PathItem.HttpMethod.GET ) populateOperation(theFhirContext, theOpenApi, null, operationDefinition.get(), operation, true, - theOperation + theOperation, enhance ) } } @@ -633,7 +744,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, operationDefinition.get(), operation, false, - theOperation + theOperation, + enhance ) } if (operationDefinition.get()!!.instance) { @@ -649,7 +761,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, operationDefinition.get(), operation, false, - theOperation + theOperation, + enhance ) } @@ -659,8 +772,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, thePaths, "/$" + operationDefinition.get()!! .code, PathItem.HttpMethod.POST ) - populateOperation(theFhirContext, theOpenApi, null, operationDefinition.get(), operation, false, theOperation - ) + populateOperation(theFhirContext, theOpenApi, null, operationDefinition.get(), operation, + false, theOperation, enhance) } } } @@ -674,7 +787,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOperationDefinition: OperationDefinition?, theOperation: Operation, theGet: Boolean, - theOperationComponent: CapabilityStatement.CapabilityStatementRestResourceOperationComponent + theOperationComponent: CapabilityStatement.CapabilityStatementRestResourceOperationComponent, + enhance: Boolean ) { if (theResourceType == null) { theOperation.addTagsItem(PAGE_SYSTEM) @@ -682,7 +796,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOperation.addTagsItem(theResourceType) } theOperation.summary = theOperationDefinition!!.title - theOperation.description = theOperationDefinition.description + theOperation.description = unescapeMarkdown(theOperationDefinition.description) if (theOperationComponent.hasExtension("https://fhir.nhs.uk/StructureDefinition/Extension-NHSDigital-CapabilityStatement-Examples")) { // val exampleOperation = getOperationResponeExample(theOperationComponent) @@ -696,18 +810,19 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, openApi, exampleList, (exampleOperation.get())?.fhirType(), - null + null, + enhance ) theOperation.responses.addApiResponse("200",response200) - addStandardResponses(openApi,theOperation.responses) + addStandardResponses(openApi,theOperation.responses, enhance) } else { - addFhirResourceResponse(theFhirContext, openApi, theOperation, "Parameters", null,theOperationComponent,null) + addFhirResourceResponse(theFhirContext, openApi, theOperation, "Parameters", null,theOperationComponent,null, enhance) } //theOperation.requestBody.content = provideContentFhirResource(theOpenApi,ctx,exampleOperation, null) } else { - addFhirResourceResponse(theFhirContext, openApi, theOperation, "Parameters", null, theOperationComponent,null) + addFhirResourceResponse(theFhirContext, openApi, theOperation, "Parameters", null, theOperationComponent,null, enhance) } val mediaType = MediaType() if (theGet) { @@ -716,7 +831,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOperation.addParametersItem(parametersItem) parametersItem.name = nextParameter.name parametersItem.setIn("query") - parametersItem.description = nextParameter.documentation + parametersItem.description = unescapeMarkdown(nextParameter.documentation) parametersItem.style = Parameter.StyleEnum.SIMPLE parametersItem.required = nextParameter.min > 0 val exampleExtensions = nextParameter.getExtensionsByUrl(HapiExtensions.EXT_OP_PARAMETER_EXAMPLE_VALUE) @@ -857,7 +972,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, Schema().type("object").title("Bundle-Message") // addSchemaFhirResource(openApi,bundleSchema,"Bundle-Message") - addFhirResourceSchema(openApi,"Bundle","https://fhir.nhs.uk/StructureDefinition/NHSDigital-Bundle-FHIRMessage") + addFhirResourceSchema(openApi,"Bundle","https://fhir.nhs.uk/StructureDefinition/NHSDigital-Bundle-FHIRMessage", enhance) mediaType.schema = ObjectSchema().`$ref`( "#/components/schemas/Bundle" ) @@ -872,7 +987,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOperation.requestBody.content.addMediaType(Constants.CT_FHIR_JSON_NEW, mediaType) } - if (theOperationDefinition.hasParameter()) { + if (enhance && theOperationDefinition.hasParameter()) { var inDoc = "\n\n ## Parameters (In) \n\n |Name | Cardinality | Type | Profile | Documentation |\n |-------|-----------|-------------|------------|------------|" var outDoc = "\n\n ## Parameters (Out) \n\n |Name | Cardinality | Type | Profile | Documentation |\n |-------|-----------|-------------|------------|------------|" for (parameter in theOperationDefinition.parameter) { @@ -910,9 +1025,9 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOperation.description += outDoc } if (theOperationDefinition.hasComment()) { - theOperation.description += "\n\n ## Comment \n\n"+theOperationDefinition.comment + theOperation.description += "\n\n ## Comment \n\n"+unescapeMarkdown(theOperationDefinition.comment) } - if (theOperationDefinition.url.equals("http://hl7.org/fhir/OperationDefinition/MessageHeader-process-message") + if (enhance && theOperationDefinition.url.equals("http://hl7.org/fhir/OperationDefinition/MessageHeader-process-message") || theOperationDefinition.url.equals("https://fhir.nhs.uk/OperationDefinition/MessageHeader-process-message")) { var supportedDocumentation = "\n\n ## Supported Messages \n\n" @@ -923,7 +1038,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, for (supportedMessage in messaging.supportedMessage) { val idStr = getProfileName(supportedMessage.definition) supportedDocumentation += "* $idStr \n" - mediaType.examples[idStr] = getMessageExample(openApi, supportedMessage) + mediaType.examples[idStr] = getMessageExample(openApi, supportedMessage, enhance) } } theOperation.description += supportedDocumentation @@ -989,10 +1104,11 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOperation: Operation, theExampleSupplier: List, theResourceType: String?, - profile: String? + profile: String?, + enhance: Boolean ) { val requestBody = RequestBody() - requestBody.content = provideContentFhirResource(theOpenApi, theExampleSupplier,theResourceType, profile) + requestBody.content = provideContentFhirResource(theOpenApi, theExampleSupplier,theResourceType, profile, enhance) theOperation.requestBody = requestBody } @@ -1014,20 +1130,34 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theResourceType: String?, resftfulIntraction : CapabilityStatement.ResourceInteractionComponent?, operationComponent: CapabilityStatement.CapabilityStatementRestResourceOperationComponent?, - profile: String? + profile: String?, + enhance: Boolean ) { theOperation.responses = ApiResponses() val response200 = ApiResponse() response200.description = "Success" if (resftfulIntraction != null) { - val exampleResponse = getInteractionResponseExample(resftfulIntraction) + var exampleResponse = getInteractionResponseExample(resftfulIntraction) + + if (resftfulIntraction.code.toCode().equals("search-type")) { + if (theResourceType !== null) { + exampleResponse = getSearchSetExample(theResourceType) + } + response200.content = provideContentFhirResource( + theOpenApi, + exampleResponse, + "Bundle", + profile, enhance + ) + } else { + response200.content = provideContentFhirResource( + theOpenApi, + exampleResponse, + theResourceType, + profile, enhance + ) + } - response200.content = provideContentFhirResource( - theOpenApi, - exampleResponse, - theResourceType, - profile - ) } if (operationComponent != null) { @@ -1037,7 +1167,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOpenApi, exampleResponse, theResourceType, - profile + profile, enhance ) } @@ -1047,17 +1177,17 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOpenApi, genericExampleSupplier(theFhirContext, theResourceType), theResourceType, - profile + profile, enhance ) } theOperation.responses.addApiResponse("200", response200) - addStandardResponses(theOpenApi,theOperation.responses) + addStandardResponses(theOpenApi,theOperation.responses, enhance) } - private fun addStandardResponses(theOpenApi: OpenAPI,responses: ApiResponses) { + private fun addStandardResponses(theOpenApi: OpenAPI,responses: ApiResponses, enhance: Boolean) { val response4xx = ApiResponse() var example = Example() example.value = getErrorOperationOutcome() @@ -1067,7 +1197,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOpenApi, exampleResponse, "OperationOutcome", - null + null, + enhance ) responses.addApiResponse("4xx", response4xx) @@ -1081,7 +1212,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOpenApi, exampleResponse, "OperationOutcome", - null + null, + enhance ) responses.addApiResponse("403", response403) } @@ -1121,7 +1253,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, return ctx?.newJsonParser()?.setPrettyPrint(true)?.encodeResourceToString(operationOutcome) } - private fun getMessageExample(openApi: OpenAPI,supportedMessage : CapabilityStatement.CapabilityStatementMessagingSupportedMessageComponent) : Example { + private fun getMessageExample(openApi: OpenAPI,supportedMessage : CapabilityStatement.CapabilityStatementMessagingSupportedMessageComponent, enhance: Boolean) : Example { var supportedDocumentation = "" val example = Example() @@ -1133,7 +1265,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, if (resourceChain is MessageDefinition) { if (resourceChain.url == supportedMessage.definition) { if (resourceChain.hasDescription()) { - example.summary = resourceChain.description + example.summary = unescapeMarkdown(resourceChain.description) } if (resourceChain.hasPurpose()) { supportedDocumentation += "\n ### Purpose" + resourceChain.purpose @@ -1153,11 +1285,11 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, profile = "" } else { profile = getDocumentationPath(profile) - addFhirResourceSchema(openApi, foci.code, foci.profile) - addResoureTag(openApi, foci.code,foci.profile) + addFhirResourceSchema(openApi, foci.code, foci.profile, enhance) + addResoureTag(openApi, foci.code,foci.profile, enhance, "") } val idStr = getProfileName(foci.profile) - supportedDocumentation += "| [$resource](https://www.hl7.org/fhir/$resource.html) | [$idStr]($profile) | $min | $max | \n" + supportedDocumentation += "| [$resource](https://www.hl7.org/fhir/R4/$resource.html) | [$idStr]($profile) | $min | $max | \n" } } // only process this loop once @@ -1178,11 +1310,14 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, example.value = ctx?.newJsonParser()?.encodeResourceToString(messageExample?.get()) } } - example.description = supportedDocumentation + example.description = unescapeMarkdown(supportedDocumentation) return example } + private fun getExampleFromPackages(request: Boolean, extension: Extension, create : Boolean) : Supplier? { + return null + /* // TODO Return array of examples including documentation val path = (extension.getExtensionByUrl("value").value as Reference).reference val pathParts = path.split("/") @@ -1214,7 +1349,13 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, println("----- Not found " + request + path) } return null + + */ } + + + + private fun getRequestExample(interaction : CapabilityStatement.ResourceInteractionComponent) : List{ // val examples = mutableListOf() @@ -1233,7 +1374,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, exampleOAS.summary = (exampleExt.getExtensionString("summary") as String) } if (exampleExt.hasExtension("description")) { - exampleOAS.description = (exampleExt.getExtensionString("description") as String) + exampleOAS.description = unescapeMarkdown((exampleExt.getExtensionString("description") as String)) } } } @@ -1263,6 +1404,33 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, } return emptyList() } + + fun getSearchSetExample(resourceType : String) : List { + val examples = mutableListOf() + val exampleOAS = Example() + examples.add(exampleOAS) + val bundle = Bundle() + bundle.type = Bundle.BundleType.SEARCHSET + bundle.addLink( + Bundle.BundleLinkComponent() + .setRelation("self") + .setUrl(exampleServer + exampleServerPrefix + resourceType + "?parameterExample=123&page=1") + ) + bundle.addLink( + Bundle.BundleLinkComponent() + .setRelation("next") + .setUrl(exampleServer + exampleServerPrefix + resourceType + "?parameterExample=123&page=2") + ) + val example = ctx?.getResourceDefinition(resourceType)?.newInstance() + example?.setId("1234") + bundle.entry.add( + Bundle.BundleEntryComponent().setResource(example as Resource) + .setFullUrl(exampleServer + exampleServerPrefix + resourceType + "/1234") + ) + bundle.total = 1 + exampleOAS.value = ctx?.newJsonParser()?.encodeResourceToString(bundle) + return examples + } private fun getResponseExample(apiExtension : Extension,searchExample : Boolean,createCall : Boolean) : List { val examples = mutableListOf() if (apiExtension.hasExtension("example")) { @@ -1384,7 +1552,8 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, theOpenApi: OpenAPI, examples: List, resourceType: String?, - profile: String? + profile: String?, + enhance: Boolean ): Content { val retVal = Content() var resourceType2 = resourceType @@ -1400,7 +1569,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, if (resourceType2 == null && theExampleSupplier != null) resourceType2 = theExampleSupplier.fhirType() // if (resourceType2 != null) addJSONSchema(theOpenApi, resourceType2) - val jsonSchema = resourceType2?.let { getMediaType(theOpenApi, it, profile) } + val jsonSchema = resourceType2?.let { getMediaType(theOpenApi, it, profile, enhance) } if (theExampleSupplier != null) { if (jsonSchema != null) { @@ -1408,7 +1577,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, } } retVal.addMediaType(Constants.CT_FHIR_JSON_NEW, jsonSchema) - val xmlSchema = resourceType2?.let { getMediaType(theOpenApi, it, profile) } + val xmlSchema = resourceType2?.let { getMediaType(theOpenApi, it, profile, enhance) } if (theExampleSupplier != null) { if (xmlSchema != null) { @@ -1417,7 +1586,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, } if (generateXML) retVal.addMediaType(Constants.CT_FHIR_XML_NEW, xmlSchema) } else { - val jsonSchema = getMediaType(theOpenApi,resourceType2, profile) + val jsonSchema = getMediaType(theOpenApi,resourceType2, profile, enhance) // Ensure schema is added //if (resourceType2 != null) addJSONSchema(theOpenApi, resourceType2) @@ -1501,7 +1670,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, /* protected fun getIndexTemplate(): ClassLoaderTemplateResource? { return ClassLoaderTemplateResource( - myResourcePathToClasspath["/swagger-ui/index.html"], + myResourcePathToClasspath["/swagger-ui/404.html"], StandardCharsets.UTF_8.name() ) } @@ -1557,7 +1726,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, var description = "" if (searchParameter?.description != null) { - var desc = searchParameter.description + var desc = unescapeMarkdown(searchParameter.description) if (desc.split("*").size>1) { val exps = desc.split("*") for (exp in exps) { @@ -1605,29 +1774,35 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, when (searchParameter.type) { Enumerations.SearchParamType.TOKEN -> { val array = ArraySchema() - array.items = StringSchema().format("token") + array.items = StringSchema().format("token").description("token format: [system]|[code],[code],[system]") + // Should really be added to the StringSchema only but this gets around UI issues array.format("token") parameter.schema = array // parameter.schema.type = "string" - parameter.schema.example = "[system]|[code],[code],[system]" + // parameter.schema.example = "[system]|[code],[code],[system]" } Enumerations.SearchParamType.REFERENCE -> { - parameter.schema = StringSchema().format("reference") - parameter.schema.example = "[type]/[id] or [id] or [uri]" + parameter.schema = StringSchema().format("reference").description("reference format: [type]/[id] or [id] or [uri]") + // parameter.schema.example = "[type]/[id] or [id] or [uri]" } Enumerations.SearchParamType.DATE -> { val array = ArraySchema() - array.items = StringSchema().format("date") + array.items = StringSchema().format("date").pattern("([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1])\n" + + ")?)?") // Should really be added to the StringSchema only but this gets around UI issues array.format("date") parameter.schema = array parameter.description = "See FHIR documentation for more details." - parameter.schema.example = "eq2013-01-14" + // parameter.schema.example = "eq2013-01-14" + } + Enumerations.SearchParamType.NUMBER -> { + parameter.schema = StringSchema().type("number").pattern("[0]|[-+]?[1-9][0-9]*") + // parameter.schema.example = "LS15" } Enumerations.SearchParamType.STRING -> { - parameter.schema = StringSchema().type("string") - parameter.schema.example = "LS15" + parameter.schema = StringSchema().type("string").pattern("^[\\s\\S]+\$") + // parameter.schema.example = "LS15" } else -> { parameter.schema = StringSchema().format(nextSearchParam.type.toCode()) @@ -1638,13 +1813,19 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, if (parameters.size>1) { description += "\n\n Chained search parameter. Please see [chained](http://www.hl7.org/fhir/search.html#chaining)" } - if (first) description += "\n\n | Name | Type | Expression | \n |--------|--------|--------| \n " + if (first) description += "\n\n **Search Parameter Conformance** \n\n | Conformance Expectation | Name | OAS format / FHIR Type | \n |--------|--------|--------| \n " + var conformance = "" + val conformanceExt = nextSearchParam.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation") + if (conformanceExt !== null && conformanceExt.hasValue()) { + conformance = "**" + (conformanceExt.value as CodeType).value + "**" + } if (searchParameter != null) { - description += "| $name | [" + type?.lowercase() + " ](https://www.hl7.org/fhir/search.html#" + type?.lowercase() + ")| $expression | \n" + description += "| $conformance | [$name](https://www.hl7.org/fhir/R4/$originalResourceType.html#search) | [" + type?.lowercase() + " ](https://www.hl7.org/fhir/R4/search.html#" + type?.lowercase() + ")| \n" } else { - description += "\n\n Caution: This does not appear to be a valid search parameter. **Please check HL7 FHIR conformance.**" + description += "\n\n **Caution:** This does not appear to be a valid search parameter. Please check HL7 FHIR conformance." } + if (parameters.size>1) { if (searchParameter?.type != Enumerations.SearchParamType.REFERENCE) { description += "\n\n Caution: This does not appear to be a valid search parameter. Chained search paramters **MUST** always be on reference types Please check Hl7 FHIR conformance." @@ -1679,24 +1860,15 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, return description } - private fun getMediaType(openApi: OpenAPI, resourceType: String?, profile: String?) : MediaType { + private fun getMediaType(openApi: OpenAPI, resourceType: String?, profile: String?, enhance: Boolean) : MediaType { val mediaType = MediaType().schema(ObjectSchema().`$ref`( "#/components/schemas/$resourceType" //"https://hl7.org/fhir/R4/fhir.schema.json#/definitions/$resourceType" )) - addFhirResourceSchema(openApi,resourceType, profile) + addFhirResourceSchema(openApi,resourceType, profile, enhance) return mediaType } - /* - private fun addSchemaFhirResource(openApi: OpenAPI, schema : Schema, schemaName : String?) { - ensureComponentsSchemasPopulated(openApi) - if (!openApi.components.schemas.containsKey(schemaName)) { - openApi.components.addSchemas(schemaName,schema) - } - } -*/ - private fun ensureComponentsSchemasPopulated(theOpenApi: OpenAPI) { if (theOpenApi.components == null) { theOpenApi.components = Components() @@ -1706,7 +1878,7 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, } } - private fun addFhirResourceSchema(openApi: OpenAPI, resourceType: String?, profile: String?) { + private fun addFhirResourceSchema(openApi: OpenAPI, resourceType: String?, profile: String?, enhance: Boolean) { // Add schema ensureComponentsSchemasPopulated(openApi) if (!openApi.components.schemas.containsKey(resourceType)) { @@ -1716,83 +1888,111 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, var schemaList = mutableMapOf>() schema.description = - "HL7 FHIR Schema [$resourceType](https://hl7.org/fhir/R4/fhir.schema.json#/definitions/$resourceType)." + ". HL7 FHIR Documentation [$resourceType](\"https://www.hl7.org/fhir/$resourceType.html\")" + "HL7 FHIR Schema [$resourceType](https://hl7.org/fhir/R4/fhir.schema.json#/definitions/$resourceType)." + + " HL7 FHIR Documentation [$resourceType](https://www.hl7.org/fhir/R4/$resourceType.html)" - // This doesn't appear to be used. Consider removing schema.externalDocs = ExternalDocumentation() schema.externalDocs.description = resourceType - schema.externalDocs.url = "https://www.hl7.org/fhir/$resourceType.html" + if (profile !== null) { + val structureDefinition = getProfile(profile) + if (structureDefinition !== null) { + schema.externalDocs.description = structureDefinition.title + schema.externalDocs.url = getDocumentationPath(profile) + } + // Won't work if NHS England fixes URL resolution + if ((structureDefinition == null || schema.externalDocs.url.equals(profile)) + && resourceType !== null) { + val profileNew = capabilityStatementApplier.getProfile(resourceType) + val structureDefinition = getProfile(profileNew) + if (structureDefinition !== null) { + schema.description += " \n\n NHS England/HL7 UK Conformance Documentation (Schema constraints) [" + structureDefinition.title + "](" +getDocumentationPath(profileNew) + ")" + } + schema.externalDocs.description = profile + schema.externalDocs.url = getDocumentationPath(profile) + } + + } else { + if (resourceType !== null) { + val profileNew = capabilityStatementApplier.getProfile(resourceType) + if (profileNew !== null) { + val structureDefinition = getProfile(profileNew) + if (structureDefinition !== null) { + schema.externalDocs.description = structureDefinition.title + schema.externalDocs.url = getDocumentationPath(profileNew) + } + } + } + } + if (resourceType != null) { schemaList.put(resourceType, schema) } - if (profile != null) { - val structureDefinition = getProfile(profile) - if (structureDefinition is StructureDefinition) { + /* Disabled 27/Jan/2024 This is done via API teams, no reason to enter into that conversation - if (structureDefinition.hasDescription()) { - schema.description += "\n\n " + structureDefinition.description - } - if (structureDefinition.hasPurpose()) { - schema.description += "\n\n " + structureDefinition.purpose - } + if (profile != null) { - for (element in structureDefinition.snapshot.element) { - if ((element.hasDefinition() || - element.hasShort() || - element.hasType() || - element.hasBinding()) && - (element.hasMustSupport() || (element.hasMin() && element.min > 0)) - ) { - val paths = element.id.split(".") - var title = paths[paths.size - 1] - /* if (element.hasSliceName()) { - title += " (" + element.sliceName + ")" - }*/ - var elementSchema: Schema? = null - - if (element.hasType()) { - if (element.typeFirstRep.code[0].isUpperCase()) { - elementSchema = Schema().type("object") + val structureDefinition = getProfile(profile) + if (structureDefinition is StructureDefinition) { + schema.description += "\n\n Profile: [" + structureDefinition.url+"]("+this.getDocumentationPath(structureDefinition.url)+")" + if (enhance) { + for (element in structureDefinition.snapshot.element) { + if ((element.hasDefinition() || + element.hasShort() || + element.hasType() || + element.hasBinding()) && + (element.hasMustSupport() || (element.hasMin() && element.min > 0)) + ) { + val paths = element.id.split(".") + var title = paths[paths.size - 1] + /* if (element.hasSliceName()) { + title += " (" + element.sliceName + ")" + }*/ + var elementSchema: Schema? = null + + if (element.hasType()) { + if (element.typeFirstRep.code[0].isUpperCase()) { + elementSchema = Schema().type("object") + } else { + elementSchema = Schema() + .type("string") + } } else { elementSchema = Schema() .type("string") } - } else { - elementSchema = Schema() - .type("string") - } - if (element.hasBase() && element.base.max.equals("*")) { - elementSchema = ArraySchema().type("array").items(elementSchema) - } + if (element.hasBase() && element.base.max.equals("*")) { + elementSchema = ArraySchema().type("array").items(elementSchema) + } - if (elementSchema != null) { - elementSchema.description = getElementDescription(element) - if (element.hasMin()) elementSchema.minimum = BigDecimal(element.min) + if (elementSchema != null) { + elementSchema.description = unescapeMarkdown(getElementDescription(element)) + if (element.hasMin()) elementSchema.minimum = BigDecimal(element.min) - var parent = "" - for (i in 0 until (paths.size - 1)) { - if (!parent.isEmpty()) parent += "." - parent += paths[i] - } - if (schemaList.get(element.id) == null) { - schemaList.put(element.id, elementSchema) - } - val parentSchema = schemaList.get(parent) - if (parentSchema is ArraySchema) { - parentSchema.items.addProperties(title, elementSchema) - } else { - parentSchema?.addProperties(title, elementSchema) + var parent = "" + for (i in 0 until (paths.size - 1)) { + if (!parent.isEmpty()) parent += "." + parent += paths[i] + } + if (schemaList.get(element.id) == null) { + schemaList.put(element.id, elementSchema) + } + val parentSchema = schemaList.get(parent) + if (parentSchema is ArraySchema) { + parentSchema.items.addProperties(title, elementSchema) + } else { + parentSchema?.addProperties(title, elementSchema) + } } } } } } - } + } */ if (resourceType == null) { System.out.println("resourceTyoe null") } else { @@ -1850,296 +2050,68 @@ class OpenAPIParser(@Qualifier("R4") private val ctx: FhirContext, if (profile.startsWith("https://www.hl7.org")) return "" // todo disable for now and try using schema instead return "" - /* - val structureDefinition = supportChain.fetchStructureDefinition(profile) - var description = "" - if (structureDefinition is StructureDefinition) { - for (element in structureDefinition.snapshot.element) { - if ((element.hasDefinition() || - element.hasShort() || - element.hasType() || - element.hasBinding()) && - element.hasMustSupport() - ) { - // section title - description += "\n\n ### " + element.path.replace(structureDefinition.type + ".", "") - if (element.hasSliceName()) { - description += " ("+element.sliceName+ ")" - } - - description += getElementDescription(element) - - } - } - } - return description - - */ } - private fun getElementDescription(element : ElementDefinition) : String { - - var table = "\n\n| | |\n|----|----|" - // header body - /* - if (element.hasMustSupport() && element.mustSupport) { - description += "\n `mustSupport`" - } -*/ - table += "\n|Element Id|"+element.id+"|" - table += "\n|[Cardinality](https://www.hl7.org/fhir/conformance-rules.html#cardinality)|"+element.min+".."+element.max+"|" - - - if (element.hasFixed()) { - if (element.fixed is UriType) { - table += "\n|Fixed Value|"+(element.fixed as UriType).value+"|" - } - if (element.fixed is CodeType) { - table += "\n|Fixed Value|"+(element.fixed as CodeType).value+"|" - } - } - - if (element.hasBinding()) { - if (element.binding.hasValueSet()) - { - val valueSet = supportChain.fetchValueSet(element.binding.valueSet) - var description = "["+(valueSet as ValueSet).name + "](" + getCanonicalUrl(element.binding.valueSet) +")" - if (element.binding.hasStrength()) description += " (" + element.binding.strength.display + ")" - if (element.binding.hasDescription()) { - var elementDescription = element.binding.description - elementDescription = "
" + elementDescription.replace("\\n","\n") - description += elementDescription + " " - } - table += "\n|[Terminology Binding](https://www.hl7.org/fhir/terminologies.html)|"+description+"|" - } - } - - if (element.hasSliceName()) { - table += "\n|[Slice Name](https://www.hl7.org/fhir/profiling.html#slicing)|"+element.sliceName+"|" - } - if (element.hasSlicing()) { - var description = "" - if (element.slicing.hasRules()) { - description += " *"+element.slicing.rules.name + "*" - } - if (element.slicing.hasDiscriminator()) { - for (discrimninator in element.slicing.discriminator) { - description += " discriminator - " - if (discrimninator.hasType()) { - description += " *"+discrimninator.type.name + "*" - } - if (discrimninator.hasPath()) { - description += " *"+discrimninator.path + "*" - } - } - } - if (element.slicing.hasDescription()) { - description += "
"+element.slicing.description - } - table += "\n|[Slicing](https://www.hl7.org/fhir/profiling.html#slicing)|"+description+"|" - } - - // Data type - if (element.hasType()) { - var description = "" - for (type in element.type) { - - description += "["+type.code+"](https://www.hl7.org/fhir/datatypes.html#"+type.code+")" - var itemDescription="" - var first = true - for (target in type.targetProfile) { - if (itemDescription.isEmpty()) description+= "(" - val profile = supportChain.fetchStructureDefinition(target.value) - if (!first) { - itemDescription += " " - } else { - first = false - } - itemDescription += "["+(profile as StructureDefinition).name + "]("+ getCanonicalUrl(target.value) +")" - - } - first = true - for (target in type.profile) { - if (itemDescription.isEmpty()) description+= "(" - val profile = supportChain.fetchStructureDefinition(target.value) - if (!first) { - itemDescription += " " - } else { - first = false - } - itemDescription += "["+(profile as StructureDefinition).name+ "](" +getCanonicalUrl(target.value) +")" - } - - if (itemDescription.isNotEmpty()) description+= itemDescription + ")" - if (type.hasAggregation()) { - for (aggregation in type.aggregation) { - description += "
Aggregation - [" + aggregation.code+"](http://www.hl7.org/fhir/valueset-resource-aggregation-mode.html)" - } - } - } - table += "\n|[type](https://www.hl7.org/fhir/datatypes.html)|"+description+"|" - } - var description = table + "\n\n
" - // Documentation section - /* - if (element.hasShort()) { - - description += "\n\n " + element.short - } - */ - - if (element.hasDefinition()) { - description += "\n\n #### Definition" - description += "\n\n " + element.definition.replace("\\n","\n") - } - - if (element.hasRequirements()) { - description += "\n\n #### Requirements" - description += "\n\n " + element.requirements.replace("\\n","\n") - } - - if (element.hasComment()) { - description += "\n\n #### Comment" - description += "\n\n " + element.comment.replace("\\n","\n") - } - - if (element.hasConstraint()) { - var displayConstraints = false - for (constraint in element.constraint) { - if (doDisplay(constraint.key)) displayConstraints = true - } - - if (displayConstraints) { - description += "\n\n #### Constraints \n" - for (constraint in element.constraint) { - if (doDisplay(constraint.key)) description += "\n- **" + constraint.key + "** (*" + constraint.severity + "*) " + constraint.human.replace( - "\\n", - "\n" - ) - } - } - } - - return description - } - - private fun doDisplay(key : String) : Boolean { - if (key.startsWith("ext")) return false - if (key.startsWith("ele")) return false - if (key.startsWith("dom")) return false - return true - } - - private fun addResoureTag(openApi: OpenAPI,resourceType: String?, profile: String?) { + private fun addResoureTag( + openApi: OpenAPI, + resourceType: String?, + profile: String?, + enhance: Boolean, + documentation: String? + ) { // potential flaw here if multiple profiles are used. for (tags in openApi.tags) { if (tags.name.equals(resourceType)) return } // Try using schema for describing the profile . - addFhirResourceSchema(openApi,resourceType,profile) + addFhirResourceSchema(openApi,resourceType,profile, enhance) val resourceTag = Tag() resourceTag.name = resourceType - - //addFhirResourceSchema(openApi, resourceType, nextResource.profile) - - if (profile != null) { - resourceTag.extensions = mutableMapOf() - resourceTag.extensions.put("x-HL7-FHIR-Profile",profile) - val idStr = getProfileName(profile) - val documentation = getDocumentationPath(profile) - resourceTag.description = "" //""Resource (schema): [FHIR $resourceType](https://www.hl7.org/fhir/$resourceType.html)" - - var profileDef = getBaseProfile(profile) - - if (profileDef !=null) { - if (profileDef.hasDescription()) { - resourceTag.description += "\n\n "+profileDef.description - } - if (profileDef.hasPurpose()) { - resourceTag.description += "\n\n "+profileDef.purpose - } + if (documentation !== null) resourceTag.description = documentation + /* if (enhance) { + if (resourceTag.description == null) { + resourceTag.description = "" + } else { + resourceTag.description += "\n\n " } - resourceTag.description += "\n\n Profile (constraints): [$idStr]($documentation)" - resourceTag.description += "\n\n" + getProfileDescription(profile) - - profileDef = getProfile(profile) + resourceTag.description += "Base Definition: [$resourceType](https://hl7.org/fhir/R4/$resourceType)" - if (profileDef !=null) { + if (profile != null) { + resourceTag.extensions = mutableMapOf() + resourceTag.extensions.put("x-HL7-FHIR-Profile", profile) + val idStr = getProfileName(profile) + val documentation = getDocumentationPath(profile) - if (profileDef.hasDescription()) { - resourceTag.description += "\n\n "+profileDef.description - } - if (profileDef.hasPurpose()) { - resourceTag.description += "\n\n "+profileDef.purpose - } + resourceTag.description += " Profile: [$idStr]($documentation)" } - - } else { - resourceTag.description = "Resource type: $resourceType" } +*/ openApi.addTagsItem(resourceTag) } - fun generateMarkdown(profile :String) : String { - var mainDescription = "" - var subDescription = "" - var index = "" - - - if (profile != null) { - val structureDefinition = getProfile(profile) - if (structureDefinition is StructureDefinition) { - - if (structureDefinition.hasDescription()) { - mainDescription += "\n\n " + structureDefinition.description - } - if (structureDefinition.hasPurpose()) { - mainDescription += "\n\n " + structureDefinition.purpose - } - - for (element in structureDefinition.snapshot.element) { - val paths = element.path.split(".") - if ( - element.hasMustSupport() || element.hasFixed() || (element.hasSliceName() && !paths[paths.size-1].equals("extension")) - || element.id.split(".").size == 1) { - val paths = element.id.split(".") - var title = "" - - - if (paths.size>1){ - for (i in 2..paths.size) { - if (title.isNotEmpty()) title += "." - title += paths[i-1] - } - index += "\n- "+title+"" - subDescription += "\n\n\n ## "+title - subDescription += getElementDescription(element) - } else { - mainDescription += getElementDescription(element) - } - - - - } - } + fun getDocumentationPath(profile: String?) : String { + if (profile == null) return "" + // Only process UK profiles + if (!profile.contains("https://fhir.nhs.uk/") + && !profile.contains("https://fhir.hl7.org.uk")) return profile + + val configurationInputStream = ClassPathResource("manifest.json").inputStream + var path = profile + for(guide in fhirPackage) { + if (!guide.version.contains("0.0.0") && ( + guide.packageName.contains("england") || + guide.packageName.contains("ukcore") + )) { + path = "https://simplifier.net/resolve?fhirVersion=R4&scope="+ guide.packageName + "@" + guide.version + "&canonical="+profile } } - return mainDescription + "\n\n" + index + subDescription + if (path == null) return "" + return path } - private fun getPackageCanonicalUrl(profile : String, npmPackage: NpmPackage?) : String { - val npm= npmPackage?.npm?.get("name").toString().replace("\"","") + "@" + npmPackage?.npm?.get("version").toString().replace("\"","") - return " "+ npm + "&canonical="+ profile.replace("|","|") - } - private fun getDocumentationPathNpm(profile : String, npmPackage : NpmPackage) : String { - return getPackageCanonicalUrl(profile,npmPackage) - } - private fun getCanonicalUrl(resourceUrl : String ) :String { - val npm = npmPackages?.get(npmPackages.size-1) // get last package - return getPackageCanonicalUrl(resourceUrl, npm) - } + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/VerifyOAS.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/oas/OpenAPItoCapabilityStatementConversion.kt similarity index 64% rename from src/main/kotlin/uk/nhs/england/fhirvalidator/service/VerifyOAS.kt rename to src/main/kotlin/uk/nhs/england/fhirvalidator/service/oas/OpenAPItoCapabilityStatementConversion.kt index e1a3500..dcc3434 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/service/VerifyOAS.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/service/oas/OpenAPItoCapabilityStatementConversion.kt @@ -1,4 +1,4 @@ -package uk.nhs.england.fhirvalidator.service +package uk.nhs.england.fhirvalidator.service.oas //import io.swagger.models.parameters.QueryParameter import ca.uhn.fhir.context.FhirContext @@ -14,22 +14,183 @@ import io.swagger.v3.oas.models.examples.Example import io.swagger.v3.oas.models.media.ArraySchema import io.swagger.v3.oas.models.media.MediaType import io.swagger.v3.oas.models.parameters.QueryParameter +import mu.KLogging +import org.apache.commons.text.StringEscapeUtils import org.hl7.fhir.instance.model.api.IBaseResource import org.hl7.fhir.r4.model.* +import org.hl7.fhir.r4.model.CapabilityStatement.TypeRestfulInteraction.READ +import org.hl7.fhir.r4.model.CapabilityStatement.TypeRestfulInteraction.SEARCHTYPE import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service +import uk.nhs.england.fhirvalidator.service.interactions.FHIRMessage +import uk.nhs.england.fhirvalidator.interceptor.CapabilityStatementApplier +import uk.nhs.england.fhirvalidator.service.SearchParameterSupport +import java.util.* @Service -class VerifyOAS(@Qualifier("R4") private val ctx: FhirContext?, - @Qualifier("SupportChain") private val supportChain: IValidationSupport, - private val searchParameterSupport : SearchParameterSupport, - private val fhirValidator: FhirValidator, - private val messageDefinitionApplier: MessageDefinitionApplier, - private val capabilityStatementApplier: CapabilityStatementApplier) +class OpenAPItoCapabilityStatementConversion(@Qualifier("R4") private val ctx: FhirContext?, + @Qualifier("SupportChain") private val supportChain: IValidationSupport, + private val searchParameterSupport : SearchParameterSupport, + private val fhirValidator: FhirValidator, + private val FHIRMessage: FHIRMessage, + private val capabilityStatementApplier: CapabilityStatementApplier +) { // var implementationGuideParser: ImplementationGuideParser? = ImplementationGuideParser(ctx!!) val objectMapper = ObjectMapper() + companion object : KLogging() + + fun convert(openAPI : OpenAPI) : CapabilityStatement { + var capabilityStatement = CapabilityStatement() + capabilityStatement.status = Enumerations.PublicationStatus.UNKNOWN + capabilityStatement.fhirVersion = Enumerations.FHIRVersion._4_0_1 + capabilityStatement.format.add(CodeType("application/fhir+json")) + capabilityStatement.kind = CapabilityStatement.CapabilityStatementKind.REQUIREMENTS + capabilityStatement.date = Date() + + var rest =CapabilityStatement.CapabilityStatementRestComponent() + rest.mode = CapabilityStatement.RestfulCapabilityMode.SERVER + capabilityStatement.rest.add(rest) + val outcomes = mutableListOf() + if (openAPI.info !== null) { + capabilityStatement.title = openAPI.info.title + capabilityStatement.description = escapeMarkdown(openAPI.info.description) + } + for (apiPaths in openAPI.paths) { + // To cope with eRS OAS + if (apiPaths.key !== null && ( + apiPaths.key.contains("STU3") || + apiPaths.key.contains("STU2") + )) continue; + var path = apiPaths.key.removePrefix("/FHIR/R4") + path = path.removePrefix("/") + val paths = path.split("/") + var resourceType = paths[0] + var multiPathParameter : CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent? = null + for(it in paths) { + if (!it.contains("{") && !it.contains("$") && !it.startsWith("_")) { + if (it !== resourceType && resourceType.equals("Patient")) { + multiPathParameter = CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent() + multiPathParameter.name = "patient" + val extension = Extension().setUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation") + extension.setValue(CodeType().setValue("SHALL")) + multiPathParameter.type = Enumerations.SearchParamType.TOKEN + multiPathParameter.extension.add(extension) + } + resourceType = it + } + } + + var resource : CapabilityStatement.CapabilityStatementRestResourceComponent? = null + + rest.resource.forEach { + if (it.type.equals(resourceType)) { + resource = it + } + } + if (resource == null) { + resource = CapabilityStatement.CapabilityStatementRestResourceComponent().setType(resourceType) + if (apiPaths.value !== null && apiPaths.value.description !== null) { + resource!!.documentation = apiPaths.value.description + } + rest.addResource(resource) + + } + var operation = "" + if (paths.size > 1) operation = paths[1] + if (paths[0].startsWith("$")) operation = paths[0] + + if (!resourceType.startsWith("$") && !resourceType.equals("metadata")) { + val codeSystem = supportChain.fetchCodeSystem("http://hl7.org/fhir/resource-types") + + } + if (operation.isNotEmpty() && operation.startsWith("$")) { + val operationDefinition = getOperationDefinition(operation) + + } + if (operation.isNotEmpty() && operation.startsWith("_search")) { + // TODO + } + + // check all parameters + if (apiPaths.value.get != null && apiPaths.value.get.parameters != null) { + var hasParameters = false + for (apiParameter in apiPaths.value.get.parameters) { + if (apiParameter is QueryParameter) { + hasParameters = true + val searchParam = CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent() + searchParam.name = apiParameter.name + if (apiParameter.description !== null) { + searchParam.documentation = escapeMarkdown(apiParameter.description) + } + if (apiParameter.required !== null && apiParameter.required) { + val extension = Extension().setUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation") + extension.setValue(CodeType().setValue("SHALL")) + searchParam.extension.add(extension) + } + + + when (apiParameter.schema.type) { + "string" -> { + searchParam.type = Enumerations.SearchParamType.STRING + } + "boolean" -> { + searchParam.type = Enumerations.SearchParamType.STRING + } + "integer" -> { + searchParam.type = Enumerations.SearchParamType.NUMBER + } + "array" -> { + searchParam.type = Enumerations.SearchParamType.STRING + } + else ->{ + logger.info(searchParam.name + " type= " + apiParameter.schema.type ) + searchParam.type = Enumerations.SearchParamType.STRING + } + } + when (apiParameter.schema.format) { + "string" -> { + searchParam.type = Enumerations.SearchParamType.STRING + } + "token" -> { + searchParam.type = Enumerations.SearchParamType.TOKEN + } + "date" -> { + searchParam.type = Enumerations.SearchParamType.DATE + } + "number" -> { + searchParam.type = Enumerations.SearchParamType.NUMBER + } + "reference" -> { + searchParam.type = Enumerations.SearchParamType.REFERENCE + } + else ->{ + logger.info(searchParam.name + " format= " + apiParameter.schema.format) + searchParam.type = Enumerations.SearchParamType.STRING + } + } + + if (resource !== null) resource!!.searchParam.add(searchParam) + } + } + var interaction = CapabilityStatement.ResourceInteractionComponent() + if (hasParameters || multiPathParameter !== null ) { + interaction.setCode(SEARCHTYPE) + if (multiPathParameter !== null && resource !== null ) { + resource!!.searchParam.add(multiPathParameter) + } + + } else { + interaction.setCode(READ) + } + if (apiPaths.value.get.description !== null) interaction.documentation = escapeMarkdown(apiPaths.value.get.description) + resource?.interaction?.add(interaction) + + } + } + return capabilityStatement + } fun validate(openAPI : OpenAPI) : List { // check all examples validate @@ -37,7 +198,7 @@ class VerifyOAS(@Qualifier("R4") private val ctx: FhirContext?, val outcomes = mutableListOf() if (openAPI.info.extensions == null || openAPI.info.extensions.get("x-HL7-FHIR-NpmPackages") == null) { - addOperationIssue(outcomes,OperationOutcome.IssueType.BUSINESSRULE, OperationOutcome.IssueSeverity.WARNING, "No FHIR package extension found") + addOperationIssue(outcomes,OperationOutcome.IssueType.BUSINESSRULE, OperationOutcome.IssueSeverity.INFORMATION, "No FHIR package extension found in the OAS specification. This a comment, not an error") .location.add(StringType("OAS: info.extensions.x-HL7-FHIR-NpmPackages")) } for (apiPaths in openAPI.paths) { @@ -148,13 +309,31 @@ class VerifyOAS(@Qualifier("R4") private val ctx: FhirContext?, operationIssue.location.add(StringType("OAS: "+apiPaths.key + "/get/" + apiParameter.name+"/schema/type")) } - if (apiParameter.schema is ArraySchema && apiParameter.schema.format.equals("token") && apiParameter.explode) { - val operationIssue = addOperationIssue(outcomes,OperationOutcome.IssueType.CODEINVALID, OperationOutcome.IssueSeverity.ERROR,"For array of format = token, explode should be set to false") - operationIssue.location.add(StringType("OAS: "+apiPaths.key + "/get/" + apiParameter.name+"/schema/type")) - } - if (apiParameter.schema is ArraySchema && apiParameter.schema.format.equals("date") && !apiParameter.explode) { - val operationIssue = addOperationIssue(outcomes,OperationOutcome.IssueType.CODEINVALID, OperationOutcome.IssueSeverity.ERROR,"For array of format = date, explode should be set to true") - operationIssue.location.add(StringType("OAS: "+apiPaths.key + "/get/" + apiParameter.name+"/schema/type")) + if (apiParameter.schema is ArraySchema && apiParameter.schema.format !== null) { + if (apiParameter.schema.format.equals( + "token" + ) && apiParameter.explode + ) { + val operationIssue = addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.ERROR, + "For array of format = token, explode should be set to false" + ) + operationIssue.location.add(StringType("OAS: " + apiPaths.key + "/get/" + apiParameter.name + "/schema/type")) + } + if (apiParameter.schema.format.equals( + "date" + ) && !apiParameter.explode + ) { + val operationIssue = addOperationIssue( + outcomes, + OperationOutcome.IssueType.CODEINVALID, + OperationOutcome.IssueSeverity.ERROR, + "For array of format = date, explode should be set to true" + ) + operationIssue.location.add(StringType("OAS: " + apiPaths.key + "/get/" + apiParameter.name + "/schema/type")) + } } } Enumerations.SearchParamType.NUMBER -> { @@ -351,8 +530,8 @@ class VerifyOAS(@Qualifier("R4") private val ctx: FhirContext?, fun validateResource(resource: IBaseResource, profile: String?): OperationOutcome? { if (profile != null) return fhirValidator.validateWithResult(resource, ValidationOptions().addProfile(profile)).toOperationOutcome() as? OperationOutcome - capabilityStatementApplier.applyCapabilityStatementProfiles(resource) - val messageDefinitionErrors = messageDefinitionApplier.applyMessageDefinition(resource) + capabilityStatementApplier.applyCapabilityStatementProfiles(resource, false) + val messageDefinitionErrors = FHIRMessage.applyMessageDefinition(resource) if (messageDefinitionErrors != null) { return messageDefinitionErrors } @@ -373,4 +552,7 @@ class VerifyOAS(@Qualifier("R4") private val ctx: FhirContext?, return listOf(inputResource) } + fun escapeMarkdown(markdown : String ) : String { + return StringEscapeUtils.escapeHtml4(markdown) + } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/shared/PrePopulatedValidationSupport.java b/src/main/kotlin/uk/nhs/england/fhirvalidator/shared/PrePopulatedValidationSupport.java index 34c4a70..accdb48 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/shared/PrePopulatedValidationSupport.java +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/shared/PrePopulatedValidationSupport.java @@ -9,10 +9,7 @@ import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IPrimitiveType; -import org.hl7.fhir.r4.model.CodeSystem; -import org.hl7.fhir.r4.model.NamingSystem; -import org.hl7.fhir.r4.model.StructureDefinition; -import org.hl7.fhir.r4.model.ValueSet; +import org.hl7.fhir.r4.model.*; import org.jetbrains.annotations.Nullable; import javax.annotation.Nonnull; @@ -38,6 +35,7 @@ public class PrePopulatedValidationSupport extends BaseStaticResourceValidationS private final Map myValueSets; private final Map myOtherConformanceResources; + /** * Constructor */ @@ -68,6 +66,16 @@ public PrePopulatedValidationSupport(FhirContext theFhirContext, Map T fetchResource(@Nullable Class theClass, String theUri) { + System.out.println("Fetch "+theUri); + return null; + } + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/CorsFilter.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/CorsFilter.kt deleted file mode 100644 index 71e7324..0000000 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/CorsFilter.kt +++ /dev/null @@ -1,36 +0,0 @@ -package uk.nhs.england.fhirvalidator.util - -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.http.HttpHeaders -import java.io.IOException -import javax.servlet.* -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -class CorsFilter :Filter { - - - @Throws(IOException::class, ServletException::class) - override fun doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) { - val response = res as HttpServletResponse - val request = req as HttpServletRequest - if ("OPTIONS" != request.method) { - response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*") - chain.doFilter(req, res) - } else { - // log.debug("Cors Filter: {}", request.method) - response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*") - response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, PUT, GET, OPTIONS, DELETE") - response.setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600") - response.setHeader( - HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, - "X-FHIR-Starter,authorization,Prefer,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers" - ) - } - } - - override fun init(filterConfig: FilterConfig?) {} - - override fun destroy() {} -} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/FhirSystems.java b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/FhirSystems.java index 1638759..8f08f11 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/FhirSystems.java +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/FhirSystems.java @@ -34,6 +34,7 @@ public final class FhirSystems { public static final String EMIS_PRACTITIONER_IDENTIFIER = "https://emis.com/Id/Practitioner/DBID"; public static final String SNOMED_CT = "http://snomed.info/sct"; + public static final String LOINC = " http://loinc.org"; public static final String DMandD= "https://dmd.nhs.uk"; diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/MyUriResolver.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/MyUriResolver.kt new file mode 100644 index 0000000..86b5ee3 --- /dev/null +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/MyUriResolver.kt @@ -0,0 +1,19 @@ +package uk.nhs.england.fhirvalidator.util + +import javax.xml.transform.Source +import javax.xml.transform.TransformerException +import javax.xml.transform.URIResolver +import javax.xml.transform.stream.StreamSource + +internal class MyUriResolver : URIResolver { + @Throws(TransformerException::class) + override fun resolve(href: String, base: String?): Source? { + try { + val inputStream = this.javaClass.classLoader.getResourceAsStream("xslt/$href") + return StreamSource(inputStream) + } catch (ex: Exception) { + ex.printStackTrace() + return null + } + } +} diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/FHIRExamples.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/OASExamples.kt similarity index 51% rename from src/main/kotlin/uk/nhs/england/fhirvalidator/util/FHIRExamples.kt rename to src/main/kotlin/uk/nhs/england/fhirvalidator/util/OASExamples.kt index 5c833d5..6c6a0a8 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/FHIRExamples.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/OASExamples.kt @@ -6,8 +6,8 @@ import com.fasterxml.jackson.databind.ObjectMapper import java.lang.StringBuilder -class FHIRExamples { - public fun loadExample(fileName :String, ctx : FhirContext): JsonNode { +class OASExamples { + public fun loadFHIRExample(fileName :String, ctx : FhirContext): JsonNode { val classLoader = javaClass.classLoader val inputStream = classLoader.getResourceAsStream("Examples/"+fileName) @@ -19,4 +19,16 @@ class FHIRExamples { } + public fun loadOASExample(fileName :String, ctx : FhirContext): JsonNode { + + val classLoader = javaClass.classLoader + val inputStream = classLoader.getResourceAsStream("OAS/"+fileName) + + val jsonStrings = inputStream.bufferedReader().readLines() + var sb = StringBuilder() + for (str in jsonStrings) sb.append(str) + return ObjectMapper().readTree(sb.toString()) + + } + } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/ProfileApplier.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/ProfileApplier.kt index a3951e4..b62afeb 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/util/ProfileApplier.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/util/ProfileApplier.kt @@ -1,7 +1,6 @@ package uk.nhs.england.fhirvalidator.util import org.hl7.fhir.instance.model.api.IBaseResource -import org.hl7.fhir.instance.model.api.IPrimitiveType import org.hl7.fhir.r4.model.Bundle fun getResourcesOfType(resource: IBaseResource, resourceType: String?): List { @@ -19,9 +18,12 @@ fun getResourcesOfType(resource: IBaseResource, resourceType: String?): List, profile: IPrimitiveType) { +fun applyProfile(resources: List, profile: String) { resources.stream().forEach { - it.meta.profile.clear() - it.meta.addProfile(profile.value) + var found = false + it.meta.profile.forEach { + if (it.value.equals(profile)) found = true + } + if (!found) it.meta.addProfile(profile) } } diff --git a/src/main/kotlin/uk/nhs/england/fhirvalidator/validationSupport/SwitchedTerminologyServiceValidationSupport.kt b/src/main/kotlin/uk/nhs/england/fhirvalidator/validationSupport/SwitchedTerminologyServiceValidationSupport.kt index a1e78db..c2a5080 100644 --- a/src/main/kotlin/uk/nhs/england/fhirvalidator/validationSupport/SwitchedTerminologyServiceValidationSupport.kt +++ b/src/main/kotlin/uk/nhs/england/fhirvalidator/validationSupport/SwitchedTerminologyServiceValidationSupport.kt @@ -5,8 +5,8 @@ import ca.uhn.fhir.context.support.ConceptValidationOptions import ca.uhn.fhir.context.support.IValidationSupport import ca.uhn.fhir.context.support.ValidationSupportContext import ca.uhn.fhir.context.support.ValueSetExpansionOptions +import mu.KLogging import org.hl7.fhir.instance.model.api.IBaseResource -import uk.nhs.england.fhirvalidator.controller.VerifyController import java.util.function.Predicate class SwitchedTerminologyServiceValidationSupport( @@ -15,6 +15,9 @@ class SwitchedTerminologyServiceValidationSupport( private val override: IValidationSupport, private val codeSystemPredicate: Predicate ) : IValidationSupport { + + companion object : KLogging() + override fun getFhirContext(): FhirContext { return fhirContext } @@ -80,11 +83,11 @@ class SwitchedTerminologyServiceValidationSupport( theExpansionOptions: ValueSetExpansionOptions?, theValueSetToExpand: IBaseResource ): IValidationSupport.ValueSetExpansionOutcome? { - VerifyController.logger.info("Switched validation expansion called") + logger.info("Switched validation expansion called") val outcome = default.expandValueSet(theValidationSupportContext, theExpansionOptions, theValueSetToExpand) if (outcome != null && outcome.error == null) return outcome if (outcome != null && outcome.error !== null) { - VerifyController.logger.info(outcome.error) + logger.info(outcome.error) } return override.expandValueSet(theValidationSupportContext, theExpansionOptions, theValueSetToExpand) } diff --git a/src/main/resources/Examples/Bundle-message-Diagnostics-laboratory-order.json b/src/main/resources/Examples/Bundle-message-Diagnostics-laboratory-order.json new file mode 100644 index 0000000..c2b1e12 --- /dev/null +++ b/src/main/resources/Examples/Bundle-message-Diagnostics-laboratory-order.json @@ -0,0 +1,291 @@ +{ + "resourceType": "Bundle", + "id": "path-R4-example-bundle-LFT-UandE-request", + "meta": { + "lastUpdated": "2022-03-07T09:48:00+00:00", + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Bundle" + ] + }, + "identifier": { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "c2f8848f-a3f3-4018-861f-b369244ed101" + }, + "type": "message", + "entry": [ + { + "fullUrl": "urn:uuid:f18a2226-c0ab-480d-b80a-b6561fe8f9c4", + "resource": { + "resourceType": "MessageHeader", + "id": "f18a2226-c0ab-480d-b80a-b6561fe8f9c4", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-MessageHeader" + ] + }, + "eventCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/message-event", + "code": "laboratory-order" + }, + "destination": [ + { + "name": "TD008362 PATH LAB 001", + "endpoint": "TBC", + "receiver": { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338" + } + } + ], + "sender": { + "reference": "urn:uuid:3c43b5b3-06d6-445f-ae9a-48d5f05df434" + }, + "source": { + "endpoint": "TBC" + }, + "focus": [ + { + "reference": "urn:uuid:1c38d507-9ad7-4b49-ba91-7da204842cac" + } + ] + } + }, + { + "fullUrl": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "resource": { + "resourceType": "Organization", + "id": "8a6d85b8-9837-4fed-a257-4cf207988338", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" + ] + }, + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "Y8J7D" + } + ], + "name": "TD008362 PATH LAB 001", + "address": [ + { + "line": [ + "PATHOLOGY LAB", + "7-8 WELLINGTON PLACE" + ], + "city": "LEEDS", + "district": "WEST YORKSHIRE", + "postalCode": "LS1 4AP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:3c43b5b3-06d6-445f-ae9a-48d5f05df434", + "resource": { + "resourceType": "Organization", + "id": "3c43b5b3-06d6-445f-ae9a-48d5f05df434", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" + ] + }, + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "B82033" + } + ], + "name": "PICKERING MEDICAL PRACTICE", + "address": [ + { + "line": [ + "SOUTHGATE" + ], + "city": "PICKERING", + "district": "NORTH YORKSHIRE", + "postalCode": "YO18 8BL" + } + ] + } + }, + { + "fullUrl": "urn:uuid:9a835acf-d715-4d84-8dcf-a8435f6417fe", + "resource": { + "resourceType": "Practitioner", + "id": "9a835acf-d715-4d84-8dcf-a8435f6417fe", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Practitioner" + ] + }, + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/sds-user-id", + "value": "TBC" + } + ], + "name": [ + { + "use": "official", + "family": "GASKELL", + "given": [ + "Gale" + ], + "prefix": [ + "Dr" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "resource": { + "resourceType": "Patient", + "id": "ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Patient" + ] + }, + "identifier": [ + { + "extension": [ + { + "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus", + "code": "number-present-and-verified", + "display": "Number present and verified" + } + ] + } + } + ], + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9727710638" + } + ], + "name": [ + { + "use": "official", + "family": "WELSH", + "given": [ + "Joel" + ] + } + ], + "gender": "male", + "birthDate": "1972-08-23", + "address": [ + { + "line": [ + "ACONBURY", + "LARPOOL DRIVE" + ], + "city": "WHITBY", + "postalCode": "YO22 4ND" + } + ] + } + }, + { + "fullUrl": "urn:uuid:1c38d507-9ad7-4b49-ba91-7da204842cac", + "resource": { + "resourceType": "ServiceRequest", + "id": "1c38d507-9ad7-4b49-ba91-7da204842cac", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-ServiceRequest-Lab" + ] + }, + "identifier": [ + { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046-001" + } + ], + "requisition": { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046" + }, + "status": "active", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "26958001", + "display": "Hepatic function panel" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "authoredOn": "2022-03-07T09:48:00+00:00", + "requester": { + "reference": "urn:uuid:9a835acf-d715-4d84-8dcf-a8435f6417fe", + "display": "GASKELL, Dr Gale" + }, + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ] + } + }, + { + "fullUrl": "urn:uuid:8660ef6a-65ef-408f-92ce-b4d6d03d783c", + "resource": { + "resourceType": "ServiceRequest", + "id": "8660ef6a-65ef-408f-92ce-b4d6d03d783c", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-ServiceRequest-Lab" + ] + }, + "identifier": [ + { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046-002" + } + ], + "requisition": { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046" + }, + "status": "active", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "252167001", + "display": "Urea and electrolytes" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "authoredOn": "2022-03-07T09:48:00+00:00", + "requester": { + "reference": "urn:uuid:9a835acf-d715-4d84-8dcf-a8435f6417fe", + "display": "GASKELL, Gale" + }, + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ] + } + } + ] +} diff --git a/src/main/resources/Examples/Bundle-message-Diagnostics-unsolicited-observations.json b/src/main/resources/Examples/Bundle-message-Diagnostics-unsolicited-observations.json new file mode 100644 index 0000000..3101b8d --- /dev/null +++ b/src/main/resources/Examples/Bundle-message-Diagnostics-unsolicited-observations.json @@ -0,0 +1,1190 @@ +{ + "resourceType": "Bundle", + "id": "path-R4-example-bundle-LFT-UandE-report", + "meta": { + "lastUpdated": "2022-03-08T14:23:00+00:00", + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Bundle" + ] + }, + "identifier": { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "d8d2d20e-8c44-466d-8640-7a516db7cd27" + }, + "type": "message", + "entry": [ + { + "fullUrl": "urn:uuid:f18a2226-c0ab-480d-b80a-b6561fe8f9c4", + "resource": { + "resourceType": "MessageHeader", + "id": "f18a2226-c0ab-480d-b80a-b6561fe8f9c4", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-MessageHeader" + ] + }, + "eventCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/message-event", + "code": "unsolicited-observations" + }, + "destination": [ + { + "name": "PICKERING MEDICAL PRACTICE", + "endpoint": "TBC", + "receiver": { + "reference": "urn:uuid:3c43b5b3-06d6-445f-ae9a-48d5f05df434" + } + } + ], + "sender": { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338" + }, + "source": { + "endpoint": "TBC" + }, + "focus": [ + { + "reference": "urn:uuid:35d46ca1-f253-4c97-b7ee-fb5fccdf6c20" + } + ] + } + }, + { + "fullUrl": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "resource": { + "resourceType": "Organization", + "id": "8a6d85b8-9837-4fed-a257-4cf207988338", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" + ] + }, + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "Y8J7D" + } + ], + "name": "TD008362 PATH LAB 001", + "address": [ + { + "line": [ + "PATHOLOGY LAB", + "7-8 WELLINGTON PLACE" + ], + "city": "LEEDS", + "district": "WEST YORKSHIRE", + "postalCode": "LS1 4AP" + } + ] + } + }, + { + "fullUrl": "urn:uuid:3c43b5b3-06d6-445f-ae9a-48d5f05df434", + "resource": { + "resourceType": "Organization", + "id": "3c43b5b3-06d6-445f-ae9a-48d5f05df434", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" + ] + }, + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/ods-organization-code", + "value": "B82033" + } + ], + "name": "PICKERING MEDICAL PRACTICE", + "address": [ + { + "line": [ + "SOUTHGATE" + ], + "city": "PICKERING", + "district": "NORTH YORKSHIRE", + "postalCode": "YO18 8BL" + } + ] + } + }, + { + "fullUrl": "urn:uuid:9a835acf-d715-4d84-8dcf-a8435f6417fe", + "resource": { + "resourceType": "Practitioner", + "id": "9a835acf-d715-4d84-8dcf-a8435f6417fe", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Practitioner" + ] + }, + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/sds-user-id", + "value": "TBC" + } + ], + "name": [ + { + "use": "official", + "family": "GASKELL", + "given": [ + "Gale" + ], + "prefix": [ + "Dr" + ] + } + ] + } + }, + { + "fullUrl": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "resource": { + "resourceType": "Patient", + "id": "ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Patient" + ] + }, + "identifier": [ + { + "extension": [ + { + "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus", + "code": "number-present-and-verified", + "display": "Number present and verified" + } + ] + } + } + ], + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "9727710638" + } + ], + "name": [ + { + "use": "official", + "family": "WELSH", + "given": [ + "Joel" + ] + } + ], + "gender": "male", + "birthDate": "1972-08-23", + "address": [ + { + "line": [ + "ACONBURY", + "LARPOOL DRIVE" + ], + "district": "NORTH YORKSHIRE", + "postalCode": "YO22 4ND" + } + ] + } + }, + { + "fullUrl": "urn:uuid:1c38d507-9ad7-4b49-ba91-7da204842cac", + "resource": { + "resourceType": "ServiceRequest", + "id": "1c38d507-9ad7-4b49-ba91-7da204842cac", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-ServiceRequest-Lab" + ] + }, + "identifier": [ + { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046-001" + } + ], + "requisition": { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046" + }, + "status": "active", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "26958001", + "display": "Hepatic function panel" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "authoredOn": "2022-03-07T09:48:00+00:00", + "requester": { + "reference": "urn:uuid:9a835acf-d715-4d84-8dcf-a8435f6417fe", + "display": "GASKELL, Dr Gale" + }, + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ] + } + }, + { + "fullUrl": "urn:uuid:8660ef6a-65ef-408f-92ce-b4d6d03d783c", + "resource": { + "resourceType": "ServiceRequest", + "id": "8660ef6a-65ef-408f-92ce-b4d6d03d783c", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-ServiceRequest-Lab" + ] + }, + "identifier": [ + { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046-002" + } + ], + "requisition": { + "system": "http://B82033-pickeringmedicalpractice.com/labrequest", + "value": "REQ-20220307-000046" + }, + "status": "active", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "252167001", + "display": "Urea and electrolytes" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "authoredOn": "2022-03-07T09:48:00+00:00", + "requester": { + "reference": "urn:uuid:9a835acf-d715-4d84-8dcf-a8435f6417fe", + "display": "GASKELL, Gale" + }, + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ] + } + }, + { + "fullUrl": "urn:uuid:35d46ca1-f253-4c97-b7ee-fb5fccdf6c20", + "resource": { + "resourceType": "DiagnosticReport", + "id": "35d46ca1-f253-4c97-b7ee-fb5fccdf6c20", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-DiagnosticReport-Lab" + ] + }, + "identifier": [ + { + "system": "http://Y8J7D-pathlab001.com/report", + "value": "REP-20220308-008902" + } + ], + "basedOn": [ + { + "reference": "urn:uuid:1c38d507-9ad7-4b49-ba91-7da204842cac" + }, + { + "reference": "urn:uuid:8660ef6a-65ef-408f-92ce-b4d6d03d783c" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0074", + "code": "LAB", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "721981007", + "display": "Diagnostic studies report" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "specimen": [ + { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + } + ], + "result": [ + { + "reference": "urn:uuid:33a88119-6dbc-4bdf-809a-c1d822b74e90" + }, + { + "reference": "urn:uuid:a5c7f5e2-eb95-469b-b588-f7861c260ccb" + } + ] + } + }, + { + "fullUrl": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d", + "resource": { + "resourceType": "Specimen", + "id": "bab0eaec-1ec5-4598-b660-90bb38a1030d", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Specimen" + ] + }, + "identifier": [ + { + "system": "http://B82033-pickeringmedicalpractice.com/specimen", + "value": "SPC-REQ-20220307-000014" + } + ], + "accessionIdentifier": { + "system": "http://Y8J7D-pathlab001.com/specimen", + "value": "SPC-LAB-20220307-007856" + }, + "status": "available", + "type": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "122555007", + "display": "Venous blood specimen" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "receivedTime": "2022-03-07T14:54:00+00:00", + "request": [ + { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + } + ], + "collection": { + "collectedDateTime": "2022-03-07T10:02:00+00:00" + } + } + }, + { + "fullUrl": "urn:uuid:33a88119-6dbc-4bdf-809a-c1d822b74e90", + "resource": { + "resourceType": "Observation", + "id": "33a88119-6dbc-4bdf-809a-c1d822b74e90", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-LabGroup" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "9920b5d3-9f19-41df-8d5a-fd2d4288e305" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "26958001", + "display": "Hepatic function panel" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "hasMember": [ + { + "reference": "urn:uuid:47faffbf-34c0-45b2-9c65-285f89fd1521" + }, + { + "reference": "urn:uuid:a0a65e1f-8aba-47a7-ab20-014f2943e7dd" + }, + { + "reference": "urn:uuid:aa8aa37b-3a69-478f-a2be-947af624d7cb" + }, + { + "reference": "urn:uuid:3f98327b-f215-4bc5-bd52-ed6477a3da4a" + } + ] + } + }, + { + "fullUrl": "urn:uuid:47faffbf-34c0-45b2-9c65-285f89fd1521", + "resource": { + "resourceType": "Observation", + "id": "47faffbf-34c0-45b2-9c65-285f89fd1521", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "a26ada79-ac32-4ff8-a3e4-fb5950462271" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1107221000000109", + "display": "Total bilirubin substance concentration in serum" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 6, + "unit": "umol/L", + "system": "http://unitsofmeasure.org", + "code": "umol/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "high": { + "value": 21, + "unit": "umol/L", + "system": "http://unitsofmeasure.org", + "code": "umol/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:a0a65e1f-8aba-47a7-ab20-014f2943e7dd", + "resource": { + "resourceType": "Observation", + "id": "a0a65e1f-8aba-47a7-ab20-014f2943e7dd", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "78443cb9-f248-44ef-9e6b-37fc4a592c1b" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1105861000000106", + "display": "Albumin mass concentration in serum" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 47, + "unit": "g/L", + "system": "http://unitsofmeasure.org", + "code": "g/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "low": { + "value": 35, + "unit": "g/L", + "system": "http://unitsofmeasure.org", + "code": "g/L" + }, + "high": { + "value": 50, + "unit": "g/L", + "system": "http://unitsofmeasure.org", + "code": "g/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:aa8aa37b-3a69-478f-a2be-947af624d7cb", + "resource": { + "resourceType": "Observation", + "id": "aa8aa37b-3a69-478f-a2be-947af624d7cb", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "b9c64863-06b5-4e98-b226-8ef28059f238" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1106051000000106", + "display": "Alkaline phosphatase enzyme activity in serum" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 96, + "unit": "iu/L", + "system": "http://unitsofmeasure.org", + "code": "[iU]/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "low": { + "value": 30, + "unit": "iu/L", + "system": "http://unitsofmeasure.org", + "code": "[iU]/L" + }, + "high": { + "value": 130, + "unit": "iu/L", + "system": "http://unitsofmeasure.org", + "code": "[iU]/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:3f98327b-f215-4bc5-bd52-ed6477a3da4a", + "resource": { + "resourceType": "Observation", + "id": "3f98327b-f215-4bc5-bd52-ed6477a3da4a", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "9f022172-f721-4657-ab23-a28157e783af" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1106081000000100", + "display": "Alanine aminotransferase enzyme activity in serum" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 15, + "unit": "iu/L", + "system": "http://unitsofmeasure.org", + "code": "[iU]/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "high": { + "value": 40, + "unit": "iu/L", + "system": "http://unitsofmeasure.org", + "code": "[iU]/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:a5c7f5e2-eb95-469b-b588-f7861c260ccb", + "resource": { + "resourceType": "Observation", + "id": "a5c7f5e2-eb95-469b-b588-f7861c260ccb", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-LabGroup" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "c949a08a-49f9-4093-9f17-67d23ec92e46" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "26958001", + "display": "Hepatic function panel" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "hasMember": [ + { + "reference": "urn:uuid:c6989afa-156a-4f7e-ab91-d4249680d8bf" + }, + { + "reference": "urn:uuid:f5a0e88f-a76a-4526-8927-579771471c58" + }, + { + "reference": "urn:uuid:aa2151a3-3f5b-4f0d-9074-52563aa77c6c" + }, + { + "reference": "urn:uuid:3c6b11c8-83b6-4402-90b9-2e1e7400d7cc" + }, + { + "reference": "urn:uuid:e6127f03-4a96-45d3-abd8-1adcf0189be4" + } + ] + } + }, + { + "fullUrl": "urn:uuid:c6989afa-156a-4f7e-ab91-d4249680d8bf", + "resource": { + "resourceType": "Observation", + "id": "c6989afa-156a-4f7e-ab91-d4249680d8bf", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "ac255464-4557-40ee-8f53-ef3104b10872" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1110281000000107", + "display": "Urea substance concentration in serum" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 3.7, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "low": { + "value": 2.5, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + }, + "high": { + "value": 7.8, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:f5a0e88f-a76a-4526-8927-579771471c58", + "resource": { + "resourceType": "Observation", + "id": "f5a0e88f-a76a-4526-8927-579771471c58", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "b1890fe7-ef3b-4d74-bc2f-665059d0c9d7" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1107871000000107", + "display": "Sodium substance concentration in serum" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 139, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "low": { + "value": 133, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + }, + "high": { + "value": 146, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:aa2151a3-3f5b-4f0d-9074-52563aa77c6c", + "resource": { + "resourceType": "Observation", + "id": "aa2151a3-3f5b-4f0d-9074-52563aa77c6c", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "b88011a3-e10b-4f35-b388-5622c4e8d808" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1107751000000106", + "display": "Potassium substance concentration in plasma" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 4.7, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "low": { + "value": 3.5, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + }, + "high": { + "value": 5.3, + "unit": "mmol/L", + "system": "http://unitsofmeasure.org", + "code": "mmol/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:3c6b11c8-83b6-4402-90b9-2e1e7400d7cc", + "resource": { + "resourceType": "Observation", + "id": "3c6b11c8-83b6-4402-90b9-2e1e7400d7cc", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "86fb479a-ab58-4f99-81de-af848d9af40c" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1107001000000108", + "display": "Creatinine substance concentration in serum" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 73, + "unit": "umol/L", + "system": "http://unitsofmeasure.org", + "code": "umol/L" + }, + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + }, + "referenceRange": [ + { + "low": { + "value": 59, + "unit": "umol/L", + "system": "http://unitsofmeasure.org", + "code": "umol/L" + }, + "high": { + "value": 104, + "unit": "umol/L", + "system": "http://unitsofmeasure.org", + "code": "umol/L" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:e6127f03-4a96-45d3-abd8-1adcf0189be4", + "resource": { + "resourceType": "Observation", + "id": "e6127f03-4a96-45d3-abd8-1adcf0189be4", + "meta": { + "profile": [ + "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation-Lab" + ] + }, + "identifier": [ + { + "system": "https://tools.ietf.org/html/rfc4122", + "value": "c6d25926-fb74-400b-98b8-47ae7393f127" + } + ], + "status": "final", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/observation-category", + "code": "laboratory", + "display": "Laboratory" + } + ] + } + ], + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "1011481000000105", + "display": "eGFR (estimated glomerular filtration rate) using creatinine Chronic Kidney Disease Epidemiology Collaboration equation per 1.73 square metres" + } + ] + }, + "subject": { + "reference": "urn:uuid:ab87a3f8-1d37-44a9-804e-5e962598a6e4", + "display": "WELSH, Joel" + }, + "issued": "2022-03-08T14:23:00+00:00", + "performer": [ + { + "reference": "urn:uuid:8a6d85b8-9837-4fed-a257-4cf207988338", + "display": "TD008362 PATH LAB 001" + } + ], + "valueQuantity": { + "value": 100, + "unit": "mL/min/1.73m2", + "system": "http://unitsofmeasure.org", + "code": "mL/min/((173/100).m2)" + }, + "note": [ + { + "text": "Calculated eGFR is not valid in children or pregnancy.\nLess accurate with acute change in creatinine (AKI).\nCaution with high or low muscle mass or amputation.\nAvoid blood sampling within 12 hours of eating meat.\nEthnicity factor comment removed Dec21 NG203." + } + ], + "specimen": { + "reference": "urn:uuid:bab0eaec-1ec5-4598-b660-90bb38a1030d" + } + } + } + ] +} diff --git a/src/main/resources/Examples/Bundle-message-Medications-dispense-notification.json b/src/main/resources/Examples/Bundle-message-Medications-dispense-notification.json new file mode 100644 index 0000000..6df3c09 --- /dev/null +++ b/src/main/resources/Examples/Bundle-message-Medications-dispense-notification.json @@ -0,0 +1,179 @@ +{ + "resourceType": "Bundle", + "id": "830a2a41-cca8-46a3-a35c-3237cb9828e4", + "type": "message", + "timestamp": "2021-05-07T16:15:32Z", + "entry": [ + { + "fullUrl": "urn:message-header-167434", + "resource": { + "resourceType": "MessageHeader", + "id": "urn:message-header-167434", + "eventCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/message-event", + "code": "dispense-notification", + "display": "Dispense Notification" + }, + "source": { + "name": "ACME Clinical Systems", + "software": "ACME Pharmacy", + "version": "4.1.15", + "endpoint": "urn:nhs-uk:addressing:ods:T48NT" + }, + "focus": [ + { + "reference": "urn:med-disp-324234234" + } + ] + } + }, + { + "fullUrl": "urn:patient-113582401", + "resource": { + "resourceType": "Patient", + "id": "urn:patient-113582401", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "113582401" + } + ], + "name": [ + { + "use": "official", + "text": "Ms Anne Teak", + "family": "Teak", + "given": [ + "Anna" + ], + "prefix": [ + "Ms" + ] + } + ], + "gender": "female", + "birthDate": "1987-03-29" + } + }, + { + "fullUrl": "urn:staff-0002", + "resource": { + "resourceType": "Practitioner", + "id": "urn:staff-0002", + "name": [ + { + "text": "Dr Allo Kate", + "family": "Kate", + "given": [ + "Allo" + ], + "prefix": [ + "Dr" + ] + } + ], + "qualification": [ + { + "code": { + "coding": [ + { + "system": "https://fhir.hl7.org.uk/Id/gpc-number", + "code": "123543", + "display": "General Pharmaceutical Council" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:medication-39732411000001106", + "resource": { + "resourceType": "Medication", + "id": "urn:medication-39732411000001106", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "39732411000001106", + "display": "Amoxicillin 500mg capsules" + } + ] + } + } + }, + { + "fullUrl": "urn:med-disp-324234234", + "resource": { + "resourceType": "MedicationDispense", + "id": "urn:med-disp-324234234", + "identifier": [ + { + "system": "urn:[organisation_name]:[system_name]", + "value": "urn:16099e16-2494-4a2b-b0e6-93eabd00c41b" + } + ], + "status": "in-progress", + "medicationReference": { + "reference": "urn:medication-39732411000001106", + "display": "Amoxicillin 500mg capsules" + }, + "subject": { + "reference": "urn:patient-113582401", + "display": "Ms Anne Teak" + }, + "performer": [ + { + "actor": { + "reference": "urn:staff-0002", + "display": "Dr Allo Kate" + } + } + ], + "authorizingPrescription": [ + { + "reference": "urn:med-req-1023938" + } + ], + "quantity": { + "value": 21, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + }, + "whenPrepared": "2021-05-07T16:15:32Z", + "dosageInstruction": [ + { + "timing": { + "repeat": { + "frequency": 3, + "period": 1, + "periodUnit": "d" + } + }, + "route": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "428673006", + "display": "oral" + } + ] + }, + "doseAndRate": [ + { + "doseQuantity": { + "value": 1, + "unit": "tablet", + "system": "http://snomed.info/sct", + "code": "428673006" + } + } + ] + } + ] + } + } + ] +} diff --git a/src/main/resources/Examples/Bundle-message-Medications-prescription-order.json b/src/main/resources/Examples/Bundle-message-Medications-prescription-order.json new file mode 100644 index 0000000..92faf2d --- /dev/null +++ b/src/main/resources/Examples/Bundle-message-Medications-prescription-order.json @@ -0,0 +1,177 @@ +{ + "resourceType": "Bundle", + "id": "d0a503d2-6809-4055-be82-308183e64734", + "type": "message", + "timestamp": "2021-05-07T16:15:32Z", + "entry": [ + { + "fullUrl": "urn:message-header-167434", + "resource": { + "resourceType": "MessageHeader", + "id": "urn:message-header-167434", + "eventCoding": { + "system": "https://fhir.nhs.uk/CodeSystem/message-event", + "code": "prescription-order", + "display": "Prescription Order" + }, + "source": { + "name": "ACME Clinical Systems", + "software": "ACME ePMA", + "version": "3.5.68", + "endpoint": "urn:nhs-uk:addressing:ods:T48NT" + }, + "focus": [ + { + "reference": "urn:med-req-1023938" + } + ] + } + }, + { + "fullUrl": "urn:patient-011223344", + "resource": { + "resourceType": "Patient", + "id": "urn:patient-011223344", + "identifier": [ + { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "2377954310" + } + ], + "name": [ + { + "use": "official", + "text": "Mrs Anne Teak", + "family": "Teak", + "given": [ + "Anne" + ], + "prefix": [ + "Mrs" + ] + } + ], + "gender": "female", + "birthDate": "1956-02-04" + } + }, + { + "fullUrl": "urn:staff-1112", + "resource": { + "resourceType": "Practitioner", + "id": "urn:staff-1112", + "name": [ + { + "text": "Dr Maikeu Well", + "family": "Well", + "given": [ + "Maikeu" + ], + "prefix": [ + "Dr" + ] + } + ], + "qualification": [ + { + "code": { + "coding": [ + { + "system": "https://fhir.hl7.org.uk/Id/gmc-number", + "code": "2145879", + "display": "General Medical Council" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:medication-38769117", + "resource": { + "resourceType": "Medication", + "id": "urn:medication-38769117", + "code": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "27658006", + "display": "Amoxicillin" + } + ] + } + } + }, + { + "fullUrl": "urn:med-req-1023938", + "resource": { + "resourceType": "MedicationRequest", + "id": "urn:med-req-1023938", + "status": "active", + "intent": "order", + "category": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-category", + "code": "inpatient", + "display": "inpatient" + } + ] + } + ], + "priority": "routine", + "medicationReference": { + "reference": "urn:medication-38769117" + }, + "subject": { + "reference": "urn:patient-011223344", + "display": "Mrs Anne Teak" + }, + "authoredOn": "2020-05-15T15:00:00Z", + "requester": { + "reference": "urn:staff-1112", + "display": "Dr Maikeu Well" + }, + "recorder": { + "reference": "urn:staff-1112", + "display": "Dr Maikeu Well" + }, + "dosageInstruction": [ + { + "timing": { + "repeat": { + "frequency": 3, + "period": 1, + "periodUnit": "d" + } + }, + "route": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "26643006", + "display": "Oral" + } + ] + }, + "doseAndRate": [ + { + "doseQuantity": { + "value": 500, + "unit": "milligram", + "system": "http://unitsofmeasure.org", + "code": "mg" + } + } + ] + } + ], + "substitution": { + "allowedBoolean": false + } + } + } + ] +} diff --git a/src/main/resources/Examples/Bundle-message.json b/src/main/resources/Examples/Bundle-message.json deleted file mode 100644 index 26e1d82..0000000 --- a/src/main/resources/Examples/Bundle-message.json +++ /dev/null @@ -1,1380 +0,0 @@ -{ - "resourceType": "Bundle", - "id": "79120f41-a431-4f08-bcc5-1e67006fcae0", - "meta": { - "versionId": "1.0.0-alpha", - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.nhs.uk/StructureDefinition/BARSBundleMessage" - ] - }, - "type": "message", - "timestamp": "2021-10-11T12:15:10+00:00", - "entry": [ - { - "fullUrl": "urn:uuid:c89a8895-56fe-41de-b20b-fab6efa99c99", - "resource": { - "resourceType": "MessageHeader", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.nhs.uk/StructureDefinition/BARSMessageHeader-servicerequest-request" - ] - }, - "extension": [ - { - "url": "https://fhir.nhs.uk/StructureDefinition/CDSSExtension", - "extension": [ - { - "url": "RequesterCDSSsoftware", - "valueString": "Pathways" - }, - { - "url": "RequesterCDSSversion", - "valueString": "30.2.0" - } - ] - } - ], - "eventCoding": { - "system": "https://fhir.nhs.uk/CodeSystem/message-events-bars", - "code": "servicerequest-request" - }, - "destination": [ - { - "endpoint": "http://fhir.nhs.uk/Id/dos-service-id|111111111", - "receiver": { - "reference": "urn:uuid:d5ffd0cd-ec7e-48a1-84f1-91f4c0eb8fc5" - } - } - ], - "sender": { - "reference": "urn:uuid:07939a0c-2854-46ff-9282-ad906bc93679" - }, - "source": { - "name": "Emergency service", - "software": "Anon Patient Manager", - "version": "2.1.45", - "contact": { - "system": "phone", - "value": "+44 (0113) 123 4567" - }, - "endpoint": "http://fhir.nhs.uk/Id/dos-service-id|2222222222" - }, - "reason": { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/message-reason-bars", - "code": "new" - } - ] - }, - "focus": [ - { - "reference": "urn:uuid:236bb75d-90ef-461f-b71e-fde7f899802c" - } - ], - "definition": "https://fhir.nhs.uk/MessageDefinition/bars-message-servicerequest-request-referral" - } - }, - { - "fullUrl": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d", - "resource": { - "resourceType": "Encounter", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Encounter" - ] - }, - "identifier": [ - { - "system": "https://sender.url/Id/case-number", - "value": "sender1234" - } - ], - "status": "finished", - "class": { - "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", - "code": "EMER", - "display": "emergency" - }, - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "episodeOfCare": [ - { - "reference": "d877b820-e72b-44d1-a627-195f54bfc606" - } - ], - "period": { - "start": "2021-02-19T07:15:00+10:00" - } - } - }, - { - "fullUrl": "urn:uuid:38e9c018-adbb-4579-9cd8-45f4f890b93b", - "resource": { - "resourceType": "CarePlan", - "meta": { - "lastUpdated": "2021-11-26T15:15:15+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-CarePlan" - ] - }, - "status": "completed", - "intent": "plan", - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "supportingInfo": [ - { - "reference": "urn:uuid:e53b2595-7875-4687-80e9-23a0c8cb8ea0", - "display": "Person expectations and wishes" - }, - { - "reference": "urn:uuid:ea37a499-245c-40e9-b0fa-df4383c4d413", - "display": "Safeguarding Concerns Flag" - }, - { - "reference": "urn:uuid:75f0e2c7-79db-4518-8a03-edcf096fccbb", - "display": "Additional Information Sources" - } - ], - "activity": [ - { - "outcomeCodeableConcept": [ - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/pathways-sd-codes", - "code": "4389", - "display": "ED post tonsillectomy bleeding" - } - ], - "text": "Pathways Assessment SD Code" - }, - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/pathways-dx-codes", - "code": "DX02", - "display": "The individual needs to attend an emergency treatment centre within 1 hour." - } - ], - "text": "Pathways Assessment DX Code" - }, - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/pathways-pathway-codes", - "code": "PA21", - "display": "Chest and Upper Back Pain" - } - ], - "text": "Presenting Complaint - selected Pathway or Template" - }, - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/pathways-sg-codes", - "code": "1010", - "display": "Allergic Reaction" - } - ], - "text": "Pathways Assessment SG Code - Chief Complaint" - }, - { - "text": "PATHWAYS ASSESSMENT:/n An injury or health problem was the reason for the contact./n Heavy bleeding had not occurred in the previous 2 hours./n An illness or health problem was the main problem. - bleeding for 15 minutes/n The individual was not fighting for breath./n The main reason for the assessment was not an allergic reaction, heart attack, chest/upper back pain, probable/n stroke, recent fit/seizure or suicide attempt./n The main reason for contact was not new confusion, declared diabetic hypo/hyperglycaemia, or ICD shock./n The skin on the torso felt normal, warm or hot./n Pathway Selected: PW818, Nosebleeds without Injury/n The individual was not feeling faint or dizzy./n The nose was continuing to bleed./n There was no nasal foreign body./n Constant pressure for at least 10 minutes had not been applied./n There was no spontaneous bruising, abnormal bleeding or frequent nosebleeds within the previous 2 weeks./n The individual did not use anticoagulant medication or have a bleeding/clotting disorder." - } - ] - } - ] - } - }, - { - "fullUrl": "urn:uuid:236bb75d-90ef-461f-b71e-fde7f899802c", - "resource": { - "resourceType": "ServiceRequest", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.nhs.uk/StructureDefinition/BARSServiceRequest-request-referral" - ] - }, - "basedOn": [ - { - "reference": "urn:uuid:38e9c018-adbb-4579-9cd8-45f4f890b93b" - } - ], - "status": "active", - "intent": "plan", - "category": [ - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/message-category-servicerequest", - "code": "referral", - "display": "Transfer of Care" - } - ] - } - ], - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "occurrencePeriod": { - "start": "2021-10-13T16:20:27+07:00" - }, - "authoredOn": "2021-10-11T15:23:30+00:00", - "requester": { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - }, - "performer": [ - { - "reference": "urn:uuid:d5ffd0cd-ec7e-48a1-84f1-91f4c0eb8fc5" - } - ], - "supportingInfo": [ - { - "reference": "urn:uuid:65508934-c9e6-46d2-a393-af096b502daf", - "display": "Rejected Services - Patient Choice in Service Selection - Details" - }, - { - "reference": "urn:uuid:41e591ab-d333-4fb8-87b4-d35f740b6bfc", - "display": "Rejected Services - Patient Choice in Service Selection - Flag" - } - ], - "patientInstruction": "ADVICE GIVEN: If there are any new symptoms, or if the condition gets worse, changes or you have any other concerns, call us back." - } - }, - { - "fullUrl": "urn:uuid:49073ea7-2d55-433f-9bce-9d3e798cfe40", - "resource": { - "resourceType": "HealthcareService", - "meta": { - "lastUpdated": "2021-11-26T15:00:00+00:00", - "profile": [ - "http://hl7.org/fhir/StructureDefinition/HealthcareService", - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-HealthcareService" - ] - }, - "identifier": [ - { - "system": "http://fhir.nhs.uk/Id/dos-service-id", - "value": "111111111" - } - ], - "active": true, - "providedBy": { - "reference": "urn:uuid:d5ffd0cd-ec7e-48a1-84f1-91f4c0eb8fc5" - }, - "name": "Emergency Department - Adult" - } - }, - { - "fullUrl": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8", - "resource": { - "resourceType": "Patient", - "meta": { - "lastUpdated": "2021-11-26T15:00:00+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Patient" - ] - }, - "extension": [ - { - "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-EthnicCategory", - "valueCodeableConcept": { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-EthnicCategory", - "code": "A", - "display": "British, Mixed British" - } - ] - } - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/patient-religion", - "valueCodeableConcept": { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/v3-ReligiousAffiliation", - "code": "1041", - "display": "Roman Catholic Church" - } - ] - } - } - ], - "identifier": [ - { - "extension": [ - { - "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus", - "valueCodeableConcept": { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus", - "code": "number-present-and-verified", - "display": "Number present and verified" - } - ] - } - } - ], - "system": "https://fhir.nhs.uk/Id/nhs-number", - "value": "3478526985" - } - ], - "name": [ - { - "use": "official", - "text": "Mrs Julie Jones", - "family": "Jones", - "given": [ - "Julie" - ], - "prefix": [ - "Mrs" - ] - } - ], - "gender": "female", - "birthDate": "1959-05-04", - "address": [ - { - "use": "home", - "type": "both", - "text": "22 Brightside Crescent, Overtown, West Yorkshire, LS10 4YU", - "line": [ - "22 Brightside Crescent" - ], - "city": "Overtown", - "district": "West Yorkshire", - "postalCode": "LS10 4YU" - } - ], - "contact": [ - { - "extension": [ - { - "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactRank", - "valuePositiveInt": 1 - } - ], - "relationship": [ - { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/ValueSet/UKCore-PersonRelationshipType", - "code": "ONESELF", - "display": "self" - } - ] - } - ], - "telecom": [ - { - "system": "phone", - "value": "01138698975", - "use": "home", - "rank": 2 - }, - { - "system": "phone", - "value": "07736312544", - "use": "mobile", - "rank": 1 - }, - { - "system": "email", - "value": "jjones@hotmail.co.uk", - "use": "home", - "rank": 3 - } - ] - }, - { - "extension": [ - { - "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactRank", - "valuePositiveInt": 2 - } - ], - "relationship": [ - { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/ValueSet/UKCore-PersonRelationshipType", - "code": "EP", - "display": "Emergency contact person" - } - ] - } - ], - "name": { - "family": "Grayson", - "given": [ - "Jack" - ] - }, - "telecom": [ - { - "system": "phone", - "value": "0789 1234567", - "use": "mobile", - "rank": 1 - } - ], - "gender": "male" - } - ], - "communication": [ - { - "language": { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage", - "code": "en", - "display": "English" - } - ] - }, - "preferred": true - } - ], - "generalPractitioner": [ - { - "reference": "urn:uuid:c8c21609-cb27-4958-8eb2-37c76f3def85" - } - ] - } - }, - { - "fullUrl": "urn:uuid:1e744e34-6bbb-4aa9-8b20-fa3bb91f9d8f", - "resource": { - "resourceType": "PractitionerRole", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-PractitionerRole" - ] - }, - "practitioner": { - "reference": "urn:uuid:07dec093-be12-42f4-ade5-0d582d255ef1" - }, - "organization": { - "reference": "urn:uuid:c8c21609-cb27-4958-8eb2-37c76f3def85" - }, - "specialty": [ - { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "408443003", - "display": "General medical practice" - } - ] - } - ] - } - }, - { - "fullUrl": "urn:uuid:b5e27389-3ca5-4cbc-9173-73f0c74915d9", - "resource": { - "resourceType": "Organization", - "meta": { - "lastUpdated": "2021-11-26T15:00:00+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" - ] - }, - "name": "Practitioner Org" - } - }, - { - "fullUrl": "urn:uuid:c8c21609-cb27-4958-8eb2-37c76f3def85", - "resource": { - "resourceType": "Organization", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" - ] - }, - "identifier": [ - { - "system": "https://fhir.nhs.uk/id/ods-organization-code", - "value": "G82080" - } - ], - "name": "Patient's Surgery" - } - }, - { - "fullUrl": "urn:uuid:07dec093-be12-42f4-ade5-0d582d255ef1", - "resource": { - "resourceType": "Practitioner", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Practitioner" - ] - }, - "identifier": [ - { - "system": "https://fhir.nhs.uk/Id/sds-role-profile-id", - "value": "G823658" - } - ], - "name": [ - { - "family": "Smith", - "given": [ - "John" - ] - } - ], - "telecom": [ - { - "system": "phone", - "value": "0205663859", - "use": "work" - } - ] - } - }, - { - "fullUrl": "urn:uuid:d5ffd0cd-ec7e-48a1-84f1-91f4c0eb8fc5", - "resource": { - "resourceType": "Organization", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" - ] - }, - "identifier": [ - { - "system": "https://fhir.nhs.uk/id/ods-organization-code", - "value": "RYE" - } - ], - "name": "Receiving/performing Organization" - } - }, - { - "fullUrl": "urn:uuid:07939a0c-2854-46ff-9282-ad906bc93679", - "resource": { - "resourceType": "Organization", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Organization" - ] - }, - "identifier": [ - { - "system": "https://fhir.nhs.uk/id/ods-organization-code", - "value": "RND" - } - ], - "name": "Sender Organization" - } - }, - { - "fullUrl": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56", - "resource": { - "resourceType": "Practitioner", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Practitioner" - ] - }, - "identifier": [ - { - "system": "https://fhir.nhs.uk/Id/sds-role-profile-id", - "value": "PT2489" - } - ], - "name": [ - { - "family": "BLAKE", - "given": [ - "Marcy" - ] - } - ], - "telecom": [ - { - "system": "phone", - "value": "0205568263", - "use": "work" - } - ] - } - }, - { - "fullUrl": "urn:uuid:b923aa53-2376-4015-a07d-afe8bf2310eb", - "resource": { - "resourceType": "PractitionerRole", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-PractitionerRole" - ] - }, - "practitioner": { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - }, - "organization": { - "reference": "urn:uuid:b5e27389-3ca5-4cbc-9173-73f0c74915d9" - }, - "code": [ - { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "224608005", - "display": "Administrative healthcare staff" - } - ] - } - ], - "specialty": [ - { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "408443003", - "display": "General medical practice" - } - ] - } - ] - } - }, - { - "fullUrl": "urn:uuid:30b7b6e3-93f0-4061-b90e-71f43d5fb06d", - "resource": { - "resourceType": "MedicationStatement", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-MedicationStatement" - ] - }, - "status": "active", - "category": { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/medication-statement-category", - "code": "outpatient", - "display": "Outpatient" - } - ] - }, - "medicationCodeableConcept": { - "coding": [ - { - "system": "https://dmd.nhs.uk/", - "code": "8280711000001102", - "display": "Aspirin 50mg/5ml oral solution" - } - ] - }, - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "context": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "effectiveDateTime": "2021-09-23", - "dateAsserted": "2021-10-22", - "reasonCode": [ - { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "65363002", - "display": "Otitis Media" - } - ] - } - ], - "dosage": [ - { - "text": "2 capsules 4 times a day.", - "timing": { - "repeat": { - "frequency": 4, - "period": 1, - "periodUnit": "d" - } - }, - "asNeededCodeableConcept": { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "16001004", - "display": "Otalgia" - } - ] - }, - "site": { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "123851003", - "display": "Mouth region structure" - } - ] - }, - "route": { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "26643006", - "display": "Oral" - } - ] - }, - "method": { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "421984009", - "display": "Until finished" - } - ] - }, - "doseAndRate": [ - { - "doseQuantity": { - "value": 500, - "unit": "milligram", - "system": "http://unitsofmeasure.org", - "code": "mg" - } - } - ] - } - ] - } - }, - { - "fullUrl": "urn:uuid:68e01f49-cf16-4d88-8b06-5c9f40676fdd", - "resource": { - "resourceType": "AllergyIntolerance", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-AllergyIntolerance" - ] - }, - "clinicalStatus": { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", - "code": "active", - "display": "Active" - } - ] - }, - "verificationStatus": { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-verification", - "code": "confirmed", - "display": "Confirmed" - } - ] - }, - "type": "allergy", - "category": [ - "medication" - ], - "code": { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "372687004", - "display": "Amoxicillin" - } - ] - }, - "patient": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "recordedDate": "2021-10-10T13:00:00+00:00", - "recorder": { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - }, - "asserter": { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - }, - "reaction": [ - { - "manifestation": [ - { - "coding": [ - { - "system": "http://snomed.info/sct", - "code": "247472004", - "display": "Urticarial rash" - } - ] - } - ], - "severity": "mild" - } - ] - } - }, - { - "fullUrl": "urn:uuid:ea37a499-245c-40e9-b0fa-df4383c4d413", - "resource": { - "resourceType": "Flag", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "http://hl7.org/fhir/StructureDefinition/Flag", - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Flag" - ] - }, - "status": "active", - "category": [ - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/flag-categories-bars", - "code": "SG", - "display": "Safeguarding Concern" - } - ] - } - ], - "code": { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/safeguarding-codes-bars", - "code": "U", - "display": "Unspecified Safeguarding Concern Identified" - } - ] - }, - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "period": { - "start": "2020-11-10T19:57:26.961Z", - "end": "2021-11-20T19:57:26.961Z" - } - } - }, - { - "fullUrl": "urn:uuid:3fe61915-32d2-4d41-953a-1d4ff56030e0", - "resource": { - "resourceType": "Flag", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "http://hl7.org/fhir/StructureDefinition/Flag", - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Flag" - ] - }, - "status": "active", - "category": [ - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/flag-categories-bars", - "code": "RA", - "display": "Reasonable Adjustment" - } - ] - } - ], - "code": { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/reasonable-adjustment-codes-bars", - "code": "adjustforneedlephobia", - "display": "Adjust for needle phobia" - } - ] - }, - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "period": { - "start": "2018-11-10T19:57:26.961Z" - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - } - } - }, - { - "fullUrl": "urn:uuid:41e591ab-d333-4fb8-87b4-d35f740b6bfc", - "resource": { - "resourceType": "Flag", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "http://hl7.org/fhir/StructureDefinition/Flag", - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Flag" - ] - }, - "status": "active", - "category": [ - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/flag-categories-bars", - "code": "RS", - "display": "Rejected Services" - } - ] - } - ], - "code": { - "text": "Patient Choice in Service Selection" - }, - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "period": { - "start": "2018-11-10T19:57:26.961Z" - } - } - }, - { - "fullUrl": "urn:uuid:65508934-c9e6-46d2-a393-af096b502daf", - "resource": { - "resourceType": "QuestionnaireResponse", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-QuestionnaireResponse" - ] - }, - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/questionnaireresponse-reason", - "valueCodeableConcept": { - "text": "Rejected Services - Patient Choice in Service Selection" - } - } - ], - "status": "completed", - "subject": { - "reference": "urn:uuid:41e591ab-d333-4fb8-87b4-d35f740b6bfc" - }, - "authored": "2021-10-13T16:28:00+07:00", - "author": { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - }, - "source": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "item": [ - { - "linkId": "RejectedServices", - "text": "Rejected Services", - "item": [ - { - "linkId": "Service1", - "item": [ - { - "linkId": "ServiceId", - "answer": [ - { - "valueString": "200000359" - } - ] - }, - { - "linkId": "ServiceName", - "answer": [ - { - "valueString": "Test DoS Service" - } - ] - }, - { - "linkId": "RejectionReason", - "answer": [ - { - "valueCoding": { - "system": "https://fhir.nhs.uk/CodeSystem/dos-rejected-reasons-bars", - "code": "26", - "display": "Rejected for patient choice" - } - } - ] - }, - { - "linkId": "RejectionComment", - "answer": [ - { - "valueString": "Same reason, Patient refused service due to parking" - } - ] - } - ] - }, - { - "linkId": "Service2", - "item": [ - { - "linkId": "ServiceId", - "answer": [ - { - "valueString": "200000360" - } - ] - }, - { - "linkId": "ServiceName", - "answer": [ - { - "valueString": "2nd Test DoS Service" - } - ] - }, - { - "linkId": "RejectionReason", - "answer": [ - { - "valueCoding": { - "system": "https://fhir.nhs.uk/CodeSystem/dos-rejected-reasons-bars", - "code": "26", - "display": "Rejected for patient choice" - } - } - ] - }, - { - "linkId": "RejectionComment", - "answer": [ - { - "valueString": "Same reason, Patient refused service due to parking" - } - ] - } - ] - } - ] - } - ] - } - }, - { - "fullUrl": "urn:uuid:0a6689a2-ebb4-48a2-825f-9c88c5959684", - "resource": { - "resourceType": "Observation", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation" - ] - }, - "status": "final", - "code": { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/household-composition-bars", - "code": "LivesAlone", - "display": "Lives Alone" - } - ] - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "effectiveDateTime": "2021-10-23", - "performer": [ - { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - } - ] - } - }, - { - "fullUrl": "urn:uuid:660f804e-9003-4623-b6c0-9f0faae50433", - "resource": { - "resourceType": "Observation", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation" - ] - }, - "status": "final", - "code": { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/v3-LivingArrangement", - "code": "N", - "display": "Nursing Home" - } - ] - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "effectiveDateTime": "2021-10-23", - "performer": [ - { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - } - ] - } - }, - { - "fullUrl": "urn:uuid:f2d2a6f8-1ef5-40a6-a697-849bb1264a91", - "resource": { - "resourceType": "Observation", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation" - ] - }, - "status": "final", - "code": { - "text": "Patient Reported Symptoms" - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "effectiveDateTime": "2021-10-23", - "performer": [ - { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - } - ], - "note": [ - { - "authorString": "Mrs Julie Jones", - "text": "Chest pain on and off for several days. Advised to contact 111" - } - ] - } - }, - { - "fullUrl": "urn:uuid:e53b2595-7875-4687-80e9-23a0c8cb8ea0", - "resource": { - "resourceType": "Observation", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Observation" - ] - }, - "status": "final", - "code": { - "text": "Expectations and wishes" - }, - "subject": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "encounter": { - "reference": "urn:uuid:8c63d621-4d86-4f57-8699-e8e22d49935d" - }, - "effectiveDateTime": "2021-10-23", - "performer": [ - { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - } - ], - "note": [ - { - "authorString": "BLAKE, Marcy", - "text": "The patient wishes to not be admitted to hospital unless deemed completely necessary. They have long term conditions which are better managed at home" - } - ] - } - }, - { - "fullUrl": "urn:uuid:75f0e2c7-79db-4518-8a03-edcf096fccbb", - "resource": { - "resourceType": "QuestionnaireResponse", - "meta": { - "lastUpdated": "2021-10-11T15:23:30+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-QuestionnaireResponse" - ] - }, - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/questionnaireresponse-reason", - "valueCodeableConcept": { - "text": "Additional Information Sources" - } - } - ], - "status": "completed", - "authored": "2021-10-13T16:28:00+07:00", - "author": { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - }, - "source": { - "reference": "urn:uuid:7d948662-bade-450e-b6c5-9bb6ee39cb56" - }, - "item": [ - { - "linkId": "AdditionalSources", - "text": "Additional Lookup Sources", - "item": [ - { - "linkId": "Source1", - "item": [ - { - "linkId": "SourceName", - "answer": [ - { - "valueString": "Healthcare Gateway MIG" - } - ] - }, - { - "linkId": "SourceURL", - "answer": [ - { - "valueUri": "http://www.healthcaregateway.co.uk/mig/patNatNo-4563225478" - } - ] - } - ] - }, - { - "linkId": "Source2", - "item": [ - { - "linkId": "SourceName", - "answer": [ - { - "valueString": "Graphnet" - } - ] - }, - { - "linkId": "SourceURL", - "answer": [ - { - "valueUri": "http://www.graphnet.co.uk/record/NHSNo-4563225478" - } - ] - } - ] - }, - { - "linkId": "Source3", - "item": [ - { - "linkId": "SourceName", - "answer": [ - { - "valueString": "Local SPN" - } - ] - }, - { - "linkId": "SPNTitle", - "answer": [ - { - "valueString": "Abusive patient" - } - ] - }, - { - "linkId": "SPNDetail", - "answer": [ - { - "valueString": "On one encounter with the patient they were verbally abusive to attending staff. Patient should not be seen alone" - } - ] - }, - { - "linkId": "SPNActiveDate", - "answer": [ - { - "valueDateTime": "2021-11-10T19:45:28.654Z" - } - ] - }, - { - "linkId": "SPNReviewDate", - "answer": [ - { - "valueDateTime": "2022-05-10T19:45:28.654Z" - } - ] - } - ] - } - ] - } - ] - } - }, - { - "fullUrl": "urn:uuid:1e91008e-96d0-438b-873c-c6d2c007fc29", - "resource": { - "resourceType": "Consent", - "meta": { - "lastUpdated": "2021-11-26T15:00:00+00:00", - "profile": [ - "https://fhir.hl7.org.uk/StructureDefinition/UKCore-Consent" - ] - }, - "status": "active", - "scope": { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/consentscope", - "code": "patient-privacy" - } - ] - }, - "category": [ - { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/consent-categories-bars", - "code": "DRC", - "display": "Direct Care" - } - ] - } - ], - "patient": { - "reference": "urn:uuid:9589fb37-87a2-48d8-968f-b371429208a8" - }, - "dateTime": "2021-11-26", - "policyRule": { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", - "code": "IMPLIED" - } - ] - } - } - } - ] -} diff --git a/src/main/resources/Examples/Encounter-ADTA03.json b/src/main/resources/Examples/Encounter-ADTA03.json deleted file mode 100644 index 03c2a73..0000000 --- a/src/main/resources/Examples/Encounter-ADTA03.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "resourceType": "Encounter", - "id": "adt-ao3-converted", - "meta": { - "versionId": "1", - "lastUpdated": "2022-07-26T06:38:54.907+00:00", - "source": "#zinyvQkLDsiddCuu" - }, - "extension": [ - { - "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AdmissionMethod", - "valueCodeableConcept": { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/CodeSystem/NHSDataModelAndDictionary-AdmissionMethod", - "code": "82" - } - ] - } - } - ], - "identifier": [ - { - "system": "https://fhir.yorkhospitals.nhs.uk/Id/visitId", - "value": "11554" - } - ], - "status": "finished", - "class": { - "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", - "code": "SS", - "display": "short stay" - }, - "serviceType": { - "coding": [ - { - "system": "https://fhir.nhs.uk/CodeSystem/NHSDataModelAndDictionary-treatment-function", - "code": "501" - } - ] - }, - "subject": { - "reference": "Patient/6853093", - "identifier": { - "system": "https://fhir.nhs.uk/Id/nhs-number", - "value": "9333333333" - } - }, - "participant": [ - { - "type": [ - { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", - "code": "ATND", - "display": "attender" - } - ] - } - ], - "individual": { - "identifier": { - "system": "https://fhir.hl7.org.uk/Id/gmc-number", - "value": "C3456789" - }, - "display": "Dr Samuel Darwin" - } - }, - { - "type": [ - { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", - "code": "ADM", - "display": "admitter" - } - ] - } - ], - "individual": { - "identifier": { - "system": "https://fhir.hl7.org.uk/Id/gmc-number", - "value": "C3456789" - }, - "display": "Dr Samuel Darwin" - } - }, - { - "type": [ - { - "coding": [ - { - "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", - "code": "CON", - "display": "consultant" - } - ] - } - ], - "individual": { - "identifier": { - "system": "https://fhir.hl7.org.uk/Id/gmc-number", - "value": "C3456789" - }, - "display": "Dr Samuel Darwin" - } - } - ], - "period": { - "start": "2010-03-30T11:00:00+01:00", - "end": "2010-03-31T17:15:00+01:00" - }, - "reasonReference": [ - { - "display": "Labour" - } - ], - "hospitalization": { - "admitSource": { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-SourceOfAdmissionEngland", - "code": "79" - } - ] - }, - "dischargeDisposition": { - "coding": [ - { - "system": "https://fhir.hl7.org.uk/CodeSystem/NHSDataModelAndDictionary-DischargeDestination", - "code": "19" - } - ] - } - }, - "location": [ - { - "location": { - "identifier": { - "system": "https://fhir.nhs.uk/Id/ods-site-code", - "value": "RCB55" - }, - "display": "York Hospital" - }, - "status": "active" - } - ], - "serviceProvider": { - "identifier": { - "system": "https://fhir.nhs.uk/Id/ods-organization-code", - "value": "RCB" - }, - "display": "York and Scarborough Teaching Hospitals NHS Trust" - } -} diff --git a/src/main/resources/Examples/UKCore-Access-Patient-Provider.json b/src/main/resources/Examples/UKCore-Access-Patient-Provider.json new file mode 100644 index 0000000..92f93f8 --- /dev/null +++ b/src/main/resources/Examples/UKCore-Access-Patient-Provider.json @@ -0,0 +1,210 @@ +{ + "resourceType": "CapabilityStatement", + "id": "UKCoreAccessPatientIndexProvider", + "text": { + "status": "extensions", + "div": "

Provider supports read-only access to a patient index for the purposes of direct care and subject of care access.

\n
ModeSERVER
Description
Transaction
System History
System Search
Resource TypeProfileReadSearchUpdateCreate
Patienthttps://fhir.hl7.org.uk/uk-core-access/StructureDefinition/UKCoreAccessPatientIndexPatienty

" + }, + "url": "https://fhir.hl7.org.uk/uk-core-access/CapabilityStatement/UKCoreAccessPatientIndexProvider", + "version": "0.1.0", + "title": "UKCore Access Patient Index Provider", + "status": "active", + "date": "2023-02-01", + "publisher": "HL7 UK", + "contact": [ + { + "name": "HL7 UK", + "telecom": [ + { + "system": "url", + "value": "https://www.hl7.org.uk/" + } + ] + } + ], + "description": "Provider supports read-only access to a patient index for the purposes of direct care and subject of care access.", + "jurisdiction": [ + { + "coding": [ + { + "system": "urn:iso:std:iso:3166", + "code": "GB", + "display": "United Kingdom of Great Britain and Northern Ireland" + } + ] + } + ], + "kind": "requirements", + "fhirVersion": "4.0.1", + "format": [ + "json" + ], + "rest": [ + { + "mode": "server", + "resource": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHALL" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + }, + { + "url": "required", + "valueString": "birthdate" + }, + { + "url": "required", + "valueString": "family" + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + }, + { + "url": "required", + "valueString": "birthdate" + }, + { + "url": "required", + "valueString": "name" + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + }, + { + "url": "required", + "valueString": "gender" + }, + { + "url": "required", + "valueString": "family" + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + }, + { + "url": "required", + "valueString": "gender" + }, + { + "url": "required", + "valueString": "name" + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination" + } + ], + "type": "Patient", + "profile": "https://fhir.hl7.org.uk/uk-core-access/StructureDefinition/UKCoreAccessPatientIndexPatient", + "interaction": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHALL" + } + ], + "code": "search-type" + } + ], + "searchParam": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + } + ], + "name": "_id", + "type": "token" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + } + ], + "name": "birthdate", + "type": "date" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + } + ], + "name": "family", + "type": "string" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHALL" + } + ], + "name": "gender", + "type": "token" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHOULD" + } + ], + "name": "given", + "type": "string" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHALL" + } + ], + "name": "identifier", + "type": "token" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation", + "valueCode": "SHALL" + } + ], + "name": "name", + "type": "string" + } + ] + } + ] + } + ] +} diff --git a/src/main/resources/OAS/Imaging.json b/src/main/resources/OAS/Imaging.json new file mode 100644 index 0000000..7663345 --- /dev/null +++ b/src/main/resources/OAS/Imaging.json @@ -0,0 +1,560 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Diagnostic Imaging Report FHIR - FHIR API", + "version": "0.3.0", + "description": "## Overview\n\nThe Diagnostic Imaging Report FHIR API enables you to access a patient's diagnostic imaging reports held within hospital trusts systems in England. \nThis API is part of the wider National Imaging Registry solution in which a national registry of a patient's diagnostic imaging and associated reports \nis held in the [National Record Locator V3.0 API](https://digital.nhs.uk/developer/api-catalogue/national-record-locator-fhir).\n\nIt works like this:\n\n1. Query the [National Record Locator V3.0 Consumer API](https://digital.nhs.uk/developer/api-catalogue/national-record-locator-fhir/v3/consumer) to discover the patient's medical imaging history across England.\n2. Use the URLs from the NRL results to retrieve a diagnostic report (using this API).\n\nThis API can only be used in conjunction with the National Record Locator V3.0. You will first use the [National Record Locator V3.0 Consumer API](https://digital.nhs.uk/developer/api-catalogue/national-record-locator-consumer-fhir) \nto search for pointers to a patient's imaging study reports, then use the information in the search results to retrieve the report from this API. \nThis removes the need for organisations to create duplicate copies of radiology reports across systems and organisations by enabling access to diagnostic imaging report \ninformation directly from the source system in a hospital trust.\n\nThe API provides only the means to retrieve a single radiology report - it does not provide a search interface as you will search for diagnostic imaging studies using the [National Record Locator V3.0 Consumer API](https://digital.nhs.uk/developer/api-catalogue/national-record-locator-fhir/v3/consumer)\n\n### Data availability, timing and quality\n\nNormally, the system which is responsible for publishing details of imaging study reports to the NRL will also be the system which will provide this FHIR API.\nWhen a pointer is published to the NRL, all NRL consumers who have onboarded to consume these pointers will be able to retrieve them immediately. The expectation therefore is that when publishing a pointer, \nthe report will immediately be available for consumption by a consumer. \n\nDuring the Alpha phase, only synthetic data will be conveyed by this API. In live use, data quality will rely upon the data quality of the responsible system.\n\n## Who can use this API\n\nThis 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 demonstrate you have a valid use case as part of digital onboarding.\n\nClient systems must first verify NHS Numbers used in queries. This can be done either directly by\nthe client system, or by taking a feed from an upstream system which has this responsibility. In either case\nNHS Numbers used in queries must be have been verified by one of the following mechanisms:\n\n * The [PDS FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir) or the [PDS HL7 V3 API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-hl7-v3)\n * A Spine Mini Service PDS (SMSP) Provider\n * The [Demographics Batch Service](https://digital.nhs.uk/developer/api-catalogue/demographics-batch-service)\n\nConnecting parties must have an appointed Clinical Safety Officer and undertake a Clinical Safety Assessment to use this API in Beta and beyond.\n\n## API status and roadmap\n\nThis API is [in development](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses) and will be tested in an Alpha phase before progressing into a Beta phase involving live patient data.\n\nTo see our roadmap, or to suggest, comment or vote on features for this API, see our\n[interactive product backlog](https://nhs-digital-api-management.featureupvote.com/suggestions/483146/diagnostic-imaging-report-api).\n\nIf you have any other queries, [contact us](https://digital.nhs.uk/developer/help-and-support).\n\n## Service level\n\nThis API is a Bronze service, meaning it is operational and supported only during business hours (8am to 6pm),\nMonday to Friday, excluding bank holidays.\n\nFor more details, see [service levels](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#service-levels).\n\n## Technology\n\nThis API is [RESTful](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#basic-rest).\n\nIt conforms to the [FHIR](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#fhir)\nglobal standard for health care data exchange, specifically to [FHIR R4 (v4.0.1)](https://hl7.org/fhir/r4/), except\nthat it does not support the [capabilities](http://hl7.org/fhir/R4/http.html#capabilities) interaction.\n\nIt includes some country-specific FHIR extensions, which conform to\n[FHIR UK Core](https://digital.nhs.uk/services/fhir-uk-core), specifically\n[fhir.r4.ukcore.stu1 0.5.1](https://simplifier.net/packages/fhir.r4.ukcore.stu1/0.5.1).\n\nYou do not need to know much about FHIR to use this API - FHIR APIs are just RESTful APIs that follow specific rules.\n\nIn particular, resource names are capitalised in camel case and are singular - in this API only the `DiagnosticReport` resource is used. \n\nThere are [libraries and SDKs available](https://digital.nhs.uk/developer/guides-and-documentation/api-technologies-at-nhs-digital#fhir-libraries-and-sdks) to help with FHIR API integration.\n\nWe also have some request and response examples below which you could use as templates for your solution.\n\n## Network access\nThis API is available on the internet.\n\nFor more details see [Network access for APIs](https://digital.nhs.uk/developer/guides-and-documentation/network-access-for-apis).\n\n## Security and authorisation\n\nThis API uses the following access modes:\n\n* [Application-restricted RESTful API - signed JWT authentication](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication) (for Integration and Live environments)\n\n## Environments and testing\n\n| Environment | Base URL |\n| ----------------- | ---------------------------------------------------------------------- |\n| Sandbox | `https://sandbox.api.service.nhs.uk/diagnostic-imaging-report/FHIR/R4/` |\n| Integration test | `https://int.api.service.nhs.uk/diagnostic-imaging-report/FHIR/R4/` |\n\n\n### Sandbox testing\n\nOur [sandbox environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#sandbox-testing):\n* is for early developer testing\n* only covers a limited set of scenarios\n* is open access, so does not allow you to test authorisation\n\nFor details of sandbox test scenarios, or to try out the sandbox using our 'Try this API' feature, see the\ndocumentation for each endpoint.\n\nAlternatively, you can try out the sandbox using our Postman collection:\n\n[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/TBC)\n\n### Integration testing\n\nOur [integration test environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing):\n\n* is for formal integration testing\n* includes authorisation\n\nIt also includes ready-to-use test data and scenarios. For details [contact us](https://digital.nhs.uk/developer/help-and-support).\n\nFor more details see [integration testing with our RESTful APIs](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing-with-our-restful-apis).\n\n## Onboarding\n\nWhen used beyond the Alpha, you need to get your software approved by us before it can go live with this API. We call this onboarding. The onboarding process can sometimes be quite long, so it is worth planning well ahead.\n\nAs part of this process, you need to demonstrate that you can manage risks and that your software conforms technically with the requirements for this API.\n\nInformation on this page might impact the design of your software. For details, see [Onboarding support information](https://digital.nhs.uk/developer/api-catalogue/diagnostic-imaging-report/onboarding-support-information).\n\nTo understand how our online digital onboarding process works, see [digital onboarding](https://digital.nhs.uk/developer/guides-and-documentation/digital-onboarding#using-the-digital-onboarding-portal).\n\nParticipants in the Alpha will not need to onboard software. The above is provided for information to inform planning beyond Alpha.\n\n## Errors\n\nWe use standard HTTP status codes to show whether an API request succeeded or not. They are usually in the range:\n\n* 200 to 299 if it succeeded, including code 202 if it was accepted by an API that needs to wait for further action\n* 400 to 499 if it failed because of a client error by your application\n* 500 to 599 if it failed because of an error on our server\n\nErrors specific to each API are shown in the Endpoints section, under Response. See our [reference guide](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#http-status-codes) for more on errors.\n", + "license": { + "name": "MIT License details", + "url": "https://opensource.org/license/mit/" + }, + "contact": { + "name": "NHS England API Management", + "url": "https://digital.nhs.uk/developer/help-and-support", + "email": "api.management@nhs.net" + } + }, + "servers": [ + { + "url": "https://sandbox.api.service.nhs.uk/diagnostic-imaging-report/FHIR/R4", + "description": "Sandbox environment." + }, + { + "url": "https://int.api.service.nhs.uk/diagnostic-imaging-report/FHIR/R4", + "description": "Integration test environment." + } + ], + "security": [ + { + "APIKeyAuth": [] + }, + { + "OAuth2": [] + } + ], + "paths": { + "/DiagnosticReport": { + "get": { + "summary": "Get a single diagnostic imaging report", + "operationId": "readDiagnosticReport", + "description": "# Get a single diagnostic imaging report\n\nThis endpoint will return a single [DiagnosticReport](https://simplifier.net/guide/uk-core-implementation-guide-stu2/Home/ProfilesandExtensions/Profile-UKCore-DiagnosticReport?version=1.1.3) FHIR UKCore resource.\n\n## Input \n\n Specify the unique identifier for the report in the URL Path. This URL will normally have been retrieved from the National Record Locator\n\n## Response (Success)\n\nA successful response will contain a single [DiagnosticReport](https://simplifier.net/guide/uk-core-implementation-guide-stu2/Home/ProfilesandExtensions/Profile-UKCore-DiagnosticReport?version=1.1.3).\n\nOnly the following response attributes will be present:\n\n| Attribute | Description |\n| --------- | ----------- |\n| id | The unique identifier for the report as held in the local system |\n| subject | The NHS number of the patient. |\n| identifier | The accession number of the study prefixed with the ODS code of the organisation responsible for the report. Specified in the format {ODS Code}.{Accession Number}. This avoids duplicate identifiers for patient studies. |\n| identifier | The report version identifier. |\n| code | Fixed value of 371525003 taken from the [UKCoreReportCode](https://simplifier.net/packages/fhir.r4.ukcore.stu2/1.1.3/files/2047341/~overview) ValueSet. \n| performer | The organization responsible for issuing the report. Specified as an ODS code. |\n| resultsInterpreter | The GMC number and name of the practitioner responsible for the report’s conclusions and interpretations. |\n| issued | The date/time when the report was issued |\n| conclusion | Free text report contents as stored in the reporting system. |\n\n## Response (Error)\n\nClient (4XX) errors will be returned as a single OperationOutcome resource in the following specific scenarios:\n\n| HTTP Status | Error Code | Description |\n| ----------- | ---------------- | ----------- |\n| 400 | VALIDATION_ERROR | A parameter or value has resulted in a validation error. This may be caused by a missing or invalid header or `id` path parameter |\n| 401 | ACCESS_DENIED | Access Denied |\n| 404 | RESOURCE_NOT_FOUND | The radiology report specified by the `id` path parameter was not found on the server |\n\nThe OperationOutcome resource will contain the following attributes:\n\n| Attribute | Description |\n| --------------------- | ----------- |\n| issue.severity | The severity of the issue taken from the possible values listed at https://hl7.org/fhir/codesystem-issue-severity.html |\n| issue.code | Describes the type of the issue. The system that creates an OperationOutcome SHALL choose the most applicable code from the IssueType value set defined at https://hl7.org/fhir/codesystem-issue-type.html |\n| details.coding.system | Fixed value of https://fhir.hl7.org.uk/CodeSystem/UKCore-SpineErrorOrWarningCode |\n| details.coding.value | A code taken from the set of values defined at https://fhir.hl7.org.uk/CodeSystem/UKCore-SpineErrorOrWarningCode |\n| details.coding.display | The display value associated with the code defined at https://fhir.hl7.org.uk/CodeSystem/UKCore-SpineErrorOrWarningCode |\n| issue.diagnostics | More detailed diagnostic information available to the system at the time of the error. |\n\nThe specific details of the error can be found in the `issue.diagnostics` attribute of the response\n", + "parameters": [ + { + "$ref": "#/components/parameters/id" + }, + { + "$ref": "#/components/parameters/requestId" + }, + { + "$ref": "#/components/parameters/correlationId" + }, + { + "$ref": "#/components/parameters/odsCode" + }, + { + "$ref": "#/components/parameters/reportURL" + } + ], + "responses": { + "200": { + "description": "Successful retrieval of a single diagnostic imaging report", + "content": { + "application/fhir+json": { + "schema": { + "$ref": "#/components/schemas/DiagnosticReport" + }, + "example": { + "resourceType": "DiagnosticReport", + "id": "80d50a66-748e-4328-922f-17fce9d0fc77", + "status": "final", + "identifier": [ + { + "system": "https://example.com/accessionnumber", + "value": "HospitalID.AccessionNumber" + }, + { + "system": "https://example.com/radiologyreportversion", + "value": "1.0" + } + ], + "subject": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/nhs-number", + "value": "1234567892" + }, + "display": "SMITH, John" + }, + "code": { + "coding": [ + { + "system": "http://snomed.info/sct" + }, + { + "code": "371525003" + }, + { + "display": "Clinical procedure report (record artifact)" + } + ] + }, + "performer": { + "identifier": { + "system": "https://fhir.nhs.uk/Id/ods-organisation-code", + "value": "ZZ123456" + }, + "display": "King Charles University Hospital, Testham" + }, + "resultsInterpreter": { + "identifier": { + "system": "https://fhir.hl7.org.uk/Id/gmc-number", + "value": "1234567" + }, + "display": "FICTITIOUS, Ralph" + }, + "issued": "2023-09-07T11:45:41+11:00", + "conclusion": "Normal - no action" + } + } + }, + "headers": { + "X-Correlation-Id": { + "$ref": "#/components/headers/CorrelationId" + }, + "X-Request-Id": { + "$ref": "#/components/headers/RequestId" + } + } + }, + "4XX": { + "description": "A client error as described above", + "content": { + "application/fhir+json": { + "schema": { + "$ref": "#/components/schemas/OperationOutcome" + }, + "example": { + "resourceType": "OperationOutcome", + "issue": [ + { + "severity": "error", + "code": "required", + "details": { + "coding": [ + { + "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-SpineErrorOrWarningCode" + }, + { + "code": "VALIDATION_ERROR" + }, + { + "display": "A parameter or value has resulted in a validation error" + } + ] + }, + "diagnostics": "The id path parameter was missing from the request." + } + ] + } + } + }, + "headers": { + "X-Correlation-Id": { + "$ref": "#/components/headers/CorrelationId" + }, + "X-Request-Id": { + "$ref": "#/components/headers/RequestId" + } + } + } + } + } + } + }, + "components": { + "schemas": { + "DiagnosticReport": { + "type": "object", + "properties": { + "resourceType": { + "type": "string", + "enum": [ + "DiagnosticReport" + ] + }, + "id": { + "type": "string", + "pattern": "[A-Za-z0-9\\-\\.]{1,64}", + "description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes." + }, + "identifier": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Identifier" + } + }, + "status": { + "type": "string", + "pattern": "[A-Za-z0-9\\-\\.]{1,64}", + "description": "A value from https://hl7.org/fhir/r4/valueset-diagnostic-report-status.html" + }, + "subject": { + "$ref": "#/components/schemas/NHSNumberReference" + }, + "code": { + "$ref": "#/components/schemas/DiagnosticReportCodeableConcept" + }, + "issued": { + "type": "string", + "pattern": "([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]+)?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))", + "description": "Date and time when this version of the report was made in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz (e.g. 2015-02-07T13:28:17.239+02:00 or 2017-01-01T00:00:00Z)." + }, + "performer": { + "$ref": "#/components/schemas/PerformerReference" + }, + "resultsInterpreter": { + "$ref": "#/components/schemas/ResultsInterpreterReference" + }, + "conclusion": { + "type": "string", + "pattern": "[^\\s]+(\\s[^\\s]+)*", + "description": "Clinical conclusion (interpretation) of test results. For radiology domain reports, this will be the free-text report." + } + } + }, + "OperationOutcome": { + "type": "object", + "properties": { + "resourceType": { + "type": "string", + "description": "FHIR Resource Type.", + "default": "OperationOutcome" + }, + "issue": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OperationOutcomeIssue" + }, + "minItems": 1 + } + }, + "required": [ + "resourceType", + "issue" + ] + }, + "OperationOutcomeIssue": { + "type": "object", + "properties": { + "severity": { + "type": "string", + "pattern": "[^\\s]+(\\s[^\\s]+)*", + "description": "Indicates whether the issue indicates a variation from successful processing. The system that creates an OperationOutcome SHALL choose the most applicable code from the IssueSeverity value set defined at https://hl7.org/fhir/codesystem-issue-severity.html" + }, + "code": { + "type": "string", + "pattern": "[^\\s]+(\\s[^\\s]+)*", + "description": "Describes the type of the issue. The system that creates an OperationOutcome SHALL choose the most applicable code from the IssueType value set defined at https://hl7.org/fhir/codesystem-issue-type.html, and may additional provide its own code for the error in the details element." + }, + "details": { + "$ref": "#/components/schemas/OperationOutcomeCodeableConcept" + }, + "diagnostics": { + "type": "string", + "pattern": "[ \\r\\n\\t\\S]+", + "description": "Additional diagnostic information about the issue." + } + }, + "required": [ + "severity", + "code" + ] + }, + "OperationOutcomeCodeableConcept": { + "type": "object", + "properties": { + "coding": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OperationOutcomeCoding" + } + } + } + }, + "OperationOutcomeCoding": { + "type": "object", + "properties": { + "system": { + "type": "string", + "description": "Fixed value of `https://fhir.hl7.org.uk/CodeSystem/UKCore-SpineErrorOrWarningCode`" + }, + "code": { + "type": "string", + "description": "Value from ValueSet listed at https://simplifier.net/packages/fhir.r4.ukcore.stu2/1.1.3/files/2047077" + }, + "display": { + "type": "string", + "description": "Definition assocatiated with the value https://simplifier.net/packages/fhir.r4.ukcore.stu2/1.1.3/files/2047077" + } + } + }, + "DiagnosticReportCodeableConcept": { + "type": "object", + "properties": { + "coding": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DiagnosticReportCoding" + } + } + } + }, + "DiagnosticReportCoding": { + "type": "object", + "properties": { + "system": { + "type": "string", + "description": "Fixed value of `http://snomed.info/sct`" + }, + "code": { + "type": "string", + "description": "Fixed value of `371525003`" + }, + "display": { + "type": "string", + "description": "Fixed value of `Clinical procedure report (record artifact)`" + } + } + }, + "Identifier": { + "type": "object", + "properties": { + "system": { + "type": "string", + "pattern": "\\S*", + "description": "Establishes the namespace for the value – that is, a URL that describes a set values that are unique." + }, + "value": { + "type": "string", + "pattern": "[ \\r\\n\\t\\S]+", + "description": "Accession number identifier values are prefixed with the ODS Code of the organisation responsible for the production of the report. They are specified in the format {ODS Code}.{Accession Number}'" + } + } + }, + "NHSNumberIdentifier": { + "type": "object", + "properties": { + "system": { + "type": "string", + "pattern": "\\S*", + "description": "Fixed value of `https://fhir.nhs.uk/Id/nhs-number`" + }, + "value": { + "type": "string", + "pattern": "[ \\r\\n\\t\\S]+", + "description": "The NHS Number" + } + } + }, + "ResultsInterpreterIdentifier": { + "type": "object", + "properties": { + "system": { + "type": "string", + "pattern": "\\S*", + "description": "Fixed value of `https://fhir.hl7.org.uk/Id/gmc-number`." + }, + "value": { + "type": "string", + "description": "The GMC number of the reporting practitioner" + } + } + }, + "OrganisationIdentifier": { + "type": "object", + "properties": { + "system": { + "type": "string", + "pattern": "\\S*", + "description": "Fixed value of `https://fhir.nhs.uk/Id/ods-organisation-code`." + }, + "value": { + "type": "string", + "pattern": "[ \\r\\n\\t\\S]+", + "description": "The ODS Code" + } + } + }, + "ResultsInterpreterReference": { + "type": "object", + "properties": { + "identifier": { + "$ref": "#/components/schemas/ResultsInterpreterIdentifier" + }, + "display": { + "type": "string", + "pattern": "[ \\r\\n\\t\\S]+", + "description": "The name of the practitioner in the format `SURNAME, forenames`." + } + } + }, + "PerformerReference": { + "type": "object", + "properties": { + "identifier": { + "$ref": "#/components/schemas/OrganisationIdentifier" + }, + "display": { + "type": "string", + "pattern": "[ \\r\\n\\t\\S]+", + "description": "The name of the organisation." + } + } + }, + "NHSNumberReference": { + "type": "object", + "properties": { + "identifier": { + "$ref": "#/components/schemas/NHSNumberIdentifier" + }, + "display": { + "type": "string", + "pattern": "[ \\r\\n\\t\\S]+", + "description": "Name of the patient for display purposes, in the format `SURNAME, forenames`" + } + } + }, + "DiagnosticReportId": { + "type": "string", + "pattern": "[A-Za-z0-9\\-\\.]{1,64}" + }, + "BackEndURL": { + "type": "string", + "pattern": "(http(s)?:\\/\\/.)?(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&=]*)" + }, + "RequestHeaderOdsCode": { + "type": "string" + }, + "RequestHeaderRequestId": { + "type": "string", + "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" + }, + "RequestHeaderCorrelationId": { + "type": "string", + "example": "11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA" + } + }, + "securitySchemes": { + "APIKeyAuth": { + "type": "apiKey", + "name": "API Key (for sandbox only)", + "in": "query" + }, + "OAuth2": { + "type": "oauth2", + "description": "For Integration and Live environments. OAuth2 client credentials flow with signed JWT for authentication. For more information, see: https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication", + "flows": { + "clientCredentials": { + "tokenUrl": "https://example.com/token", + "refreshUrl": "https://example.com/token", + "scopes": {} + } + } + } + }, + "parameters": { + "id": { + "name": "id", + "in": "query", + "required": true, + "description": "logical identifier of the diagnostic report", + "schema": { + "$ref": "#/components/schemas/DiagnosticReportId" + }, + "examples": { + "valid": { + "summary": "Valid", + "value": "ea83fd3f-d71e-421f-9a9f-5b69127a77b7" + }, + "invalid": { + "summary": "Invalid as empty", + "value": null + } + } + }, + "odsCode": { + "name": "NHSD-End-User-Organisation-ODS", + "description": "ODS Code for Organisation as defined at https://www.datadictionary.nhs.uk/attributes/organisation_identifier.html", + "in": "header", + "schema": { + "$ref": "#/components/schemas/RequestHeaderOdsCode" + }, + "required": true, + "examples": { + "valid": { + "summary": "Valid", + "value": "Y05868" + }, + "invalid": { + "summary": "Invalid ODS code (should be minimum of 3 and maximum of 8 characters)", + "value": "XY" + } + } + }, + "reportURL": { + "name": "NHSE-NRL-Pointer-URL", + "description": "The URL of the report at the local report API. This is the URL which the national report API proxy will call. The client will have previously queried the NRL V3.0 Consumer API for a patient's imaging report history and will have extracte this URL from the results.", + "in": "header", + "schema": { + "$ref": "#/components/schemas/BackEndURL" + }, + "required": true, + "examples": { + "valid": { + "summary": "Valid", + "value": "https://an-ris-system.org.nhs.uk/some-path/FHIR/R4/DiagnosticReport?id=c9d0e5e3-ac48-4285-8f9c-af9b30d235f1" + }, + "invalid": { + "summary": "Invalid as URL is not resolvable", + "value": "some-path/FHIR/R4/DiagnosticReport?id=c9d0e5e3-ac48-4285-8f9c-af9b30d235f1" + } + } + }, + "requestId": { + "name": "X-Request-ID", + "description": "A globally unique identifier (GUID) for the request, which can be used to trace the request if you contact our helpdesk.\n\nMust be a universally unique identifier (UUID) (ideally version 4).\n\nMirrored back in a response header.\n", + "in": "header", + "required": false, + "schema": { + "$ref": "#/components/schemas/RequestHeaderRequestId" + } + }, + "correlationId": { + "name": "X-Correlation-ID", + "description": "An optional ID which you can use to track transactions across multiple systems, and we use to de-duplicate repeated requests and to trace the request if you contact our helpdesk.\n\nIf you re-send a failed request please re-send this ID in the header.\n\nIt can take any value, but we recommend avoiding `.` characters.\n\nMirrored back in a response header.\n", + "in": "header", + "required": false, + "schema": { + "$ref": "#/components/schemas/RequestHeaderCorrelationId" + } + } + }, + "headers": { + "CorrelationId": { + "schema": { + "type": "string", + "example": "11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA", + "description": "The X-Correlation-ID from the request header, if supplied, mirrored back.\n" + } + }, + "RequestId": { + "schema": { + "type": "string", + "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", + "description": "The X-Request-ID from the request header, if supplied, mirrored back.\n" + } + } + } + } +} diff --git a/src/main/resources/OAS/PDS.json b/src/main/resources/OAS/PDS.json new file mode 100644 index 0000000..746db61 --- /dev/null +++ b/src/main/resources/OAS/PDS.json @@ -0,0 +1 @@ +{"openapi":"3.0.0","info":{"version":"v1.2.2156-beta","title":"Personal Demographics Service (FHIR) API","description":"## Overview \nUse this API to access the [Personal Demographics Service (PDS)](https://digital.nhs.uk/services/demographics) - the national electronic database of NHS patient details such as name, address, date of birth, related people, registered GP and NHS number.\n\nYou can:\n* search for patients\n* get patient details\n* update patient details\n* verify an NHS number for a patient\n\nYou cannot currently use this API to:\n* create a new record for a birth - use [PDS HL7 V3 API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-hl7-v3)\n* receive birth notifications - use [PDS HL7 V3 API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-hl7-v3) or [PDS Notifications FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-notifications-fhir) \n* create a record for a new patient - use [PDS HL7 V3 API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-hl7-v3)\n* register a new patient at a GP Practice - use [NHAIS GP Links API](https://digital.nhs.uk/developer/api-catalogue/nhais-gp-links)\n* receive patient death notifications - use [PDS Notifications FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-notifications-fhir) \n* receive notifications about a patient's change of address - use [PDS Notifications FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-notifications-fhir) \n* receive notifications about a patient's change of GP - use [PDS Notifications FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-notifications-fhir) \n* receive notifications about any PDS record change - use [PDS Notifications FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-notifications-fhir) \n\nYou can read and update the following data:\n* NHS number (read only)\n* name\n* gender\n* addresses and contact details\n* birth information\n* death information\n* registered GP\n* nominated pharmacy\n* dispensing doctor pharmacy\n* medical appliance supplier pharmacy\n* related people, such as next of kin (read only - update coming soon)\n\n### Patients included in PDS\nRegardless of nationality, or where they live now, PDS includes all patients who have ever been registered with a GP practice, or treated by a health or care organisation (even as a visitor or migrant) in England, Wales, the Isle of Man, or in a UK Defence Medical Services unit anywhere in the world. \n\nAll patients in PDS have an NHS number which is unique. The 10-digit NHS number is used in England, Wales, the Isle of Man, Scotland and Northern Ireland, but not the Channel Islands. Scotland and Northern Ireland have their own distinct number ranges.\n\n### Access modes\nThis API has three access modes:\n\n| Access mode | Functions | Availability |\n| ------------------------------ | ------------------ | ------------ |\n| [Application-restricted access](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#application-restricted-apis) |Search for a patient (single result).
Get patient details. | Available in production ([stable](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#api-status)) |\n| [Healthcare worker access](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis) |Search for patients (multiple results).
Get patient details.
Update patient details. | Available in production ([beta](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#api-status)) |\n| [Patient access](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis) |Get own details.
Update own details (limited). | Available in production ([beta](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#api-status)) |\n\nFor further details about the access modes for this API, see [Security and authorisation](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir#api-description__security-and-authorisation) below.\n\n## Who can use this API\nThis API can only be used where there is a [legal basis](http://digital.nhs.uk/services/demographics/access-data-on-the-personal-demographics-service) to do so. Make sure you have a valid use case before you go too far with your development. You must demonstrate you have a [valid use case](https://digital.nhs.uk/services/demographics/access-data-on-the-personal-demographics-service) as part of digital onboarding. \n\nYou must do this before you can go live (see ‘Onboarding’ below).\n\n### Who can access PDS records\nHealth and care organisations in England and the Isle of Man can access PDS records. Legitimate direct care examples include NHS organisations delivering healthcare, local authorities delivering care, third sector and private sector health and care organisations, and developers delivering systems to health and care organisations. \n\nHealth and care organisations in Wales access their own version of PDS called the Welsh Demographics Service (WDS) which is connected to PDS behind the scenes. \n\nHealth and care organisations in Scotland, Northern Ireland and the Channel Islands access their own equivalents of PDS.\n\nPatients who receive health and social care or make use of NHS services in England, Wales, the Isle of Man, Scotland, Northern Ireland and the Channel Islands.\n\n### Existing API users\nTo find out which healthcare software development organisations and products are already using this API, see [PDS FHIR API - integrated products](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir/integrated-products).\n\n## Related APIs\nThe following APIs also give access to the Personal Demographics Service:\n- [Personal Demographics Service (SMSP) API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-smsp) - this API is now deprecated.\n- [Personal Demographics Service (HL7 V3) API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-hl7-v3) - use this if you want to use functions that are not yet available on the FHIR API, such as creating a new record for a birth, receiving birth notifications, or creating a record for a new patient (except when registering a new patient at a GP Practice, use [NHAIS](https://digital.nhs.uk/services/nhais)). For birth notifications, another option is [PDS Notifications - FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-notifications-fhir).\n\nOnce our roadmap is complete, the above APIs will become redundant.\n\nThe following APIs are also related to this API:\n- [Personal Demographics Service Notifications - FHIR API](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-notifications-fhir) - use this to subscribe to be notified of a set of patient record changes, including any record update, birth, death, change of address and change of GP.\n- [Organisation Data Service FHIR API](https://developer.nhs.uk/apis/ods/) - use this to get full details for the organisations related to the patient, such as their registered GP or nominated pharmacy.\n- [Ordnance Survey (OS Places) API](https://digital.nhs.uk/developer/api-catalogue/ordnance-survey-places-api) - use this to identify, look up and verify addresses prior to a PDS update.\n\n## API status and roadmap\n### Application-restricted access\nThis access mode is [in production](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses):\n* you should strongly consider it as the primary choice for PDS integration\n* we do not make routine breaking changes, if it cannot be avoided, for example, for security reasons, we will give advance notice\n \n### Healthcare worker access\nThis access mode is [in production, beta](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses), meaning:\n- we might make breaking changes, but only if we cannot avoid it, and we will give advance notice\n\nIf you would like to be involved in our beta programme, [contact us](https://digital.nhs.uk/developer/help-and-support).\n \n### Patient access\nThis access mode is [in production, beta](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#statuses), meaning:\n- we might make breaking changes, but only if we cannot avoid it, and we will give advance notice\n\nIf you would like to be involved in our beta programme, [contact us](https://digital.nhs.uk/developer/help-and-support).\n\n### Roadmap\nTo see our roadmap, or to suggest, comment or vote on features for this API, see our [interactive product backlog](https://nhs-digital-api-management.featureupvote.com/?order=popular&filter=allexceptdone&tag=pds-fhir-api).\n\nIf you have any other queries, please [contact us](https://digital.nhs.uk/developer/help-and-support).\n\n## Service level\n\nThis API is a platinum service, meaning it is operational and supported 24 hours a day, 365 days a year.\n\nFor more details, see [service levels](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#service-levels).\n\n## Technology\nThis API is [RESTful](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#basic-rest).\n\nIt conforms to the [FHIR](https://digital.nhs.uk/developer/guides-and-documentation/our-api-technologies#fhir) global standard for health care data exchange, specifically to [FHIR R4 (v4.0.1)](https://hl7.org/fhir/r4/), except that it does not support the [capabilities](http://hl7.org/fhir/R4/http.html#capabilities) interaction.\n\nIt includes some country-specific FHIR extensions, which are built against [FHIR UK Core](https://digital.nhs.uk/services/fhir-uk-core), specifically [UK.core.r4 1.0.0](https://simplifier.net/packages/uk.core.r4/1.0.0).\n\nYou do not need to know much about FHIR to use this API - FHIR APIs are just RESTful APIs that follow specific rules.\nIn particular:\n- resource names are capitalised and singular, for example `/Patient` not `/patients`\n- array names are singular, for example `line` not `lines` for address lines\n- data items that are country-specific and thus not included in the FHIR global base resources are usually wrapped in an `extension` object\n\nThere are [libraries and SDKs available](https://digital.nhs.uk/developer/guides-and-documentation/api-technologies-at-nhs-digital#fhir-libraries-and-sdks) to help with FHIR API integration.\n\n## Network access\nThis API is available on the internet and, indirectly, on the [Health and Social Care Network (HSCN)](https://digital.nhs.uk/services/health-and-social-care-network).\n\nTo use this API with [NHS smartcards](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/nhs-smartcards-for-developers), the end user needs an HSCN connection, although internet-facing alternatives to smartcards are available.\n\nFor more details see [Network access for APIs](https://digital.nhs.uk/developer/guides-and-documentation/network-access-for-apis).\n\n## Security and authorisation\n\nThis API has three access modes:\n- application-restricted access\n- healthcare worker access\n- patient access\n\n### Application-restricted access\nUse this access mode if you need to:\n* search for a patient – and only get a result if there is a unique match\n* get a single patient's details\n\nThis access mode is [application-restricted](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#application-restricted-apis), meaning we authenticate the calling application but not the end user.\n\nThe end user could be:\n* a healthcare worker - in which case you must ensure they are authenticated and suitably authorised locally\n* a patient - in which case you must ensure they are authenticated locally\n* not present at all - for example as part of a back end process to check NHS numbers for data flowing from one system to another\n\nTo use this access mode, use the following security pattern:\n* [Application-restricted RESTful API - signed JWT authentication](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication)\n\n### Healthcare worker access\nUse this access mode if the end user is a healthcare worker and you need to: \n* search for patients – and be able to present a list of matches for the user to choose from \n* get patient details \n* update patient details \n\nThis access mode is [user-restricted](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis), meaning an end user must be present, authenticated and authorised.\n\nThe end user must be:\n* a healthcare worker\n* strongly authenticated, using either an [NHS smartcard or a modern alternative](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/nhs-smartcards-for-developers)\n* authorised, using [national role-based access control (RBAC)](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/national-rbac-for-developers)\n\nTo use this access mode, use one of the following security patterns:\n\n|\tSecurity pattern\t\t |\tTechnical details\t |\tAdvantages | Disadvantages |\n|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ---------------------------------------------------------| -------------------------------------------------------------------------|---------------------------------------------------------------------------|\n|[NHS CIS2 - combined authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-cis2-combined-authentication-and-authorisation) |OAuth 2.0 authorisation code flow with API key and secret |No need to integrate and onboard separately with NHS CIS2. |No access to user information.
Not recommended for use in GP software. |\n|[NHS CIS2 - separate authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-cis2-separate-authentication-and-authorisation) |OAuth 2.0 token exchange with signed JWT |Gives access to user information.
Recommended for use in GP software. |Need to integrate and onboard separately with NHS CIS2. |\n\n### Patient access\nUse this access mode if the end user is a patient and you need to: \n* get the patient’s own details\n* update the patient’s own details\n\nThis access mode is [user-restricted](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis), meaning an end user must be present, authenticated and authorised.\n\nThe end user must be:\n* a patient who receives health and social care or makes use of NHS services\n* strongly authenticated, using [NHS login](https://digital.nhs.uk/services/nhs-login)\n\nTo use this access mode, use one of the following security patterns:\n\n|\tSecurity pattern\t\t |\tTechnical details\t |\tAdvantages\t | Disadvantages |\n|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ----------------------------------------------------| ------------------------------------------------------------|---------------------------------------------------------|\n|[NHS login - combined authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-combined-authentication-and-authorisation) |OAuth 2.0 authorisation code with API key and secret |No need to integrate and onboard separately with NHS login. |No access to user information. |\n|[NHS login - separate authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-separate-authentication-and-authorisation) |OAuth 2.0 token exchange with signed JWT |Gives access to user information. |Need to integrate and onboard separately with NHS login. |\n\n## Errors\nWe use standard HTTP status codes to show whether an API request succeeded or not. They are usually in the range:\n\n* 200 to 299 if it succeeded, including code 202 if it was accepted by an API that needs to wait for further action\n* 400 to 499 if it failed because of a client error by your application\n* 500 to 599 if it failed because of an error on our server\n\nErrors specific to each API are shown in the Endpoints section, under Response. See our [reference guide](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#http-status-codes) for more on errors.\n\n## Open source\nYou might find the following [open source](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#open-source) resources useful:\n\n| Resource | Description | Links |\n|---------------------------|----------------------------------------------------------------------|--------------------------------------------------------------------------------|\n| PDS FHIR API | Source code for the API proxy, sandbox and specification. | [GitHub repo](https://github.com/NHSDigital/personal-demographics-service-api) |\n| FHIR libraries and SDKs | Various open source libraries for integrating with FHIR APIs. | [FHIR libraries and SDKs](https://digital.nhs.uk/developer/guides-and-documentation/api-technologies-at-nhs-digital#fhir-libraries-and-sdks) |\n| nhs-number | Python package containing utilities for NHS numbers including validity checks, normalisation and generation. | [GitHub repo](https://github.com/uk-fci/nhs-number) \\| [Python Package index](https://pypi.org/project/nhs-number/) \\| [Docs](https://nhs-number.uk-fci.tech/) |\n\nWe currently don't have any open source client libraries or sample code for this API. If you think this would be useful, you can [upvote the suggestion on our Interactive Product Backlog](https://nhs-digital-api-management.featureupvote.com/suggestions/107439/client-libraries-and-reference-implementations).\n\nThe source code for the PDS FHIR back end (the Core Spine source code) is not currently in the open. If you think this would be useful, you can [upvote the suggestion on our Interactive Product Backlog](https://nhs-digital-api-management.featureupvote.com/suggestions/466692/open-source-core-spine-including-pds-eps-scr-and-more).\n\n## Environments and testing\n\n| Environment | Base URL |\n| ----------------- | ---------------------------------------------------------------------- |\n| Sandbox | `https://sandbox.api.service.nhs.uk/personal-demographics/FHIR/R4/` |\n| Integration test | `https://int.api.service.nhs.uk/personal-demographics/FHIR/R4/` |\n| Production | `https://api.service.nhs.uk/personal-demographics/FHIR/R4/` |\n\n### Sandbox testing\nOur [sandbox environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#sandbox-testing):\n* is for early developer testing\n* only covers a limited set of scenarios\n* is stateless, so does not actually persist any updates\n* is open access, so does not allow you to test authorisation\n\nFor details of sandbox test scenarios, or to try out the sandbox using our 'Try this API' feature, see the documentation for each endpoint.\n\nAlternatively, you can try out the sandbox using our Postman collection:\n\n[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/14719036-953f067f-30b9-4552-8252-7cc10b21dad3)\n\n### Integration testing\nOur [integration test environment](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing):\n* is for formal integration testing\n* is stateful, so persists updates\n* includes authorisation, with options for user-restricted access (with or without [smartcards](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/nhs-smartcards-for-developers) and application-restricted access\n \nFor read-only testing, you can either use our [PDS FHIR API test data packs](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir/pds-fhir-api-test-data) or set up your own test data.\n\nTo test updating patient details, you must set up your own test data.\n\nFor more details see [integration testing with our RESTful APIs](https://digital.nhs.uk/developer/guides-and-documentation/testing#integration-testing-with-our-restful-apis).\n\n### Production smoke testing\nYou must not use real patient data for smoke testing in the production environment.\n\nRather, use our [production test patient](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir/pds-fhir-api-test-data#production-smoke-testing).\n\n## Onboarding\nYou need to get your software approved by us before it can go live with this API. We call this onboarding. The onboarding process can sometimes be quite long, so it’s worth planning well ahead.\n\nAs part of this process, you need to demonstrate your technical conformance to the requirements for this API. For more details according to your access mode, see:\n* [PDS FHIR API technical conformance - application-restricted access mode](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir/pds-fhir-technical-conformance---application-restricted-access-mode)\n* [PDS FHIR API technical conformance - healthcare worker access mode](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir/pds-fhir-technical-conformance---healthcare-worker-access-mode)\n\nYou also need to demonstrate that you can manage risks. This might impact the design of your software. For details, see [Onboarding support information](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir/onboarding-support-information).\n\nTo understand how our online digital onboarding process works, see [digital onboarding](https://digital.nhs.uk/developer/guides-and-documentation/digital-onboarding). \n\n
\n
\n
\n
\n \n \"\"\n \n
\n
\n
\n

To get started, sign in or create a developer account, then select 'product onboarding'.

\n
\n
\n
\n","contact":{"name":"Personal Demographics Service FHIR API Support","url":"https://digital.nhs.uk/developer/help-and-support","email":"ssd.nationalservicedesk@nhs.net"}},"servers":[{"url":"https://sandbox.api.service.nhs.uk/personal-demographics/FHIR/R4","description":"Sandbox environment."},{"url":"https://int.api.service.nhs.uk/personal-demographics/FHIR/R4","description":"Integration test environment."},{"url":"https://api.service.nhs.uk/personal-demographics/FHIR/R4","description":"Production environment."}],"paths":{"/Patient":{"parameters":[{"in":"header","name":"Authorization","description":"An [OAuth 2.0 bearer token](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis).\n\nRequired in all environments except sandbox.\n","required":false,"schema":{"type":"string","format":"^Bearer\\ [[:ascii:]]+$","example":"Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM"}},{"in":"header","name":"NHSD-Session-URID","description":"\nThe user role ID (URID) for the current session. Also known as a user role profile ID (URPID).\n\nThis header is optional.\n\nIn Application-restricted access mode this header is ignored.\n\nIn Healthcare worker access mode if you send this header it must be valid for the logged-in user. See [determine the user's role](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-cis2-separate-authentication-and-authorisation#step-9-determine-the-user-s-role) for guidance.\n","required":false,"schema":{"type":"string","pattern":"^[0-9]+$","example":"555254240100"}},{"in":"header","name":"X-Request-ID","required":false,"description":"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.\n\nMust be a universally unique identifier (UUID) (ideally version 4).\n\nMirrored back in a response header.\n\nIf you re-send a failed request, use the same value in this header.\n","schema":{"type":"string","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"}},{"in":"header","name":"X-Correlation-ID","required":false,"description":"An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding `.` characters.\n\nMirrored back in a response header.\n","schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"}},{"in":"header","name":"NHSD-End-User-Organisation-ODS","required":false,"description":"The ODS code of the user.\n\nMandatory for client applications which service multiple end user organisations (EUO). This will allow the calls to be attributed to the correct EUO.\n","schema":{"type":"string","example":"Y12345"}}],"get":{"summary":"Search for a patient","operationId":"search-patient","externalDocs":{"description":"ODS codes and documentation.","url":"https://fhir.nhs.uk/Id/ods-organization-code"},"description":"## Overview\nUse this endpoint to search for a patient in PDS.\n\nYou can search using various combinations of:\n * given name\n * family name\n * gender\n * postcode\n * date of birth - which can be a range\n * date of death - which can be a range\n * registered GP practice\n * email address\n * phone number\n\n \nThere are various search options, such as fuzzy search, exact match, history and wildcards.\n\nThe behaviour of this endpoint depends on which access mode you are using:\n\n| Access mode | Behaviour |\n| ------------------------------ | ------------------------------------------ |\n| Application-restricted access | Only a single unique match returned |\n| Healthcare worker access | Up to 50 matching patient records returned |\n| Patient access | Not yet available |\n\n## Search options\nThe following sections explain the various search options.\nWhich options you choose depends very much on your use case, and getting it right is really important.\nIf you need help, [contact us](https://digital.nhs.uk/developer/help-and-support).\n\n### Application-restricted access mode\nIn this access mode, you only get a single matching patient record, and only if it's a unique match.\n\nUse search options that are likely to find a unique match. In our experience, the following is a good starting point:\n * search on given name, family name, postcode and date of birth - this combination should uniquely identify a patient\n * for given name, use the first three characters and a wildcard, for example to search for `Annabel`, use `Ann*` - this caters for different name spellings and abbreviations\n * for postcode, use the first two characters and a wildcard, for example to search for `LS11 6AD`, use `LS*` - this caters for people who have moved locally but not updated PDS\n * use a non-fuzzy search - this reduces the chance of multiple matches\n * use a non-exact match - an exact match does not work with wildcards\n * include history - this increases the chance of a match\n\nFor more details, see the following sections.\n\n### Healthcare worker access mode\nIn this access mode - where the end user is a strongly authenticated healthcare worker - you can get up to 50 matching patient records.\nThis allows the end user to choose the best match.\n\nUse search parameters that are relevant to your use case - for example date of death is not always appropriate.\n\nTo protect patient privacy, design your search to minimise the number of matching patients.\nFor example, you could:\n * encourage users to enter as many search parameters as they can\n * force users to try a non-fuzzy search first and then only offer a fuzzy search if they cannot find the patient\n\nFor more details, see the following sections.\n\n### Non-fuzzy search\nA non-fuzzy search:\n * allows wildcards in names and postcodes\n * does not match homophones or transposed names\n * can optionally search history, such as previous names and addresses\n\nIt is less likely to return multiple matches than a fuzzy search, so is more suitable for finding a unique match.\n\nThe minimum search parameters are:\n * family name - which can include wildcards\n * date of birth - which can be a range\n\n \n### Fuzzy search\nA fuzzy search:\n * matches common homophones, such as `Smith` and `Smythe`, using the [Soundex](https://en.wikipedia.org/wiki/Soundex) algorithm\n * checks for transposed names, such as `Adam Thomas` and `Thomas Adam`\n * always searches history, such as previous names and addresses\n\nIt is more likely to include multiple matches than a non-fuzzy search, so is not ideal for finding a unique match.\n\nIt is also more likely to include false positives - other patients that match the search criteria.\nTherefore, for privacy reasons, it is better to use it only if a non-fuzzy match has failed.\n\nYou must use one of the following search parameter combinations:\n * given name, family name and date of birth\n * family name, date of birth, gender and postcode\n * given name, date of birth, gender and postcode\n\nIf you include the date of death or registered GP practice query parameters, they are not used in the search. However they do affect the patient's matching score - a mismatch reduces the returned score.\n\n### History\nPDS holds historic information, including previous names and addresses.\n\nA fuzzy search always includes history. For a non-fuzzy search, you can request to include history.\n\nSearching history can match patients when only a previous name or address is known, or if a patient provides a previous name or address on the assumption that their record hasn’t been updated. When a search done on historic data results in a match, the patient's current data will be returned in the response message, not the historic data used to identify the match.\n\n### Exact match\nYou can request an exact match.\nThis might be useful if you are verifying an NHS number against details you already believe to be correct.\nIt is unlikely to work well with wildcards or fuzzy search.\n\n### Names\nMatching names can be difficult due to:\n * multiple given names, such as in `Jane Anne Smith`\n * [compound given names](https://en.wikipedia.org/wiki/Given_name#Compound), such as in `John Paul Smith`\n * multiple or double-barrelled surnames, such as in `Michael Smith-Jones`\n * homophones, such as `Smith` and `Smythe` or `Ann` and `Anne`\n * abbreviated names, such as `Bob` instead of `Robert`\n * transposed names, such as `Adam Thomas` instead of `Thomas Adam`\n * previous names, such as maiden names\n * special characters such as in `O'Reilly`, `Jones-Smith` or `Kociński`\n * spelling mistakes, either in the search criteria or in PDS\n\nTo deal with some of these issues:\n * we search across all types of name - usual, nickname and temporary\n * a fuzzy search matches homophones, transposed names and previous names\n * for a non fuzzy search, you can optionally search previous names and use wildcards. Wildcards will match against the start of the name string, for example the start of a compound name.\n\n### Gender\nPDS has four options for gender - `male`, `female`, `other` and `unknown`.\nFor some people, the gender held in PDS might not match the gender they identify with.\n\nIn these cases, searching by gender might not find the patient.\nThese are edge cases but are important to consider because gender can be a sensitive issue for the people in question.\n\nIn general, we recommend not including gender as a search parameter.\n \n### Date of birth and death\nSometimes, the exact date of birth or death is not known when doing a search.\nSometimes, the date of birth or death is not accurate in PDS.\nFor example, if only the year of birth is known, the day and month of birth might be recorded as the first of January - for example, `01/01/1932`.\n\nIn such cases, searching a range of dates can help. This can result in multiple matches, so might not work well when searching for a unique match.\n\n### Postcode\nPeople sometimes move locally, meaning the postcode in PDS is out of date, but does at least match on the first two characters.\n\nSearching for the first two characters of the postcode and a wildcard can work well. For example, to search for `LS11 6AD`, use `LS*`.\nThis is only possible for a non-fuzzy search.\n\nThis can result in multiple matches, but it has been known to work well in some cases - even for unique matches.\n\n### General practitioner\nThis is an ODS code. If you use it, it must match exactly.\n\n### Phone number and email address\nIf you use phone number and/or email address, only exact matches will be returned.\n * Wildcards are not supported\n * Only current data will be searched, unless a history search is also requested in which case the match will take into account both current and historic data\n * Email addresses are not case-sensitive.\n\n## Patient data returned\nThe patient data returned on a search is not the full set of data that is returned on a retrieval by NHS number. The following data is included:\n* NHS number\n* names - usual, nickname and temporary\n* gender\n* birth information, apart from place of birth\n* death information\n* address - home address\n* contact details\n* registered GP\n* restricted patient flag\n\nThe following data is excluded:\n* place of birth\n* names, apart from usual, nickname and temporary \n* addresses, apart from home address\n* pharmacy details\n* communication details\n* contact preferences\n\n### Restricted patients\nSome patients are tagged as [restricted](https://digital.nhs.uk/services/demographics/restricting-access-to-a-patients-demographic-record) and are sometimes known as sensitive patients. When performing a search, restricted patients can be returned; however, location sensitive fields such as `address`, `telecom`, `contact` and `generalPractitioner` are removed.\n\nIf `address-postalcode`, `address-postcode`, or `general-practitioner` are included in the search parameters, no restricted patients are returned even if a match is identified.\n\nThe restricted flag can be found in the data under `meta/security` on the patient resource.\n\n### Invalidated patients\nSome patients are marked as invalidated in PDS - also known as `redacted` in FHIR terminology. Invalidated patient records are not returned in search results.\nIf an invalidated patient record has been superseded, the superseding record is returned.\n\n## Scoring\nEvery matched patient in the result list includes a score to indicate how closely the patient matched the search parameters.\n\nA score of 1.0 indicates an exact match. A score of less than 1.0 indicates a partial match.\n\nThe result list is sorted in descending score order - best match first.\n\nUse the `_exact-match` query parameter to return exact matches only - where the score is 1.0.\n\n## Clinical safety and privacy\nThis endpoint can return multiple matching patients for a given search, including partial matches.\n\nEnsure that you design your software to minimise the following risks:\n* an end user selects the wrong patient from the results presented, so there is a risk of clinical harm; for example due to retrieval of the wrong clinical data\n* the end user has access to patients’ personal data, so there is a risk to patient privacy\n\nNote that:\n* we record an access request in our audit trail for all patients matched in a PDS search\n* it is almost certainly a good idea to display search results in descending score order - best match first\n\nPlease consider the information your application returns to users. For example a patient's temporary address can be used to perform a successful search. The home address will be included in the response. For citizen facing services please be aware of this behaviour and do not present a different address to the patient, unless they are logged in at a sufficiently high proof point.\n\n## Sandbox testing\nYou can test the following scenarios in our sandbox environment:\n\n| Scenario | Request | Response |\n| ----------------------------------------| ----------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------------------------------------------------------------------|\n| Basic search with phone & email positive| `family`=`Smith`, `gender`=`female`, `birthdate`=`eq2010-10-22`, `email`=`jane.smith@example.com`, `phone`=`01632960587` | HTTP Status 200 with single search result. |\n| Basic search with phone & email negative| `family`=`Smith`, `gender`=`female`, `birthdate`=`eq2010-10-22`, `email`=`deb.trotter@example.com`, `phone`=`0121111111` | HTTP Status 200 with no search results\n| Wildcard search without phone/email | `family`=`Sm*`, `gender`=`female`, `birthdate`=`eq2010-10-22` | HTTP Status 200 with search result of two. |\n| Wildcard search with email and phone | `family`=`Sm*`, `gender`=`female`, `birthdate`=`eq2010-10-22`, `email`=`jane.smith@example.com`, `phone`=`01632960587` | HTTP Status 200 with single search result. |\n| Search with limited results | `family`=`Sm*`, `gender`=`female`, `birthdate`=`eq2010-10-22`, `email`=`jane.smith@example.com`, `phone`=`01632960587`, `_max-results`=`1` | HTTP Status 200 with single search result. |\n| Search with date range | `family`=`Smith`, `gender`=`female`, `birthdate`=`ge2010-10-21`, `birthdate`=`le2010-10-23`, `email`=`jane.smith@example.com`, `phone`=`01632960587` | HTTP Status 200 with single search result. |\n| Fuzzy search with phone and email | `family`=`Smith`, `given`=`Jane`, `gender`=`female`, `birthdate`=`eq2010-10-22`, `email`=`jane.smith@example.com`, `phone`=`01632960587`, `_fuzzy-match`=`true` | HTTP Status 200 with single search result. |\n| Fuzzy search without phone or email | `family`=`Smith`, `given`=`Jane`, `gender`=`female`, `birthdate`=`eq2010-10-22` | HTTP Status 200 with search result of two.\n| Restricted patient search | `family`=`Smythe`, `given`=`Janet`, `gender`=`female`, `birthdate`=`eq2005-06-16`, `email`=`janet.smythe@example.com`, `phone`=`01632960587` | HTTP Status 200 with single search result with restricted data omitted. |\n| Compound name search | `family`=`Smith`, `given`=`John Paul`, `given`=`James`, `gender`=`female`, `birthdate`=`eq2010-10-22`, `email`=`johnp.smith@example.com`, `phone`=`01632960587` | HTTP Status 200 with single search result. |\n| Unsuccessful search | Any other valid search query parameters | HTTP Status 200 with no search results |\n| Valid/invalid search criteria | `family`=`Sm*`, `gender`=`female`, 'invalidParam'='123', `birthdate`=`eq2010-10-22`, `email`=`j.smith@example.com`, `phone`=`0163` | HTTP Status 400 with problem description |\n| Unsuccessful search on email/phone only | `email`=`j.smith@example.com`, `phone`=`0163` | HTTP Status 400 with problem description |\n| Invalid date format | `birthdate` or `death-date` query parameters with values not in format `YYYY-MM-DD` | HTTP Status 400 with problem description |\n| Too few search parameters | Any invalid combination of query parameters | HTTP Status 400 with problem description |\n| Missing X-Request-ID | `id`=`9000000009` (or any other valid NHS number) | HTTP Status 412 with problem description |\n\nYou can try out the sandbox using the 'Try this API' feature on this page.\n\nAlternatively, you can try out the sandbox using our Postman collection:\n\n\n[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/a1ce1b055839caa384a8?action=collection%2Fimport)\n","parameters":[{"name":"_fuzzy-match","description":"A fuzzy search is performed, including checks for homophones, transposed names and historic information.\n\nYou cannot use wildcards with a fuzzy search.\n","example":false,"in":"query","required":false,"schema":{"type":"boolean","default":false}},{"name":"_exact-match","description":"The search only returns results where the `score` field is 1.0. Use this with care - it is unlikely to work with fuzzy search or wildcards.","example":false,"in":"query","required":false,"schema":{"type":"boolean","default":false}},{"name":"_history","description":"The search looks for matches in historic information such as previous names and addresses.\n\nThis parameter has no effect for a fuzzy search, which always includes historic information.\n","example":true,"in":"query","required":false,"schema":{"type":"boolean","default":false}},{"name":"_max-results","description":"The maximum number of matching patients to return. For healthcare worker access, this must be between 1 and 50, and the default is 50.\nFor application-restricted access, this must be 1, and the default is 1.\nIf too many patients match the search criteria, we return a `TOO_MANY_MATCHES` error.\n","example":1,"in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"family","description":"The patient's family name (surname).\n\nNot case sensitive. Max 35 characters.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n","examples":{"simple":{"value":"Smith","summary":"Matches Smythe if `_fuzzy-match` is specified."},"wildcarded":{"value":"Sm*t*","summary":"Wildcards must contain at least two characters, this matches Smith, Smythe"}},"in":"query","required":false,"schema":{"type":"string"}},{"name":"given","description":"The patient's given names.\n\nNot case sensitive. Max 35 characters.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nWildcard searches will match the start of the first given name and not subsequent given names, for example the given names \"Alan Michael\" can be searched with \"Ala*\" but not \"Mic*\".\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n\nA patient may have more than one given name. Subsequent given names are commonly referred to as 'middle names'.\nSpecify multiple given names by repeating this parameter.\nTo search for `Jane Anne Smith` use `given=Jane&given=Anne&family=Smith`.\n\nThe first given name may be a [compound name](https://en.wikipedia.org/wiki/Given_name#Compound), for example `John Paul`.\nTo search for `John Paul James Smith` (where `John Paul` is the first given name, `James` is the second given name, and `Smith` the family name) use `given=John%20Paul&given=James&family=Smith`.\n\nNote that it is not necessary to specify subsequent given (middle) names, and that doing so may impact your search results in the case they are not recorded in the demographics system.\n","example":"Jane","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}}},{"name":"gender","description":"Gender with which the patient most strongly identifies.","example":"female","in":"query","required":false,"schema":{"type":"string","enum":["male","female","other","unknown"],"example":"female"}},{"name":"birthdate","in":"query","description":"Date of birth in the format `yyyy-mm-dd`. To specify a range, use `birthdate=geyyyy-mm-dd&birthdate=leyyyy-mm-dd`.","examples":{"simple":{"value":["eq2010-10-22"],"description":"Exact match date"},"rangege":{"value":["ge2010-10-22"],"description":"Greater than or equals match, which matches 2010-10-22 or 2010-10-23"},"rangele":{"value":["le2010-10-22"],"description":"Less than or equals match, which matches 2010-10-22 or 2010-10-21"}},"required":false,"schema":{"type":"array","items":{"type":"string"}}},{"name":"death-date","in":"query","description":"Date of death in the format `yyyy-mm-dd`. To specify a range, use `death-date=geyyyy-mm-dd&death-date=leyyyy-mm-dd`.\n\nFor a fuzzy search, this is ignored for matching but included in the score calculation.\n","examples":{"simple":{"value":"eq2010-10-22","description":"Exact match date"},"rangege":{"value":"ge2010-10-22","description":"Greater than or equals match which matches 2010-10-22 or 2010-10-23"},"rangele":{"value":"le2010-10-22","description":"Less than or equals match, which matches 2010-10-22 or 2010-10-21"}},"required":false,"schema":{"type":"string","format":"date"}},{"name":"address-postalcode","description":"The postcode of any of the patient’s known addresses.\n\nNot case sensitive.\nSpaces are ignored, for example `LS16AE` and `LS1 6AE` both match `LS1 6AE`.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n","examples":{"simple":{"value":"LS1 6AE","summary":"Spaces ignored, would match LS16AE"},"wildcarded":{"value":"LS1*","summary":"Matches 'LS16AE', 'LS1 6AE' and 'LS1 6AB'"}},"in":"query","required":false,"schema":{"type":"string"}},{"name":"address-postcode","description":"**N.B. that address-postcode will be deprecated in the future, address-postalcode should be used instead. \nIf both address-postcode and address-postalcode are provided, an INVALID_SEARCH_DATA error will be returned.**\nThe postcode of any of the patient’s known addresses.\n\nNot case sensitive.\nSpaces are ignored, for example `LS16AE` and `LS1 6AE` both match `LS1 6AE`.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n","examples":{"simple":{"value":"LS1 6AE","summary":"Spaces ignored, would match LS16AE"},"wildcarded":{"value":"LS1*","summary":"Matches 'LS16AE', 'LS1 6AE' and 'LS1 6AB'"}},"in":"query","required":false,"schema":{"type":"string"}},{"name":"general-practitioner","description":"The Organisation Data Service (ODS) code of the patient's registered GP practice.\n\nNot case sensitive.\nFor a fuzzy search, this is ignored for matching but included in the score calculation.\n","example":"Y12345","in":"query","required":false,"schema":{"type":"string"}},{"name":"email","description":"Email address\n","example":"jane.smith@example.com","in":"query","required":false,"schema":{"type":"string"}},{"name":"phone","description":"Phone number\n","example":"01632960587","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"A completed search. This might contain zero, one or many matching patients, or it might contain a 'TOO_MANY_MATCHES' error.\n","headers":{"X-Correlation-Id":{"schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"},"description":"The X-Correlation-ID from the request header, if supplied, mirrored back.\n"},"X-Request-Id":{"schema":{"type":"string","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"},"description":"The X-Request-ID from the request header, if supplied, mirrored back.\n"}},"content":{"application/fhir+json":{"schema":{"type":"object","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"Bundle"},"type":{"type":"string","description":"FHIR Bundle Type.","default":"searchset"},"timestamp":{"type":"string","description":"Time the search was performed.","format":"datetime","example":"2019-12-25T12:00:00+00:00"},"total":{"type":"integer","description":"Number of resources returned in search.","example":1},"entry":{"type":"array","description":"A list of matched patients. Empty if none found. The patients are ordered by match score, best first. A maximum of 50 patients are returned.\n","items":{"type":"object","properties":{"fullUrl":{"type":"string","description":"Absolute URL of the resource described in this item.","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/9000000009"},"search":{"type":"object","properties":{"score":{"description":"Search score from 0.0 to 1.0.","type":"number","minimum":0,"maximum":1,"example":0.75}}},"resource":{"type":"object","additionalProperties":false,"properties":{"resourceType":{"type":"string","description":"FHIR resource type.","default":"Patient"},"id":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"identifier":{"type":"array","description":"Identifier and system of identification used for this Patient.","items":{"type":"object","maxItems":1,"required":["value"],"properties":{"system":{"type":"string","format":"url","description":"System identifier belongs to.","default":"https://fhir.nhs.uk/Id/nhs-number"},"value":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"extension":{"type":"array","description":"FHIR extensions.","items":{"type":"object","description":"Status indicating if NHS number is present and verified.","properties":{"url":{"type":"string","description":"URL of the extension definition.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus"]},"valueCodeableConcept":{"type":"object","description":"NHS Number Verification Status Indicator.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"01"},"display":{"type":"string","description":"Representation defined by the system.","example":"Number present and verified"}}}}}}}}}}}},"meta":{"type":"object","description":"Metadata about this resource.","properties":{"versionId":{"type":"string","description":"The NHS England assigned version of the patient resource.","example":"2"},"security":{"type":"array","description":"The level of security on the patients record, which affects which fields are populated on retrieval. The possible responses are:\n* U - unrestricted. All available data is returned.\n* R - restricted. Any sensitive data around the patient's location, so `address`, `generalPractitioner` and `telecom`, are removed from the response.\n* REDACTED - redacted. The patient record has been marked as invalid, so the data should not be used. This code is never returned; you receive a 404, and appropriate error response, if an invalidated patient retrieval is attempted.\n","maxItems":1,"items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the value set specification.","example":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality"},"code":{"type":"string","description":"Code defined by the system value set.","enum":["U","R","V","REDACTED"],"example":"U"},"display":{"type":"string","description":"Representation defined by the system.","enum":["unrestricted","restricted","redacted"],"example":"unrestricted"}}}}}},"name":{"type":"array","description":"List of names associated with the patient.\nThis is only fully populated on a retrieval or a successful update, only the `usual`, `nickname` and `temp` names are returned on a search. \n","minItems":1,"items":{"type":"object","required":["use","family"],"additionalProperties":false,"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"123"},"use":{"type":"string","description":"How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval.\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n","enum":["usual","temp","nickname","old","maiden"],"example":"usual"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"given":{"type":"array","maxItems":5,"description":"Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n","example":["Jane Marie Anne","Jo","Adele"],"items":{"type":"string","maxLength":35,"example":"Jane"}},"family":{"type":"string","maxLength":35,"description":"Family name (often called Surname).","example":"Smith"},"prefix":{"type":"array","description":"Name prefixes, titles, and prenominals.","example":["Mrs"],"items":{"type":"string","example":"Mrs"}},"suffix":{"type":"array","description":"Name suffices and postnominals.","example":["MBE","PhD"],"items":{"type":"string","example":"MBE"}}}}},"gender":{"type":"string","description":"Classification of the gender of a patient. The classification is phenotypical rather than genotypical, i.e. it does not provide codes for medical or scientific purposes.\nIt is the administrative gender that the patient wishes to be known as. In some cases, this may not be the same as the patient’s registered birth gender, or their current clinical gender.\n","enum":["male","female","other","unknown"],"example":"female"},"birthDate":{"description":"The date on which the patient was born or is officially deemed to have been born.\n\nIt is a date in the format `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned. \n","example":"2010-10-22","type":"string","format":"date"},"multipleBirthInteger":{"type":"integer","minimum":1,"maximum":9,"description":"The order in which the patient was born, with 1 indicating the first or only birth in the sequence, 2 indicating the second birth in the sequence, 3 indicating the third, and so on up to 7.\n\nThere are two other valid values; `8` meaning `Not applicable` and `9` meaning `Not known`.\n","example":1},"deceasedDateTime":{"description":"The date and time on which a person died or is officially deemed to have died, if applicable and known.\n\nIt is a datetime in the format `yyyy-mm-ddTHH:MM:SS+HH:MM` or `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned.\n","example":"2010-10-22T00:00:00+00:00","type":"string","format":"date-time","pattern":"^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$"},"address":{"type":"array","description":"List of addresses associated with the patient.\n\nThis is only fully populated on a retrieval or a successful update, only the `home` address is returned on a search.\nWhen a patient tagged as `restricted` is retrieved, all addresses are removed from the response.\n","items":{"type":"object","description":"An address associated with the patient.","required":["use"],"properties":{"id":{"type":"string","description":"Unique system identifier for this address.","example":"456"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"use":{"type":"string","description":"Purpose of this address:\n * `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n * `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n * `billing` - an address used for correspondence purposes only\n * `work` - an office address. This can be returned due to legacy data but cannot be added or replaced on update\n\n A patient should have no more than one current `temp` and/or `billing` address.\n However, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\n Where multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (e.g. by examining period dates).\n\n A `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\n However additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\n When sending correspondence to a patient:\n *\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and end dates.\n *\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and end dates.\n * if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n","enum":["home","work","temp","billing"],"example":"home"},"text":{"type":"string","description":"Where a `temp` address is provided a descriptor text must be sent.\nThe list of possible values are:\n* `Second Home` - a patient's second home\n* `Student Accommodation` - a patient's place of residence while at university\n* `Respite Care Address` - where the patient resides during respite care\n* `Temporary Residence Address` - where the patient resides for a specific period of time\n* `Convalescence Home` - the address for a patient during a period of recovery\n* `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n* `Holiday Home` - the address for a patient during a holiday\n\nA patient can also register temporarily at a GP practice using a temporary address. Temporary GP registration information does not appear on the PDS, but the address used for it may.\n","enum":["Second Home","Student Accommodation","Respite Care Address","Temporary Residence Address","Convalescence Home","Mobile Home","Holiday Home"],"example":"Student Accommodation"},"line":{"type":"array","description":"All lines of the address except the postal code.\n\nSystems must apply the following formatting convention when adding or replacing addresses lines:\n*\tline 1 - premises ID and/or house name, e.g. `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, e.g. `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), e.g. `Boxgrove`\n*\tline 4 - post town, e.g. `Leeds`\n*\tline 5 - county (if present), e.g. `West Yorkshire`\n\nIf any of the lines are blank, they are not returned due to FHIR conformance constraints.\n","maxItems":5,"items":{"type":"string"},"example":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"]},"postalCode":{"type":"string","description":"Postal code of the address.","example":"LS1 6AE"},"extension":{"type":"array","description":"List of address keys formatted as a FHIR extension. This can include up to one Unique Property Reference Number (UPRN), and up to one Postal Address File (PAF) key. If no keys for the address are known, the array will be empty. Otherwise it will be a list of objects which specify the value of the address key and the code system for it","items":{"anyOf":[{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'PAF'.","enum":["PAF"],"example":"PAF"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in PAF format. An 8 digit number including leading zeroes, formatted as a string.","minLength":8,"maxLength":8,"pattern":"^[0-9]{8}$","example":"12345678"}}}]}}}},{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'UPRN'.","enum":["UPRN"],"example":"UPRN"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in UPRN format. A number containing from 1 up to 12 digits.","minLength":1,"maxLength":12,"pattern":"^[0-9]{1,12}$","example":"123456789012"}}}]}}}}]}}}}},"telecom":{"type":"array","description":"List of contact points for the patient; for example, phone numbers or email addresses.\nWhen a patient tagged as `restricted` is retrieved, all contact points are removed from the response.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}},"contact":{"type":"array","description":"A list of patient contacts. Only emergency contacts are returned. Any other contacts are returned on the patients `Related Person`.\nWhen a patient tagged as `restricted` is retrieved, all contacts are removed from the response.\n","items":{"title":"Schema for a patient contact.","type":"object","additionalProperties":false,"required":["relationship","telecom"],"properties":{"id":{"type":"string","example":"C123"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"relationship":{"type":"array","description":"The contact relationship wrapper object that holds the details of the relationship to the patient.\n\nThis is only returned when an Emergency Contact number has been set on `telecom`. The only valid code is `C`, which means `Emergency Contact`.\n","minItems":1,"maxItems":1,"items":{"type":"object","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one contact relationship.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","format":"url","default":"http://terminology.hl7.org/CodeSystem/v2-0131"},"code":{"type":"string","description":"Coded value for contact relationship.","example":"C"},"display":{"type":"string","description":"Display-friendly representation of the contact relationship code.","example":"Emergency Contact"}}}}}}},"telecom":{"type":"array","description":"List of Telecom objects on the contact only contains `system` and `value`.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}}}}},"generalPractitioner":{"type":"array","maxItems":1,"description":"General Practice (not practitioner) with which the patient is, or was, registered. Always contains zero or one general practitioner object.\nWhen a patient tagged as `restricted` is retrieved, the General Practice is removed from the response.\n","items":{"description":"General practice (not practitioner) with which the patient is or was registered.","type":"object","required":["identifier"],"properties":{"id":{"description":"Object identifier (OID) specific to the returned details - this should be return exactly the same in any update.","type":"string","example":"254406A3"},"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}}},"extension":{"type":"array","description":"Wrapper array for the patient's death notification status; this is a FHIR extension. Always contains zero or one death notification status object.\n","items":{"anyOf":[{"type":"object","description":"Wrapper object for death notification details.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of death notification extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus"]},"extension":{"type":"array","description":"Array containing exactly one death notification status code object and exactly one effective date object.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for death notification status code.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `deathNotificationStatus`.","default":"deathNotificationStatus","enum":["deathNotificationStatus"]},"valueCodeableConcept":{"type":"object","description":"Death Notification Status.","properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["system","code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol, in syntax, defined by the system:\n* `1` - Informal - death notice received via an update from a local NHS Organisation such as GP or Trust\n* `2` - Formal - death notice received from Registrar of Deaths. Only these endpoints are allowed to add a Formal death:\n - National Back Office using the Demographic Spine Application (DSA)\n - Office of National Statistics (ONS)\n - Maternity sites\n* `U` - Removed. This is a possible response, but it cannot be used on an update because Spine will reject it\n","example":"2","enum":["1","2","U"]},"display":{"type":"string","description":"Representation defined by the system.","example":"Formal - death notice received from Registrar of Deaths","enum":["Informal - death notice received via an update from a local NHS Organisation such as GP or Trust","Formal - death notice received from Registrar of Deaths","Removed"]}}}}}}}},{"type":"object","description":"Wrapper object for death notification effective date.","required":["url","valueDateTime"],"properties":{"url":{"type":"string","description":"Key of this object. Always `systemEffectiveDate`.","default":"systemEffectiveDate","enum":["systemEffectiveDate"]},"valueDateTime":{"type":"string","description":"Date and time at which death notification status took effect.","format":"date-time","example":"2010-10-22T00:00:00+00:00"}}}]}}}}]}}}}}}}}},"example":{"resourceType":"Bundle","type":"searchset","timestamp":"2019-12-25T12:00:00+00:00","total":1,"entry":[{"fullUrl":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/9000000009","search":{"score":0.75},"resource":{"resourceType":"Patient","id":"9000000009","identifier":[{"system":"https://fhir.nhs.uk/Id/nhs-number","value":"9000000009","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus","version":"1.0.0","code":"01","display":"Number present and verified"}]}}]}],"meta":{"versionId":"2","security":[{"system":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality","code":"U","display":"unrestricted"}]},"name":[{"id":"123","use":"usual","period":{"start":"2020-01-01","end":"2021-12-31"},"given":["Jane"],"family":"Smith","prefix":["Mrs"],"suffix":["MBE"]}],"gender":"female","birthDate":"2010-10-22","multipleBirthInteger":1,"deceasedDateTime":"2010-10-22T00:00:00+00:00","address":[{"id":"456","period":{"start":"2020-01-01","end":"2021-12-31"},"use":"home","line":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"],"postalCode":"LS1 6AE","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"PAF"}},{"url":"value","valueString":"12345678"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"UPRN"}},{"url":"value","valueString":"123456789012"}]}]}],"telecom":[{"id":"789","period":{"start":"2020-01-01","end":"2021-12-31"},"system":"phone","value":"01632960587","use":"home"},{"id":"790","period":{"start":"2019-01-01","end":"2022-12-31"},"system":"email","value":"jane.smith@example.com","use":"home"},{"id":"OC789","period":{"start":"2020-01-01","end":"2021-12-31"},"system":"other","value":"01632960587","use":"home","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem","code":"textphone","display":"Minicom (Textphone)"}}]}],"contact":[{"id":"C123","period":{"start":"2020-01-01","end":"2021-12-31"},"relationship":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0131","code":"C","display":"Emergency Contact"}]}],"telecom":[{"system":"phone","value":"01632960587"}]}],"generalPractitioner":[{"id":"254406A3","type":"Organization","identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345","period":{"start":"2020-01-01","end":"2021-12-31"}}}],"extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","extension":[{"url":"deathNotificationStatus","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus","version":"1.0.0","code":"2","display":"Formal - death notice received from Registrar of Deaths"}]}},{"url":"systemEffectiveDate","valueDateTime":"2010-10-22T00:00:00+00:00"}]}]}}]}}}},"4XX":{"description":"An error occurred as follows:\n\n| HTTP status | Error code | Description |\n| ----------- | -------------------------- | --------------------------------------------- |\n| 200 | TOO_MANY_MATCHES | Too many matches were found - user should be told to refine their search parameters.\t|\n| 400 | INVALID_SEARCH_DATA\t | Invalid combination of search parameters. For details, see the `diagnostics` field. |\n| 400 | UNSUPPORTED_SERVICE | No search parameters provided. |\n| 400 | MISSING_VALUE | Missing header or query parameter. For details, see the `diagnostics` field. |\n| 400 | INVALID_VALUE | Invalid header or query parameter. For details, see the `diagnostics` field. |\n| 400 | ADDITIONAL_PROPERTIES | Unrecognised query parameter. For details, see the `diagnostics` field. |\n| 401 | ACCESS_DENIED | Access token missing, invalid or expired, or calling application not configured for this operation. |\n| 403 | INVALID_VALUE | Multiple results requested when using the API in application-restricted mode. |\n| 408 | UNABLE_TO_CALL_SERVICE | The downstream domain processing has not completed within the configured timeout period. |\n| 429 | TOO_MANY_REQUESTS | You have exceeded your application's [rate limit](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#rate-limits). |\n","content":{"application/fhir+json":{"schema":{"type":"object","description":"Outcome of an operation that does not result in a resource or bundle being returned, for example an error or an async/batch submission.\nThere are a number of possible error codes that can be returned along with a more detailed description in the `display` field.\n","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"OperationOutcome"},"issue":{"type":"array","description":"List of issues that have occurred.","minItems":1,"items":{"type":"object","required":["severity","code"],"properties":{"severity":{"type":"string","enum":["fatal","error","warning","information"],"description":"Severity of the error.","example":"error"},"code":{"type":"string","description":"FHIR error code.","example":"invalid","enum":["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"]},"details":{"type":"object","description":"Internal error code.","properties":{"coding":{"type":"array","items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"INVALID_VALUE"},"display":{"type":"string","description":"Representation defined by the system.","example":"Provided value is invalid"}}}}}},"diagnostics":{"type":"string","description":"Additional diagnostic information about the issue. This information is subject to change.","example":"Invalid value - 2019-01 in field 'birthDate'"},"expression":{"type":"string","description":"FHIRPath of element(s) related to the error.","example":"Patient.name.given"}}}}}},"example":{"resourceType":"OperationOutcome","issue":[{"severity":"error","code":"value","details":{"coding":[{"system":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode","version":"1","code":"INVALID_VALUE","display":"Provided value is invalid"}]},"diagnostics":"Invalid value - 'mal' in field 'gender'"}]}}}}}}},"/Patient/{id}":{"parameters":[{"name":"id","in":"path","description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","required":true,"schema":{"type":"string","example":"9000000009"}},{"in":"header","name":"Authorization","description":"An [OAuth 2.0 bearer token](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis).\n\nRequired in all environments except sandbox.\n","required":false,"schema":{"type":"string","format":"^Bearer\\ [[:ascii:]]+$","example":"Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM"}},{"in":"header","name":"NHSD-Session-URID","description":"\nThe user role ID (URID) for the current session. Also known as a user role profile ID (URPID).\n\nThis header is optional.\n\nIn Application-restricted access mode this header is ignored.\n\nIn Healthcare worker access mode if you send this header it must be valid for the logged-in user. See [determine the user's role](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-cis2-separate-authentication-and-authorisation#step-9-determine-the-user-s-role) for guidance.\n","required":false,"schema":{"type":"string","pattern":"^[0-9]+$","example":"555254240100"}},{"in":"header","name":"X-Request-ID","required":false,"description":"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.\n\nMust be a universally unique identifier (UUID) (ideally version 4).\n\nMirrored back in a response header.\n\nIf you re-send a failed request, use the same value in this header.\n","schema":{"type":"string","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"}},{"in":"header","name":"X-Correlation-ID","required":false,"description":"An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding `.` characters.\n\nMirrored back in a response header.\n","schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"}},{"in":"header","name":"NHSD-End-User-Organisation-ODS","required":false,"description":"The ODS code of the user.\n\nMandatory for client applications which service multiple end user organisations (EUO). This will allow the calls to be attributed to the correct EUO.\n","schema":{"type":"string","example":"Y12345"}}],"get":{"description":"## Overview\nUse this endpoint to get patient details from PDS for a given NHS number.\n\nYou cannot get a patient's related people details, use the RelatedPerson endpoint instead.\n\n## Superseded patients\nSome patients are marked as superseded, this means that for some reason the original resource is no longer valid and has been replaced with a different resource.\n\nOn retrieval of a superseded resource, the new resource is automatically returned in place of the requested resource. You can spot a superseded resource when the `id` is not the same as the one requested.\n\nWhen retrieving a superseding resource you must update your system with the new resource and remove the superseded resource, ensuring that the same `id` does not exist against another resource in your system.\n\n## Restricted patients\nSome patients are tagged as [restricted](https://digital.nhs.uk/services/demographics/restricting-access-to-a-patients-demographic-record) and are sometimes known as sensitive patients. Restricted patients can be retrieved; however, location sensitive fields such as `address`, `telecom` and `generalPractitioner` are removed.\n\nThe restricted flag can be found in the data under `meta/security` on the patient resource.\n\n## Sandbox test scenarios\nYou can test the following scenarios in our sandbox environment:\n\n| Scenario | Request | Response |\n| -------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |\n| Patient exists | `id`=`9000000009` | HTTP Status 200 with patient data in response |\n| Sensitive patient exists | `id`=`9000000025` | HTTP Status 200 with patient data in response with the restricted data removed |\n| Patient exists with minimal data | `id`=`9000000033` | HTTP Status 200 with patient data in response, there will be very little data so can be used as an example of a patient with bad data quality |\n| Patient does not exist | `id`=`9111231130` (or any other valid NHS number) | HTTP Status 404 with problem description |\n| Invalid NHS number | `id`=`9000000000` (or any invalid NHS number) | HTTP Status 400 with problem description |\n| Missing X-Request-ID | `id`=`9000000009` (or any other valid NHS number) | HTTP Status 412 with problem description |\n\nYou can try out the sandbox using the 'Try this API' feature on this page.\n\nAlternatively, you can try out the sandbox using our Postman collection:\n\n[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/14719036-953f067f-30b9-4552-8252-7cc10b21dad3)\n","summary":"Get patient details","operationId":"get-patient","responses":{"200":{"description":"Information successfully returned.","headers":{"ETag":{"schema":{"type":"string","pattern":"^W/\"[0-9]+\"$","example":"W/\"2\""},"description":"Record version identifier enclosed in quotes and preceded by 'W/'. For example, `W/\"2\"`.\n\nCorresponds to `meta.versionId` attribute in the patient resource body.\n\nWhen you retrieve a patient resource, you get a version number for the resource (in the `ETag` response header and in the `versionId` field in the response).\nYou must then pass the resource's version number in any update request (in the `If-Match` response header) made for the patient.\n"},"X-Correlation-Id":{"schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"},"description":"The X-Correlation-ID from the request header, if supplied, mirrored back.\n"},"X-Request-Id":{"schema":{"type":"string","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"},"description":"The X-Request-ID from the request header, if supplied, mirrored back.\n"}},"content":{"application/fhir+json":{"schema":{"type":"object","required":["id"],"additionalProperties":false,"properties":{"resourceType":{"type":"string","description":"FHIR resource type.","default":"Patient"},"id":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"identifier":{"type":"array","description":"Identifier and system of identification used for this Patient.","items":{"type":"object","maxItems":1,"required":["value"],"properties":{"system":{"type":"string","format":"url","description":"System identifier belongs to.","default":"https://fhir.nhs.uk/Id/nhs-number"},"value":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"extension":{"type":"array","description":"FHIR extensions.","items":{"type":"object","description":"Status indicating if NHS number is present and verified.","properties":{"url":{"type":"string","description":"URL of the extension definition.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus"]},"valueCodeableConcept":{"type":"object","description":"NHS Number Verification Status Indicator.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"01"},"display":{"type":"string","description":"Representation defined by the system.","example":"Number present and verified"}}}}}}}}}}}},"meta":{"type":"object","description":"Metadata about this resource.","properties":{"versionId":{"type":"string","description":"The NHS England assigned version of the patient resource.","example":"2"},"security":{"type":"array","description":"The level of security on the patients record, which affects which fields are populated on retrieval. The possible responses are:\n* U - unrestricted. All available data is returned.\n* R - restricted. Any sensitive data around the patient's location, so `address`, `generalPractitioner` and `telecom`, are removed from the response.\n* REDACTED - redacted. The patient record has been marked as invalid, so the data should not be used. This code is never returned; you receive a 404, and appropriate error response, if an invalidated patient retrieval is attempted.\n","maxItems":1,"items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the value set specification.","example":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality"},"code":{"type":"string","description":"Code defined by the system value set.","enum":["U","R","V","REDACTED"],"example":"U"},"display":{"type":"string","description":"Representation defined by the system.","enum":["unrestricted","restricted","redacted"],"example":"unrestricted"}}}}}},"name":{"type":"array","description":"List of names associated with the patient. \n","minItems":1,"items":{"type":"object","required":["use","family"],"additionalProperties":false,"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"123"},"use":{"type":"string","description":"How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval.\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n","enum":["usual","temp","nickname","old","maiden"],"example":"usual"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"given":{"type":"array","maxItems":5,"description":"Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n","example":["Jane Marie Anne","Jo","Adele"],"items":{"type":"string","maxLength":35,"example":"Jane"}},"family":{"type":"string","maxLength":35,"description":"Family name (often called Surname).","example":"Smith"},"prefix":{"type":"array","description":"Name prefixes, titles, and prenominals.","example":["Mrs"],"items":{"type":"string","example":"Mrs"}},"suffix":{"type":"array","description":"Name suffices and postnominals.","example":["MBE","PhD"],"items":{"type":"string","example":"MBE"}}}}},"gender":{"type":"string","description":"Classification of the gender of a patient. The classification is phenotypical rather than genotypical, i.e. it does not provide codes for medical or scientific purposes.\nIt is the administrative gender that the patient wishes to be known as. In some cases, this may not be the same as the patient’s registered birth gender, or their current clinical gender.\n","enum":["male","female","other","unknown"],"example":"female"},"birthDate":{"description":"The date on which the patient was born or is officially deemed to have been born.\n\nIt is a date in the format `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned. \n","example":"2010-10-22","type":"string","format":"date"},"multipleBirthInteger":{"type":"integer","minimum":1,"maximum":9,"description":"The order in which the patient was born, with 1 indicating the first or only birth in the sequence, 2 indicating the second birth in the sequence, 3 indicating the third, and so on up to 7.\n\nThere are two other valid values; `8` meaning `Not applicable` and `9` meaning `Not known`.\n","example":1},"deceasedDateTime":{"description":"The date and time on which a person died or is officially deemed to have died, if applicable and known.\n\nIt is a datetime in the format `yyyy-mm-ddTHH:MM:SS+HH:MM` or `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned.\n","example":"2010-10-22T00:00:00+00:00","type":"string","format":"date-time","pattern":"^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$"},"address":{"type":"array","description":"List of addresses associated with the patient.\n\nThese are fully populated on a retrieval or a successful update, only the `home` address is returned on a search.\nWhen a patient tagged as `restricted` is retrieved, all addresses are removed from the response.\n","items":{"type":"object","description":"An address associated with the patient.","required":["use"],"properties":{"id":{"type":"string","description":"Unique system identifier for this address.","example":"456"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"use":{"type":"string","description":"Purpose of this address:\n * `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n * `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n * `billing` - an address used for correspondence purposes only\n * `work` - an office address. This can be returned due to legacy data but cannot be added or replaced on update\n\n A patient should have no more than one current `temp` and/or `billing` address.\n However, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\n Where multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (e.g. by examining period dates).\n\n A `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\n However additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\n When sending correspondence to a patient:\n *\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and end dates.\n *\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and end dates.\n * if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n","enum":["home","work","temp","billing"],"example":"home"},"text":{"type":"string","description":"Where a `temp` address is provided a descriptor text must be sent.\nThe list of possible values are:\n* `Second Home` - a patient's second home\n* `Student Accommodation` - a patient's place of residence while at university\n* `Respite Care Address` - where the patient resides during respite care\n* `Temporary Residence Address` - where the patient resides for a specific period of time\n* `Convalescence Home` - the address for a patient during a period of recovery\n* `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n* `Holiday Home` - the address for a patient during a holiday\n\nA patient can also register temporarily at a GP practice using a temporary address. Temporary GP registration information does not appear on the PDS, but the address used for it may.\n","enum":["Second Home","Student Accommodation","Respite Care Address","Temporary Residence Address","Convalescence Home","Mobile Home","Holiday Home"],"example":"Student Accommodation"},"line":{"type":"array","description":"All lines of the address except the postal code.\n\nSystems must apply the following formatting convention when adding or replacing addresses lines:\n*\tline 1 - premises ID and/or house name, e.g. `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, e.g. `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), e.g. `Boxgrove`\n*\tline 4 - post town, e.g. `Leeds`\n*\tline 5 - county (if present), e.g. `West Yorkshire`\n\nIf any of the lines are blank, they are not returned due to FHIR conformance constraints.\n","maxItems":5,"items":{"type":"string"},"example":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"]},"postalCode":{"type":"string","description":"Postal code of the address.","example":"LS1 6AE"},"extension":{"type":"array","description":"List of address keys formatted as a FHIR extension. This can include up to one Unique Property Reference Number (UPRN), and up to one Postal Address File (PAF) key. If no keys for the address are known, the array will be empty. Otherwise it will be a list of objects which specify the value of the address key and the code system for it","items":{"anyOf":[{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'PAF'.","enum":["PAF"],"example":"PAF"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in PAF format. An 8 digit number including leading zeroes, formatted as a string.","minLength":8,"maxLength":8,"pattern":"^[0-9]{8}$","example":"12345678"}}}]}}}},{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'UPRN'.","enum":["UPRN"],"example":"UPRN"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in UPRN format. A number containing from 1 up to 12 digits.","minLength":1,"maxLength":12,"pattern":"^[0-9]{1,12}$","example":"123456789012"}}}]}}}}]}}}}},"telecom":{"type":"array","description":"List of contact points for the patient; for example, phone numbers or email addresses.\nWhen a patient tagged as `restricted` is retrieved, all contact points are removed from the response.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}},"contact":{"type":"array","description":"A list of patient contacts. Only emergency contacts are returned and only emergency contacts should be added. Any other contacts should be added to the patients `Related Person`.\nPatients designate here any contact number they desire to be used in case of an emergency.\nNote, while a patient may also desire to record various related persons telecom details, these do not separately allow for a concept of emergency contact; only ranking. See RelatedPerson endpoint.\nWhen a patient tagged as `restricted` is retrieved, all contacts are removed from the response.\n","items":{"title":"Schema for a patient contact.","type":"object","additionalProperties":false,"required":["relationship","telecom"],"properties":{"id":{"type":"string","example":"C123"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"relationship":{"type":"array","description":"The contact relationship wrapper object that holds the details of the relationship to the patient.\n\nThis is only returned when an Emergency Contact number has been set on `telecom`. The only valid code is `C`, which means `Emergency Contact`.\n","minItems":1,"maxItems":1,"items":{"type":"object","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one contact relationship.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","format":"url","default":"http://terminology.hl7.org/CodeSystem/v2-0131"},"code":{"type":"string","description":"Coded value for contact relationship.","example":"C"},"display":{"type":"string","description":"Display-friendly representation of the contact relationship code.","example":"Emergency Contact"}}}}}}},"telecom":{"type":"array","description":"List of Telecom objects on the contact only contains `system` and `value`.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}}}}},"generalPractitioner":{"type":"array","maxItems":1,"description":"General Practice (not practitioner) with which the patient is, or was, registered. Always contains zero or one general practitioner object.\nWhen a patient tagged as `restricted` is retrieved, the General Practice is removed from the response.\n","items":{"description":"General practice (not practitioner) with which the patient is or was registered.","type":"object","required":["identifier"],"properties":{"id":{"description":"Object identifier (OID) specific to the returned details - this should be return exactly the same in any update.","type":"string","example":"254406A3"},"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}}},"managingOrganization":{"description":"The managing organization of a de-registered patient. This will not be returned when the reason for de-registration is death.","type":"object","required":["identifier"],"properties":{"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}},"extension":{"type":"array","description":"Wrapper array for the patient's pharmacies, death notification status, communication details, contact preferences and place of birth; these are all FHIR extensions.\nAlways contains zero or one of each pharmacy object, zero or one death notification status object, zero or one communication details object, zero or one contact preference and zero or one place of birth object.\nWhen a patient tagged as `restricted` is retrieved, the pharmacy and birth place extensions are removed from the response.\n","items":{"anyOf":[{"type":"object","description":"Wrapper object for the patient's nominated pharmacy. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-NominatedPharmacy FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy"]},"valueReference":{"type":"object","description":"Reference to a pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's nominated pharmacy organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the nominated pharmacy, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y12345"}}}}}}},{"type":"object","description":"Wrapper object for the patient's dispensing doctor. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-DispensingDoctor FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization"]},"valueReference":{"type":"object","description":"Reference to a GP practice pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's dispensing doctor organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the dispensing doctor, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y23456"}}}}}}},{"type":"object","description":"Wrapper object for the patient's medical appliance supplier. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-MedicalApplianceSupplier FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier"]},"valueReference":{"type":"object","description":"Reference to medical appliance supplier pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's medical appliance supplier organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the medical appliance supplier, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y34567"}}}}}}},{"type":"object","description":"Wrapper object for death notification details.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of death notification extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus"]},"extension":{"type":"array","description":"Array containing exactly one death notification status code object and exactly one effective date object.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for death notification status code.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `deathNotificationStatus`.","default":"deathNotificationStatus","enum":["deathNotificationStatus"]},"valueCodeableConcept":{"type":"object","description":"Death Notification Status.","properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["system","code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol, in syntax, defined by the system:\n* `1` - Informal - death notice received via an update from a local NHS Organisation such as GP or Trust\n* `2` - Formal - death notice received from Registrar of Deaths. Only these endpoints are allowed to add a Formal death:\n - National Back Office using the Demographic Spine Application (DSA)\n - Office of National Statistics (ONS)\n - Maternity sites\n* `U` - Removed. This is a possible response, but it cannot be used on an update because Spine will reject it\n","example":"2","enum":["1","2","U"]},"display":{"type":"string","description":"Representation defined by the system.","example":"Formal - death notice received from Registrar of Deaths","enum":["Informal - death notice received via an update from a local NHS Organisation such as GP or Trust","Formal - death notice received from Registrar of Deaths","Removed"]}}}}}}}},{"type":"object","description":"Wrapper object for death notification effective date.","required":["url","valueDateTime"],"properties":{"url":{"type":"string","description":"Key of this object. Always `systemEffectiveDate`.","default":"systemEffectiveDate","enum":["systemEffectiveDate"]},"valueDateTime":{"type":"string","description":"Date and time at which death notification status took effect.","format":"date-time","example":"2010-10-22T00:00:00+00:00"}}}]}}}},{"type":"object","description":"Wrapper object for communication details. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of communication extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication"]},"extension":{"type":"array","description":"Definition of communication extension.\n\nThe array must have one item, a valueCodeableConcept for the language and can optionally include a valueBoolean for if an interpreter is required.","minItems":1,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Wrapper object for communication language.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `language`.","default":"language","enum":["language"]},"valueCodeableConcept":{"type":"object","description":"Human language.","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one language code.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of the Language Code System. Always uses the 'UKCore-HumanLanguage' Code System.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage"},"version":{"type":"string","description":"Version of the language code system.","example":"1.0.0"},"code":{"type":"string","description":"Language code based on [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) standard plus extensions for braille, makaton and sign languages, which are:\n* `q1` - Braille\n* `q2` - American Sign Language\n* `q3` - Australian Sign Language\n* `q4` - British Sign Language\n* `q5` - Makaton\nAll valid codes combined can be found at https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage.\n","example":"fr"},"display":{"type":"string","description":"Display-friendly representation of the language code (such as English). If there is a language code with no defined mapping, `Unknown` will be returned.","example":"French"}}}}}}}},{"type":"object","description":"Wrapper object for whether an interpreter is required.","required":["url","valueBoolean"],"properties":{"url":{"type":"string","description":"Key of this object. Always `interpreterRequired`.","default":"interpreterRequired","enum":["interpreterRequired"]},"valueBoolean":{"type":"boolean","description":"Whether an interpreter is required.","example":true}}}]}}}},{"type":"object","description":"Wrapper object for preferred contact details; the written communication format, preferred contact time and method. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the contact preference extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference"]},"extension":{"description":"Wrapper array containing zero or one preferred contact method, zero or one preferred written communication format; and zero or one preferred contact time.","type":"array","maxItems":3,"items":{"oneOf":[{"type":"object","description":"Wrapper object for preferred written communication format.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredWrittenCommunicationFormat`.","default":"PreferredWrittenCommunicationFormat"},"valueCodeableConcept":{"type":"object","description":"Preferred Written Communication Format.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred written communication extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat"]},"code":{"type":"string","description":"A code to identify the preferred written communication format of a patient, contact or related person.\n* 11 - Large print\n* 12 - Braille\n* 13 - Audio tape\n","example":"12"},"display":{"type":"string","description":"Display-friendly representation of the preferred written communication format code.","example":"Braille"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact method.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactMethod`.","default":"PreferredContactMethod","enum":["PreferredContactMethod"]},"valueCodeableConcept":{"type":"object","description":"Preferred Contact Method.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred contact method extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod"]},"code":{"type":"string","description":"A code to identify to identify the preferred contact method of a patient, contact or related person.\n* 1\t- Letter\n* 2\t- Visit\n* 3\t- Telephone\n* 4\t- E-mail\n* 5\t- Minicom (Textphone)\n* 6\t- Telephone contact via proxy\n* 7\t- Sign language\n* 8\t- No Telephone contact\n","example":"1"},"display":{"type":"string","description":"Display-friendly representation of the preferred contact method code.","example":"Letter"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact times.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactTimes`.","default":"PreferredContactTimes","enum":["PreferredContactTimes"]},"valueString":{"type":"string","maximum":40,"description":"A free-text description about the preferred contact times.","example":"Not after 7pm"}}}]}}}},{"type":"object","description":"Wrapper object for place of birth details. This will not be returned on a restricted patient.","required":["url","valueAddress"],"properties":{"url":{"type":"string","description":"Definition of place of birth extension.","default":"http://hl7.org/fhir/StructureDefinition/patient-birthPlace","enum":["http://hl7.org/fhir/StructureDefinition/patient-birthPlace"]},"valueAddress":{"type":"object","additionalProperties":false,"properties":{"city":{"type":"string","description":"Town or city of birth.","example":"Manchester"},"district":{"type":"string","description":"County or metropolitan district of birth.","example":"Greater Manchester"},"country":{"type":"string","description":"A coded value for a patient's country of birth.\n\nFrom [ISO 3166-1](http://hl7.org/fhir/valueset-iso3166-1-3.html) plus codes from the UK Internal Code list which do not have entries in ISO 3166-1.\n\nUK Internal Codes:\n* `1` - England\n* `2` - Scotland\n* `3` - Wales\n* `4` - Northern Ireland\n* `7` - Sark\n* `9` - Alderney\n* `10` - Channel Islands\n","example":"GBR"}}}}},{"type":"object","description":"An extension to carry the reason a PDS record has been removed from the Patient Demographic Service. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the removal from registration extension.","default":"https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration","enum":["https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration"],"readOnly":true},"extension":{"type":"array","description":"An extension reason a PDS record has been removed from the Patient Demographic Service.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for removalFromRegistrationCode.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"To identify the removal reason code.","default":"removalFromRegistrationCode","enum":["removalFromRegistrationCode"],"readOnly":true},"valueCodeableConcept":{"type":"object","description":"PDS Removal Reason Exit Code","required":["coding"],"properties":{"coding":{"type":"array","description":"Array containing exactly one removal reason exit code object","items":{"type":"object","required":["system","code","display"],"properties":{"system":{"type":"string","format":"url","description":"URL of the Removal Reason Exit Code. Always uses the 'PDS-RemovalReasonExitCode' Code System.","example":"https://fhir.nhs.uk/CodeSystem/PDS-RemovalReasonExitCode","readOnly":true},"code":{"type":"string","description":"A CodeSystem that identifies the reason a PDS record has been removed.","example":"SCT","enum":["DEA","EMB","SCT","NIT","TRA","ORR"]},"display":{"type":"string","description":"Display-friendly representation of the removal reason exit code.","example":"Transferred to Scotland"}}}}}}}},{"type":"object","description":"Wrapper object for removal from registration effective time.","required":["url","valuePeriod"],"properties":{"url":{"type":"string","description":"Key of this object. Always `effectiveTime`.","default":"effectiveTime","enum":["effectiveTime"],"readOnly":true},"valuePeriod":{"type":"object","description":"The effective time of removal of the Patient record from PDS.","required":["start"],"properties":{"start":{"type":"string","format":"date-time","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01T00:00:00+00:00"},"end":{"type":"string","format":"date-time","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31T00:00:00+00:00"}}}}}]}}}}]}}}},"example":{"resourceType":"Patient","id":"9000000009","identifier":[{"system":"https://fhir.nhs.uk/Id/nhs-number","value":"9000000009","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus","version":"1.0.0","code":"01","display":"Number present and verified"}]}}]}],"meta":{"versionId":"2","security":[{"system":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality","code":"U","display":"unrestricted"}]},"name":[{"id":"123","use":"usual","period":{"start":"2020-01-01","end":"2021-12-31"},"given":["Jane"],"family":"Smith","prefix":["Mrs"],"suffix":["MBE"]}],"gender":"female","birthDate":"2010-10-22","multipleBirthInteger":1,"deceasedDateTime":"2010-10-22T00:00:00+00:00","generalPractitioner":[{"id":"254406A3","type":"Organization","identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345","period":{"start":"2020-01-01","end":"2021-12-31"}}}],"managingOrganization":{"type":"Organization","identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345","period":{"start":"2020-01-01","end":"2021-12-31"}}},"extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy","valueReference":{"identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345"}}},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization","valueReference":{"identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y23456"}}},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier","valueReference":{"identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y34567"}}},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","extension":[{"url":"deathNotificationStatus","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus","version":"1.0.0","code":"2","display":"Formal - death notice received from Registrar of Deaths"}]}},{"url":"systemEffectiveDate","valueDateTime":"2010-10-22T00:00:00+00:00"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","extension":[{"url":"language","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage","version":"1.0.0","code":"fr","display":"French"}]}},{"url":"interpreterRequired","valueBoolean":true}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","extension":[{"url":"PreferredWrittenCommunicationFormat","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","code":"12","display":"Braille"}]}},{"url":"PreferredContactMethod","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","code":"1","display":"Letter"}]}},{"url":"PreferredContactTimes","valueString":"Not after 7pm"}]},{"url":"http://hl7.org/fhir/StructureDefinition/patient-birthPlace","valueAddress":{"city":"Manchester","district":"Greater Manchester","country":"GBR"}},{"url":"https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration","extension":[{"url":"removalFromRegistrationCode","valueCodeableConcept":{"coding":[{"system":"https://fhir.nhs.uk/CodeSystem/PDS-RemovalReasonExitCode","code":"SCT","display":"Transferred to Scotland"}]}},{"url":"effectiveTime","valuePeriod":{"start":"2020-01-01T00:00:00+00:00","end":"2021-12-31T00:00:00+00:00"}}]}],"telecom":[{"id":"789","period":{"start":"2020-01-01","end":"2021-12-31"},"system":"phone","value":"01632960587","use":"home"},{"id":"790","period":{"start":"2019-01-01","end":"2022-12-31"},"system":"email","value":"jane.smith@example.com","use":"home"},{"id":"OC789","period":{"start":"2020-01-01","end":"2021-12-31"},"system":"other","value":"01632960587","use":"home","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem","code":"textphone","display":"Minicom (Textphone)"}}]}],"contact":[{"id":"C123","period":{"start":"2020-01-01","end":"2021-12-31"},"relationship":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0131","code":"C","display":"Emergency Contact"}]}],"telecom":[{"system":"phone","value":"01632960587"}]}],"address":[{"id":"456","period":{"start":"2020-01-01","end":"2021-12-31"},"use":"home","line":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"],"postalCode":"LS1 6AE","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"PAF"}},{"url":"value","valueString":"12345678"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"UPRN"}},{"url":"value","valueString":"123456789012"}]}]},{"id":"T456","period":{"start":"2020-01-01","end":"2021-12-31"},"use":"temp","text":"Student Accommodation","line":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"],"postalCode":"LS1 6AE","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"PAF"}},{"url":"value","valueString":"12345678"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"UPRN"}},{"url":"value","valueString":"123456789012"}]}]}]}}}},"4XX":{"description":"An error occurred as follows:\n\n| HTTP status | Error code | Description |\n| ----------- | -------------------------- | --------------------------------------------- |\n| 400 | INVALID_RESOURCE_ID | Invalid NHS number. |\n| 400 | UNSUPPORTED_SERVICE | Missing NHS number. |\n| 400 | MISSING_VALUE | Missing header parameter. For details, see the `diagnostics` field. |\n| 400 | INVALID_VALUE | Invalid header parameter. For details, see the `diagnostics` field. |\n| 401 | ACCESS_DENIED | Access token missing, invalid or expired, or calling application not configured for this operation. |\n| 403 | ACCESS_DENIED | Patient cannot perform this action. |\n| 404 | RESOURCE_NOT_FOUND | Patient does not exist for given NHS number. |\n| 404 | INVALIDATED_RESOURCE | Patient did exist for given NHS number, but has been invalidated and not superseded by another NHS number. |\n| 408 | UNABLE_TO_CALL_SERVICE | The downstream domain processing has not completed within the configured timeout period. |\n| 429 | TOO_MANY_REQUESTS | You have exceeded your application's [rate limit](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#rate-limits). |\n","content":{"application/fhir+json":{"schema":{"type":"object","description":"Outcome of an operation that does not result in a resource or bundle being returned, for example an error or an async/batch submission.\nThere are a number of possible error codes that can be returned along with a more detailed description in the `display` field.\n","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"OperationOutcome"},"issue":{"type":"array","description":"List of issues that have occurred.","minItems":1,"items":{"type":"object","required":["severity","code"],"properties":{"severity":{"type":"string","enum":["fatal","error","warning","information"],"description":"Severity of the error.","example":"error"},"code":{"type":"string","description":"FHIR error code.","example":"invalid","enum":["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"]},"details":{"type":"object","description":"Internal error code.","properties":{"coding":{"type":"array","items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"INVALID_VALUE"},"display":{"type":"string","description":"Representation defined by the system.","example":"Provided value is invalid"}}}}}},"diagnostics":{"type":"string","description":"Additional diagnostic information about the issue. This information is subject to change.","example":"Invalid value - 2019-01 in field 'birthDate'"},"expression":{"type":"string","description":"FHIRPath of element(s) related to the error.","example":"Patient.name.given"}}}}}},"example":{"resourceType":"OperationOutcome","issue":[{"severity":"error","code":"structure","details":{"coding":[{"system":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode","version":"1","code":"MISSING_VALUE","display":"Required value is missing"}]},"diagnostics":"Missing value - 'birth_date/birth_date_range_start/birth_date_range_end'"}]}}}}}},"patch":{"description":"## Overview\nUse this endpoint to update patient details in PDS.\n\nThis is a 'PATCH' operation - you can update specific parts of the patient record, such as name or gender, without having to update the entire record.\n\nWhen you make a PATCH request with your application, the endpoint will respond with a successful (200) response code, along with the updated patient resource, or, an unsuccessful (4xx/5xx) response. \n\n99.99% of all updates complete in under 10 seconds. If an update takes longer than 10 seconds, the endpoint responds with an HTTP status of 503 (Gateway Timeout). \n\nYou can alter the timeout period using the `X-Sync-Wait` header. If you re-submit the update, use the same `X-Request-ID` header.\n\nThe behaviour of this endpoint depends on which access mode you are using:\n\n| Access mode | Behaviour restrictions |\n| ------------------------------ | ----------------------------------- |\n| Application-restricted access | Updates not allowed |\n| Healthcare worker access | Updates allowed |\n| Patient access | Updates allowed |\n\n## Patient resource versioning\nTo update a patient's resource you must have retrieved it first, to ensure you are working against an up-to-date patient resource.\n\nWhen you retrieve a patient resource, you get a version number for the resource (in the `ETag` response header in the form `W/\"2\"` and in the `versionId` field in the response, in the form `\"2\"`).\n\nYou must then pass the patient's version number in the update request (in the `If-Match` response header).\n\nIt is recommended you use the value from the `Etag` header as this is in the correct form the `If-Match` header is expected, for example `W/\"2\"` and can be mirrored back in the request.\n\nThe update only succeeds, if the patient resource has not been updated in our database between your first retrieval and the update request.\n\nIf the update succeeds, you will receive the updated patient resource, this will contain the new resource version number.\n\nIf you make a subsequent update you must use the new version number.\n\n## JSON Patch\nTo update a patient record, a [JSON Patch](https://tools.ietf.org/html/rfc6902) should be sent. A JSON Patch consists of one or more patch objects within a list.\n\nIt is recommended that all desired updates are sent together in a single request as a list of patches.\nThis is the most efficient approach and reduces the danger of race conditions occurring when updating the patient record multiple times in a short period of time.\n\nWhen processing the list of patch objects, each patch must be valid and pass all the business rules against the data. If one patch object fails, none of the patch objects are applied.\n\nA patch object consists of:\n* an operation, `op` - this is required.\n* a path to the data that you want to change, `path` - this is required.\n* the value that is assigned, `value` - this is required for `add`, `replace` and `test`; but should not be included for a `remove`.\n\nThe following operations are supported:\n* `add` - to add a new value.\n* `replace` - to replace an existing value.\n* `remove` - to remove an existing value.\n* `test` - to test the state of a value is as expected before continuing with the update.\n\nPaths point to a single value, list or object, for example:\n* `/gender` - pointing to the gender value.\n* `/name` - point to the name list.\n* `/name/0` - pointing to the 1st object in the name list.\n* `/address/0/line/1` - pointing to the 2nd line string in the 1st address object.\n\nThe value can be set to any valid value for that path, so could be a null, a string, an object or a list.\n\n### Addition\n\n`add` should be used to add new items to a patient.\n\nAdding a simple data item such as the date of death can be done using a patch such as:\n\n```json\n{\n \"patches\": [\n { \"op\": \"add\", \"path\": \"/deceasedDate\", \"value\": \"2020-01-01\" }\n ]\n}\n```\n\nAdding to a list such as a `name` should be done by including the whole object in the value field. Note, the list index is `-` this is because when adding to a list, the index is not known:\n\n```json\n{\n \"patches\": [\n {\n \"op\": \"add\",\n \"path\": \"/name/-\",\n \"value\": {\n \"use\": \"usual\",\n \"period\": { \"start\": \"2019-12-31\" },\n \"prefix\": [\"Dr\"],\n \"given\": [\n \"Joe\",\n \"Horation\",\n \"Maximus\"\n ],\n \"family\": \"Bloggs\",\n \"suffix\": [\"PhD\"]\n }\n }\n ]\n}\n```\n\nWhen adding a base level list item such as a new name or address, ensure the index is always `-`, otherwise the request is rejected. For example, `/name/-`.\nThe reason for this is because the backend system makes the decision on the ordering of the listed objects to ensure they are always returned in the same order.\n\nIf you are adding to a sub-element that is a list, such as an additional given name, it is valid to provide an exact index. So the following is valid:\n\n```json\n{\n \"patches\": [\n {\n \"op\": \"add\", \"path\": \"/name/0/id\", \"value\": \"8F8B957D\"\n },\n {\n \"op\": \"add\", \"path\": \"/name/0/given/0\", \"value\": \"Rose\"\n }\n ]\n}\n```\n\nIt is possible to `add` a sub-element to an existing object in a patch request. If the object already exists and you have the object `id`, you must supply it or the update is rejected.\nThe following patch is allowed:\n\n```json\n{\n \"patches\": [\n {\n \"op\": \"add\", \"path\": \"/name/0/id\", \"value\": \"8F8B957D\"\n },\n {\n \"op\": \"add\", \"path\": \"/name/0/given/0\", \"value\": \"Rose\"\n }\n ]\n}\n```\n\nbut the following is not allowed:\n\n```json\n{\n \"patches\": [\n {\n \"op\": \"add\", \"path\": \"/name/0/given/-\", \"value\": \"Rose\"\n }\n ]\n}\n```\n\n### Replacing\n\n`replace` should be used to alter existing items on the patient.\n\nReplacing a simple data item such as the gender can be done using a patch such as:\n\n```json\n{\n \"patches\": [\n { \"op\": \"replace\", \"path\": \"/gender\", \"value\": \"male\" }\n ]\n}\n```\n\nReplacing a list item can be done in two ways which may be dependent on any external development libraries that can be used to create the patch.\n\nThe first approach is to replace the whole list item:\n\n```json\n{\n \"patches\": [\n {\n \"op\": \"replace\",\n \"path\": \"/name/0\",\n \"value\": {\n \"id\": \"123\",\n \"use\": \"usual\",\n \"period\": { \"start\": \"2019-12-31\" },\n \"prefix\": [\"Dr\"],\n \"given\": [\n \"Joe\",\n \"Horation\",\n \"Maximus\"\n ],\n \"family\": \"Bloggs\",\n \"suffix\": [\"PhD\"]\n }\n }\n ]\n}\n```\n\nThe second approach is to replace just a part, or parts, of the list object keys if all others remain the same:\n\n```json\n{\n \"patches\": [\n { \"op\": \"replace\", \"path\": \"/name/0/id\", \"value\": \"123\" },\n { \"op\": \"replace\", \"path\": \"/name/0/prefix/0\", \"value\": \"Mr\" },\n { \"op\": \"replace\", \"path\": \"/name/0/family\", \"value\": \"Smith\" }\n ]\n}\n```\n\nAn added requirement to ensure no accidental data loss or replacement of the wrong list item, you must always include the list `id` or `url`. This is in the object on retrieval so just needs to be mirrored back. You should not include an ID on an addition as this is automatically generated by the system and is a unique object ID, so only our system can guarantee that.\n\n### Removal\n\n`remove` should be used to delete existing items on a patient.\n\nRemoving a simple data item such as the gender can be done using a patch such as:\n\n```json\n{\n \"patches\": [\n { \"op\": \"remove\", \"path\": \"/gender\" }\n ]\n}\n```\n\nNote, that in this scenario, although the patch is perfectly valid, the update is still rejected as a patients gender cannot be removed.\n\nRemoving a list item should only be done on the whole item object, not individual sub-items; instead use the replace operation.\n\nTo remove a list item, a `test` operation must immediately proceed the `remove` . This is an added requirement to ensure no accidental data loss occurs or the wrong item is removed. The test operation should be used to assert either:\n\n* the `id` - the object ID for items that have one - for example `name`, `address` or `telecom`.\n* the `url` - the URL for the extension being removed.\n* the whole object being removed.\n\nAn example of a list item removal using the `id` would be:\n\n```json\n{\n \"patches\": [\n { \"op\": \"test\", \"path\": \"/name/0/id\", \"value\": \"123\" },\n { \"op\": \"remove\", \"path\": \"/name/0\" }\n ]\n}\n```\n\nAn example of a extension list item removal using the `url` would be:\n\n```json\n{\n \"patches\": [\n { \"op\": \"test\", \"path\": \"/extension/0/url\", \"value\": \"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus\" },\n { \"op\": \"remove\", \"path\": \"/extension/0\" }\n ]\n}\n```\n\nAn example of a list item removal using the whole object would be:\n\n```json\n{\n \"patches\": [\n { \n \"op\": \"test\",\n \"path\": \"/name/0\",\n \"value\": {\n \"id\": \"123\",\n \"use\": \"usual\",\n \"period\": { \"start\": \"2019-12-31\" },\n \"prefix\": [\"Dr\"],\n \"given\": [\n \"Joe\",\n \"Horation\",\n \"Maximus\"\n ],\n \"family\": \"Bloggs\",\n \"suffix\": [\"PhD\"]\n }\n },\n { \"op\": \"remove\", \"path\": \"/name/0\" }\n ]\n}\n```\n\nSpecial care should be taken when performing multiple removals in the same list; as removing a particular index could affect all subsequent index positions. The next two examples perform **exactly** the same operation.\n\nUsing the following initial (simplified) data, with the intention of removing the names in index 1 (Irwin) and 2 (Bruce):\n\n```json\n{\n \"name\": [\n {\"id\": \"2\", \"family\": \"Parker\"},\n {\"id\": \"3\", \"family\": \"Irwin\"},\n {\"id\": \"4\", \"family\": \"Bruce\"},\n {\"id\": \"5\", \"family\": \"Sharpe\"}\n ]\n}\n```\n\n**Example 1**:\n\n```json\n{\n \"patches\": [\n { \"op\": \"test\", \"path\": \"/name/1/id\", \"value\": \"3\" },\n { \"op\": \"remove\", \"path\": \"/name/1\" },\n { \"op\": \"test\", \"path\": \"/name/1/id\", \"value\": \"4\" },\n { \"op\": \"remove\", \"path\": \"/name/1\" }\n ]\n}\n```\n\nAfter the 1st removal the data looks like:\n\n```json\n{\n \"name\": [\n {\"id\": \"2\", \"family\": \"Parker\"},\n {\"id\": \"4\", \"family\": \"Bruce\"},\n {\"id\": \"5\", \"family\": \"Sharpe\"}\n ]\n}\n```\n\nmeaning Irwin has been removed, Bruce has moved from index 2 -> 1 and Sharpe from 3 -> 2.\n\nSo after applying the 2nd removal the data looks like:\n\n```json\n{\n \"name\": [\n {\"id\": \"2\", \"family\": \"Parker\"},\n {\"id\": \"5\", \"family\": \"Sharpe\"}\n ]\n}\n```\n\nWhich is the intended outcome. Using the same index 1 for both removals may look unexpected, but the way JSON Patch works is iterating over each patch operation in turn and making the change to the list index positions. This means a developer needs to account for lists changing from one operation to the next.\n\n**Example 2**:\n\n```json\n{\n \"patches\": [\n { \"op\": \"test\", \"path\": \"/name/2/id\", \"value\": \"4\" },\n { \"op\": \"remove\", \"path\": \"/name/2\" },\n { \"op\": \"test\", \"path\": \"/name/1/id\", \"value\": \"3\" },\n { \"op\": \"remove\", \"path\": \"/name/1\" }\n ]\n}\n```\n\nAfter the 1st removal the data looks like:\n\n```json\n{\n \"name\": [\n {\"id\": \"2\", \"family\": \"Parker\"},\n {\"id\": \"3\", \"family\": \"Irwin\"},\n {\"id\": \"5\", \"family\": \"Sharpe\"}\n ]\n}\n```\n\nApplying the 2nd removal the data looks like:\n\n```json\n{\n \"name\": [\n {\"id\": \"2\", \"family\": \"Parker\"},\n {\"id\": \"5\", \"family\": \"Sharpe\"}\n ]\n}\n```\n\nWhich is the intended outcome. Providing the patches with the indexes descending means that the list stays in a stable format the whole way through as the only changes to the index positions are items have been passed over already.\n\n**Example 3 - a failure**\n\n```json\n{\n \"patches\": [\n { \"op\": \"test\", \"path\": \"/name/1/id\", \"value\": \"3\" },\n { \"op\": \"remove\", \"path\": \"/name/1\" },\n { \"op\": \"test\", \"path\": \"/name/2/id\", \"value\": \"4\" },\n { \"op\": \"remove\", \"path\": \"/name/2\" }\n ]\n}\n```\n\nAfter the 1st removal the data looks like:\n\n```json\n{\n \"name\": [\n {\"id\": \"2\", \"family\": \"Parker\"},\n {\"id\": \"4\", \"family\": \"Bruce\"},\n {\"id\": \"5\", \"family\": \"Sharpe\"}\n ]\n}\n```\n\nWhen applying the 2nd test, it fails as the index 2 ID is `5`, but the test was looking for `4`. An error is returned and none of the updates provided would be made to the database.\n\nThis failure example is a good reason for forcing the use of the `test` operation. If there was no test, index 2 would have been blindly removed, meaning the final state of the data would look like:\n\n```json\n{\n \"name\": [\n {\"id\": \"2\", \"family\": \"Parker\"},\n {\"id\": \"4\", \"family\": \"Bruce\"}\n ]\n}\n```\n\nWhich is incorrect, as Irwin and Sharpe were removed instead of Irwin and Bruce.\n\n\n## Patient data fields\n\n### Address\n\nList item found under `address` field.\n\nIn a JSON Patch request the path should be:\n* `/address/0` if the address to be replaced or removed is the first item in the list. If it is the second item in the list the path is `/address/1`, and so on.\n* `/address/-` when adding a new address.\n\nAn address consists of 5 lines of unstructured text, postcode, and address keys. Address keys can include a PAF and a UPRN.\n\nPostcode is optional but strongly encouraged.\nIf the address has no postcode, use a [pseudo postcode from the list defined by the Office for National Statistics](https://digital.nhs.uk/services/organisation-data-service/data-downloads/office-for-national-statistics-data) (see the ‘look_ups’ file).\n\nIn particular, for a patient at no fixed abode, use the pseudo postcode `ZZ99 3VZ`.\n\nWe recommend you use the [OS Places API](https://digital.nhs.uk/developer/api-catalogue/ordnance-survey-places-api) for looking up and verifying addresses prior to a PDS update. The PDS FHIR API cannot yet handle UPRNs required by the OS Places API. We are planning to support these in future.\n\nWhen adding or replacing address lines, use the following rules:\n*\tline 1 - premises ID and/or house name, for example `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, for example `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), for example `Boxgrove`\n*\tline 4 - post town, for example `Leeds`\n*\tline 5 - county (if present), for example `West Yorkshire`\n\nWhen updating an address, you should populate lines 1 or 2, and line 4. You should not include line 5 in manually created addresses but you may include it in PAF-derived addresses. The address ID must also be included in the update as shown in the below examples.\n\nThere are exceptions:\n* if you submit a postcode and PAF key, in which case the lines are automatically populated, however if there are no matches or too many matches the message is rejected due to missing address lines\n* if you use a pseudo postcode, for example `ZZ99 3VZ` meaning `no fixed abode`\n\nWhen creating the FHIR payload message, to be fully FHIR compliant all empty lines should be removed, so for example:\n\n```json\n{\n \"address\": {\n \"line\": [\n \"\",\n \"23 Mill Lane\",\n \"\",\n \"Leeds\",\n \"\"\n ]\n }\n\n}\n```\n\nshould be sent in as:\n\n```json\n {\n \"address\": {\n \"line\": [\n \"23 Mill Lane\",\n \"Leeds\"\n ]\n }\n\n }\n```\n\nhowever if you do not do this the message is not rejected; the response is in that form though.\n\nTo ensure consistent data across all patient addresses, you should match addresses to the PAF and send them in PAF format including the PAF key.\nIf you do not include the PAF key it is added to the address if a match is found\nAdditionally the provided address lines and post code are enriched and reformatted if necessary.\n\nThe following address types are supported:\n* `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n* `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n* `billing` - an address used for correspondence purposes only\n\nA patient must have no more than one current `temp` and/or `billing` address.\nHowever, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\nWhere multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (for example by examining period dates).\n\nA `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\nHowever additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\nWhen sending correspondence to a patient:\n*\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and to dates.\n*\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and to dates.\n* if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n\nNot all local systems support `temp` and `billing` addresses, so these are not uniformly maintained. Therefore, where the patient contact has clinical or business significance, the precedence of these addresses over the `home` address should be determined by a user wherever possible.\nWhen the end date for a `temp` or `billing` address passes, local systems should use the patient’s `home` address. It is extremely rare that no home address is present on a patient record.\n\nBe aware of the following business rules:\n* you cannot add more than one of each address use types; `home`, `temp` or `billing`\n* `work` address `use` type is a valid response but cannot be added or replaced as it is a legacy value. An address with the `work` type can be removed though\n* any `temp` address must have both a `period start` and a `period end` date. The provision of a period end date has particular importance in order to avoid temporary addresses that are no longer relevant to the patient still being held as current data available to any system retrieving the patient record. A suggested default where no actual period end is known is 30 days later than the period start, up to a maximum of 3 months.\n* any `billing` address must have both a `period start` and a `period end` date. The provision of a period end date has particular importance in order to avoid correspondence addresses that are no longer relevant to the patient still being held as current data available to any system retrieving the patient record. A suggested default where no actual period end is known is 30 days later than the period start, up to a maximum of 12 months.\n* the date period is optional; where present they must be valid dates and the `end` date cannot be before the `start` date\n* the period `start` date is optional, however if provided cannot be a future date. If it is not provided it defaults to the date of update\n* where a `temp` address is provided a description must be sent using the `text` field, the list of possible values are:\n * `Second Home` - a patient's second home\n * `Student Accommodation` - a patient's place of residence while at university\n * `Respite Care Address` - where the patient resides during respite care\n * `Temporary Residence Address` - where the patient resides for a specific period of time\n * `Convalescence Home` - the address for a patient during a period of recovery\n * `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n * `Holiday Home` - the address for a patient during a holiday\n\n### Communication\n\nSingle item found under `extension` with the extension URL `https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication`.\n\nIn a JSON Patch request, where the communication extension does not exist the path should be:\n* `/extension/-` when adding a communication extension.\n\nWhere you are replacing/removing the full communication extension, the path should be:\n* `/extension/0` if the communication extension is the first item in the list. If it is the second item in the list the path is `/extension/1`, and so on.\n\nWhere the communication extension already exists and you wish to replace a specific sub-extension, then the path should be:\n* `/extension/0/extension/1` if the communication extension is the first item in the list and the sub-extension is the second item in the list.\n\nYou can find examples of the above requests in our sandbox Postman collection\n\nThere are a number of business rules that should be taken into account:\n* preferred language must not be supplied where it is English even though the [code list](https://simplifier.net/resolve?target=simplifier&scope=uk.nhsdigital.r4&canonical=https://fhir.hl7.org.uk/ValueSet/UKCore-HumanLanguage) contains a value for English (en).\n* any language codes outside the accepted list are rejected; such as local system `qa` codes.\n\n### Contact preferences\nSingle item found under `extension` with the extension URL `https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference`.\n\nIn a JSON Patch request, where the Contact Preference extension does not exist or you are replacing/removing the full list of Contact preferences, the path should be:\n* `/extension/0` if the contact preference is the first item in the list. If it is the second item in the list the path is `/extension/1`, and so on.\n* `/extension/-` when adding a contact preference.\n\nWhere the Contact Preference extension already exists and you wish to add, replace or remove a specific contact preference(s) sub-extension, then the path should be:\n* `/extension/0/extension/1` if the contact preference extension is the first item in the list and the method is the second item in the sub-extension list.\n\nYou can find examples of the above requests in our sandbox Postman collection \n\nThere are a number of business rules that should be taken into account:\n* a patient can have `0` or `1` contact preference.\n* preferred contact time is a free-text field limited to 40 characters.\n* where a contact time is specified a contact method must also exist.\n\n### Date of birth\n\nSingle item found under `birthDate` field.\n\nIn a JSON Patch request the path should be `/birthDate`.\n\nWhen adding or updating the birth date, the update should be in the format `yyyy-mm-dd`.\n\nThere are a number of business rules that should be taken into account:\n* cannot be removed.\n* cannot be a date in the future.\n* cannot be after the deceased date, if present.\n\n### Date of death\n\nSingle item found under `deceasedDateTime` field.\n\nIn a JSON Patch request the path should be `/deceasedDateTime`.\n\nWhen adding or updating the deceased date time, the update should be in the format `yyyy-mm-ddTHH:MM:SS+HH:MM`.\n\nThere are a number of business rules that should be taken into account:\n* cannot be removed.\n* cannot be a date in the future.\n* cannot be before the birth date.\n* cannot be replaced if the death notification status is 2 (formal).\n* when adding date of death, a death notification status must also be added.\n\n### Death notification\n\nSingle item found under `extension` with the extension URL `https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus`.\n\nIn a JSON Patch request the path should be:\n* `/extension/0` if the death notification is the first item in the list. If it is the second item in the list the path is `/extension/1`, and so on.\n* `/extension/-` when adding a death notification.\n\nYou can find examples of the above requests in our sandbox Postman collection\n\nThere are a number of business rules that should be taken into account:\n* cannot be removed.\n* cannot be replaced if the death notification status is formal (2).\n* only certain endpoints can set a death notification of formal (2).\n* when adding a death notification, a deceased date time must also be added.\n\n### Emergency contact\n\nList item found under `contact` field.\n\nIn a JSON Patch request the path should be:\n* `/contact/0` if the contact to be replaced or removed is the first item in the list. If it is the second item in the list the path is `/contact/1`, and so on.\n* `/contact/-` when adding a new contact.\n\nOnly emergency contact details should be added to `contact`, regular telecommunication methods such as home phone should be added to the `telecom` field.\nAny other contact relationship types are rejected.\n\nThere are a number of business rules that should be taken into account:\n* in any telecom child object the `use` key should not be present.\n* in any telecom child object the system cannot be `fax`.\n* the date period is optional; where present they must be valid dates and the `end` date cannot be before the `start` date.\n* the period `start` date is optional, however if provided cannot be a future date. If it is not provided it defaults to the date of update.\n* the date period, if present, should be on the parent `contact` object and not any `telecom` child objects.\n* if the system is email, the value must be a valid email format, for example john.smith@example.com; and must be more than 6 characters and less than 90 characters\n* the relationship can only be `C` meaning `Emergency Contact`\n\n### Gender\n\nSingle item found under `gender` field.\n\nIn a JSON Patch request the path should be `/gender`.\n\nWhen setting a gender, the local system should encourage the user to select `male` or `female` rather than `unknown`.\nThe fourth value of gender, `other`, meaning indeterminate; i.e. unable to be classified as either male or female; should never pro-actively be set by local systems - although this value can be retrieved due to legacy data or data quality issues.\n\nThere are a number of business rules that should be taken into account:\n * cannot be removed.\n * can only be `male`, `female` or `unknown`.\n * cannot set gender to `other`.\n\n### General practice\n\nList item found under `generalPractitioner` field. Although only a single general practice is allowed.\n\nIn a JSON Patch request the path should be:\n* `/generalPractitioner/0` for replacing or removing the general practice.\n* `/generalPractitioner/-` when adding a new general practice.\n\nThere are a number of business rules that should be taken into account:\n* only valid GP Practice codes may be used, see [Organisation Data Service FHIR API](https://developer.nhs.uk/apis/ods/) for more details on valid codes.\n* the period `start` date is optional, however if provided cannot be a future date. If it is not provided it defaults to the date of update.\n* do not provide a period `end` date.\n* the general practice should only be updated by primary care systems, [NHAIS](https://digital.nhs.uk/services/nhais) or by the National Back Office.\n* removal of a general practice can only be done by [NHAIS](https://digital.nhs.uk/services/nhais) or by the National Back Office.\n* only a single general practice is supported; emergency, temporary and additional practices must be maintained in the local system only.\n\n### Managing Organisation (internal-use only)\n\nSingle item found under `managingOrganization` field.\n\nIn a JSON Patch request the path should be `/managingOrganization`.\n\nThe following business rules should be observed:\n* only valid GP Practice codes may be used, see [Organisation Data Service FHIR API](https://developer.nhs.uk/apis/ods/) for more details on valid codes.\n* the period `start` date is optional, however if provided cannot be a future date. If it is not provided it defaults to the date of update.\n* only a single general practice is supported; emergency, temporary and additional practices must be maintained in the local system only.\n\n### Multiple birth order\n\nSingle item found under `multipleBirthInteger` field.\n\nIn a JSON Patch request the path should be `/multipleBirthInteger`.\n\nWhen adding or updating the birth order, the update should be an integer in the range `1` - `9` inclusive. These values have differing meanings:\n* 1 - 7 indicates the order of birth, with 1 indicating the first or only birth in the sequence, 2 indicating the second birth in the sequence, 3 indicating the third, and so on up to 7.\n* 8 - `Not applicable`\n* 9 - `Not known`\n\n### Name\n\nList item found under `name` field.\n\nIn a JSON Patch request the path should be:\n* `/name/0` if the name to be replaced or removed is the first item in the list. If it is the second item in the list the path is `/name/1`, and so on.\n* `/name/-` when adding a new name.\n\nThere are a number of business rules that should be taken into account:\n* cannot add more than one `usual` name.\n* cannot remove the `usual` name.\n* cannot add more than one `nickname`.\n* can have multiple instances of all other name use types.\n* cannot replace the use type on an existing name. For example, once a name is a nickname, it cannot be changed directly to an alias. You must instead remove the nickname and add the alias.\n* the first character of each `suffix` item must be `A-Z`.\n* the date period is optional; where present they must be valid dates and the `end` date cannot be before the `start` date.\n* the period `start` date is optional, however if provided cannot be a future date. If it is not provided it defaults to the date of update.\n* supplied name data can only contain characters from the following ranges:\n\n| Character Code/Range | Examples |\n|----------------------|---------------|\n| 65-90 | A-Z |\n| 97-122 | a-z |\n| 45 | Apostrophe |\n| 39 | Hyphen |\n| 32 | Space |\n| 192-214 | À, Æ, Ö, ... |\n| 216-246 | Ø, ß, ö, ... |\n| 248-383 | ø, ü, ÿ, ... |\n| 46 | Full-stop |\n| 48-57\t | Numbers |\n\n* the `period` is optional, but if included the `end` date cannot be before the `start` date. They can however be in the past, present or future.\n* the full available range of generally recognised titles are permitted, however, if any of the following are used then the value input must conform to the following format:\n * Mr\n * Mrs\n * Ms\n * Dr\n * Rev\n * Sir\n * Lady\n * Lord\n* any trailing full stops at the end of a prefix are automatically removed; for example `Mrs.` changes to `Mrs`.\n\n### Pharmacy\n\nSingle item found under `extension` with one of the extension urls:\n* `https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy`\n* `https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier`\n* `https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization`\n\nIn a JSON Patch request the path should be:\n* `/extension/0` if the pharmacy is the first item in the list. If it is the second item in the list the path is `/extension/1`, and so on\n* `/extension/-` when adding a pharmacy\n\nThere are a number of business rules that should be taken into account:\n* multiple pharmacies are allowed, however only one of each type\n* there are no effective date periods, only a single current instance of each type is supported\n* only valid National Pharmacy codes may be used for the pharmacy identifier, see [Organisation Data Service FHIR API](https://developer.nhs.uk/apis/ods/) for more details on valid codes\n\n### Place of birth\n\nSingle item found under `extension` with the extension URL `http://hl7.org/fhir/StructureDefinition/patient-birthPlace`.\n\nIn a JSON Patch request the path should be:\n* `/extension/0` if the place of birth is the first item in the list. If it is the second item in the list the path is `/extension/1`, and so on\n* `/extension/-` when adding a place of birth\n\nThere are a number of business rules that should be taken into account:\n* the three fields, `city`, `district` and `country` are all optional, however at least one of them must be provided\n* country is a coded value and must be in the set of valid values\n\n### Telecom\n\nList item found under `telecom` field.\n\nIn a JSON Patch request the path should be:\n* `/telecom/0` if the telecom to be replaced or removed is the first item in the list. If it is the second item in the list the path is `/telecom/1`, and so on\n* `/telecom/-` when adding a new telecom\n\nEmergency contact details should not be added to the `telecom` field, instead they should be added to the `contact` field.\n\nThere are a number of business rules that should be taken into account:\n* the date period is optional; where present they must be valid dates and the `end` date cannot be before the `start` date\n* the period `start` date is optional, however if provided cannot be a future date. If it is not provided it defaults to the date of update.\n* if the telecom system is email, the value must be a valid email format, for example john.smith@example.com; and must be more than 6 characters and less than 90 characters\n\n## Access Mode\n\n### Healthcare worker access\n\nA user with Healthcare worker access will be able to update the following fields:\n* Address\n* Communication\n* Contact preferences\n* Date of birth\n* Date of death\n* Death notification\n* Emergency contact\n* Gender\n* General practice\n* Managing Organisation (internal use only)\n* Multiple birth order\n* Name\n* Pharmacy\n* Place of birth\n* Telecom\n\n### Patient access\n\nA user with Patient access will be able to update the following fields:\n* Address\n* Pharmacy\n* Telecom (mobile and email only)\n\n## Sandbox test scenarios\n\nYou can test the following scenarios in our sandbox environment.\n\nThings to note when using the sandbox for PATCH:\n* Your changes are not persisted.\n* JSON Patch operations themselves are validated, but the resulting resource is not validated for correctness; meaning any business rules are not applied.\n* You can use the patient with minimal data, `9000000033` to test adding all data types (as most of them are missing on this patient), that would normally be present (e.g. gender).\n\n| Scenario | Request | Response |\n| ----------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------ |\n| Successful update | `id`=`9000000009`

Body: One of the provided examples or your own combination of patches

Headers: `If-Match`=`W/\"2\"`, `Content-Type`=`application/json-patch+json` | HTTP Status 200 with updated patient resource. |\n| Patient does not exist | `id`=`9111231130` (or any other valid NHS number) | HTTP Status 404 with problem description |\n| Invalid NHS number | `id`=`9000000000` (or any invalid NHS number) | HTTP Status 400 with problem description |\n| Missing resource version identifier | `If-Match` header missing or set to format other than `W/\"\"` | HTTP Status 412 with problem description |\n| Incorrect resource version | `If-Match`=`W/\"1\"` | HTTP Status 412 with problem description |\n| Wrong content type | `Content-Type` header missing or other than `application/json-patch+json` | HTTP Status 400 with problem description |\n| No patches sent | Send body with no `patches` attribute | HTTP Status 400 with problem description |\n| Invalid patch operations | Send body with invalid JSON patches in `patches` attribute | HTTP Status 400 with problem description |\n| Missing X-Request-ID | `id`=`9000000009` (or any other valid NHS number) | HTTP Status 412 with problem description |\n\nYou can try out the sandbox using the 'Try this API' feature on this page.\n\nAlternatively, you can try out the sandbox using our Postman collection:\n\n[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/14719036-953f067f-30b9-4552-8252-7cc10b21dad3)\n","summary":"Update patient details","operationId":"update-patient-partial","externalDocs":{"description":"IETF RFC 6902, which defines json-patch.","url":"https://tools.ietf.org/html/rfc6902"},"parameters":[{"in":"header","name":"If-Match","description":"Latest known version identifier enclosed in quotes preceded by `W/`.\n\nSend the value of the patient's `ETag` response header on patient retrieval when updating a patient.\nThis is to ensure that any updates are applied against an up-to-date version of the patient resource.\n","required":true,"schema":{"type":"string","pattern":"^W/\"[0-9]+\"$","example":"W/\"2\""}},{"in":"header","name":"Content-Type","description":"For a PATCH request, this must be set to `application/json-patch+json`.\n","required":true,"schema":{"type":"string","example":"application/json-patch+json"}}],"requestBody":{"required":true,"content":{"application/json-patch+json":{"schema":{"type":"object","required":["patches"],"properties":{"patches":{"type":"array","items":{"type":"object","required":["op","path"],"properties":{"op":{"type":"string","enum":["remove","add","replace","test"]},"path":{"description":"The location of the information to remove, add or replace. The '-' character must be used to add new items to arrays, e.g. names, addresses.","type":"string","format":"jsonpointer","externalDocs":{"description":"IETF RFC 6901 JavaScript Object Notation (JSON) Pointer.","url":"https://tools.ietf.org/html/rfc6901"}},"value":{"description":"The information to be added or replaced. Should not be included on a remove.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"object"}]}}}}}},"examples":{"add-deceased-date-time":{"summary":"Add a new single item (deceasedDateTime) to the patient","value":{"patches":[{"op":"add","path":"/deceasedDateTime","value":"2010-10-22T00:00:00+00:00"}]}},"add-name":{"summary":"Add a new list item (name) to the patient","value":{"patches":[{"op":"add","path":"/name/-","value":{"use":"usual","period":{"start":"2019-12-31"},"prefix":["Dr"],"given":["Joe","Horation","Maximus"],"family":"Bloggs","suffix":["PhD"]}}]}},"add-extension":{"summary":"Add a an extension (nominated pharmacy) to the Patient","value":{"patches":[{"op":"add","path":"/extension/-","value":{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy","valueReference":{"identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345","period":{"start":"2020-01-01","end":"2021-12-31"}}}}}]}},"update-gender":{"summary":"Update the simple item (gender)","value":{"patches":[{"op":"replace","path":"/gender","value":"male"}]}},"update-address":{"summary":"Update specific fields on a list item (address)","value":{"patches":[{"op":"replace","path":"/address/0/id","value":"456"},{"op":"replace","path":"/address/0/line/0","value":"2 Whitehall Quay"},{"op":"replace","path":"/address/0/postalCode","value":"LS1 4BU"}]}},"update-address-alternative":{"summary":"Update whole object on a list item (address)","value":{"patches":[{"op":"replace","path":"/address/0","value":{"id":"456","period":{"start":"2020-01-01","end":"2021-12-31"},"use":"home","line":["2 Whitehall Quay","Leeds","West Yorkshire"],"postalCode":"LS1 4BU","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"PAF"}},{"url":"value","valueString":"9876543"}]}]}}]}},"update-extension":{"summary":"Update an extension (death notification)","value":{"patches":[{"op":"replace","path":"/extension/3","value":{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","extension":[{"url":"deathNotificationStatus","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus","version":"1.0.0","code":"1","display":"Informal - death notice received via an update from a local NHS Organisation such as GP or Trust"}]}}]}}]}},"delete-gender":{"summary":"Remove a single item (gender) no longer in use","value":{"patches":[{"op":"remove","path":"/gender"}]}},"delete-name":{"summary":"Remove a list item (name) no longer in use, using test pointing to the name items id","value":{"patches":[{"op":"test","path":"/name/0/id","value":"123"},{"op":"remove","path":"/name/0"}]}},"delete-name-alternative":{"summary":"Remove a list item (name) no longer in use, using test pointing to the name object","value":{"patches":[{"op":"test","path":"/name/0","value":{"id":"123","use":"usual","period":{"start":"2020-01-01","end":"2021-12-31"},"given":["Jane"],"family":"Smith","prefix":["Mrs"],"suffix":["MBE"]}},{"op":"remove","path":"/name/0"}]}},"delete-extension":{"summary":"Remove an extension (dispensing doctor pharmacy) no longer in use","value":{"patches":[{"op":"test","path":"/extension/1/url","value":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization"},{"op":"remove","path":"/extension/1"}]}}}}}},"responses":{"200":{"description":"Patient updated.","headers":{"ETag":{"schema":{"type":"string","pattern":"^W/\"[0-9]+\"$","example":"W/\"2\""},"description":"Record version identifier enclosed in quotes and preceded by 'W/'. For example, `W/\"2\"`.\n\nCorresponds to `meta.versionId` attribute in the patient resource body.\n\nWhen you retrieve a patient resource, you get a version number for the resource (in the `ETag` response header and in the `versionId` field in the response).\nYou must then pass the resource's version number in any update request (in the `If-Match` response header) made for the patient.\n"},"X-Correlation-Id":{"schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"},"description":"The X-Correlation-ID from the request header, if supplied, mirrored back.\n"},"X-Request-Id":{"schema":{"type":"string","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"},"description":"The X-Request-ID from the request header, if supplied, mirrored back.\n"}},"content":{"application/fhir+json":{"schema":{"type":"object","required":["id"],"additionalProperties":false,"properties":{"resourceType":{"type":"string","description":"FHIR resource type.","default":"Patient"},"id":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"identifier":{"type":"array","description":"Identifier and system of identification used for this Patient.","items":{"type":"object","maxItems":1,"required":["value"],"properties":{"system":{"type":"string","format":"url","description":"System identifier belongs to.","default":"https://fhir.nhs.uk/Id/nhs-number"},"value":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"extension":{"type":"array","description":"FHIR extensions.","items":{"type":"object","description":"Status indicating if NHS number is present and verified.","properties":{"url":{"type":"string","description":"URL of the extension definition.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus"]},"valueCodeableConcept":{"type":"object","description":"NHS Number Verification Status Indicator.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"01"},"display":{"type":"string","description":"Representation defined by the system.","example":"Number present and verified"}}}}}}}}}}}},"meta":{"type":"object","description":"Metadata about this resource.","properties":{"versionId":{"type":"string","description":"The NHS England assigned version of the patient resource.","example":"2"},"security":{"type":"array","description":"The level of security on the patients record, which affects which fields are populated on retrieval. The possible responses are:\n* U - unrestricted. All available data is returned.\n* R - restricted. Any sensitive data around the patient's location, so `address`, `generalPractitioner` and `telecom`, are removed from the response.\n* REDACTED - redacted. The patient record has been marked as invalid, so the data should not be used. This code is never returned; you receive a 404, and appropriate error response, if an invalidated patient retrieval is attempted.\n","maxItems":1,"items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the value set specification.","example":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality"},"code":{"type":"string","description":"Code defined by the system value set.","enum":["U","R","V","REDACTED"],"example":"U"},"display":{"type":"string","description":"Representation defined by the system.","enum":["unrestricted","restricted","redacted"],"example":"unrestricted"}}}}}},"name":{"type":"array","description":"List of names associated with the patient. \n","minItems":1,"items":{"type":"object","required":["use","family"],"additionalProperties":false,"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"123"},"use":{"type":"string","description":"How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval.\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n","enum":["usual","temp","nickname","old","maiden"],"example":"usual"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"given":{"type":"array","maxItems":5,"description":"Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n","example":["Jane Marie Anne","Jo","Adele"],"items":{"type":"string","maxLength":35,"example":"Jane"}},"family":{"type":"string","maxLength":35,"description":"Family name (often called Surname).","example":"Smith"},"prefix":{"type":"array","description":"Name prefixes, titles, and prenominals.","example":["Mrs"],"items":{"type":"string","example":"Mrs"}},"suffix":{"type":"array","description":"Name suffices and postnominals.","example":["MBE","PhD"],"items":{"type":"string","example":"MBE"}}}}},"gender":{"type":"string","description":"Classification of the gender of a patient. The classification is phenotypical rather than genotypical, i.e. it does not provide codes for medical or scientific purposes.\nIt is the administrative gender that the patient wishes to be known as. In some cases, this may not be the same as the patient’s registered birth gender, or their current clinical gender.\n","enum":["male","female","other","unknown"],"example":"female"},"birthDate":{"description":"The date on which the patient was born or is officially deemed to have been born.\n\nIt is a date in the format `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned. \n","example":"2010-10-22","type":"string","format":"date"},"multipleBirthInteger":{"type":"integer","minimum":1,"maximum":9,"description":"The order in which the patient was born, with 1 indicating the first or only birth in the sequence, 2 indicating the second birth in the sequence, 3 indicating the third, and so on up to 7.\n\nThere are two other valid values; `8` meaning `Not applicable` and `9` meaning `Not known`.\n","example":1},"deceasedDateTime":{"description":"The date and time on which a person died or is officially deemed to have died, if applicable and known.\n\nIt is a datetime in the format `yyyy-mm-ddTHH:MM:SS+HH:MM` or `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned.\n","example":"2010-10-22T00:00:00+00:00","type":"string","format":"date-time","pattern":"^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$"},"address":{"type":"array","description":"List of addresses associated with the patient.\n\nThese are fully populated on a retrieval or a successful update, only the `home` address is returned on a search.\nWhen a patient tagged as `restricted` is retrieved, all addresses are removed from the response.\n","items":{"type":"object","description":"An address associated with the patient.","required":["use"],"properties":{"id":{"type":"string","description":"Unique system identifier for this address.","example":"456"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"use":{"type":"string","description":"Purpose of this address:\n * `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n * `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n * `billing` - an address used for correspondence purposes only\n * `work` - an office address. This can be returned due to legacy data but cannot be added or replaced on update\n\n A patient should have no more than one current `temp` and/or `billing` address.\n However, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\n Where multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (e.g. by examining period dates).\n\n A `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\n However additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\n When sending correspondence to a patient:\n *\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and end dates.\n *\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and end dates.\n * if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n","enum":["home","work","temp","billing"],"example":"home"},"text":{"type":"string","description":"Where a `temp` address is provided a descriptor text must be sent.\nThe list of possible values are:\n* `Second Home` - a patient's second home\n* `Student Accommodation` - a patient's place of residence while at university\n* `Respite Care Address` - where the patient resides during respite care\n* `Temporary Residence Address` - where the patient resides for a specific period of time\n* `Convalescence Home` - the address for a patient during a period of recovery\n* `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n* `Holiday Home` - the address for a patient during a holiday\n\nA patient can also register temporarily at a GP practice using a temporary address. Temporary GP registration information does not appear on the PDS, but the address used for it may.\n","enum":["Second Home","Student Accommodation","Respite Care Address","Temporary Residence Address","Convalescence Home","Mobile Home","Holiday Home"],"example":"Student Accommodation"},"line":{"type":"array","description":"All lines of the address except the postal code.\n\nSystems must apply the following formatting convention when adding or replacing addresses lines:\n*\tline 1 - premises ID and/or house name, e.g. `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, e.g. `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), e.g. `Boxgrove`\n*\tline 4 - post town, e.g. `Leeds`\n*\tline 5 - county (if present), e.g. `West Yorkshire`\n\nIf any of the lines are blank, they are not returned due to FHIR conformance constraints.\n","maxItems":5,"items":{"type":"string"},"example":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"]},"postalCode":{"type":"string","description":"Postal code of the address.","example":"LS1 6AE"},"extension":{"type":"array","description":"List of address keys formatted as a FHIR extension. This can include up to one Unique Property Reference Number (UPRN), and up to one Postal Address File (PAF) key. If no keys for the address are known, the array will be empty. Otherwise it will be a list of objects which specify the value of the address key and the code system for it","items":{"anyOf":[{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'PAF'.","enum":["PAF"],"example":"PAF"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in PAF format. An 8 digit number including leading zeroes, formatted as a string.","minLength":8,"maxLength":8,"pattern":"^[0-9]{8}$","example":"12345678"}}}]}}}},{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'UPRN'.","enum":["UPRN"],"example":"UPRN"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in UPRN format. A number containing from 1 up to 12 digits.","minLength":1,"maxLength":12,"pattern":"^[0-9]{1,12}$","example":"123456789012"}}}]}}}}]}}}}},"telecom":{"type":"array","description":"List of contact points for the patient; for example, phone numbers or email addresses.\nWhen a patient tagged as `restricted` is retrieved, all contact points are removed from the response.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}},"contact":{"type":"array","description":"A list of patient contacts. Only emergency contacts are returned and only emergency contacts should be added. Any other contacts should be added to the patients `Related Person`.\nPatients designate here any contact number they desire to be used in case of an emergency.\nNote, while a patient may also desire to record various related persons telecom details, these do not separately allow for a concept of emergency contact; only ranking. See RelatedPerson endpoint.\nWhen a patient tagged as `restricted` is retrieved, all contacts are removed from the response.\n","items":{"title":"Schema for a patient contact.","type":"object","additionalProperties":false,"required":["relationship","telecom"],"properties":{"id":{"type":"string","example":"C123"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"relationship":{"type":"array","description":"The contact relationship wrapper object that holds the details of the relationship to the patient.\n\nThis is only returned when an Emergency Contact number has been set on `telecom`. The only valid code is `C`, which means `Emergency Contact`.\n","minItems":1,"maxItems":1,"items":{"type":"object","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one contact relationship.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","format":"url","default":"http://terminology.hl7.org/CodeSystem/v2-0131"},"code":{"type":"string","description":"Coded value for contact relationship.","example":"C"},"display":{"type":"string","description":"Display-friendly representation of the contact relationship code.","example":"Emergency Contact"}}}}}}},"telecom":{"type":"array","description":"List of Telecom objects on the contact only contains `system` and `value`.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}}}}},"generalPractitioner":{"type":"array","maxItems":1,"description":"General Practice (not practitioner) with which the patient is, or was, registered. Always contains zero or one general practitioner object.\nWhen a patient tagged as `restricted` is retrieved, the General Practice is removed from the response.\n","items":{"description":"General practice (not practitioner) with which the patient is or was registered.","type":"object","required":["identifier"],"properties":{"id":{"description":"Object identifier (OID) specific to the returned details - this should be return exactly the same in any update.","type":"string","example":"254406A3"},"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}}},"managingOrganization":{"description":"The managing organization of a de-registered patient. This will not be returned when the reason for de-registration is death.","type":"object","required":["identifier"],"properties":{"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}},"extension":{"type":"array","description":"Wrapper array for the patient's pharmacies, death notification status, communication details, contact preferences and place of birth; these are all FHIR extensions.\nAlways contains zero or one of each pharmacy object, zero or one death notification status object, zero or one communication details object, zero or one contact preference and zero or one place of birth object.\nWhen a patient tagged as `restricted` is retrieved, the pharmacy and birth place extensions are removed from the response.\n","items":{"anyOf":[{"type":"object","description":"Wrapper object for the patient's nominated pharmacy. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-NominatedPharmacy FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy"]},"valueReference":{"type":"object","description":"Reference to a pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's nominated pharmacy organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the nominated pharmacy, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y12345"}}}}}}},{"type":"object","description":"Wrapper object for the patient's dispensing doctor. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-DispensingDoctor FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization"]},"valueReference":{"type":"object","description":"Reference to a GP practice pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's dispensing doctor organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the dispensing doctor, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y23456"}}}}}}},{"type":"object","description":"Wrapper object for the patient's medical appliance supplier. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-MedicalApplianceSupplier FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier"]},"valueReference":{"type":"object","description":"Reference to medical appliance supplier pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's medical appliance supplier organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the medical appliance supplier, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y34567"}}}}}}},{"type":"object","description":"Wrapper object for death notification details.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of death notification extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus"]},"extension":{"type":"array","description":"Array containing exactly one death notification status code object and exactly one effective date object.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for death notification status code.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `deathNotificationStatus`.","default":"deathNotificationStatus","enum":["deathNotificationStatus"]},"valueCodeableConcept":{"type":"object","description":"Death Notification Status.","properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["system","code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol, in syntax, defined by the system:\n* `1` - Informal - death notice received via an update from a local NHS Organisation such as GP or Trust\n* `2` - Formal - death notice received from Registrar of Deaths. Only these endpoints are allowed to add a Formal death:\n - National Back Office using the Demographic Spine Application (DSA)\n - Office of National Statistics (ONS)\n - Maternity sites\n* `U` - Removed. This is a possible response, but it cannot be used on an update because Spine will reject it\n","example":"2","enum":["1","2","U"]},"display":{"type":"string","description":"Representation defined by the system.","example":"Formal - death notice received from Registrar of Deaths","enum":["Informal - death notice received via an update from a local NHS Organisation such as GP or Trust","Formal - death notice received from Registrar of Deaths","Removed"]}}}}}}}},{"type":"object","description":"Wrapper object for death notification effective date.","required":["url","valueDateTime"],"properties":{"url":{"type":"string","description":"Key of this object. Always `systemEffectiveDate`.","default":"systemEffectiveDate","enum":["systemEffectiveDate"]},"valueDateTime":{"type":"string","description":"Date and time at which death notification status took effect.","format":"date-time","example":"2010-10-22T00:00:00+00:00"}}}]}}}},{"type":"object","description":"Wrapper object for communication details. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of communication extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication"]},"extension":{"type":"array","description":"Definition of communication extension.\n\nThe array must have one item, a valueCodeableConcept for the language and can optionally include a valueBoolean for if an interpreter is required.","minItems":1,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Wrapper object for communication language.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `language`.","default":"language","enum":["language"]},"valueCodeableConcept":{"type":"object","description":"Human language.","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one language code.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of the Language Code System. Always uses the 'UKCore-HumanLanguage' Code System.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage"},"version":{"type":"string","description":"Version of the language code system.","example":"1.0.0"},"code":{"type":"string","description":"Language code based on [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) standard plus extensions for braille, makaton and sign languages, which are:\n* `q1` - Braille\n* `q2` - American Sign Language\n* `q3` - Australian Sign Language\n* `q4` - British Sign Language\n* `q5` - Makaton\nAll valid codes combined can be found at https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage.\n","example":"fr"},"display":{"type":"string","description":"Display-friendly representation of the language code (such as English). If there is a language code with no defined mapping, `Unknown` will be returned.","example":"French"}}}}}}}},{"type":"object","description":"Wrapper object for whether an interpreter is required.","required":["url","valueBoolean"],"properties":{"url":{"type":"string","description":"Key of this object. Always `interpreterRequired`.","default":"interpreterRequired","enum":["interpreterRequired"]},"valueBoolean":{"type":"boolean","description":"Whether an interpreter is required.","example":true}}}]}}}},{"type":"object","description":"Wrapper object for preferred contact details; the written communication format, preferred contact time and method. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the contact preference extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference"]},"extension":{"description":"Wrapper array containing zero or one preferred contact method, zero or one preferred written communication format; and zero or one preferred contact time.","type":"array","maxItems":3,"items":{"oneOf":[{"type":"object","description":"Wrapper object for preferred written communication format.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredWrittenCommunicationFormat`.","default":"PreferredWrittenCommunicationFormat"},"valueCodeableConcept":{"type":"object","description":"Preferred Written Communication Format.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred written communication extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat"]},"code":{"type":"string","description":"A code to identify the preferred written communication format of a patient, contact or related person.\n* 11 - Large print\n* 12 - Braille\n* 13 - Audio tape\n","example":"12"},"display":{"type":"string","description":"Display-friendly representation of the preferred written communication format code.","example":"Braille"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact method.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactMethod`.","default":"PreferredContactMethod","enum":["PreferredContactMethod"]},"valueCodeableConcept":{"type":"object","description":"Preferred Contact Method.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred contact method extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod"]},"code":{"type":"string","description":"A code to identify to identify the preferred contact method of a patient, contact or related person.\n* 1\t- Letter\n* 2\t- Visit\n* 3\t- Telephone\n* 4\t- E-mail\n* 5\t- Minicom (Textphone)\n* 6\t- Telephone contact via proxy\n* 7\t- Sign language\n* 8\t- No Telephone contact\n","example":"1"},"display":{"type":"string","description":"Display-friendly representation of the preferred contact method code.","example":"Letter"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact times.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactTimes`.","default":"PreferredContactTimes","enum":["PreferredContactTimes"]},"valueString":{"type":"string","maximum":40,"description":"A free-text description about the preferred contact times.","example":"Not after 7pm"}}}]}}}},{"type":"object","description":"Wrapper object for place of birth details. This will not be returned on a restricted patient.","required":["url","valueAddress"],"properties":{"url":{"type":"string","description":"Definition of place of birth extension.","default":"http://hl7.org/fhir/StructureDefinition/patient-birthPlace","enum":["http://hl7.org/fhir/StructureDefinition/patient-birthPlace"]},"valueAddress":{"type":"object","additionalProperties":false,"properties":{"city":{"type":"string","description":"Town or city of birth.","example":"Manchester"},"district":{"type":"string","description":"County or metropolitan district of birth.","example":"Greater Manchester"},"country":{"type":"string","description":"A coded value for a patient's country of birth.\n\nFrom [ISO 3166-1](http://hl7.org/fhir/valueset-iso3166-1-3.html) plus codes from the UK Internal Code list which do not have entries in ISO 3166-1.\n\nUK Internal Codes:\n* `1` - England\n* `2` - Scotland\n* `3` - Wales\n* `4` - Northern Ireland\n* `7` - Sark\n* `9` - Alderney\n* `10` - Channel Islands\n","example":"GBR"}}}}},{"type":"object","description":"An extension to carry the reason a PDS record has been removed from the Patient Demographic Service. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the removal from registration extension.","default":"https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration","enum":["https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration"],"readOnly":true},"extension":{"type":"array","description":"An extension reason a PDS record has been removed from the Patient Demographic Service.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for removalFromRegistrationCode.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"To identify the removal reason code.","default":"removalFromRegistrationCode","enum":["removalFromRegistrationCode"],"readOnly":true},"valueCodeableConcept":{"type":"object","description":"PDS Removal Reason Exit Code","required":["coding"],"properties":{"coding":{"type":"array","description":"Array containing exactly one removal reason exit code object","items":{"type":"object","required":["system","code","display"],"properties":{"system":{"type":"string","format":"url","description":"URL of the Removal Reason Exit Code. Always uses the 'PDS-RemovalReasonExitCode' Code System.","example":"https://fhir.nhs.uk/CodeSystem/PDS-RemovalReasonExitCode","readOnly":true},"code":{"type":"string","description":"A CodeSystem that identifies the reason a PDS record has been removed.","example":"SCT","enum":["DEA","EMB","SCT","NIT","TRA","ORR"]},"display":{"type":"string","description":"Display-friendly representation of the removal reason exit code.","example":"Transferred to Scotland"}}}}}}}},{"type":"object","description":"Wrapper object for removal from registration effective time.","required":["url","valuePeriod"],"properties":{"url":{"type":"string","description":"Key of this object. Always `effectiveTime`.","default":"effectiveTime","enum":["effectiveTime"],"readOnly":true},"valuePeriod":{"type":"object","description":"The effective time of removal of the Patient record from PDS.","required":["start"],"properties":{"start":{"type":"string","format":"date-time","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01T00:00:00+00:00"},"end":{"type":"string","format":"date-time","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31T00:00:00+00:00"}}}}}]}}}}]}}}},"example":{"resourceType":"Patient","id":"9000000009","identifier":[{"system":"https://fhir.nhs.uk/Id/nhs-number","value":"9000000009","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus","version":"1.0.0","code":"01","display":"Number present and verified"}]}}]}],"meta":{"versionId":"2","security":[{"system":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality","code":"U","display":"unrestricted"}]},"name":[{"id":"123","use":"usual","period":{"start":"2020-01-01","end":"2021-12-31"},"given":["Jane"],"family":"Smith","prefix":["Mrs"],"suffix":["MBE"]}],"gender":"female","birthDate":"2010-10-22","multipleBirthInteger":1,"deceasedDateTime":"2010-10-22T00:00:00+00:00","generalPractitioner":[{"id":"254406A3","type":"Organization","identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345","period":{"start":"2020-01-01","end":"2021-12-31"}}}],"managingOrganization":{"type":"Organization","identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345","period":{"start":"2020-01-01","end":"2021-12-31"}}},"extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy","valueReference":{"identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y12345"}}},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization","valueReference":{"identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y23456"}}},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier","valueReference":{"identifier":{"system":"https://fhir.nhs.uk/Id/ods-organization-code","value":"Y34567"}}},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","extension":[{"url":"deathNotificationStatus","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus","version":"1.0.0","code":"2","display":"Formal - death notice received from Registrar of Deaths"}]}},{"url":"systemEffectiveDate","valueDateTime":"2010-10-22T00:00:00+00:00"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","extension":[{"url":"language","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage","version":"1.0.0","code":"fr","display":"French"}]}},{"url":"interpreterRequired","valueBoolean":true}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","extension":[{"url":"PreferredWrittenCommunicationFormat","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","code":"12","display":"Braille"}]}},{"url":"PreferredContactMethod","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","code":"1","display":"Letter"}]}},{"url":"PreferredContactTimes","valueString":"Not after 7pm"}]},{"url":"http://hl7.org/fhir/StructureDefinition/patient-birthPlace","valueAddress":{"city":"Manchester","district":"Greater Manchester","country":"GBR"}},{"url":"https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration","extension":[{"url":"removalFromRegistrationCode","valueCodeableConcept":{"coding":[{"system":"https://fhir.nhs.uk/CodeSystem/PDS-RemovalReasonExitCode","code":"SCT","display":"Transferred to Scotland"}]}},{"url":"effectiveTime","valuePeriod":{"start":"2020-01-01T00:00:00+00:00","end":"2021-12-31T00:00:00+00:00"}}]}],"telecom":[{"id":"789","period":{"start":"2020-01-01","end":"2021-12-31"},"system":"phone","value":"01632960587","use":"home"},{"id":"790","period":{"start":"2019-01-01","end":"2022-12-31"},"system":"email","value":"jane.smith@example.com","use":"home"},{"id":"OC789","period":{"start":"2020-01-01","end":"2021-12-31"},"system":"other","value":"01632960587","use":"home","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem","code":"textphone","display":"Minicom (Textphone)"}}]}],"contact":[{"id":"C123","period":{"start":"2020-01-01","end":"2021-12-31"},"relationship":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0131","code":"C","display":"Emergency Contact"}]}],"telecom":[{"system":"phone","value":"01632960587"}]}],"address":[{"id":"456","period":{"start":"2020-01-01","end":"2021-12-31"},"use":"home","line":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"],"postalCode":"LS1 6AE","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"PAF"}},{"url":"value","valueString":"12345678"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"UPRN"}},{"url":"value","valueString":"123456789012"}]}]},{"id":"T456","period":{"start":"2020-01-01","end":"2021-12-31"},"use":"temp","text":"Student Accommodation","line":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"],"postalCode":"LS1 6AE","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"PAF"}},{"url":"value","valueString":"12345678"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"UPRN"}},{"url":"value","valueString":"123456789012"}]}]}]}}}},"503":{"description":"The request timed out during processing. This does not imply the request has failed or been rejected. Error code: `SERVICE_UNAVAILABLE`.\n\nRe-send the request after the time specified in the `Retry-After` header using the same `X-Request-ID` value.\n","headers":{"RetryAfter":{"description":"Time to wait between polls in seconds","schema":{"type":"string","example":"5"}}},"content":{"application/fhir+json":{"schema":{"type":"object","description":"Outcome of an operation that does not result in a resource or bundle being returned, for example an error or an async/batch submission.\nThere are a number of possible error codes that can be returned along with a more detailed description in the `display` field.\n","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"OperationOutcome"},"issue":{"type":"array","description":"List of issues that have occurred.","minItems":1,"items":{"type":"object","required":["severity","code"],"properties":{"severity":{"type":"string","enum":["fatal","error","warning","information"],"description":"Severity of the error.","example":"error"},"code":{"type":"string","description":"FHIR error code.","example":"invalid","enum":["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"]},"details":{"type":"object","description":"Internal error code.","properties":{"coding":{"type":"array","items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"INVALID_VALUE"},"display":{"type":"string","description":"Representation defined by the system.","example":"Provided value is invalid"}}}}}},"diagnostics":{"type":"string","description":"Additional diagnostic information about the issue. This information is subject to change.","example":"Invalid value - 2019-01 in field 'birthDate'"},"expression":{"type":"string","description":"FHIRPath of element(s) related to the error.","example":"Patient.name.given"}}}}}},"example":{"resourceType":"OperationOutcome","issue":[{"severity":"error","code":"timeout","details":{"coding":[{"system":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode","version":"1","code":"SERVICE_UNAVAILABLE","display":"Service unavailable"}]},"diagnostics":"The downstream domain processing has not completed within the configured timeout period. Using the same 'X-Request-ID' header, retry your request after the time specified by the 'Retry-After' response header."}]}}}},"4XX":{"description":"An error occurred as follows:\n\n| HTTP status | Error code | Description |\n| ----------- | -------------------------- | --------------------------------------------- |\n| 400 | UNSUPPORTED_SERVICE | Missing NHS number. |\n| 400 | MISSING_VALUE | Missing header parameter. For details, see the `diagnostics` field. |\n| 400 | INVALID_VALUE | Invalid header parameter or invalid value in body of patch request. For details, see the `diagnostics` field. |\n| 400 | INVALID_UPDATE | Malformed patch request or client error after the patch was accepted and patient was not updated. For example, a start date was after the corresponding end date. |\n| 400 | INVALID_RESOURCE_ID | Invalid NHS number. |\n| 400 | VALIDATION_ERROR | This is the \"default\" error thrown when no others are applicable. |\n| 400 | UNSUPPORTED_CHARACTERS_IN_FIELD | Invalid value in body of patch request. For details, see the `diagnostics` field. |\n| 400 | ADDITIONAL_PROPERTIES | The user sent additional properties within the dictionary. For example sending a patient patch and attempting to add 'pets', which is not an allowed field within the patient resource. |\n| 400 | UNSUPPORTED_VALUE | There was an unsupported value in the request. The value may be valid in the schema - however it could be a legacy value that we do not allow to be set anymore. For example - setting the death notification status to 'removed'. The invalid value and field will be presented in the display. |\n| 400 | TOO_FEW_VALUES_SUBMITTED | The field in question has a minimum number of items and the user sent too few. |\n| 400 | TOO_MANY_VALUES_SUBMITTED | The field in question has a maximum number of items and the user sent too many. |\n| 401 | ACCESS_DENIED | Access token missing, invalid or expired, or calling application not configured for this operation. |\n| 403 | FORBIDDEN_UPDATE | The user is not permitted to update certain resources or elements, for example most users are not allowed to update the date of death once it has been set. A detailed description will be added to the display. For example - updating a sensitive patient or adding a formal death notification is only permitted from certain systems. |\n| 403 | ACCESS_DENIED | Patient cannot perform this action. |\n| 404 | RESOURCE_NOT_FOUND | Patient does not exist for given NHS number. |\n| 404 | INVALIDATED_RESOURCE | Patient record for given NHS number has been invalidated and not superseded by another NHS number. |\n| 408 | UNABLE_TO_CALL_SERVICE | The downstream domain processing has not completed within the configured timeout period. |\n| 409 | RESOURCE_VERSION_MISMATCH | The resource version in the `If-Match` header of the update request did not match the current version of the resource. See [Patient resource versioning](https://digital.nhs.uk/developer/api-catalogue/personal-demographics-service-fhir#patient-resource-versioning). |\n| 412 | PRECONDITION_FAILED | Problem with request, for example missing `If-Match` header. For details, see the `diagnostics` field. |\n| 429 | TOO_MANY_REQUESTS | You have exceeded your application's [rate limit](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#rate-limits). |\n","content":{"application/fhir+json":{"schema":{"type":"object","description":"Outcome of an operation that does not result in a resource or bundle being returned, for example an error or an async/batch submission.\nThere are a number of possible error codes that can be returned along with a more detailed description in the `display` field.\n","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"OperationOutcome"},"issue":{"type":"array","description":"List of issues that have occurred.","minItems":1,"items":{"type":"object","required":["severity","code"],"properties":{"severity":{"type":"string","enum":["fatal","error","warning","information"],"description":"Severity of the error.","example":"error"},"code":{"type":"string","description":"FHIR error code.","example":"invalid","enum":["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"]},"details":{"type":"object","description":"Internal error code.","properties":{"coding":{"type":"array","items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"INVALID_VALUE"},"display":{"type":"string","description":"Representation defined by the system.","example":"Provided value is invalid"}}}}}},"diagnostics":{"type":"string","description":"Additional diagnostic information about the issue. This information is subject to change.","example":"Invalid value - 2019-01 in field 'birthDate'"},"expression":{"type":"string","description":"FHIRPath of element(s) related to the error.","example":"Patient.name.given"}}}}}},"example":{"resourceType":"OperationOutcome","issue":[{"severity":"error","code":"structure","details":{"coding":[{"system":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode","version":"1","code":"INVALID_UPDATE","display":"Update is invalid"}]},"diagnostics":"Invalid update with error - Update unsupported for resource - 'pets'"}]}}}}}}},"/Patient/{id}/RelatedPerson":{"parameters":[{"name":"id","in":"path","description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","required":true,"schema":{"type":"string","example":"9000000009"}},{"in":"header","name":"Authorization","description":"An [OAuth 2.0 bearer token](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis).\n\nRequired in all environments except sandbox.\n","required":false,"schema":{"type":"string","format":"^Bearer\\ [[:ascii:]]+$","example":"Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM"}},{"in":"header","name":"NHSD-Session-URID","description":"\nThe user role ID (URID) for the current session. Also known as a user role profile ID (URPID).\n\nThis header is optional.\n\nIn Application-restricted access mode this header is ignored.\n\nIn Healthcare worker access mode if you send this header it must be valid for the logged-in user. See [determine the user's role](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-cis2-separate-authentication-and-authorisation#step-9-determine-the-user-s-role) for guidance.\n","required":false,"schema":{"type":"string","pattern":"^[0-9]+$","example":"555254240100"}},{"in":"header","name":"X-Request-ID","required":false,"description":"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.\n\nMust be a universally unique identifier (UUID) (ideally version 4).\n\nMirrored back in a response header.\n\nIf you re-send a failed request, use the same value in this header.\n","schema":{"type":"string","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"}},{"in":"header","name":"X-Correlation-ID","required":false,"description":"An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding `.` characters.\n\nMirrored back in a response header.\n","schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"}},{"in":"header","name":"NHSD-End-User-Organisation-ODS","required":false,"description":"The ODS code of the user.\n\nMandatory for client applications which service multiple end user organisations (EUO). This will allow the calls to be attributed to the correct EUO.\n","schema":{"type":"string","example":"Y12345"}}],"get":{"description":"## Overview\nUse this endpoint to get a patient's related people details from PDS for a given NHS number. This is a list of people who can be contacted, and how, regarding the patient. These details may be useful for a practitioner to get in contact with a next of kin or guardian.\n\n## Restricted patients\nSome patients are tagged as [restricted](https://digital.nhs.uk/services/demographics/restricting-access-to-a-patients-demographic-record) and are sometimes known as sensitive patients. Related people are not returned for a restricted patient and an empty bundle is returned.\n\nIf a related person only contains a patient reference, and when the patient is retrieved, it is restricted; location sensitive fields such as `address` and `telecom` are removed.\n\n## Sandbox test scenarios\nYou can test the following scenarios in our sandbox environment:\n\n| Scenario | Request | Response |\n| ------------------------------- | --------------------------------------------- | ------------------------------------------------------------- |\n| Multiple related people exists | `id`=`9000000009` | HTTP Status 200 with related person data in a response Bundle |\n| Single related person exists | `id`=`9000000017` | HTTP Status 200 with related person data in a response Bundle |\n| Related people do not exist | `id`=`9000000025` | HTTP Status 200 with an empty bundle |\n| Missing X-Request-ID | `id`=`9000000009` (or any other valid NHS number) | HTTP Status 412 with problem description |\n\nYou can try out the sandbox using the 'Try this API' feature on this page.\n\nAlternatively, you can try out the sandbox using our Postman collection:\n\n[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/14719036-953f067f-30b9-4552-8252-7cc10b21dad3)\n","summary":"Get a patient's related people","operationId":"get-related-people","responses":{"200":{"description":"Information successfully returned.","headers":{"ETag":{"schema":{"type":"string","pattern":"^W/\"[0-9]+\"$","example":"W/\"2\""},"description":"Record version identifier enclosed in quotes and preceded by 'W/'. For example, `W/\"2\"`.\n\nCorresponds to `meta.versionId` attribute in the patient resource body.\n\nWhen you retrieve a patient resource, you get a version number for the resource (in the `ETag` response header and in the `versionId` field in the response).\nYou must then pass the resource's version number in any update request (in the `If-Match` response header) made for the patient.\n"},"X-Correlation-Id":{"schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"},"description":"The X-Correlation-ID from the request header, if supplied, mirrored back.\n"},"X-Request-Id":{"schema":{"type":"string","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"},"description":"The X-Request-ID from the request header, if supplied, mirrored back.\n"}},"content":{"application/fhir+json":{"schema":{"type":"object","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"Bundle"},"type":{"type":"string","description":"FHIR Bundle Type.","default":"searchset"},"timestamp":{"type":"string","description":"Time the search was performed.","format":"datetime","example":"2019-12-25T12:00:00+00:00"},"total":{"type":"integer","description":"Number of resources returned in search.","example":1},"entry":{"type":"array","description":"A list of related people details attached to the patient. \n","items":{"type":"object","properties":{"fullUrl":{"type":"string","description":"Absolute URL of the resource described in this item.","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/9000000009/RelatedPerson/507B7621"},"resource":{"type":"object","additionalProperties":false,"required":["patient","relationship"],"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"507B7621"},"resourceType":{"type":"string","description":"FHIR resource type.","default":"RelatedPerson"},"patient":{"type":"object","required":["type"],"properties":{"type":{"type":"string","default":"Patient","enum":["Patient"]},"identifier":{"type":"object","description":"Identifier and system of identification used for this Patient.\n\nThis is an optional field as related person details are either a reference to another NHS number, or the details, such as name and adress, stored directly on the resource.\n","properties":{"system":{"type":"string","description":"URL for the Patient retrieval API.","format":"url","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient"},"value":{"type":"string","description":"NHS number for the related person","example":"90000000009","pattern":"^\\d{10}$"}}},"reference":{"type":"string","description":"URL for the FHIR Patient resource.","format":"url","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/90000000009"}}},"active":{"type":"boolean","default":true},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"name":{"type":"array","description":"List containing zero or one name associated with the related person.\nThis is an optional field as there may be a `patient` reference which can be used to retrieve any details about the related person.\nIf no `patient` reference is available `name` and `address` must be provided at the minimum.\n","maxItems":1,"items":{"type":"object","required":["use","family"],"additionalProperties":false,"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"123"},"use":{"type":"string","description":"How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval.\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n","enum":["usual","temp","nickname","old","maiden"],"example":"usual"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"given":{"type":"array","maxItems":5,"description":"Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n","example":["Jane Marie Anne","Jo","Adele"],"items":{"type":"string","maxLength":35,"example":"Jane"}},"family":{"type":"string","maxLength":35,"description":"Family name (often called Surname).","example":"Smith"},"prefix":{"type":"array","description":"Name prefixes, titles, and prenominals.","example":["Mrs"],"items":{"type":"string","example":"Mrs"}},"suffix":{"type":"array","description":"Name suffices and postnominals.","example":["MBE","PhD"],"items":{"type":"string","example":"MBE"}}}}},"address":{"type":"array","description":"List containing zero or one address associated with the related person.\nThis is an optional field as there may be a `patient` reference which can be used to retrieve any details about the related person.\nIf no `patient` reference is available `name` and `address` must be provided at the minimum.\n","maxItems":1,"items":{"type":"object","description":"An address associated with the patient.","required":["use"],"properties":{"id":{"type":"string","description":"Unique system identifier for this address.","example":"456"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"use":{"type":"string","description":"Purpose of this address:\n * `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n * `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n * `billing` - an address used for correspondence purposes only\n * `work` - an office address. This can be returned due to legacy data but cannot be added or replaced on update\n\n A patient should have no more than one current `temp` and/or `billing` address.\n However, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\n Where multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (e.g. by examining period dates).\n\n A `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\n However additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\n When sending correspondence to a patient:\n *\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and end dates.\n *\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and end dates.\n * if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n","enum":["home","work","temp","billing"],"example":"home"},"text":{"type":"string","description":"Where a `temp` address is provided a descriptor text must be sent.\nThe list of possible values are:\n* `Second Home` - a patient's second home\n* `Student Accommodation` - a patient's place of residence while at university\n* `Respite Care Address` - where the patient resides during respite care\n* `Temporary Residence Address` - where the patient resides for a specific period of time\n* `Convalescence Home` - the address for a patient during a period of recovery\n* `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n* `Holiday Home` - the address for a patient during a holiday\n\nA patient can also register temporarily at a GP practice using a temporary address. Temporary GP registration information does not appear on the PDS, but the address used for it may.\n","enum":["Second Home","Student Accommodation","Respite Care Address","Temporary Residence Address","Convalescence Home","Mobile Home","Holiday Home"],"example":"Student Accommodation"},"line":{"type":"array","description":"All lines of the address except the postal code.\n\nSystems must apply the following formatting convention when adding or replacing addresses lines:\n*\tline 1 - premises ID and/or house name, e.g. `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, e.g. `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), e.g. `Boxgrove`\n*\tline 4 - post town, e.g. `Leeds`\n*\tline 5 - county (if present), e.g. `West Yorkshire`\n\nIf any of the lines are blank, they are not returned due to FHIR conformance constraints.\n","maxItems":5,"items":{"type":"string"},"example":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"]},"postalCode":{"type":"string","description":"Postal code of the address.","example":"LS1 6AE"},"extension":{"type":"array","description":"List of address keys formatted as a FHIR extension. This can include up to one Unique Property Reference Number (UPRN), and up to one Postal Address File (PAF) key. If no keys for the address are known, the array will be empty. Otherwise it will be a list of objects which specify the value of the address key and the code system for it","items":{"anyOf":[{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'PAF'.","enum":["PAF"],"example":"PAF"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in PAF format. An 8 digit number including leading zeroes, formatted as a string.","minLength":8,"maxLength":8,"pattern":"^[0-9]{8}$","example":"12345678"}}}]}}}},{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'UPRN'.","enum":["UPRN"],"example":"UPRN"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in UPRN format. A number containing from 1 up to 12 digits.","minLength":1,"maxLength":12,"pattern":"^[0-9]{1,12}$","example":"123456789012"}}}]}}}}]}}}}},"telecom":{"type":"array","description":"List containing zero to five contact methods associated with the related person.\nThis is an optional field as there may be a `patient` reference which can be used to retrieve any details about the related person.\n","maxItems":5,"items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}},"relationship":{"type":"array","description":"The relationship of the related person to the patient.\n","minItems":1,"maxItems":1,"items":{"type":"object","required":["coding"],"properties":{"coding":{"type":"array","description":"Coded values for three relationship types:\n* Role\n* Type\n* Next-of-Kin\n\nThe codes used can be found at:\n* http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\n* https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole\n\nThe allowed values for `Role` are:\n* Agent - Agent of patient\n* Guardian - Guardian of patient\n* Personal - Personal relationship with the patient\n\nThe allowed values for `Type` are:\n* SPS - spouse\n* DOMPART - domestic partner\n* PRN - parent\n* PRNFOST - foster parent\n* STPPRN - step parent\n* CHILD - child\n* MTH - mother\n* FTH - father\n* SIS - sister\n* BRO - brother\n* FAMMEMB - family member\n* ONESELF - self\n* N - Next-of-Kin\n* U - Unknown\n* PolygamousPartner - Polygamous Partner of patient\n* Dependant - Dependant of patient\n* NonDependant - Non Dependant of patient\n* ProxyContact - Proxy Contact for patient\n* ProxyCommunication - Proxy Communication for patient\n* ProxyContactCommunication - Proxy Contact and Communication for patient\n* Carer - Carer of patient\n* Guardian - Guardian of patient\n* NotSpecified - Not Specified\n\nThe allowed values for `Next-of-Kin` are:\n* N - Next-of-Kin\n\n`Role` and `Type` are mandatory, so both should be present - however they both contain the `Guardian` code - so a single response is possible.\n\n`Next-of-Kin` is optional and will be absent from the response when the related person is not the Next-of-Kin.\n","minItems":1,"maxItems":3,"items":{"type":"object","required":["system","code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","format":"url","default":"https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole","enum":["http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype","https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole"]},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"Guardian"},"display":{"type":"string","description":"Human-friendly display representation defined by the system.","example":"Guardian of patient"}}}}}}},"extension":{"type":"array","description":"Wrapper array for copy correspondence, contact rank, contact preferences and communication details; these are all FHIR extensions. Always contains zero or one of each extension type.\n","items":{"anyOf":[{"type":"object","description":"Flag indicating if this person should be copied in on any contact with the Patient. This will only be returned if the value is true and the person should be copied in on correspondence, otherwise it will be omitted. \n","properties":{"url":{"type":"string","format":"url","description":"URL to FHIR Extension Specification.","default":"https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-CopyCorrespondenceIndicator","enum":["https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-CopyCorrespondenceIndicator"]},"valueBoolean":{"type":"boolean","description":"Flag indicating if this person should be copied in on correspondence. This will only be returned if the value is `true` otherwise it will not be returned and can be assumed `false`","example":true}}},{"type":"object","description":"Rank indicating order in which contacts should be tried.","properties":{"url":{"type":"string","format":"url","description":"URL to FHIR Extension Specification.","default":"https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-ContactRank","enum":["https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-ContactRank"]},"valuePositiveInt":{"type":"integer","minimum":1,"maximum":99,"description":"Rank expressed as positive integer (1 being the highest).","example":1}}},{"type":"object","description":"Wrapper object for preferred contact details; the written communication format, preferred contact time and method. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the contact preference extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference"]},"extension":{"description":"Wrapper array containing zero or one preferred contact method, zero or one preferred written communication format; and zero or one preferred contact time.","type":"array","maxItems":3,"items":{"oneOf":[{"type":"object","description":"Wrapper object for preferred written communication format.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredWrittenCommunicationFormat`.","default":"PreferredWrittenCommunicationFormat"},"valueCodeableConcept":{"type":"object","description":"Preferred Written Communication Format.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred written communication extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat"]},"code":{"type":"string","description":"A code to identify the preferred written communication format of a patient, contact or related person.\n* 11 - Large print\n* 12 - Braille\n* 13 - Audio tape\n","example":"12"},"display":{"type":"string","description":"Display-friendly representation of the preferred written communication format code.","example":"Braille"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact method.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactMethod`.","default":"PreferredContactMethod","enum":["PreferredContactMethod"]},"valueCodeableConcept":{"type":"object","description":"Preferred Contact Method.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred contact method extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod"]},"code":{"type":"string","description":"A code to identify to identify the preferred contact method of a patient, contact or related person.\n* 1\t- Letter\n* 2\t- Visit\n* 3\t- Telephone\n* 4\t- E-mail\n* 5\t- Minicom (Textphone)\n* 6\t- Telephone contact via proxy\n* 7\t- Sign language\n* 8\t- No Telephone contact\n","example":"1"},"display":{"type":"string","description":"Display-friendly representation of the preferred contact method code.","example":"Letter"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact times.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactTimes`.","default":"PreferredContactTimes","enum":["PreferredContactTimes"]},"valueString":{"type":"string","maximum":40,"description":"A free-text description about the preferred contact times.","example":"Not after 7pm"}}}]}}}},{"type":"object","description":"Wrapper object for communication details. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of communication extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication"]},"extension":{"type":"array","description":"Definition of communication extension.\n\nThe array must have one item, a valueCodeableConcept for the language and can optionally include a valueBoolean for if an interpreter is required.","minItems":1,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Wrapper object for communication language.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `language`.","default":"language","enum":["language"]},"valueCodeableConcept":{"type":"object","description":"Human language.","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one language code.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of the Language Code System. Always uses the 'UKCore-HumanLanguage' Code System.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage"},"version":{"type":"string","description":"Version of the language code system.","example":"1.0.0"},"code":{"type":"string","description":"Language code based on [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) standard plus extensions for braille, makaton and sign languages, which are:\n* `q1` - Braille\n* `q2` - American Sign Language\n* `q3` - Australian Sign Language\n* `q4` - British Sign Language\n* `q5` - Makaton\nAll valid codes combined can be found at https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage.\n","example":"fr"},"display":{"type":"string","description":"Display-friendly representation of the language code (such as English). If there is a language code with no defined mapping, `Unknown` will be returned.","example":"French"}}}}}}}},{"type":"object","description":"Wrapper object for whether an interpreter is required.","required":["url","valueBoolean"],"properties":{"url":{"type":"string","description":"Key of this object. Always `interpreterRequired`.","default":"interpreterRequired","enum":["interpreterRequired"]},"valueBoolean":{"type":"boolean","description":"Whether an interpreter is required.","example":true}}}]}}}}]}}}}}}}}},"example":{"resourceType":"Bundle","type":"searchset","timestamp":"2019-12-25T12:00:00+00:00","total":1,"entry":[{"fullUrl":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/9000000009/RelatedPerson/507B7621","resource":{"id":"507B7621","resourceType":"RelatedPerson","patient":{"type":"Patient","identifier":{"system":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient","value":"90000000009"},"reference":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/90000000009"},"active":true,"period":{"start":"2020-01-01","end":"2021-12-31"},"name":[{"use":"usual","period":{"start":"2020-01-01","end":"2021-12-31"},"given":["Jane"],"family":"Smith","prefix":["Mrs"],"suffix":["MBE"]}],"relationship":[{"coding":[{"system":"https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole","code":"Guardian","display":"Guardian of patient"}]}],"extension":[{"url":"https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-CopyCorrespondenceIndicator","valueBoolean":true},{"url":"https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-ContactRank","valuePositiveInt":1},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","extension":[{"url":"PreferredWrittenCommunicationFormat","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","code":"12","display":"Braille"}]}},{"url":"PreferredContactMethod","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","code":"1","display":"Letter"}]}},{"url":"PreferredContactTimes","valueString":"Not after 7pm"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","extension":[{"url":"language","valueCodeableConcept":{"coding":[{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage","version":"1.0.0","code":"fr","display":"French"}]}},{"url":"interpreterRequired","valueBoolean":true}]}],"telecom":[{"period":{"start":"2020-01-01","end":"2021-12-31"},"system":"phone","value":"01632960587","use":"home"}],"address":[{"period":{"start":"2020-01-01","end":"2021-12-31"},"use":"home","line":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"],"postalCode":"LS1 6AE","extension":[{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"PAF"}},{"url":"value","valueString":"12345678"}]},{"url":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","extension":[{"url":"type","valueCoding":{"system":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType","code":"UPRN"}},{"url":"value","valueString":"123456789012"}]}]}]}}]}}}},"4XX":{"description":"An error occurred as follows:\n\n| HTTP status | Error code | Description |\n| ----------- | -------------------------- | --------------------------------------------- |\n| 400 | INVALID_RESOURCE_ID | Invalid NHS number. |\n| 400 | MISSING_VALUE | Missing header parameter. For details, see the `diagnostics` field. |\n| 400 | INVALID_VALUE | Invalid header parameter. For details, see the `diagnostics` field. |\n| 401 | ACCESS_DENIED | Access token missing, invalid or expired, or calling application not configured for this operation. |\n| 404 | RESOURCE_NOT_FOUND | No related people exist for given NHS number. |\n| 404 | INVALIDATED_RESOURCE | Patient record for given NHS number has been invalidated and not superseded by another NHS number. |\n| 408 | UNABLE_TO_CALL_SERVICE | The downstream domain processing has not completed within the configured timeout period. |\n| 429 | TOO_MANY_REQUESTS | You have exceeded your application's [rate limit](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#rate-limits). |\n","content":{"application/fhir+json":{"schema":{"type":"object","description":"Outcome of an operation that does not result in a resource or bundle being returned, for example an error or an async/batch submission.\nThere are a number of possible error codes that can be returned along with a more detailed description in the `display` field.\n","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"OperationOutcome"},"issue":{"type":"array","description":"List of issues that have occurred.","minItems":1,"items":{"type":"object","required":["severity","code"],"properties":{"severity":{"type":"string","enum":["fatal","error","warning","information"],"description":"Severity of the error.","example":"error"},"code":{"type":"string","description":"FHIR error code.","example":"invalid","enum":["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"]},"details":{"type":"object","description":"Internal error code.","properties":{"coding":{"type":"array","items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"INVALID_VALUE"},"display":{"type":"string","description":"Representation defined by the system.","example":"Provided value is invalid"}}}}}},"diagnostics":{"type":"string","description":"Additional diagnostic information about the issue. This information is subject to change.","example":"Invalid value - 2019-01 in field 'birthDate'"},"expression":{"type":"string","description":"FHIRPath of element(s) related to the error.","example":"Patient.name.given"}}}}}},"example":{"resourceType":"OperationOutcome","issue":[{"severity":"error","code":"structure","details":{"coding":[{"system":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode","version":"1","code":"PRECONDITION_FAILED","display":"Required condition was not fulfilled"}]},"diagnostics":"Invalid request with error - X-Request-ID header must be supplied to access this resource"}]}}}}}}}},"components":{"headers":{"ETag":{"schema":{"type":"string","pattern":"^W/\"[0-9]+\"$","example":"W/\"2\""},"description":"Record version identifier enclosed in quotes and preceded by 'W/'. For example, `W/\"2\"`.\n\nCorresponds to `meta.versionId` attribute in the patient resource body.\n\nWhen you retrieve a patient resource, you get a version number for the resource (in the `ETag` response header and in the `versionId` field in the response).\nYou must then pass the resource's version number in any update request (in the `If-Match` response header) made for the patient.\n"},"X-Correlation-Id":{"schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"},"description":"The X-Correlation-ID from the request header, if supplied, mirrored back.\n"},"X-Request-Id":{"schema":{"type":"string","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"},"description":"The X-Request-ID from the request header, if supplied, mirrored back.\n"},"RetryAfter":{"description":"Time to wait between polls in seconds","schema":{"type":"string","example":"5"}}},"parameters":{"Id":{"name":"id","in":"path","description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","required":true,"schema":{"type":"string","example":"9000000009"}},"MessageId":{"name":"message_id","in":"path","description":"The message ID of the accepted update that needs to be submitted to confirm the resource a successfully updated.","required":true,"schema":{"type":"string","example":"20200522091633363041_000001A"}},"ObjectId":{"name":"object_id","in":"path","description":"A resource Object ID. The primary identifier of a resource.","required":true,"schema":{"type":"string","example":"507B7621"}},"IfMatch":{"in":"header","name":"If-Match","description":"Latest known version identifier enclosed in quotes preceded by `W/`.\n\nSend the value of the patient's `ETag` response header on patient retrieval when updating a patient.\nThis is to ensure that any updates are applied against an up-to-date version of the patient resource.\n","required":true,"schema":{"type":"string","pattern":"^W/\"[0-9]+\"$","example":"W/\"2\""}},"RoleId":{"in":"header","name":"NHSD-Session-URID","description":"\nThe user role ID (URID) for the current session. Also known as a user role profile ID (URPID).\n\nThis header is optional.\n\nIn Application-restricted access mode this header is ignored.\n\nIn Healthcare worker access mode if you send this header it must be valid for the logged-in user. See [determine the user's role](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-cis2-separate-authentication-and-authorisation#step-9-determine-the-user-s-role) for guidance.\n","required":false,"schema":{"type":"string","pattern":"^[0-9]+$","example":"555254240100"}},"BearerAuthorization":{"in":"header","name":"Authorization","description":"An [OAuth 2.0 bearer token](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis).\n\nRequired in all environments except sandbox.\n","required":false,"schema":{"type":"string","format":"^Bearer\\ [[:ascii:]]+$","example":"Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM"}},"ContentType":{"in":"header","name":"Content-Type","description":"For a PATCH request, this must be set to `application/json-patch+json`.\n","required":true,"schema":{"type":"string","example":"application/json-patch+json"}},"RequestID":{"in":"header","name":"X-Request-ID","required":false,"description":"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.\n\nMust be a universally unique identifier (UUID) (ideally version 4).\n\nMirrored back in a response header.\n\nIf you re-send a failed request, use the same value in this header.\n","schema":{"type":"string","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"}},"CorrelationID":{"in":"header","name":"X-Correlation-ID","required":false,"description":"An optional ID which you can use to track transactions across multiple systems. It can take any value, but we recommend avoiding `.` characters.\n\nMirrored back in a response header.\n","schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"}},"NHSD-End-User-Organisation-ODS":{"in":"header","name":"NHSD-End-User-Organisation-ODS","required":false,"description":"The ODS code of the user.\n\nMandatory for client applications which service multiple end user organisations (EUO). This will allow the calls to be attributed to the correct EUO.\n","schema":{"type":"string","example":"Y12345"}},"FuzzyMatch":{"name":"_fuzzy-match","description":"A fuzzy search is performed, including checks for homophones, transposed names and historic information.\n\nYou cannot use wildcards with a fuzzy search.\n","example":false,"in":"query","required":false,"schema":{"type":"boolean","default":false}},"ExactMatch":{"name":"_exact-match","description":"The search only returns results where the `score` field is 1.0. Use this with care - it is unlikely to work with fuzzy search or wildcards.","example":false,"in":"query","required":false,"schema":{"type":"boolean","default":false}},"History":{"name":"_history","description":"The search looks for matches in historic information such as previous names and addresses.\n\nThis parameter has no effect for a fuzzy search, which always includes historic information.\n","example":true,"in":"query","required":false,"schema":{"type":"boolean","default":false}},"MaxResults":{"name":"_max-results","description":"The maximum number of matching patients to return. For healthcare worker access, this must be between 1 and 50, and the default is 50.\nFor application-restricted access, this must be 1, and the default is 1.\nIf too many patients match the search criteria, we return a `TOO_MANY_MATCHES` error.\n","example":1,"in":"query","required":false,"schema":{"type":"integer","format":"int32"}},"Family":{"name":"family","description":"The patient's family name (surname).\n\nNot case sensitive. Max 35 characters.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n","examples":{"simple":{"value":"Smith","summary":"Matches Smythe if `_fuzzy-match` is specified."},"wildcarded":{"value":"Sm*t*","summary":"Wildcards must contain at least two characters, this matches Smith, Smythe"}},"in":"query","required":false,"schema":{"type":"string"}},"Given":{"name":"given","description":"The patient's given names.\n\nNot case sensitive. Max 35 characters.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nWildcard searches will match the start of the first given name and not subsequent given names, for example the given names \"Alan Michael\" can be searched with \"Ala*\" but not \"Mic*\".\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n\nA patient may have more than one given name. Subsequent given names are commonly referred to as 'middle names'.\nSpecify multiple given names by repeating this parameter.\nTo search for `Jane Anne Smith` use `given=Jane&given=Anne&family=Smith`.\n\nThe first given name may be a [compound name](https://en.wikipedia.org/wiki/Given_name#Compound), for example `John Paul`.\nTo search for `John Paul James Smith` (where `John Paul` is the first given name, `James` is the second given name, and `Smith` the family name) use `given=John%20Paul&given=James&family=Smith`.\n\nNote that it is not necessary to specify subsequent given (middle) names, and that doing so may impact your search results in the case they are not recorded in the demographics system.\n","example":"Jane","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}}},"Gender":{"name":"gender","description":"Gender with which the patient most strongly identifies.","example":"female","in":"query","required":false,"schema":{"type":"string","enum":["male","female","other","unknown"],"example":"female"}},"Birthdate":{"name":"birthdate","in":"query","description":"Date of birth in the format `yyyy-mm-dd`. To specify a range, use `birthdate=geyyyy-mm-dd&birthdate=leyyyy-mm-dd`.","examples":{"simple":{"value":["eq2010-10-22"],"description":"Exact match date"},"rangege":{"value":["ge2010-10-22"],"description":"Greater than or equals match, which matches 2010-10-22 or 2010-10-23"},"rangele":{"value":["le2010-10-22"],"description":"Less than or equals match, which matches 2010-10-22 or 2010-10-21"}},"required":false,"schema":{"type":"array","items":{"type":"string"}}},"DeathDate":{"name":"death-date","in":"query","description":"Date of death in the format `yyyy-mm-dd`. To specify a range, use `death-date=geyyyy-mm-dd&death-date=leyyyy-mm-dd`.\n\nFor a fuzzy search, this is ignored for matching but included in the score calculation.\n","examples":{"simple":{"value":"eq2010-10-22","description":"Exact match date"},"rangege":{"value":"ge2010-10-22","description":"Greater than or equals match which matches 2010-10-22 or 2010-10-23"},"rangele":{"value":"le2010-10-22","description":"Less than or equals match, which matches 2010-10-22 or 2010-10-21"}},"required":false,"schema":{"type":"string","format":"date"}},"AddressPostalcode":{"name":"address-postalcode","description":"The postcode of any of the patient’s known addresses.\n\nNot case sensitive.\nSpaces are ignored, for example `LS16AE` and `LS1 6AE` both match `LS1 6AE`.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n","examples":{"simple":{"value":"LS1 6AE","summary":"Spaces ignored, would match LS16AE"},"wildcarded":{"value":"LS1*","summary":"Matches 'LS16AE', 'LS1 6AE' and 'LS1 6AB'"}},"in":"query","required":false,"schema":{"type":"string"}},"AddressPostcode":{"name":"address-postcode","description":"**N.B. that address-postcode will be deprecated in the future, address-postalcode should be used instead. \nIf both address-postcode and address-postalcode are provided, an INVALID_SEARCH_DATA error will be returned.**\nThe postcode of any of the patient’s known addresses.\n\nNot case sensitive.\nSpaces are ignored, for example `LS16AE` and `LS1 6AE` both match `LS1 6AE`.\nUse `*` as a wildcard but not in the first two characters and not in fuzzy search mode.\nMust be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding), for example a space must be represented by either `%20` or `+` and a wildcard must be encoded as `%2A`.\n","examples":{"simple":{"value":"LS1 6AE","summary":"Spaces ignored, would match LS16AE"},"wildcarded":{"value":"LS1*","summary":"Matches 'LS16AE', 'LS1 6AE' and 'LS1 6AB'"}},"in":"query","required":false,"schema":{"type":"string"}},"GeneralPractitioner":{"name":"general-practitioner","description":"The Organisation Data Service (ODS) code of the patient's registered GP practice.\n\nNot case sensitive.\nFor a fuzzy search, this is ignored for matching but included in the score calculation.\n","example":"Y12345","in":"query","required":false,"schema":{"type":"string"}},"ManagingOrganization":{"name":"managing-organization","description":"**This field is for internal-use only**.\n\nThe Organisation Data Service (ODS) code of the patient's current managing organization.\nNot case sensitive.\nFor a fuzzy search, this is ignored for matching but included in the score calculation.\n","example":"Y12345","in":"query","required":false,"schema":{"type":"string"}},"ETag":{"name":"etag","schema":{"type":"string","pattern":"^W/\"[0-9]+\"$","example":"W/\"2\""},"in":"header","description":"Record version identifier enclosed in quotes and preceded by 'W/'. For example, `W/\"2\"`.\n\nCorresponds to `meta.versionId` attribute in the patient resource body.\n\nWhen you retrieve a patient resource, you get a version number for the resource (in the `ETag` response header and in the `versionId` field in the response).\nYou must then pass the resource's version number in any update request (in the `If-Match` response header) made for the patient.\n"},"XCorrelationId":{"name":"x-correlation-id","schema":{"type":"string","example":"11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"},"in":"header","description":"The X-Correlation-ID from the request header, if supplied, mirrored back.\n"},"XRequestID":{"name":"x-request-id","schema":{"type":"string","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"},"in":"header","description":"The X-Request-ID from the request header, if supplied, mirrored back.\n"},"RetryAfter":{"name":"retry-after","description":"Time to wait before retrying your request in seconds","in":"header","schema":{"type":"string","example":"5"}},"EmailAddress":{"name":"email","description":"Email address\n","example":"jane.smith@example.com","in":"query","required":false,"schema":{"type":"string"}},"PhoneNumber":{"name":"phone","description":"Phone number\n","example":"01632960587","in":"query","required":false,"schema":{"type":"string"}}},"schemas":{"Patient":{"type":"object","required":["id"],"additionalProperties":false,"properties":{"resourceType":{"type":"string","description":"FHIR resource type.","default":"Patient"},"id":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"identifier":{"type":"array","description":"Identifier and system of identification used for this Patient.","items":{"type":"object","maxItems":1,"required":["value"],"properties":{"system":{"type":"string","format":"url","description":"System identifier belongs to.","default":"https://fhir.nhs.uk/Id/nhs-number"},"value":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"extension":{"type":"array","description":"FHIR extensions.","items":{"type":"object","description":"Status indicating if NHS number is present and verified.","properties":{"url":{"type":"string","description":"URL of the extension definition.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus"]},"valueCodeableConcept":{"type":"object","description":"NHS Number Verification Status Indicator.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"01"},"display":{"type":"string","description":"Representation defined by the system.","example":"Number present and verified"}}}}}}}}}}}},"meta":{"type":"object","description":"Metadata about this resource.","properties":{"versionId":{"type":"string","description":"The NHS England assigned version of the patient resource.","example":"2"},"security":{"type":"array","description":"The level of security on the patients record, which affects which fields are populated on retrieval. The possible responses are:\n* U - unrestricted. All available data is returned.\n* R - restricted. Any sensitive data around the patient's location, so `address`, `generalPractitioner` and `telecom`, are removed from the response.\n* REDACTED - redacted. The patient record has been marked as invalid, so the data should not be used. This code is never returned; you receive a 404, and appropriate error response, if an invalidated patient retrieval is attempted.\n","maxItems":1,"items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the value set specification.","example":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality"},"code":{"type":"string","description":"Code defined by the system value set.","enum":["U","R","V","REDACTED"],"example":"U"},"display":{"type":"string","description":"Representation defined by the system.","enum":["unrestricted","restricted","redacted"],"example":"unrestricted"}}}}}},"name":{"type":"array","description":"List of names associated with the patient. \n","minItems":1,"items":{"type":"object","required":["use","family"],"additionalProperties":false,"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"123"},"use":{"type":"string","description":"How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval.\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n","enum":["usual","temp","nickname","old","maiden"],"example":"usual"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"given":{"type":"array","maxItems":5,"description":"Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n","example":["Jane Marie Anne","Jo","Adele"],"items":{"type":"string","maxLength":35,"example":"Jane"}},"family":{"type":"string","maxLength":35,"description":"Family name (often called Surname).","example":"Smith"},"prefix":{"type":"array","description":"Name prefixes, titles, and prenominals.","example":["Mrs"],"items":{"type":"string","example":"Mrs"}},"suffix":{"type":"array","description":"Name suffices and postnominals.","example":["MBE","PhD"],"items":{"type":"string","example":"MBE"}}}}},"gender":{"type":"string","description":"Classification of the gender of a patient. The classification is phenotypical rather than genotypical, i.e. it does not provide codes for medical or scientific purposes.\nIt is the administrative gender that the patient wishes to be known as. In some cases, this may not be the same as the patient’s registered birth gender, or their current clinical gender.\n","enum":["male","female","other","unknown"],"example":"female"},"birthDate":{"description":"The date on which the patient was born or is officially deemed to have been born.\n\nIt is a date in the format `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned. \n","example":"2010-10-22","type":"string","format":"date"},"multipleBirthInteger":{"type":"integer","minimum":1,"maximum":9,"description":"The order in which the patient was born, with 1 indicating the first or only birth in the sequence, 2 indicating the second birth in the sequence, 3 indicating the third, and so on up to 7.\n\nThere are two other valid values; `8` meaning `Not applicable` and `9` meaning `Not known`.\n","example":1},"deceasedDateTime":{"description":"The date and time on which a person died or is officially deemed to have died, if applicable and known.\n\nIt is a datetime in the format `yyyy-mm-ddTHH:MM:SS+HH:MM` or `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned.\n","example":"2010-10-22T00:00:00+00:00","type":"string","format":"date-time","pattern":"^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$"},"address":{"type":"array","description":"List of addresses associated with the patient.\n\nThese are fully populated on a retrieval or a successful update, only the `home` address is returned on a search.\nWhen a patient tagged as `restricted` is retrieved, all addresses are removed from the response.\n","items":{"type":"object","description":"An address associated with the patient.","required":["use"],"properties":{"id":{"type":"string","description":"Unique system identifier for this address.","example":"456"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"use":{"type":"string","description":"Purpose of this address:\n * `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n * `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n * `billing` - an address used for correspondence purposes only\n * `work` - an office address. This can be returned due to legacy data but cannot be added or replaced on update\n\n A patient should have no more than one current `temp` and/or `billing` address.\n However, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\n Where multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (e.g. by examining period dates).\n\n A `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\n However additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\n When sending correspondence to a patient:\n *\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and end dates.\n *\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and end dates.\n * if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n","enum":["home","work","temp","billing"],"example":"home"},"text":{"type":"string","description":"Where a `temp` address is provided a descriptor text must be sent.\nThe list of possible values are:\n* `Second Home` - a patient's second home\n* `Student Accommodation` - a patient's place of residence while at university\n* `Respite Care Address` - where the patient resides during respite care\n* `Temporary Residence Address` - where the patient resides for a specific period of time\n* `Convalescence Home` - the address for a patient during a period of recovery\n* `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n* `Holiday Home` - the address for a patient during a holiday\n\nA patient can also register temporarily at a GP practice using a temporary address. Temporary GP registration information does not appear on the PDS, but the address used for it may.\n","enum":["Second Home","Student Accommodation","Respite Care Address","Temporary Residence Address","Convalescence Home","Mobile Home","Holiday Home"],"example":"Student Accommodation"},"line":{"type":"array","description":"All lines of the address except the postal code.\n\nSystems must apply the following formatting convention when adding or replacing addresses lines:\n*\tline 1 - premises ID and/or house name, e.g. `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, e.g. `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), e.g. `Boxgrove`\n*\tline 4 - post town, e.g. `Leeds`\n*\tline 5 - county (if present), e.g. `West Yorkshire`\n\nIf any of the lines are blank, they are not returned due to FHIR conformance constraints.\n","maxItems":5,"items":{"type":"string"},"example":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"]},"postalCode":{"type":"string","description":"Postal code of the address.","example":"LS1 6AE"},"extension":{"type":"array","description":"List of address keys formatted as a FHIR extension. This can include up to one Unique Property Reference Number (UPRN), and up to one Postal Address File (PAF) key. If no keys for the address are known, the array will be empty. Otherwise it will be a list of objects which specify the value of the address key and the code system for it","items":{"anyOf":[{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'PAF'.","enum":["PAF"],"example":"PAF"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in PAF format. An 8 digit number including leading zeroes, formatted as a string.","minLength":8,"maxLength":8,"pattern":"^[0-9]{8}$","example":"12345678"}}}]}}}},{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'UPRN'.","enum":["UPRN"],"example":"UPRN"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in UPRN format. A number containing from 1 up to 12 digits.","minLength":1,"maxLength":12,"pattern":"^[0-9]{1,12}$","example":"123456789012"}}}]}}}}]}}}}},"telecom":{"type":"array","description":"List of contact points for the patient; for example, phone numbers or email addresses.\nWhen a patient tagged as `restricted` is retrieved, all contact points are removed from the response.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}},"contact":{"type":"array","description":"A list of patient contacts. Only emergency contacts are returned and only emergency contacts should be added. Any other contacts should be added to the patients `Related Person`.\nPatients designate here any contact number they desire to be used in case of an emergency.\nNote, while a patient may also desire to record various related persons telecom details, these do not separately allow for a concept of emergency contact; only ranking. See RelatedPerson endpoint.\nWhen a patient tagged as `restricted` is retrieved, all contacts are removed from the response.\n","items":{"title":"Schema for a patient contact.","type":"object","additionalProperties":false,"required":["relationship","telecom"],"properties":{"id":{"type":"string","example":"C123"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"relationship":{"type":"array","description":"The contact relationship wrapper object that holds the details of the relationship to the patient.\n\nThis is only returned when an Emergency Contact number has been set on `telecom`. The only valid code is `C`, which means `Emergency Contact`.\n","minItems":1,"maxItems":1,"items":{"type":"object","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one contact relationship.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","format":"url","default":"http://terminology.hl7.org/CodeSystem/v2-0131"},"code":{"type":"string","description":"Coded value for contact relationship.","example":"C"},"display":{"type":"string","description":"Display-friendly representation of the contact relationship code.","example":"Emergency Contact"}}}}}}},"telecom":{"type":"array","description":"List of Telecom objects on the contact only contains `system` and `value`.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}}}}},"generalPractitioner":{"type":"array","maxItems":1,"description":"General Practice (not practitioner) with which the patient is, or was, registered. Always contains zero or one general practitioner object.\nWhen a patient tagged as `restricted` is retrieved, the General Practice is removed from the response.\n","items":{"description":"General practice (not practitioner) with which the patient is or was registered.","type":"object","required":["identifier"],"properties":{"id":{"description":"Object identifier (OID) specific to the returned details - this should be return exactly the same in any update.","type":"string","example":"254406A3"},"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}}},"managingOrganization":{"description":"The managing organization of a de-registered patient. This will not be returned when the reason for de-registration is death.","type":"object","required":["identifier"],"properties":{"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}},"extension":{"type":"array","description":"Wrapper array for the patient's pharmacies, death notification status, communication details, contact preferences and place of birth; these are all FHIR extensions.\nAlways contains zero or one of each pharmacy object, zero or one death notification status object, zero or one communication details object, zero or one contact preference and zero or one place of birth object.\nWhen a patient tagged as `restricted` is retrieved, the pharmacy and birth place extensions are removed from the response.\n","items":{"anyOf":[{"type":"object","description":"Wrapper object for the patient's nominated pharmacy. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-NominatedPharmacy FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy"]},"valueReference":{"type":"object","description":"Reference to a pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's nominated pharmacy organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the nominated pharmacy, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y12345"}}}}}}},{"type":"object","description":"Wrapper object for the patient's dispensing doctor. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-DispensingDoctor FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization"]},"valueReference":{"type":"object","description":"Reference to a GP practice pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's dispensing doctor organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the dispensing doctor, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y23456"}}}}}}},{"type":"object","description":"Wrapper object for the patient's medical appliance supplier. This will only be populated on a retrieval and not a search.","required":["url","valueReference"],"properties":{"url":{"type":"string","description":"URL of specification of UKCore-MedicalApplianceSupplier FHIR extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier"]},"valueReference":{"type":"object","description":"Reference to medical appliance supplier pharmacy `Organization` resource.","required":["identifier"],"properties":{"identifier":{"type":"object","description":"Wrapper object for the patient's medical appliance supplier organisation code.","required":["value"],"properties":{"system":{"type":"string","description":"URL for the FHIR code system for the ODS organisation code.","default":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"type":"string","description":"Organisation code for the medical appliance supplier, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","pattern":"^[A-Za-z0-9]{3,10}$","example":"Y34567"}}}}}}},{"type":"object","description":"Wrapper object for death notification details.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of death notification extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus"]},"extension":{"type":"array","description":"Array containing exactly one death notification status code object and exactly one effective date object.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for death notification status code.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `deathNotificationStatus`.","default":"deathNotificationStatus","enum":["deathNotificationStatus"]},"valueCodeableConcept":{"type":"object","description":"Death Notification Status.","properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["system","code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol, in syntax, defined by the system:\n* `1` - Informal - death notice received via an update from a local NHS Organisation such as GP or Trust\n* `2` - Formal - death notice received from Registrar of Deaths. Only these endpoints are allowed to add a Formal death:\n - National Back Office using the Demographic Spine Application (DSA)\n - Office of National Statistics (ONS)\n - Maternity sites\n* `U` - Removed. This is a possible response, but it cannot be used on an update because Spine will reject it\n","example":"2","enum":["1","2","U"]},"display":{"type":"string","description":"Representation defined by the system.","example":"Formal - death notice received from Registrar of Deaths","enum":["Informal - death notice received via an update from a local NHS Organisation such as GP or Trust","Formal - death notice received from Registrar of Deaths","Removed"]}}}}}}}},{"type":"object","description":"Wrapper object for death notification effective date.","required":["url","valueDateTime"],"properties":{"url":{"type":"string","description":"Key of this object. Always `systemEffectiveDate`.","default":"systemEffectiveDate","enum":["systemEffectiveDate"]},"valueDateTime":{"type":"string","description":"Date and time at which death notification status took effect.","format":"date-time","example":"2010-10-22T00:00:00+00:00"}}}]}}}},{"type":"object","description":"Wrapper object for communication details. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of communication extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication"]},"extension":{"type":"array","description":"Definition of communication extension.\n\nThe array must have one item, a valueCodeableConcept for the language and can optionally include a valueBoolean for if an interpreter is required.","minItems":1,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Wrapper object for communication language.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `language`.","default":"language","enum":["language"]},"valueCodeableConcept":{"type":"object","description":"Human language.","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one language code.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of the Language Code System. Always uses the 'UKCore-HumanLanguage' Code System.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage"},"version":{"type":"string","description":"Version of the language code system.","example":"1.0.0"},"code":{"type":"string","description":"Language code based on [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) standard plus extensions for braille, makaton and sign languages, which are:\n* `q1` - Braille\n* `q2` - American Sign Language\n* `q3` - Australian Sign Language\n* `q4` - British Sign Language\n* `q5` - Makaton\nAll valid codes combined can be found at https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage.\n","example":"fr"},"display":{"type":"string","description":"Display-friendly representation of the language code (such as English). If there is a language code with no defined mapping, `Unknown` will be returned.","example":"French"}}}}}}}},{"type":"object","description":"Wrapper object for whether an interpreter is required.","required":["url","valueBoolean"],"properties":{"url":{"type":"string","description":"Key of this object. Always `interpreterRequired`.","default":"interpreterRequired","enum":["interpreterRequired"]},"valueBoolean":{"type":"boolean","description":"Whether an interpreter is required.","example":true}}}]}}}},{"type":"object","description":"Wrapper object for preferred contact details; the written communication format, preferred contact time and method. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the contact preference extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference"]},"extension":{"description":"Wrapper array containing zero or one preferred contact method, zero or one preferred written communication format; and zero or one preferred contact time.","type":"array","maxItems":3,"items":{"oneOf":[{"type":"object","description":"Wrapper object for preferred written communication format.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredWrittenCommunicationFormat`.","default":"PreferredWrittenCommunicationFormat"},"valueCodeableConcept":{"type":"object","description":"Preferred Written Communication Format.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred written communication extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat"]},"code":{"type":"string","description":"A code to identify the preferred written communication format of a patient, contact or related person.\n* 11 - Large print\n* 12 - Braille\n* 13 - Audio tape\n","example":"12"},"display":{"type":"string","description":"Display-friendly representation of the preferred written communication format code.","example":"Braille"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact method.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactMethod`.","default":"PreferredContactMethod","enum":["PreferredContactMethod"]},"valueCodeableConcept":{"type":"object","description":"Preferred Contact Method.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred contact method extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod"]},"code":{"type":"string","description":"A code to identify to identify the preferred contact method of a patient, contact or related person.\n* 1\t- Letter\n* 2\t- Visit\n* 3\t- Telephone\n* 4\t- E-mail\n* 5\t- Minicom (Textphone)\n* 6\t- Telephone contact via proxy\n* 7\t- Sign language\n* 8\t- No Telephone contact\n","example":"1"},"display":{"type":"string","description":"Display-friendly representation of the preferred contact method code.","example":"Letter"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact times.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactTimes`.","default":"PreferredContactTimes","enum":["PreferredContactTimes"]},"valueString":{"type":"string","maximum":40,"description":"A free-text description about the preferred contact times.","example":"Not after 7pm"}}}]}}}},{"type":"object","description":"Wrapper object for place of birth details. This will not be returned on a restricted patient.","required":["url","valueAddress"],"properties":{"url":{"type":"string","description":"Definition of place of birth extension.","default":"http://hl7.org/fhir/StructureDefinition/patient-birthPlace","enum":["http://hl7.org/fhir/StructureDefinition/patient-birthPlace"]},"valueAddress":{"type":"object","additionalProperties":false,"properties":{"city":{"type":"string","description":"Town or city of birth.","example":"Manchester"},"district":{"type":"string","description":"County or metropolitan district of birth.","example":"Greater Manchester"},"country":{"type":"string","description":"A coded value for a patient's country of birth.\n\nFrom [ISO 3166-1](http://hl7.org/fhir/valueset-iso3166-1-3.html) plus codes from the UK Internal Code list which do not have entries in ISO 3166-1.\n\nUK Internal Codes:\n* `1` - England\n* `2` - Scotland\n* `3` - Wales\n* `4` - Northern Ireland\n* `7` - Sark\n* `9` - Alderney\n* `10` - Channel Islands\n","example":"GBR"}}}}},{"type":"object","description":"An extension to carry the reason a PDS record has been removed from the Patient Demographic Service. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the removal from registration extension.","default":"https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration","enum":["https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration"],"readOnly":true},"extension":{"type":"array","description":"An extension reason a PDS record has been removed from the Patient Demographic Service.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for removalFromRegistrationCode.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"To identify the removal reason code.","default":"removalFromRegistrationCode","enum":["removalFromRegistrationCode"],"readOnly":true},"valueCodeableConcept":{"type":"object","description":"PDS Removal Reason Exit Code","required":["coding"],"properties":{"coding":{"type":"array","description":"Array containing exactly one removal reason exit code object","items":{"type":"object","required":["system","code","display"],"properties":{"system":{"type":"string","format":"url","description":"URL of the Removal Reason Exit Code. Always uses the 'PDS-RemovalReasonExitCode' Code System.","example":"https://fhir.nhs.uk/CodeSystem/PDS-RemovalReasonExitCode","readOnly":true},"code":{"type":"string","description":"A CodeSystem that identifies the reason a PDS record has been removed.","example":"SCT","enum":["DEA","EMB","SCT","NIT","TRA","ORR"]},"display":{"type":"string","description":"Display-friendly representation of the removal reason exit code.","example":"Transferred to Scotland"}}}}}}}},{"type":"object","description":"Wrapper object for removal from registration effective time.","required":["url","valuePeriod"],"properties":{"url":{"type":"string","description":"Key of this object. Always `effectiveTime`.","default":"effectiveTime","enum":["effectiveTime"],"readOnly":true},"valuePeriod":{"type":"object","description":"The effective time of removal of the Patient record from PDS.","required":["start"],"properties":{"start":{"type":"string","format":"date-time","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01T00:00:00+00:00"},"end":{"type":"string","format":"date-time","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31T00:00:00+00:00"}}}}}]}}}}]}}}},"PatientSearch":{"type":"object","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"Bundle"},"type":{"type":"string","description":"FHIR Bundle Type.","default":"searchset"},"timestamp":{"type":"string","description":"Time the search was performed.","format":"datetime","example":"2019-12-25T12:00:00+00:00"},"total":{"type":"integer","description":"Number of resources returned in search.","example":1},"entry":{"type":"array","description":"A list of matched patients. Empty if none found. The patients are ordered by match score, best first. A maximum of 50 patients are returned.\n","items":{"type":"object","properties":{"fullUrl":{"type":"string","description":"Absolute URL of the resource described in this item.","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/9000000009"},"search":{"type":"object","properties":{"score":{"description":"Search score from 0.0 to 1.0.","type":"number","minimum":0,"maximum":1,"example":0.75}}},"resource":{"type":"object","additionalProperties":false,"properties":{"resourceType":{"type":"string","description":"FHIR resource type.","default":"Patient"},"id":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"identifier":{"type":"array","description":"Identifier and system of identification used for this Patient.","items":{"type":"object","maxItems":1,"required":["value"],"properties":{"system":{"type":"string","format":"url","description":"System identifier belongs to.","default":"https://fhir.nhs.uk/Id/nhs-number"},"value":{"description":"The patient's NHS number. The primary identifier of a patient, unique within NHS England and Wales. Always 10 digits and must be a [valid NHS number](https://www.datadictionary.nhs.uk/attributes/nhs_number.html).","type":"string","pattern":"^\\d{10}$","example":"9000000009"},"extension":{"type":"array","description":"FHIR extensions.","items":{"type":"object","description":"Status indicating if NHS number is present and verified.","properties":{"url":{"type":"string","description":"URL of the extension definition.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus"]},"valueCodeableConcept":{"type":"object","description":"NHS Number Verification Status Indicator.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"01"},"display":{"type":"string","description":"Representation defined by the system.","example":"Number present and verified"}}}}}}}}}}}},"meta":{"type":"object","description":"Metadata about this resource.","properties":{"versionId":{"type":"string","description":"The NHS England assigned version of the patient resource.","example":"2"},"security":{"type":"array","description":"The level of security on the patients record, which affects which fields are populated on retrieval. The possible responses are:\n* U - unrestricted. All available data is returned.\n* R - restricted. Any sensitive data around the patient's location, so `address`, `generalPractitioner` and `telecom`, are removed from the response.\n* REDACTED - redacted. The patient record has been marked as invalid, so the data should not be used. This code is never returned; you receive a 404, and appropriate error response, if an invalidated patient retrieval is attempted.\n","maxItems":1,"items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the value set specification.","example":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality"},"code":{"type":"string","description":"Code defined by the system value set.","enum":["U","R","V","REDACTED"],"example":"U"},"display":{"type":"string","description":"Representation defined by the system.","enum":["unrestricted","restricted","redacted"],"example":"unrestricted"}}}}}},"name":{"type":"array","description":"List of names associated with the patient.\nThis is only fully populated on a retrieval or a successful update, only the `usual`, `nickname` and `temp` names are returned on a search. \n","minItems":1,"items":{"type":"object","required":["use","family"],"additionalProperties":false,"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"123"},"use":{"type":"string","description":"How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval.\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n","enum":["usual","temp","nickname","old","maiden"],"example":"usual"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"given":{"type":"array","maxItems":5,"description":"Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n","example":["Jane Marie Anne","Jo","Adele"],"items":{"type":"string","maxLength":35,"example":"Jane"}},"family":{"type":"string","maxLength":35,"description":"Family name (often called Surname).","example":"Smith"},"prefix":{"type":"array","description":"Name prefixes, titles, and prenominals.","example":["Mrs"],"items":{"type":"string","example":"Mrs"}},"suffix":{"type":"array","description":"Name suffices and postnominals.","example":["MBE","PhD"],"items":{"type":"string","example":"MBE"}}}}},"gender":{"type":"string","description":"Classification of the gender of a patient. The classification is phenotypical rather than genotypical, i.e. it does not provide codes for medical or scientific purposes.\nIt is the administrative gender that the patient wishes to be known as. In some cases, this may not be the same as the patient’s registered birth gender, or their current clinical gender.\n","enum":["male","female","other","unknown"],"example":"female"},"birthDate":{"description":"The date on which the patient was born or is officially deemed to have been born.\n\nIt is a date in the format `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned. \n","example":"2010-10-22","type":"string","format":"date"},"multipleBirthInteger":{"type":"integer","minimum":1,"maximum":9,"description":"The order in which the patient was born, with 1 indicating the first or only birth in the sequence, 2 indicating the second birth in the sequence, 3 indicating the third, and so on up to 7.\n\nThere are two other valid values; `8` meaning `Not applicable` and `9` meaning `Not known`.\n","example":1},"deceasedDateTime":{"description":"The date and time on which a person died or is officially deemed to have died, if applicable and known.\n\nIt is a datetime in the format `yyyy-mm-ddTHH:MM:SS+HH:MM` or `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned.\n","example":"2010-10-22T00:00:00+00:00","type":"string","format":"date-time","pattern":"^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2})$|^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$"},"address":{"type":"array","description":"List of addresses associated with the patient.\n\nThis is only fully populated on a retrieval or a successful update, only the `home` address is returned on a search.\nWhen a patient tagged as `restricted` is retrieved, all addresses are removed from the response.\n","items":{"type":"object","description":"An address associated with the patient.","required":["use"],"properties":{"id":{"type":"string","description":"Unique system identifier for this address.","example":"456"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"use":{"type":"string","description":"Purpose of this address:\n * `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n * `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n * `billing` - an address used for correspondence purposes only\n * `work` - an office address. This can be returned due to legacy data but cannot be added or replaced on update\n\n A patient should have no more than one current `temp` and/or `billing` address.\n However, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\n Where multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (e.g. by examining period dates).\n\n A `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\n However additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\n When sending correspondence to a patient:\n *\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and end dates.\n *\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and end dates.\n * if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n","enum":["home","work","temp","billing"],"example":"home"},"text":{"type":"string","description":"Where a `temp` address is provided a descriptor text must be sent.\nThe list of possible values are:\n* `Second Home` - a patient's second home\n* `Student Accommodation` - a patient's place of residence while at university\n* `Respite Care Address` - where the patient resides during respite care\n* `Temporary Residence Address` - where the patient resides for a specific period of time\n* `Convalescence Home` - the address for a patient during a period of recovery\n* `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n* `Holiday Home` - the address for a patient during a holiday\n\nA patient can also register temporarily at a GP practice using a temporary address. Temporary GP registration information does not appear on the PDS, but the address used for it may.\n","enum":["Second Home","Student Accommodation","Respite Care Address","Temporary Residence Address","Convalescence Home","Mobile Home","Holiday Home"],"example":"Student Accommodation"},"line":{"type":"array","description":"All lines of the address except the postal code.\n\nSystems must apply the following formatting convention when adding or replacing addresses lines:\n*\tline 1 - premises ID and/or house name, e.g. `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, e.g. `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), e.g. `Boxgrove`\n*\tline 4 - post town, e.g. `Leeds`\n*\tline 5 - county (if present), e.g. `West Yorkshire`\n\nIf any of the lines are blank, they are not returned due to FHIR conformance constraints.\n","maxItems":5,"items":{"type":"string"},"example":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"]},"postalCode":{"type":"string","description":"Postal code of the address.","example":"LS1 6AE"},"extension":{"type":"array","description":"List of address keys formatted as a FHIR extension. This can include up to one Unique Property Reference Number (UPRN), and up to one Postal Address File (PAF) key. If no keys for the address are known, the array will be empty. Otherwise it will be a list of objects which specify the value of the address key and the code system for it","items":{"anyOf":[{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'PAF'.","enum":["PAF"],"example":"PAF"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in PAF format. An 8 digit number including leading zeroes, formatted as a string.","minLength":8,"maxLength":8,"pattern":"^[0-9]{8}$","example":"12345678"}}}]}}}},{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'UPRN'.","enum":["UPRN"],"example":"UPRN"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in UPRN format. A number containing from 1 up to 12 digits.","minLength":1,"maxLength":12,"pattern":"^[0-9]{1,12}$","example":"123456789012"}}}]}}}}]}}}}},"telecom":{"type":"array","description":"List of contact points for the patient; for example, phone numbers or email addresses.\nWhen a patient tagged as `restricted` is retrieved, all contact points are removed from the response.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}},"contact":{"type":"array","description":"A list of patient contacts. Only emergency contacts are returned. Any other contacts are returned on the patients `Related Person`.\nWhen a patient tagged as `restricted` is retrieved, all contacts are removed from the response.\n","items":{"title":"Schema for a patient contact.","type":"object","additionalProperties":false,"required":["relationship","telecom"],"properties":{"id":{"type":"string","example":"C123"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"relationship":{"type":"array","description":"The contact relationship wrapper object that holds the details of the relationship to the patient.\n\nThis is only returned when an Emergency Contact number has been set on `telecom`. The only valid code is `C`, which means `Emergency Contact`.\n","minItems":1,"maxItems":1,"items":{"type":"object","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one contact relationship.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","format":"url","default":"http://terminology.hl7.org/CodeSystem/v2-0131"},"code":{"type":"string","description":"Coded value for contact relationship.","example":"C"},"display":{"type":"string","description":"Display-friendly representation of the contact relationship code.","example":"Emergency Contact"}}}}}}},"telecom":{"type":"array","description":"List of Telecom objects on the contact only contains `system` and `value`.\n","items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}}}}},"generalPractitioner":{"type":"array","maxItems":1,"description":"General Practice (not practitioner) with which the patient is, or was, registered. Always contains zero or one general practitioner object.\nWhen a patient tagged as `restricted` is retrieved, the General Practice is removed from the response.\n","items":{"description":"General practice (not practitioner) with which the patient is or was registered.","type":"object","required":["identifier"],"properties":{"id":{"description":"Object identifier (OID) specific to the returned details - this should be return exactly the same in any update.","type":"string","example":"254406A3"},"type":{"description":"Type of Reference being returned.","type":"string","example":"Organization"},"identifier":{"description":"Identifier and system of identification used for this Organisation.","type":"object","required":["value"],"properties":{"system":{"description":"URL for the Organisation Data Service - who are responsible for publishing codes that identify organisations and individuals across health and social care.","type":"string","example":"https://fhir.nhs.uk/Id/ods-organization-code"},"value":{"description":"Organisation code for the registered general practice, as held in the [Organisation Data Service](https://developer.nhs.uk/apis/ods/).","type":"string","pattern":"^[0-9A-Z]+$","example":"Y12345"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}}}}}}},"extension":{"type":"array","description":"Wrapper array for the patient's death notification status; this is a FHIR extension. Always contains zero or one death notification status object.\n","items":{"anyOf":[{"type":"object","description":"Wrapper object for death notification details.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of death notification extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus"]},"extension":{"type":"array","description":"Array containing exactly one death notification status code object and exactly one effective date object.","minItems":1,"maxItems":2,"items":{"oneOf":[{"type":"object","description":"Wrapper object for death notification status code.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `deathNotificationStatus`.","default":"deathNotificationStatus","enum":["deathNotificationStatus"]},"valueCodeableConcept":{"type":"object","description":"Death Notification Status.","properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["system","code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1.0.0"},"code":{"type":"string","description":"Symbol, in syntax, defined by the system:\n* `1` - Informal - death notice received via an update from a local NHS Organisation such as GP or Trust\n* `2` - Formal - death notice received from Registrar of Deaths. Only these endpoints are allowed to add a Formal death:\n - National Back Office using the Demographic Spine Application (DSA)\n - Office of National Statistics (ONS)\n - Maternity sites\n* `U` - Removed. This is a possible response, but it cannot be used on an update because Spine will reject it\n","example":"2","enum":["1","2","U"]},"display":{"type":"string","description":"Representation defined by the system.","example":"Formal - death notice received from Registrar of Deaths","enum":["Informal - death notice received via an update from a local NHS Organisation such as GP or Trust","Formal - death notice received from Registrar of Deaths","Removed"]}}}}}}}},{"type":"object","description":"Wrapper object for death notification effective date.","required":["url","valueDateTime"],"properties":{"url":{"type":"string","description":"Key of this object. Always `systemEffectiveDate`.","default":"systemEffectiveDate","enum":["systemEffectiveDate"]},"valueDateTime":{"type":"string","description":"Date and time at which death notification status took effect.","format":"date-time","example":"2010-10-22T00:00:00+00:00"}}}]}}}}]}}}}}}}}},"RelatedPersonBundle":{"type":"object","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"Bundle"},"type":{"type":"string","description":"FHIR Bundle Type.","default":"searchset"},"timestamp":{"type":"string","description":"Time the search was performed.","format":"datetime","example":"2019-12-25T12:00:00+00:00"},"total":{"type":"integer","description":"Number of resources returned in search.","example":1},"entry":{"type":"array","description":"A list of related people details attached to the patient. \n","items":{"type":"object","properties":{"fullUrl":{"type":"string","description":"Absolute URL of the resource described in this item.","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/9000000009/RelatedPerson/507B7621"},"resource":{"type":"object","additionalProperties":false,"required":["patient","relationship"],"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"507B7621"},"resourceType":{"type":"string","description":"FHIR resource type.","default":"RelatedPerson"},"patient":{"type":"object","required":["type"],"properties":{"type":{"type":"string","default":"Patient","enum":["Patient"]},"identifier":{"type":"object","description":"Identifier and system of identification used for this Patient.\n\nThis is an optional field as related person details are either a reference to another NHS number, or the details, such as name and adress, stored directly on the resource.\n","properties":{"system":{"type":"string","description":"URL for the Patient retrieval API.","format":"url","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient"},"value":{"type":"string","description":"NHS number for the related person","example":"90000000009","pattern":"^\\d{10}$"}}},"reference":{"type":"string","description":"URL for the FHIR Patient resource.","format":"url","example":"https://api.service.nhs.uk/personal-demographics/FHIR/R4/Patient/90000000009"}}},"active":{"type":"boolean","default":true},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"name":{"type":"array","description":"List containing zero or one name associated with the related person.\nThis is an optional field as there may be a `patient` reference which can be used to retrieve any details about the related person.\nIf no `patient` reference is available `name` and `address` must be provided at the minimum.\n","maxItems":1,"items":{"type":"object","required":["use","family"],"additionalProperties":false,"properties":{"id":{"type":"string","description":"Unique object identifier for this name.","example":"123"},"use":{"type":"string","description":"How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval.\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n","enum":["usual","temp","nickname","old","maiden"],"example":"usual"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"given":{"type":"array","maxItems":5,"description":"Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n","example":["Jane Marie Anne","Jo","Adele"],"items":{"type":"string","maxLength":35,"example":"Jane"}},"family":{"type":"string","maxLength":35,"description":"Family name (often called Surname).","example":"Smith"},"prefix":{"type":"array","description":"Name prefixes, titles, and prenominals.","example":["Mrs"],"items":{"type":"string","example":"Mrs"}},"suffix":{"type":"array","description":"Name suffices and postnominals.","example":["MBE","PhD"],"items":{"type":"string","example":"MBE"}}}}},"address":{"type":"array","description":"List containing zero or one address associated with the related person.\nThis is an optional field as there may be a `patient` reference which can be used to retrieve any details about the related person.\nIf no `patient` reference is available `name` and `address` must be provided at the minimum.\n","maxItems":1,"items":{"type":"object","description":"An address associated with the patient.","required":["use"],"properties":{"id":{"type":"string","description":"Unique system identifier for this address.","example":"456"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"use":{"type":"string","description":"Purpose of this address:\n * `home` - the home address is the patient's normal residence. Home address is also known as usual, main, registered, current or permanent address\n * `temp` - a temporary address is an address used for a set period of time, but where the patient's home, permanent address remains unchanged\n * `billing` - an address used for correspondence purposes only\n * `work` - an office address. This can be returned due to legacy data but cannot be added or replaced on update\n\n A patient should have no more than one current `temp` and/or `billing` address.\n However, historically this was constrained only by the integration requirements and was not enforced so theoretically more than one can exist for a patient when retrieving.\n Where multiple instances already exist for the patient it is not expected that local systems should manage those, but should choose the most appropriate one to maintain (e.g. by examining period dates).\n\n A `home` address is the patient's main residential address and should normally be used for all clinical and demographic purposes, including clinical and appointment correspondence.\n However additionally, `temp` and `billing` addresses may be provided by a patient when there is a requirement to record an alternative location for the purposes of unbroken care.\n When sending correspondence to a patient:\n *\ta present and valid `billing` address may take precedence over `home` and `temp` addresses. A patient should have only a single current `billing` address. An address is considered 'valid' according to its period start and end dates.\n *\tif no current `billing` address is provided, a `temp` address may take precedence over the `home` address, again if it is valid according to its period start and end dates.\n * if there is no valid, current `billing` and/or `temp` address, the `home` address must be used.\n","enum":["home","work","temp","billing"],"example":"home"},"text":{"type":"string","description":"Where a `temp` address is provided a descriptor text must be sent.\nThe list of possible values are:\n* `Second Home` - a patient's second home\n* `Student Accommodation` - a patient's place of residence while at university\n* `Respite Care Address` - where the patient resides during respite care\n* `Temporary Residence Address` - where the patient resides for a specific period of time\n* `Convalescence Home` - the address for a patient during a period of recovery\n* `Mobile Home` - the address of a patient's mobile home, parked for a specific period of time, e.g. the address of a caravan park\n* `Holiday Home` - the address for a patient during a holiday\n\nA patient can also register temporarily at a GP practice using a temporary address. Temporary GP registration information does not appear on the PDS, but the address used for it may.\n","enum":["Second Home","Student Accommodation","Respite Care Address","Temporary Residence Address","Convalescence Home","Mobile Home","Holiday Home"],"example":"Student Accommodation"},"line":{"type":"array","description":"All lines of the address except the postal code.\n\nSystems must apply the following formatting convention when adding or replacing addresses lines:\n*\tline 1 - premises ID and/or house name, e.g. `Flat 1` or `The Old Schoolhouse`\n*\tline 2 - house number, dependent thoroughfare name and descriptor (if present), thoroughfare name and descriptor, e.g. `23 Mill Lane`\n*\tline 3 - dependent locality/village, locality (if present), e.g. `Boxgrove`\n*\tline 4 - post town, e.g. `Leeds`\n*\tline 5 - county (if present), e.g. `West Yorkshire`\n\nIf any of the lines are blank, they are not returned due to FHIR conformance constraints.\n","maxItems":5,"items":{"type":"string"},"example":["1 Trevelyan Square","Boar Lane","City Centre","Leeds","West Yorkshire"]},"postalCode":{"type":"string","description":"Postal code of the address.","example":"LS1 6AE"},"extension":{"type":"array","description":"List of address keys formatted as a FHIR extension. This can include up to one Unique Property Reference Number (UPRN), and up to one Postal Address File (PAF) key. If no keys for the address are known, the array will be empty. Otherwise it will be a list of objects which specify the value of the address key and the code system for it","items":{"anyOf":[{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'PAF'.","enum":["PAF"],"example":"PAF"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in PAF format. An 8 digit number including leading zeroes, formatted as a string.","minLength":8,"maxLength":8,"pattern":"^[0-9]{8}$","example":"12345678"}}}]}}}},{"type":"object","description":"Unique identifier for an address.","properties":{"url":{"type":"string","description":"URL of specification of the AddressKey extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey"]},"extension":{"type":"array","description":"Specification of address key system and address key value. Contains exactly two items: one describing the code system the Address Key uses, and the other specifying the value of the Address Key.","minItems":2,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Coding system of the address key.","required":["url","valueCoding"],"properties":{"url":{"type":"string","description":"Always 'type'.","default":"type"},"valueCoding":{"type":"object","description":"URL of specification of address key format.","required":["system","code"],"properties":{"system":{"type":"string","description":"URL of Code System that describes available Address Key formats.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType"},"code":{"type":"string","description":"Address Key system. Always 'UPRN'.","enum":["UPRN"],"example":"UPRN"}}}}},{"type":"object","description":"Value of the address key.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Always 'value'.","default":"value","example":"value"},"valueString":{"type":"string","description":"Address key in UPRN format. A number containing from 1 up to 12 digits.","minLength":1,"maxLength":12,"pattern":"^[0-9]{1,12}$","example":"123456789012"}}}]}}}}]}}}}},"telecom":{"type":"array","description":"List containing zero to five contact methods associated with the related person.\nThis is an optional field as there may be a `patient` reference which can be used to retrieve any details about the related person.\n","maxItems":5,"items":{"description":"A contact point, such as a phone number or email address","type":"object","required":["system","value"],"properties":{"id":{"type":"string","description":"Unique object identifier for this contact point.","example":"789"},"period":{"type":"object","description":"Business effective period when data item was, is, or will be in use.\n","required":["start"],"properties":{"start":{"type":"string","format":"date","description":"Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.","example":"2020-01-01"},"end":{"type":"string","format":"date","description":"End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.","example":"2021-12-31"}}},"system":{"description":"Means of communication, such as phone or email.","type":"string","enum":["phone","fax","email","other"],"example":"phone"},"value":{"description":"Phone number, email address, or other identifier for use with contact system.","type":"string","example":"01632960587"},"use":{"type":"string","description":"Location associated with communication system.","enum":["home","work","temp","mobile"],"example":"home"},"extension":{"type":"array","maxItems":1,"description":"Extension that is returned when the communication type is `textphone`. The only code returned is `textphone`, which means `Minicom (Textphone)`.\n\nThe `system` is `other` when the extension is included.\n","items":{"type":"object","description":"Wrapped object for other contact system details.","properties":{"url":{"type":"string","description":"Definition of other contact system extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem"]},"valueCoding":{"type":"object","description":"URL of specification of other contact systems.","properties":{"system":{"type":"string","description":"URL of Code System that describes available contact relationships.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem"},"code":{"type":"string","description":"Coded value for the other contact system in place.","example":"textphone"},"display":{"description":"Display-friendly representation of the other contact system code.","type":"string","example":"Minicom (Textphone)"}}}}}}}}},"relationship":{"type":"array","description":"The relationship of the related person to the patient.\n","minItems":1,"maxItems":1,"items":{"type":"object","required":["coding"],"properties":{"coding":{"type":"array","description":"Coded values for three relationship types:\n* Role\n* Type\n* Next-of-Kin\n\nThe codes used can be found at:\n* http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\n* https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole\n\nThe allowed values for `Role` are:\n* Agent - Agent of patient\n* Guardian - Guardian of patient\n* Personal - Personal relationship with the patient\n\nThe allowed values for `Type` are:\n* SPS - spouse\n* DOMPART - domestic partner\n* PRN - parent\n* PRNFOST - foster parent\n* STPPRN - step parent\n* CHILD - child\n* MTH - mother\n* FTH - father\n* SIS - sister\n* BRO - brother\n* FAMMEMB - family member\n* ONESELF - self\n* N - Next-of-Kin\n* U - Unknown\n* PolygamousPartner - Polygamous Partner of patient\n* Dependant - Dependant of patient\n* NonDependant - Non Dependant of patient\n* ProxyContact - Proxy Contact for patient\n* ProxyCommunication - Proxy Communication for patient\n* ProxyContactCommunication - Proxy Contact and Communication for patient\n* Carer - Carer of patient\n* Guardian - Guardian of patient\n* NotSpecified - Not Specified\n\nThe allowed values for `Next-of-Kin` are:\n* N - Next-of-Kin\n\n`Role` and `Type` are mandatory, so both should be present - however they both contain the `Guardian` code - so a single response is possible.\n\n`Next-of-Kin` is optional and will be absent from the response when the related person is not the Next-of-Kin.\n","minItems":1,"maxItems":3,"items":{"type":"object","required":["system","code"],"properties":{"system":{"type":"string","description":"URI of the coding system specification.","format":"url","default":"https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole","enum":["http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype","https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole"]},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"Guardian"},"display":{"type":"string","description":"Human-friendly display representation defined by the system.","example":"Guardian of patient"}}}}}}},"extension":{"type":"array","description":"Wrapper array for copy correspondence, contact rank, contact preferences and communication details; these are all FHIR extensions. Always contains zero or one of each extension type.\n","items":{"anyOf":[{"type":"object","description":"Flag indicating if this person should be copied in on any contact with the Patient. This will only be returned if the value is true and the person should be copied in on correspondence, otherwise it will be omitted. \n","properties":{"url":{"type":"string","format":"url","description":"URL to FHIR Extension Specification.","default":"https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-CopyCorrespondenceIndicator","enum":["https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-CopyCorrespondenceIndicator"]},"valueBoolean":{"type":"boolean","description":"Flag indicating if this person should be copied in on correspondence. This will only be returned if the value is `true` otherwise it will not be returned and can be assumed `false`","example":true}}},{"type":"object","description":"Rank indicating order in which contacts should be tried.","properties":{"url":{"type":"string","format":"url","description":"URL to FHIR Extension Specification.","default":"https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-ContactRank","enum":["https://fhir.nhs.uk/R4/StructureDefinition/Extension-UKCore-ContactRank"]},"valuePositiveInt":{"type":"integer","minimum":1,"maximum":99,"description":"Rank expressed as positive integer (1 being the highest).","example":1}}},{"type":"object","description":"Wrapper object for preferred contact details; the written communication format, preferred contact time and method. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of the contact preference extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference"]},"extension":{"description":"Wrapper array containing zero or one preferred contact method, zero or one preferred written communication format; and zero or one preferred contact time.","type":"array","maxItems":3,"items":{"oneOf":[{"type":"object","description":"Wrapper object for preferred written communication format.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredWrittenCommunicationFormat`.","default":"PreferredWrittenCommunicationFormat"},"valueCodeableConcept":{"type":"object","description":"Preferred Written Communication Format.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred written communication extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat"]},"code":{"type":"string","description":"A code to identify the preferred written communication format of a patient, contact or related person.\n* 11 - Large print\n* 12 - Braille\n* 13 - Audio tape\n","example":"12"},"display":{"type":"string","description":"Display-friendly representation of the preferred written communication format code.","example":"Braille"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact method.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactMethod`.","default":"PreferredContactMethod","enum":["PreferredContactMethod"]},"valueCodeableConcept":{"type":"object","description":"Preferred Contact Method.","required":["coding"],"properties":{"coding":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","format":"url","description":"Definition of the preferred contact method extension.","default":"https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod","enum":["https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod"]},"code":{"type":"string","description":"A code to identify to identify the preferred contact method of a patient, contact or related person.\n* 1\t- Letter\n* 2\t- Visit\n* 3\t- Telephone\n* 4\t- E-mail\n* 5\t- Minicom (Textphone)\n* 6\t- Telephone contact via proxy\n* 7\t- Sign language\n* 8\t- No Telephone contact\n","example":"1"},"display":{"type":"string","description":"Display-friendly representation of the preferred contact method code.","example":"Letter"}}}}}}}},{"type":"object","description":"Wrapper object for preferred contact times.","required":["url","valueString"],"properties":{"url":{"type":"string","description":"Key of this object. Always `PreferredContactTimes`.","default":"PreferredContactTimes","enum":["PreferredContactTimes"]},"valueString":{"type":"string","maximum":40,"description":"A free-text description about the preferred contact times.","example":"Not after 7pm"}}}]}}}},{"type":"object","description":"Wrapper object for communication details. This will only be populated on a retrieval and not a search.","required":["url","extension"],"properties":{"url":{"type":"string","description":"Definition of communication extension.","default":"https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication","enum":["https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication"]},"extension":{"type":"array","description":"Definition of communication extension.\n\nThe array must have one item, a valueCodeableConcept for the language and can optionally include a valueBoolean for if an interpreter is required.","minItems":1,"maxItems":2,"items":{"anyOf":[{"type":"object","description":"Wrapper object for communication language.","required":["url","valueCodeableConcept"],"properties":{"url":{"type":"string","description":"Key of this object. Always `language`.","default":"language","enum":["language"]},"valueCodeableConcept":{"type":"object","description":"Human language.","required":["coding"],"properties":{"coding":{"type":"array","description":"Exactly one language code.","minItems":1,"maxItems":1,"items":{"type":"object","required":["code"],"properties":{"system":{"type":"string","description":"URL of the Language Code System. Always uses the 'UKCore-HumanLanguage' Code System.","example":"https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage"},"version":{"type":"string","description":"Version of the language code system.","example":"1.0.0"},"code":{"type":"string","description":"Language code based on [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) standard plus extensions for braille, makaton and sign languages, which are:\n* `q1` - Braille\n* `q2` - American Sign Language\n* `q3` - Australian Sign Language\n* `q4` - British Sign Language\n* `q5` - Makaton\nAll valid codes combined can be found at https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage.\n","example":"fr"},"display":{"type":"string","description":"Display-friendly representation of the language code (such as English). If there is a language code with no defined mapping, `Unknown` will be returned.","example":"French"}}}}}}}},{"type":"object","description":"Wrapper object for whether an interpreter is required.","required":["url","valueBoolean"],"properties":{"url":{"type":"string","description":"Key of this object. Always `interpreterRequired`.","default":"interpreterRequired","enum":["interpreterRequired"]},"valueBoolean":{"type":"boolean","description":"Whether an interpreter is required.","example":true}}}]}}}}]}}}}}}}}},"OperationOutcome":{"type":"object","description":"Outcome of an operation that does not result in a resource or bundle being returned, for example an error or an async/batch submission.\nThere are a number of possible error codes that can be returned along with a more detailed description in the `display` field.\n","properties":{"resourceType":{"type":"string","description":"FHIR Resource Type.","default":"OperationOutcome"},"issue":{"type":"array","description":"List of issues that have occurred.","minItems":1,"items":{"type":"object","required":["severity","code"],"properties":{"severity":{"type":"string","enum":["fatal","error","warning","information"],"description":"Severity of the error.","example":"error"},"code":{"type":"string","description":"FHIR error code.","example":"invalid","enum":["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"]},"details":{"type":"object","description":"Internal error code.","properties":{"coding":{"type":"array","items":{"type":"object","properties":{"system":{"type":"string","description":"URI of the coding system specification.","example":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode"},"version":{"type":"string","description":"Version of the coding system in use.","example":"1"},"code":{"type":"string","description":"Symbol in syntax defined by the system.","example":"INVALID_VALUE"},"display":{"type":"string","description":"Representation defined by the system.","example":"Provided value is invalid"}}}}}},"diagnostics":{"type":"string","description":"Additional diagnostic information about the issue. This information is subject to change.","example":"Invalid value - 2019-01 in field 'birthDate'"},"expression":{"type":"string","description":"FHIRPath of element(s) related to the error.","example":"Patient.name.given"}}}}}}},"examples":{"OperationOutcome":{"summary":"OperationOutcome example","value":{"resourceType":"OperationOutcome","issue":[{"severity":"error","code":"value","details":{"coding":[{"system":"https://fhir.nhs.uk/R4/CodeSystem/Spine-ErrorOrWarningCode","version":"1","code":"INVALID_RESOURCE_ID","display":"Resource Id is invalid"}]}}]}}}}} diff --git a/src/main/resources/OAS/Proxy-api.yaml b/src/main/resources/OAS/Proxy-api.yaml new file mode 100644 index 0000000..c256dc8 --- /dev/null +++ b/src/main/resources/OAS/Proxy-api.yaml @@ -0,0 +1,318 @@ +openapi: 3.0.0 +info: + version: 1.0.11 + title: Validated Relationship Service + description: This is an Open API specification for the Validated Relationship Service. +paths: + /RelatedPerson: + get: + summary: Get relationships. + parameters: + - $ref: "#/components/parameters/BearerAuthorisation" + - $ref: "#/components/parameters/proxyID" + - $ref: "#/components/parameters/patientID" + - $ref: "#/components/parameters/RequestID" + - $ref: "#/components/parameters/CorrelationID" + responses: + "200": + description: Successful retrieval. + content: + application/json: + schema: + $ref: "#/components/schemas/Relationship" + "4XX": + description: | + Bad request. + + | HTTP status | Error code | Description | + | ----------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | + | 400 | `INVALID_PROXY_IDENTIFIER` | Missing or malformed proxy NHS number. | + | 400 | `INVALID_PATIENT_IDENTIFIER` | Missing or malformed patient NHS number. | + | 400 | `NOT_SUPPORTED` | The request is not currently supported. | + | 401 | `ACCESS_DENIED` | Missing or invalid OAuth 2.0 bearer token in request. | + | 408 | `TIMEOUT` | Request timed out. | + | 429 | `THROTTLED` | You have exceeded your application's [rate limit](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#rate-limits). | + "500": + description: | + Server error. + + | HTTP status | Error code | Description | + | ----------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | + | 500 | `SERVER_ERROR` | An internal error has occurred when processing the request. | + +components: + schemas: + Relationship: + type: object + description: A FHIR searchset. + properties: + resourceType: + type: string + description: FHIR resource type. + enum: [Bundle] + type: + type: string + description: Denotes that the Bundle is a collection of resources returned as a result of a search. + enum: [searchset] + timestamp: + type: string + description: The time the search results were returned. + example: "2020-08-26T14:00:00+00:00" + total: + type: number + description: | + The number of resources contained within the Bundle. + + An empty bundle suggests that the proxy does not have patients they can act on behalf of. + example: 2 + entry: + type: array + description: | + A collection of resources contained within the Bundle. + + An empty bundle suggests that the proxy does not have patients they can act on behalf of. + items: + anyOf: + - $ref: "#/components/schemas/RelatedPerson" + - $ref: "#/components/schemas/Patient" + + RelatedPerson: + type: object + description: The proxy's details. This includes their relationship to the referenced patient. + properties: + resource: + type: object + properties: + resourceType: + type: string + description: FHIR resource type. + enum: [RelatedPerson] + identifier: + type: array + description: The proxy's NHS number. + items: + type: object + properties: + system: + type: string + description: Codesystem URL for the proxy's NHS number. + enum: ["https://fhir.nhs.uk/Id/nhs-number"] + value: + type: string + description: The proxy's NHS number. + example: "9449304130" + patient: + type: object + description: A reference to a patient the proxy is related to. + properties: + type: + type: string + description: FHIR resource type. + enum: ["Patient"] + identifier: + type: object + description: The patient's NHS number. + example: "9459304130" + relationship: + type: array + description: How the proxy is related to the patient. + items: + type: object + properties: + coding: + type: array + description: FHIR coding array. + items: + type: object + properties: + system: + type: string + description: FHIR codesystem. + enum: + [ + "https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole", + ] + code: + type: string + description: FHIR relationship type code. + enum: + - "MTH" + display: + type: string + description: FHIR relationship type. + enum: + - "MOTHER" + Patient: + type: object + description: The patient's details. + properties: + resourceType: + type: string + description: FHIR resource type. + enum: [Patient] + identifier: + type: array + description: The patient's NHS number. + items: + type: object + properties: + system: + type: string + description: Codesystem URL for the NHS number. + enum: ["https://fhir.nhs.uk/Id/nhs-number"] + value: + type: string + description: The NHS number. + example: "9000000009" + name: + type: array + description: List of names associated with the patient. + items: + type: object + required: + - use + - family + additionalProperties: false + properties: + id: + type: string + description: Unique object identifier for this name. + example: "123" + use: + type: string + description: | + How this name should be used. + * usual - Known as, conventional or the one patient normally uses. A patient always has a usual name. + * temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations. + * nickname - A name that the patient prefers to be addressed by, but is not part of their usual name. + * old - This name is no longer in use (or was never correct, but retained for records). + * maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name. + + The following use codes are included in the [name-use](https://www.hl7.org/fhir/valueset-name-use.html) value set, but should not be used and is not be returned as part of a retrieval. + * official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called "legal name". + * anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons). + enum: [usual, temp, nickname, old, maiden] + example: usual + period: + type: object + description: | + Business effective period when the name was, is, or will be in use. + required: + - start + properties: + start: + type: string + format: date + description: Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date. + example: 2020-01-01 + end: + type: string + format: date + description: End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date. + example: 2021-12-31 + given: + type: array + maxItems: 5 + description: | + Given names, including any middle names. + + Each name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space. + Subsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`. + + example: [Jane Marie Anne] + items: + type: string + maxLength: 35 + example: Jane + family: + type: string + maxLength: 35 + description: Family name (often called Surname). + example: Smith + prefix: + type: array + description: Name prefixes, titles, and prenominals. + example: [Mrs] + items: + type: string + example: Mrs + suffix: + type: array + description: Name suffices and postnominals. + example: [MBE, PhD] + items: + type: string + example: MBE + birthDate: + description: | + The date on which the patient was born or is officially deemed to have been born. + + It is a date in the format `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned. + example: "2010-10-22" + type: string + format: date + + parameters: + proxyID: + in: query + name: identifier + description: | + The proxy's NHS number. + required: false + schema: + type: string + examples: + withoutSystem: + value: "9000000009" + summary: "NHS number specified without system" + withSystem: + value: "https://fhir.nhs.uk/Id/nhs-number/9000000009" + summary: "System and NHS number specified" + + patientID: + in: query + name: patient:identifier + description: | + The patient's NHS number. + required: false + schema: + type: string + examples: + withoutSystem: + value: "9000000009" + summary: "NHS number specified without system" + withSystem: + value: "https://fhir.nhs.uk/Id/nhs-number/9000000009" + summary: "System and NHS number specified" + BearerAuthorisation: + in: header + name: Authorisation + description: | + An [OAuth 2.0 bearer token](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation#user-restricted-apis). + required: true + schema: + type: string + format: '^Bearer\ [[:ascii:]]+$' + example: "Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM" + RequestID: + in: header + name: X-Request-ID + required: true + description: | + A globally unique identifier (GUID) for the request, which we use to correlate logs through different components. + Must be a universally unique identifier (UUID) (ideally version 4). + Mirrored back in a response header. + schema: + type: string + 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 + CorrelationID: + in: header + name: X-Correlation-ID + required: false + description: | + An optional ID which you can use to track transactions across multiple systems. It can have any value, but we recommend avoiding `.` characters. + Mirrored back in a response header. + schema: + type: string + example: 11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA diff --git a/src/main/resources/OAS/proxy-api.json b/src/main/resources/OAS/proxy-api.json new file mode 100644 index 0000000..86ebf21 --- /dev/null +++ b/src/main/resources/OAS/proxy-api.json @@ -0,0 +1,431 @@ +{ + "openapi" : "3.0.0", + "info" : { + "title" : "Validated Relationship Service", + "description" : "This is an Open API specification for the Validated Relationship Service.", + "version" : "1.0.11" + }, + "servers" : [ { + "url" : "/" + } ], + "paths" : { + "/RelatedPerson" : { + "get" : { + "summary" : "Get relationships.", + "parameters" : [ { + "name" : "Authorisation", + "in" : "header", + "description" : "An [OAuth 2.0 bearer token](https:\n", + "required" : true, + "style" : "simple", + "explode" : false, + "schema" : { + "type" : "string", + "format" : "^Bearer\\ [[:ascii:]]+$", + "example" : "Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM" + } + }, { + "name" : "identifier", + "in" : "query", + "description" : "The proxy's NHS number.\n", + "required" : false, + "style" : "form", + "explode" : true, + "schema" : { + "type" : "string" + }, + "examples" : { + "withoutSystem" : { + "summary" : "NHS number specified without system", + "value" : "9000000009" + }, + "withSystem" : { + "summary" : "System and NHS number specified", + "value" : "https://fhir.nhs.uk/Id/nhs-number/9000000009" + } + } + }, { + "name" : "patient:identifier", + "in" : "query", + "description" : "The patient's NHS number.\n", + "required" : false, + "style" : "form", + "explode" : true, + "schema" : { + "type" : "string" + }, + "examples" : { + "withoutSystem" : { + "summary" : "NHS number specified without system", + "value" : "9000000009" + }, + "withSystem" : { + "summary" : "System and NHS number specified", + "value" : "https://fhir.nhs.uk/Id/nhs-number/9000000009" + } + } + }, { + "name" : "X-Request-ID", + "in" : "header", + "description" : "A globally unique identifier (GUID) for the request, which we use to correlate logs through different components.\nMust be a universally unique identifier (UUID) (ideally version 4).\nMirrored back in a response header.\n", + "required" : true, + "style" : "simple", + "explode" : false, + "schema" : { + "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}$", + "type" : "string", + "example" : "60E0B220-8136-4CA5-AE46-1D97EF59D068" + } + }, { + "name" : "X-Correlation-ID", + "in" : "header", + "description" : "An optional ID which you can use to track transactions across multiple systems. It can have any value, but we recommend avoiding `.` characters.\nMirrored back in a response header.\n", + "required" : false, + "style" : "simple", + "explode" : false, + "schema" : { + "type" : "string", + "example" : "11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA" + } + } ], + "responses" : { + "200" : { + "description" : "Successful retrieval.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Relationship" + } + } + } + }, + "4XX" : { + "description" : "Bad request.\n\n| HTTP status | Error code | Description |\n| ----------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |\n| 400 | `INVALID_PROXY_IDENTIFIER` | Missing or malformed proxy NHS number. |\n| 400 | `INVALID_PATIENT_IDENTIFIER` | Missing or malformed patient NHS number. |\n| 400 | `NOT_SUPPORTED` | The request is not currently supported. |\n| 401 | `ACCESS_DENIED` | Missing or invalid OAuth 2.0 bearer token in request. |\n| 408 | `TIMEOUT` | Request timed out. |\n| 429 | `THROTTLED` | You have exceeded your application's [rate limit](https:\n" + }, + "500" : { + "description" : "Server error.\n\n| HTTP status | Error code | Description |\n| ----------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |\n| 500 | `SERVER_ERROR` | An internal error has occurred when processing the request. |\n" + } + } + } + } + }, + "components" : { + "schemas" : { + "Relationship" : { + "type" : "object", + "properties" : { + "resourceType" : { + "type" : "string", + "description" : "FHIR resource type.", + "enum" : [ "Bundle" ] + }, + "type" : { + "type" : "string", + "description" : "Denotes that the Bundle is a collection of resources returned as a result of a search.", + "enum" : [ "searchset" ] + }, + "timestamp" : { + "type" : "string", + "description" : "The time the search results were returned.", + "example" : "2020-08-26T14:00:00+00:00" + }, + "total" : { + "type" : "number", + "description" : "The number of resources contained within the Bundle. \n\nAn empty bundle suggests that the proxy does not have patients they can act on behalf of.\n", + "example" : 2 + }, + "entry" : { + "type" : "array", + "description" : "A collection of resources contained within the Bundle.\n\nAn empty bundle suggests that the proxy does not have patients they can act on behalf of.\n", + "items" : { + "anyOf" : [ { + "$ref" : "#/components/schemas/RelatedPerson" + }, { + "$ref" : "#/components/schemas/Patient" + } ] + } + } + }, + "description" : "A FHIR searchset." + }, + "RelatedPerson" : { + "type" : "object", + "properties" : { + "resource" : { + "type" : "object", + "properties" : { + "resourceType" : { + "type" : "string", + "description" : "FHIR resource type.", + "enum" : [ "RelatedPerson" ] + }, + "identifier" : { + "type" : "array", + "description" : "The proxy's NHS number.", + "items" : { + "type" : "object", + "properties" : { + "system" : { + "type" : "string", + "description" : "Codesystem URL for the proxy's NHS number.", + "enum" : [ "https://fhir.nhs.uk/Id/nhs-number" ] + }, + "value" : { + "type" : "string", + "description" : "The proxy's NHS number.", + "example" : "9449304130" + } + } + } + }, + "patient" : { + "type" : "object", + "properties" : { + "type" : { + "type" : "string", + "description" : "FHIR resource type.", + "enum" : [ "Patient" ] + }, + "identifier" : { + "type" : "object", + "description" : "The patient's NHS number.", + "example" : "9459304130" + } + }, + "description" : "A reference to a patient the proxy is related to." + }, + "relationship" : { + "type" : "array", + "description" : "How the proxy is related to the patient.", + "items" : { + "type" : "object", + "properties" : { + "coding" : { + "type" : "array", + "description" : "FHIR coding array.", + "items" : { + "type" : "object", + "properties" : { + "system" : { + "type" : "string", + "description" : "FHIR codesystem.", + "enum" : [ "https://fhir.nhs.uk/R4/CodeSystem/UKCore-AdditionalRelatedPersonRole" ] + }, + "code" : { + "type" : "string", + "description" : "FHIR relationship type code.", + "enum" : [ "MTH" ] + }, + "display" : { + "type" : "string", + "description" : "FHIR relationship type.", + "enum" : [ "MOTHER" ] + } + } + } + } + } + } + } + } + } + }, + "description" : "The proxy's details. This includes their relationship to the referenced patient." + }, + "Patient" : { + "type" : "object", + "properties" : { + "resourceType" : { + "type" : "string", + "description" : "FHIR resource type.", + "enum" : [ "Patient" ] + }, + "identifier" : { + "type" : "array", + "description" : "The patient's NHS number.", + "items" : { + "type" : "object", + "properties" : { + "system" : { + "type" : "string", + "description" : "Codesystem URL for the NHS number.", + "enum" : [ "https://fhir.nhs.uk/Id/nhs-number" ] + }, + "value" : { + "type" : "string", + "description" : "The NHS number.", + "example" : "9000000009" + } + } + } + }, + "name" : { + "type" : "array", + "description" : "List of names associated with the patient.", + "items" : { + "required" : [ "family", "use" ], + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "description" : "Unique object identifier for this name.", + "example" : "123" + }, + "use" : { + "type" : "string", + "description" : "How this name should be used.\n* usual - Known as, conventional or the one patient normally uses. A patient always has a usual name.\n* temp - An alias or temporary name. This may also be used for temporary names assigned at birth or in emergency situations.\n* nickname - A name that the patient prefers to be addressed by, but is not part of their usual name.\n* old - This name is no longer in use (or was never correct, but retained for records).\n* maiden - Name changed for Marriage. A name used prior to changing name because of marriage. This term is not gender specific. The use of this term does not imply any particular history for a person's name.\n\nThe following use codes are included in the [name-use](https:\n* official - The formal name as registered in an official (government) registry, but which name might not be commonly used. May be called \"legal name\".\n* anonymous - Anonymous assigned name, alias, or pseudonym (used to protect a person's identity for privacy reasons).\n", + "example" : "usual", + "enum" : [ "usual", "temp", "nickname", "old", "maiden" ] + }, + "period" : { + "required" : [ "start" ], + "type" : "object", + "properties" : { + "start" : { + "type" : "string", + "description" : "Start date of time period, if known, in format `yyyy-mm-dd`. Can be a future date.", + "format" : "date", + "example" : "2020-01-01" + }, + "end" : { + "type" : "string", + "description" : "End date of time period, if known and if not ongoing, in format `yyyy-mm-dd`. Can be a future date.", + "format" : "date", + "example" : "2021-12-31" + } + }, + "description" : "Business effective period when the name was, is, or will be in use.\n" + }, + "given" : { + "maxItems" : 5, + "type" : "array", + "description" : "Given names, including any middle names.\n\nEach name(s) should be a separate item in the list. The first given name may include multiple names, separated by a space.\nSubsequent names must be broken down into list items. For example, the input `[Jane Marie Anne, Jo Adele]` returns `[Jane Marie Anne, Jo, Adele]`.\n", + "example" : [ "Jane Marie Anne" ], + "items" : { + "maxLength" : 35, + "type" : "string", + "example" : "Jane" + } + }, + "family" : { + "maxLength" : 35, + "type" : "string", + "description" : "Family name (often called Surname).", + "example" : "Smith" + }, + "prefix" : { + "type" : "array", + "description" : "Name prefixes, titles, and prenominals.", + "example" : [ "Mrs" ], + "items" : { + "type" : "string", + "example" : "Mrs" + } + }, + "suffix" : { + "type" : "array", + "description" : "Name suffices and postnominals.", + "example" : [ "MBE", "PhD" ], + "items" : { + "type" : "string", + "example" : "MBE" + } + } + }, + "additionalProperties" : false + } + }, + "birthDate" : { + "type" : "string", + "description" : "The date on which the patient was born or is officially deemed to have been born.\n\nIt is a date in the format `yyyy-mm-dd`. Due to data quality issues on a small number of patients `yyyy-mm` and `yyyy` format may also be returned.\n", + "format" : "date", + "example" : "2010-10-22" + } + }, + "description" : "The patient's details." + } + }, + "parameters" : { + "proxyID" : { + "name" : "identifier", + "in" : "query", + "description" : "The proxy's NHS number.\n", + "required" : false, + "style" : "form", + "explode" : true, + "schema" : { + "type" : "string" + }, + "examples" : { + "withoutSystem" : { + "summary" : "NHS number specified without system", + "value" : "9000000009" + }, + "withSystem" : { + "summary" : "System and NHS number specified", + "value" : "https://fhir.nhs.uk/Id/nhs-number/9000000009" + } + } + }, + "patientID" : { + "name" : "patient:identifier", + "in" : "query", + "description" : "The patient's NHS number.\n", + "required" : false, + "style" : "form", + "explode" : true, + "schema" : { + "type" : "string" + }, + "examples" : { + "withoutSystem" : { + "summary" : "NHS number specified without system", + "value" : "9000000009" + }, + "withSystem" : { + "summary" : "System and NHS number specified", + "value" : "https://fhir.nhs.uk/Id/nhs-number/9000000009" + } + } + }, + "BearerAuthorisation" : { + "name" : "Authorisation", + "in" : "header", + "description" : "An [OAuth 2.0 bearer token](https:\n", + "required" : true, + "style" : "simple", + "explode" : false, + "schema" : { + "type" : "string", + "format" : "^Bearer\\ [[:ascii:]]+$", + "example" : "Bearer g1112R_ccQ1Ebbb4gtHBP1aaaNM" + } + }, + "RequestID" : { + "name" : "X-Request-ID", + "in" : "header", + "description" : "A globally unique identifier (GUID) for the request, which we use to correlate logs through different components.\nMust be a universally unique identifier (UUID) (ideally version 4).\nMirrored back in a response header.\n", + "required" : true, + "style" : "simple", + "explode" : false, + "schema" : { + "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}$", + "type" : "string", + "example" : "60E0B220-8136-4CA5-AE46-1D97EF59D068" + } + }, + "CorrelationID" : { + "name" : "X-Correlation-ID", + "in" : "header", + "description" : "An optional ID which you can use to track transactions across multiple systems. It can have any value, but we recommend avoiding `.` characters.\nMirrored back in a response header.\n", + "required" : false, + "style" : "simple", + "explode" : false, + "schema" : { + "type" : "string", + "example" : "11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA" + } + } + } + } +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0a3ffe4..18eeb80 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -4,6 +4,9 @@ server: threads: max: 10 forward-headers-strategy: native + error: + whitelabel: + enabled=false: management: health: @@ -15,12 +18,15 @@ management: fhir: server: - name: IOPS FHIR Testing - baseUrl: https://3cdzg7kbj4.execute-api.eu-west-2.amazonaws.com/poc/Conformance - version: 6.8.0 - - - + name: FHIR Development and Testing (FHIR Validation) Skunkworks + baseUrl: http://localhost:9001 + version: 7.0.3 + +services: + R4: true + STU3: true + LOINC: false + R4B: false ###Remote terminology validation: diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 1856896..aa69cce 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -16,7 +16,7 @@ class="ch.qos.logback.core.ConsoleAppender"> - %-5level %C{1.}: %msg%n + %-5level %C{1}: %msg%n diff --git a/src/main/resources/manifest.json b/src/main/resources/manifest.json index 5aaf581..bc6afc3 100644 --- a/src/main/resources/manifest.json +++ b/src/main/resources/manifest.json @@ -3,17 +3,12 @@ "packageName": "fhir.r4.ukcore.stu3.currentbuild", "version": "0.0.9-pre-release" }, - { - "packageName": "uk.nhsdigital.r4.test", - "version": "2.8.15-prerelease" - }, { "packageName": "hl7.fhir.uv.sdc", "version": "3.0.0" }, { - "packageName": "hl7.fhir.us.core", - "version": "3.1.1" + "packageName": "fhir.r4.nhsengland.stu1", + "version": "1.1.0" } - ] diff --git a/src/main/resources/message.properties b/src/main/resources/message.properties index aad2847..23fe31c 100644 --- a/src/main/resources/message.properties +++ b/src/main/resources/message.properties @@ -35,6 +35,7 @@ aws.queueEnabled=false aws.validationSupport=false cdr.fhirServer=https://cnuc9zdola.execute-api.eu-west-2.amazonaws.com/dev npm.fhirServer=https://3cdzg7kbj4.execute-api.eu-west-2.amazonaws.com/poc/utility +loinc.fhirServer=https://fhir.loinc.org validation.fhirServer=http://localhost:9001 ################################################## diff --git a/src/main/resources/static/favicon.ico b/src/main/resources/static/favicon.ico deleted file mode 100644 index a4c5bdb..0000000 Binary files a/src/main/resources/static/favicon.ico and /dev/null differ diff --git a/src/main/resources/static/favicon.png b/src/main/resources/static/favicon.png deleted file mode 100644 index 296a680..0000000 Binary files a/src/main/resources/static/favicon.png and /dev/null differ diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html deleted file mode 100644 index 5c3e02d..0000000 --- a/src/main/resources/static/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - Old Page - - - - - -

Redirecting to OAS Specficition here

- - diff --git a/src/main/resources/xslt/DocumentToHTML.xslt b/src/main/resources/xslt/DocumentToHTML.xslt new file mode 100644 index 0000000..3698112 --- /dev/null +++ b/src/main/resources/xslt/DocumentToHTML.xslt @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="$titleStr"/> + + + +

+ +

+
+ +
+ + + + + + +
+ + + + + + + + + + + + +

+ +

+
+ +

+ + + +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Y + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + +

+ + + +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + p + + + + + + + +
diff --git a/src/main/resources/xslt/utilities-l10n.xml b/src/main/resources/xslt/utilities-l10n.xml new file mode 100644 index 0000000..f2d7485 --- /dev/null +++ b/src/main/resources/xslt/utilities-l10n.xml @@ -0,0 +1,10684 @@ + + + + + + + + + + + + + Label: Display disclaimer + + Disclaimer: the purpose of this stylesheet and the results it produces from xml messages is exclusively for testing. They are explicitly NOT suited for use in a medical practise. + Disclaimer: Deze stylesheet en de resulterende html weergave van xml berichten zijn uitsluitend bedoeld voor testdoeleinden. Zij zijn uitdrukkelijk niet bedoeld voor gebruik in de medische praktijk. + + + + Label: Table of Contents + + Table of Contents + Inhoudsopgave + Inhaltsverzeichnis + + + + Label: Signed + + Signed + Ondertekend + Unterzeichnet + + + + Label: show revisions + + Show revisions + Toon revisies + Zeige Revisionen + + + + Label: hide revisions + + Hide revisions + Verberg revisies + Verberg Revisionen + + + + Label: ClinicalDocument + + ClinicalDocument + + + + + Label: Authenticator + + Authenticator + Unterzeichnet + Signé + Firmato + Ondertekenaar + + + + Label: Legal Authenticator + + Legal Authenticator + Rechtsgültig unterzeichnet + Légal signataires + Efficace legge firmato + Juridische ondertekenaar + + + + Label: Information Recipient + + Information Recipient + Ontvanger + + + + Label: Author + + Author + Autor + Auteur + Autore + Auteur + + + + Label: Custodian + + Custodian + Verwalter + Beheerder + + + + Label: Data enterer + + Data Enterer + Erfasser + Saisie par + Registrati da + Ingevoerd door + + + + Label: Overseer + + Overseer + Mandaterende/eindverantwoordelijke + + + + Label: recordTarget + + Patient + Paziente + Patiënt + + + + Label: Informant - An informant (or source of information) is a person that provides relevant information + + Informant + Informiert + Informé + Informati + + + + Label: Participant + + Participant + + + + Label: Custodian Organization + + Custodian Organization + Verwaltende Organisation + Organisme de gestion + Organismo di gestione + Beherende organisatie + + + + Label: Performer + + Performer + Heilberufler + Zorgverlener + + + + Label: responsibleParty + + Responsible Party + Verantwoordelijke + + + + Label: encounterParticipant + + Encounter Participant + Deelnemer contact + + + + Label: location + + Location + Lokatie + + + + Label: subject + + Subject + Onderwerp + + + + + + Label: OrganizationPartOf + + Organization Part Of + Organisatie deel van + + + + Label: Organization + + Organization + Organisatie + + + + Label: Person + + Person + Persoon + + + + Label: AuthoringDevice + + Device + Apparaat + + + + Label: Place + + Place + Plaats + + + + Label: HealthCareFacility + + Health Care Facility + Zorginstelling + + + + + + Label: Patient-ID short + + MRN + PID + PID + + + + Label: Patient-ID long + + Patient-ID + Patienten ID + ID patient + ID paziente + Patiëntnummer + + + + Label: Patient-IDs long + + Patient-IDs + Patienten IDs + IDs patient + ID paziente + Patiëntnummers + + + + Label: Birthplace long + + Birthplace + Geburtsplatz + Place de naissance + Geboorteplaats + + + + Label: Birthdate long + + Birthdate + Geburtsdatum + Date de naissance + Data di nascita + Geboortedatum + + + + Label: Birthdate long and deceased + + Birthdate/deceased + Geburtsdatum/verstorben + Date de naissance/décédé + Data di nascita/defunto + Geboren/overleden + + + + Label: Deceased + + Deceased + Overleden + + + + Label: date_unknown - used for saying you know patient has died, but unknown when + + date unknown + Datum unbekannt + date inconnue + data sconosciuto + datum onbekend + + + + Label: boolean-true - used for saying Deceased: yes + + yes + ja + oui + si + ja + + + + Label: boolean-false - used for saying Deceased: no + + no + nein + non + no + nee + + + + Label: yr as in the age of someone in years + + yr + jr + Jahre + + + + Title on age to tell us to what the age is relative to. As XSL 1.0 doesn't have date functions we need content based based relativity + + At the time of death + Bij overlijden + + + + Title on age to tell us to what the age is relative to. As XSL 1.0 doesn't have date functions we need content based based relativity + + At document creation time + Bij aanmaken van het document + + + + Label: DOB (Date of birth) short + + DOB + Geburtsdatum + Geboortedatum + + + + Label: person is part of a multiple birth + + Multiple birth + Meerling + + + + Label: AdministrativeGenderCode + + Gender + Geschlecht + Geslacht + + + + Label: MaritalStatusCode + + Marital Status + Burgerlijke staat + + + + Label: LanguageCommunication + + Language Communication + Taal + + + + Label: Ethnicity + + Ethnicity + Etniciteit + + + + Label: ProficiencyLevelCode + + Proficiency Level Code + Mate van beheersing + + + + Label: Guardian (for recordTarget) + + Guardian + Voogd + + + + + + Label: relatedDocument + + Related Document + Gerelateerd document + + + + Label: ParentDocument + + Parent Document + Voorgaand document + + + + Label: documentationOf + + Documentation Of + Documentatie van + + + + Label: ServiceEvent + + Service Event + Uitgevoerde handeling + + + + Label: InFulfillmentOf + + In Fulfillment Of + Conform + + + + Label: Order + + Order + + + + Label: Authorization + + Authorization + Autorisatie + + + + Label: Consent + + Consent + Einverständniserklärung + Consentement éclairé + Dichiarazione di consenso + Toestemmingsverklaring + + + + Label: componentOf + + Component Of + Component van + + + + Label: encompassingEncounter + + Encounter + Contact + + + + Label: Encounter Id + + Encounter Id + Contact-id + + + + Label: Encounter Type + + Encounter Type + Contacttype + + + + Label: Encounter Date + + Encounter Date + Contactdatum + + + + Label: Encounter Location + + Encounter Location + Contactlocatie + + + + + + Label: Document Id + + Document Id + Document-id + + + + Label: SetId and Version + + SetId and Version + Set-Id en versie + + + + Label: ID + + ID + Id + + + + Label: setId + + Set-ID + Set-Id + + + + Label: versionNumber + + Version + Versie + + + + Label: Code + + Code + + + + Label: Title + + Title + Titel + + + + Label: effectiveTime + + Date/time + Datum/tijd + + + + Label: versionCode + + Version code + Versiecode + + + + Label: acknowledgement + + Acknowledgement + + + + Label: acknowledgementDetail + + Acknowledgement detail + + + + Label: attentionLine + + Attention line + + + + Label: keyWordText + + Key word + + + + Label: sender + + Sender + Verzender + + + + Label: receiver + + Receiver + Ontvanger + + + + Label: interactionId + + Interaction ID + Interactie-id + + + + Label: profileId + + Profile ID + Profile-id + + + + Label: transmissionQuantity + + Batch message count + Aantal berichten in de batch + + + + Label: resultTotalQuantity + + Result count total + Aantal resultaten totaal + + + + Label: resultCurrentQuantity + + Result count current + Aantal resultaten huidig + + + + Label: resultRemainingQuantity + + Result count remaining + Aantal resultaten resterend + + + + Label: justifiedDetectedIssue + + Detected issue + Gedetecteerd probleem + + + + Label: queryAck + + Query ack + + + + Label: queryByParameter + + Query by parameter + + + + Label: queryId + + Query ID + Query-id + + + + Label: queryResponseCode + + Query response code + Query antwoordcode + + + + Label: responseModalityCode + + Response modality + Antwoordmodus code + + + + Label: responsePriorityCode + + Response priority + Antwoordprioriteit + + + + Label: initialQuantity + + Initial quantity + Initiële hoeveelheid + + + + Label: initialQuantityCode + + Initial quantity code + Initiële hoeveelheid code + + + + Label: executionAndDeliveryTime + + Execution and delivery time + Antwoord sturen vóór + + + + Label: functionCode + + Function + Functie + + + + Label: copyTime + + Copy Date/time + Kopiedatum/tijd + + + + Label: time + + Time + Tijd + + + + Label: confidentialityCode + + Confidentiality + Vertrouwelijkheid + + + + Label: languageCode + + Language + Taal + + + + Label: signatureCode + + Signature Code + Handtekeningcode + + + + Label: signatureCode-S + + Signed + Getekend + + + + Label: signatureCode-I + + Intended + Zal nog tekenen + + + + Label: signatureCode-X + + Signature required + Handtekening vereist + + + + Label: addr + + Address + Adres + + + + Label: address not available + + address not available + adres niet beschikbaar + + + + Label: telecom + + Telecom + + + + Label: telecom information not available + + telecom information not available + telecominformatie niet beschikbaar + + + + Label: name + + Name + Naam + + + + Label: statusCode + + Status + + + + Label: text + + Text + Tekst + + + + Label: priorityCode + + Priority + Prioriteit + + + + Label: dischargeDispositionCode + + Discharge Disposition + Ontslagstatus + + + + + + Label: Contents (i.e. bodyChoice NonXMLBody/StructuredBody or Section) + + Contents + Contents + Contents + Contents + Inhoud + + + + Label: Section + + Section + Sectie + + + + Label: Section Author + + Section Author + Auteur sectie + + + + Label: Section Subject + + Section Subject + Subject sectie + + + + Label: Section Informant + + Section Informant + Informant sectie + + + + + + Label: Supporting author + + Supporting author + Mitbehandelnde Heilberufler + Ondersteunend zorgverlener + + + + Label: Payer + + Payer + Betaler + + + + Label: Policy Number (for payer) + + Policy Number + Polisnummer + + + + Label: Insured + + Insured + Versicherungsnehmer + Assuré + Assicurati + Verzekerde + + + + Label: Insurance Company + + Insurance Company + Versicherung + Assurance + Assicurazione + Verzekeraar + + + + Title for documents + + Clinical Document + Klinisch document + + + + Label: Created on + + Created on + Erzeugt am + Création + Generata + Gemaakt op + + + + Label: Authored on + + Authored on + Gemaakt op + + + + Label: Exam Date + + Exam Date + Datum onderzoek + + + + Label: Exam Time + + Exam Time + Tijd onderzoek + + + + Label: Next of Kin (for recordTarget) + + Next of Kin + Familie + + + + Title: Table of Contents + + Table of Contents + Inhoud + + + + Dates: January + + January + Januar + Janvier + Gennaio + januari + + + + Dates: February + + February + Februar + Février + Febbraio + februari + + + + Dates: March + + March + März + Mars + März + maart + + + + Dates: April + + April + Avril + Marzo + april + + + + Dates: May + + May + Mai + Mai + Maggio + mei + + + + Dates: June + + June + Juni + Juin + Giugno + juni + + + + Dates: July + + July + Juli + Juillet + Luglio + juli + + + + Dates: August + + August + Août + Agosto + augustus + + + + Dates: September + + September + Septembre + Settembre + september + + + + Dates: October + + October + Oktober + Octobre + Ottobre + oktober + + + + Dates: November + + November + Novembre + Novembre + november + + + + Dates: December + + December + Dezember + Décembre + Dicembre + december + + + + Dates: Monday + + Monday + maandag + + + + Dates: Tuesday + + Tuesday + dinsdag + + + + Dates: Wednesday + + Wednesday + woensdag + + + + Dates: Thursday + + Thursday + donderdag + + + + Dates: Friday + + Friday + vrijdag + + + + Dates: Saturday + + Saturday + zaterdag + + + + Dates: Sunday + + Sunday + zondag + + + + Dates: Monday (short) + + Mon + maa + + + + Dates: Tuesday (short) + + Tue + din + + + + Dates: Wednesday (short) + + Wed + woe + + + + Dates: Thursday (short) + + Thu + don + + + + Dates: Friday (short) + + Fri + vri + + + + Dates: Saturday (short) + + Sat + zat + + + + Dates: Sunday (short) + + Sun + zon + + + + Time: h for hours in 14h in English or 14u in Dutch + + h + u + + + + Label: Electronically generated by + + Electronically generated by + Elektronisch gegenereerd door + + + + Label: Cannot display the text + + Cannot display the text + Kan tekst niet weergeven + + + + Label: Coded Entries + + Coded Entries + Gecodeerde onderdelen + + + + Label: displayname + + Displayname + Weergavenaam + + + + Label: qualifier + + qualifier + + + + Label: value + + value + waarde + + + + Label: Value + + Value + Waarde + + + + Label: Quantity + + Quantity + Hoeveelheid + + + + Label: Unit + + Unit + Eenheid + + + + Label: Units + + Units + Eenheden + + + + Label: unit + + unit + eenheid + + + + Label: units + + units + eenheden + + + + Label: x units per y unit + + per + per + + + + Label: Reference + + Reference + Verwijzing + + + + Dates: Time + + Time + Zeit + Tijd + + + + Dates: from (as in from/to) + + from + von + van + + + + Dates: From (as in from/to) + + From + Von + Van + + + + Dates: to (as in from/to) + + to + zu + tot + + + + Dates: To (as in from/to) + + To + Zu + Tot + + + + Dates: Up To (as in from/to) + + Up To + tot + + + + Intervals @inclusive="true" + + inclusive + inclusief + + + + Interval width: for (for 3 days) + + for + voor + + + + Interval: every (as every 6 hours) + + every + elke + + + + Label: NHS Number + + NHS Number + NHS nummer + + + + Label: Document Created + + Document Created + Aanmaakdatum + + + + Label: Document Owner + + Document Owner + Eigenaar + + + + Dates: on + + on + am + le + il + op + + + + Dates: On (on August 2) + + On + Am + Le + Il + Op + + + + Dates: at + + at + am + le + il + op + + + + Dates: At (as in At 7PM) + + At + Am + Le + Il + Op + + + + Label: Encounter Type + + Encounter Type + Type contact + + + + Label: Encounter Time + + Encounter Time + Datum/tijd contact + + + + Label: Care Setting Type + + Care Setting Type + Type zorginstelling + + + + Label: Recipient + + Recipient + Ontvanger + + + + Label: Referrer + + Referrer + Verwijzer + + + + Label: Referring Organization + + Referring Organization + Verwijzende organisatie + + + + Label: Document ID + + Document ID + Document-id + + + + Label: Version + + Version + Versie + + + + Label: Primary Recipient + + Primary Recipient + Empfänger + Destinataire + Destinatario + Ontvanger + + + + Label: Primary Recipients + + Primary Recipients + Empfänger + Destinataires + Destinatario + Ontvangers + + + + Label: Copy Recipient + + Copy Recipient + Kopie an + Copie à + In copia a + Kopie naar + + + + Label: Copy Recipients + + Copy Recipients + Kopie an + Copie à + In copia a + Kopie naar + + + + Label: Tel (telecom type) + + Tel + + + + Label: Fax (telecom type) + + Fax + + + + Label: Email (telecom type) + + Email + Mail + E-mail + + + + Label: Web (telecom type) + + Web + + + + Label: Contact details + + Contact details + Contactgegevens + + + + Label: Diagnostic Radiology + + Diagnostic Radiology + Diagnostische radiologie + + + + Label: Consultant + + Consultant + + + + Label: Cannot display the text + + Cannot display the text + Kan de tekst niet weergeven + + + + Label: Facility ID + + Facility ID + Lokatie-id + + + + Label: Not available + + Not available + Niet beschikbaar + + + + Label: First day of period reported + + First day of period reported + Eerste dag van verslagperiode + + + + Label: Last day of period reported + + Last day of period reported + Laatste dag van verslagperiode + + + + Label: Footnote + + Footnote + Voetnoot + + + + Label: Information not available + + Information not available + Informatie niet beschikbaar + + + + Label: Race + + Race + Ras + + + + + + Label: AdministrativeGender: Male + + Male + Männlich + Masculin + Maschile + Man + + + + Label: AdministrativeGender: Female + + Female + Weiblich + Féminin + Femminile + Vrouw + + + + Label: AdministrativeGender: Undifferentiated + + Undifferentiated + Ongedifferentieerd + + + + Label: ActCode: ActEncounterCode: Ambulatory + + ambulatory + ambulant + + + + Label: ActCode: ActEncounterCode: Emergency + + emergency + noodgeval + + + + Label: ActCode: ActEncounterCode: Field + + field + buiten + + + + Label: ActCode: ActEncounterCode: Home Health + + home health + thuiszorg + + + + Label: ActCode: ActEncounterCode: Inpatient + + inpatient + klinisch + + + + Label: ActCode: ActEncounterCode: Acute + + acute + spoed + + + + Label: ActCode: ActEncounterCode: Inpatient non-acute + + inpatient non-acute + klinisch niet-acuut + + + + Label: ActCode: ActEncounterCode: Short stay + + short stay + dagbehandeling + + + + Label: ActCode: ActEncounterCode: Virtual + + virtual + virtueel + + + + Label: ActClass act + + act + + + + Label: ActClass accommodation + + accommodation + accommodatie + + + + Label: ActClass account + + account + + + + Label: ActClass accession + + accession + accessie + + + + Label: ActClass financial adjudication + + financial adjudication + financiële adjudicatie + + + + Label: ActClass control act + + control act + + + + Label: ActClass action + + action + actie + + + + Label: ActClass information + + information + informatie + + + + Label: ActClass state transition control + + state transition control + statusovergang control + + + + Label: ActClass contract + + contract + + + + Label: ActClass financial contract + + financial contract + financieel contract + + + + Label: ActClass coverage + + coverage + verzekeringsdekking + + + + Label: ActClass consent + + consent + toestemming + + + + Label: ActClass container registration + + container registration + containerregistratie + + + + Label: ActClass clinical trial timepoint event + + clinical trial timepoint event + + + + Label: ActClass disciplinary action + + disciplinary action + disciplinaire maatregel + + + + Label: ActClass exposure + + exposure + blootstelling + + + + Label: ActClass acquisition exposure + + acquisition exposure + acquisitie blootstelling + + + + Label: ActClass transmission exposure + + transmission exposure + overdracht blootstelling + + + + Label: ActClass incident + + incident + + + + Label: ActClass inform + + inform + informeren + + + + Label: ActClass invoice element + + invoice element + + + + Label: ActClass working list + + working list + werklijst + + + + Label: ActClass monitoring program + + monitoring program + monitoring programma + + + + Label: ActClass observation + + observation + observatie + + + + Label: ActClass detected issue + + detected issue + gedetecteerd probleem + + + + Label: ActClass battery + + battery + batterij + + + + Label: ActClass clinical trial + + clinical trial + + + + Label: ActClass Condition Node + + Condition Node + Conditienode + + + + Label: ActClass concern + + concern + aandachtspunt + + + + Label: ActClass Condition + + Condition + Conditie + + + + Label: ActClass public health case + + public health case + volksgezondheidsgeval + + + + Label: ActClass outbreak + + outbreak + uitbraak + + + + Label: ActClass diagnostic image + + diagnostic image + diagnostiekbeeld + + + + Label: ActClass genomic observation + + genomic observation + genetische observatie + + + + Label: ActClass determinant peptide + + determinant peptide + + + + Label: ActClass expression level + + expression level + uitdrukkingsniveau + + + + Label: ActClass locus + + locus + + + + Label: ActClass phenotype + + phenotype + fenotype + + + + Label: ActClass polypeptide + + polypeptide + + + + Label: ActClass bio sequence + + bio sequence + + + + Label: ActClass bio sequence variation + + bio sequence variation + bio sequence variatia + + + + Label: ActClass investigation + + investigation + onderzoek + + + + Label: ActClass observation series + + observation series + observatieserie + + + + Label: ActClass correlated observation sequences + + correlated observation sequences + gecorreleerde observatie sequenties + + + + Label: ActClass position + + position + positie + + + + Label: ActClass position accuracy + + position accuracy + + + + Label: ActClass position coordinate + + position coordinate + + + + Label: ActClass specimen observationActClassSpecObs + + specimen observationActClassSpecObs + + + + Label: ActClass Verification + + Verification + Verificatie + + + + Label: ActClass bounded ROI + + bounded ROI + vaste ROI + + + + Label: ActClass overlay ROI + + overlay ROI + overliggende ROI + + + + Label: ActClass left lateral decubitus + + left lateral decubitus + linker laterale decubitus + + + + Label: ActClass prone + + prone + + + + Label: ActClass right lateral decubitus + + right lateral decubitus + rechter laterale decubitus + + + + Label: ActClass Semi-Fowler's + + Semi-Fowler's + + + + Label: ActClass sitting + + sitting + zittend + + + + Label: ActClass standing + + standing + staand + + + + Label: ActClass supine + + supine + + + + Label: ActClass reverse trendelenburg + + reverse trendelenburg + omgekeerde trendelenburg + + + + Label: ActClass trendelenburg + + trendelenburg + + + + Label: ActClass care provision + + care provision + + + + Label: ActClass encounter + + encounter + bezoek + + + + Label: ActClass policy + + policy + + + + Label: ActClass jurisdictional policy + + jurisdictional policy + juridische policy + + + + Label: ActClass organizational policy + + organizational policy + organisatie policy + + + + Label: ActClass scope of practice policy + + scope of practice policy + behandelpolicy + + + + Label: ActClass standard of practice policy + + standard of practice policy + standaard behandelpolicy + + + + Label: ActClass procedure + + procedure + + + + Label: ActClass substance administration + + substance administration + substantie toediening + + + + Label: ActClass Substance Extraction + + Substance Extraction + substantie extractie + + + + Label: ActClass Specimen Collection + + Specimen Collection + Monster collectie + + + + Label: ActClass registration + + registration + registratie + + + + Label: ActClass review + + review + + + + Label: ActClass specimen treatment + + specimen treatment + monmster behandeling + + + + Label: ActClass supply + + supply + middel + + + + Label: ActClass diet + + diet + dieet + + + + Label: ActClass storage + + storage + opslag + + + + Label: ActClass Substitution + + Substitution + Substitutie + + + + Label: ActClass transfer + + transfer + overplaatsing + + + + Label: ActClass transportation + + transportation + transport + + + + Label: ActClass financial transaction + + financial transaction + financiële transactie + + + + Label: ActClass compositionAttestable unit + + composition + compositie + + + + Label: ActClass document + + document + + + + Label: ActClass clinical document + + clinical document + klinisch document + + + + Label: ActClass CDA Level One clinical document + + CDA Level One clinical document + CDA Level One klinisch document + + + + Label: ActClass record container + + record container + + + + Label: ActClass category + + category + categorie + + + + Label: ActClass document body + + document body + documentinhoud + + + + Label: ActClass document sectionSection + + document section + documentsectie + + + + Label: ActClass topic + + topic + onderwerp + + + + Label: ActClass extract + + extract + + + + Label: ActClass electronic health record + + electronic health record + electronisch gezondheidsdossier + + + + Label: ActClass folder + + folder + map + + + + Label: ActClass grouper + + grouper + groepering + + + + Label: ActClass Cluster + + cluster + + + + Label: OID AcknowledgementType CA + + Commit Accept + Technische bevestiging + + + + Label: OID AcknowledgementType CE + + Commit Error + Technische fout + + + + Label: OID AcknowledgementType CR + + Commit Reject + Technische weigering + + + + Label: OID AcknowledgementType AA + + Application Accept + Applicatie bevestiging + + + + Label: OID AcknowledgementType AE + + Application Error + Applicatie bevestiging + + + + Label: OID AcknowledgementType AR + + Application Reject + Applicatie weigering + + + + Label: OID AcknowledgementDetail W + + Warning + Waarschuwing + + + + Label: OID AcknowledgementDetail I + + Information + Informatie + + + + Label: OID AcknowledgementDetail E + + Error + Fout + + + + Label: QueryResponse AE + + AE (Application error, query aborted) + AE (Applicatie probleem, beantwoording afgebroken) + + + + Label: QueryResponse NF + + NF (Nothing found, no errors) + NF (Niets gevonden, geen fouten) + + + + Label: QueryResponse OK + + OK (Data found) + OK (Data gevonden) + + + + Label: QueryResponse QE + + QE (Query Parameter Error, query aborted) + QE (Queryparameter fout, beantwoording afgebroken) + + + + Label: OID ResponseModality-B + + B (Batch) + + + + Label: OID ResponseModality-R + + R (Realtime) + + + + Label: OID ResponseModality-T + + T (Bolus) + T (Bolus, niet gebruiken) + + + + Label: QueryPriority D + + D (Deferred) + + + + Label: QueryPriority I + + I (Immediate) + + + + Label: QueryRequestLimit RD + + RD (Records) + + + + Label: Confidentiality: Normal + + Normal + Normaal + + + + Label: Confidentiality: Restricted + + Restricted + Vertrouwelijk + + + + Label: Confidentiality: Very restricted + + Very restricted + Zeer vertrouwelijk + + + + Label: NullFlavor NI + + Unknown + Unbekannt + Inconnu + Sconosciuta + Onbekend + + + + Label: NullFlavor INV + + Invalid + Ongeldig + + + + Label: NullFlavor MSK + + Masked + Afgeschermd + + + + Label: NullFlavor NA + + Not Applicable + n.v.t. + + + + Label: NullFlavor NINF + + Negative Infinity + Negatief oneindig + + + + Label: NullFlavor PINF + + Positive Infinity + Positief oneindig + + + + Label: NullFlavor UNC + + Un-encoded + Niet gecodeerd + + + + Label: NullFlavor UNK + + Unknown + Onbekend + + + + Label: Status active + + Active + Actief + + + + Label: Status completed + + Completed + Afgerond + + + + Label: Status cancelled + + Cancelled + Geannuleerd + + + + Label: Status nullified + + Nullified + Opgeheven + + + + Label: Status aborted + + Aborted + Afgebroken + + + + Label: Status obsolete + + Obsolete + Obsoleet + + + + Label: Status suspended + + Suspended + Opgeschort + + + + Label: Status new + + New + Nieuw + + + + Label: Status normal + + Normal + Normaal + + + + Label: Status pending + + Pending + Voorlopig + + + + Label: Status terminated + + Terminated + Beëindigd + + + + Label: Status inactive + + Inactive + Inactief + + + + Label: Status executing + + Executing + In uitvoering + + + + Label: Status waitContinuedQueryResponse + + Wait continued query response + Wacht op volgende antwoord op vraag + + + + Label: Status deliveredResponse + + Delivered response + Afgeleverd antwoord + + + + Label: ParticipationFunction caregiver information receiver + + caregiver information receiver + zorgverlener informatieontvanger + + + + Label: ParticipationFunction legitimate relationship information receiver + + legitimate relationship information receiver + legitieme relatie informatieontvanger + + + + Label: ParticipationFunction care team information receiver + + care team information receiver + zorgteam informatieontvanger + + + + Label: ParticipationFunction work area information receiver + + work area information receiver + werkomgeving informatieontvanger + + + + Label: ParticipationFunction legal guardian consent author + + legal guardian consent author + wettelijke vertegenwoordiger toestemming auteur + + + + Label: ParticipationFunction healthcare power of attorney consent author + + healthcare power of attorney consent author + zorgadvocaat toestemming auteur + + + + Label: ParticipationFunction personal representative consent author + + personal representative consent author + persoonlijke vertegenwoordiger toestemming auteur + + + + Label: ParticipationFunction authorized provider masking author + + authorized provider masking author + geautoriseerde zorgverlener gemaskeerd auteur + + + + Label: ParticipationFunction subject of consent author + + subject of consent author + onderwerp van toestemming auteur + + + + Label: ParticipationFunction consent overrider + + consent overrider + toestemming verbreker + + + + Label: ParticipationFunction emergency overrider + + emergency overrider + verbreker in noodgeval + + + + Label: ParticipationFunction claims adjudication + + claims adjudication + claim adjudicatie + + + + Label: ParticipationFunction enrollment broker + + enrollment broker + + + + Label: ParticipationFunction ffs management + + ffs management + + + + Label: ParticipationFunction managed care management + + managed care management + + + + Label: ParticipationFunction provider management + + provider management + + + + Label: ParticipationFunction utilization management + + utilization management + + + + Label: ParticipationFunction fully insured + + fully insured + volledig verzekerd + + + + Label: ParticipationFunction self insured + + self insured + zelf verzekerd + + + + Label: ParticipationFunction payor contracting + + payor contracting + + + + Label: ParticipationFunction reinsures + + reinsures + + + + Label: ParticipationFunction retrocessionaires + + retrocessionaires + + + + Label: ParticipationFunction subcontracting risk + + subcontracting risk + + + + Label: ParticipationFunction underwriting + + underwriting + + + + Label: ParticipationFunction admitting physician + + admitting physician + opnamearts + + + + Label: ParticipationFunction anesthesist + + anesthesist + + + + Label: ParticipationFunction anesthesia nurse + + anesthesia nurse + anesthesie-verpleegkundige + + + + Label: ParticipationFunction attending physician + + attending physician + behandelend arts + + + + Label: ParticipationFunction discharging physician + + discharging physician + ontslagarts + + + + Label: ParticipationFunction first assistant surgeon + + first assistant surgeon + eerste chirurgisch assistent + + + + Label: ParticipationFunction midwife + + midwife + verloskundige + + + + Label: ParticipationFunction nurse assistant + + nurse assistant + verpleegkundig assistent + + + + Label: ParticipationFunction primary care physician + + primary care physician + eerstelijns arts + + + + Label: ParticipationFunction primary surgeon + + primary surgeon + eerste chirurg + + + + Label: ParticipationFunction rounding physician + + rounding physician + afrondende chirurg + + + + Label: ParticipationFunction second assistant surgeon + + second assistant surgeon + tweede chirurgisch assistent + + + + Label: ParticipationFunction scrub nurse + + scrub nurse + verpleegster + + + + Label: ParticipationFunction third assistant + + third assistant + derde assistent + + + + Label: OID ParticipationSignature + + intended + heeft de intentie + + + + Label: OID ParticipationSignature + + signed + heeft getekend + + + + Label: OID ParticipationSignature + + required + moet tekenen + + + + Label: ParticipationType Participation + + Participation + Participatie + + + + Label: ParticipationType admitter + + admitter + opgenomen door + + + + Label: ParticipationType attender + + attender + behandeld door + + + + Label: ParticipationType callback contact + + callback contact + contactpersoon + + + + Label: ParticipationType consultant + + consultant + + + + Label: ParticipationType discharger + + discharger + ontslagen door + + + + Label: ParticipationType escort + + escort + begeleider + + + + Label: ParticipationType referrer + + referrer + verwijzer + + + + Label: ParticipationType author (originator) + + author (originator) + auteur (oorspronkelijk) + + + + Label: ParticipationType informant + + informant + + + + Label: ParticipationType Transcriber + + Transcriber + transscribent + + + + Label: ParticipationType data entry person + + data entry person + ingevoerd door + + + + Label: ParticipationType witness + + witness + getuige + + + + Label: ParticipationType custodian + + custodian + beheerder + + + + Label: ParticipationType direct target + + direct target + direct doel + + + + Label: ParticipationType baby + + baby + + + + Label: ParticipationType consumable + + consumable + eet- of drinkbaar + + + + Label: ParticipationType device + + device + apparaat + + + + Label: ParticipationType non-reuseable device + + non-reuseable device + niet-herbruikbaar apparaat + + + + Label: ParticipationType reusable device + + reusable device + herbruikbaar apparaat + + + + Label: ParticipationType donor + + donor + + + + Label: ParticipationType ExposureAgent + + ExposureAgent + + + + Label: ParticipationType ExposureParticipation + + ExposureParticipation + + + + Label: ParticipationType ExposureTarget + + ExposureTarget + + + + Label: ParticipationType ExposureSource + + ExposureSource + + + + Label: ParticipationType product + + product + + + + Label: ParticipationType subject + + subject + + + + Label: ParticipationType specimen + + specimen + monster + + + + Label: ParticipationType indirect target + + indirect target + indirect doel + + + + Label: ParticipationType beneficiary + + beneficiary + begunstigde + + + + Label: ParticipationType causative agent + + causative agent + veroorzakende agent + + + + Label: ParticipationType coverage target + + coverage target + verzekerde + + + + Label: ParticipationType guarantor party + + guarantor party + garantstaande partij + + + + Label: ParticipationType holder + + holder + verzekeringshouder + + + + Label: ParticipationType record target + + record target + patiënt + + + + Label: ParticipationType receiver + + receiver + ontvanger + + + + Label: ParticipationType information recipient + + information recipient + informatieontvanger + + + + Label: ParticipationType ugent notification contact + + urgent notification contact + contactpersoon bij nood + + + + Label: ParticipationType primary information recipient + + primary information recipient + bedoelde informatieontvanger + + + + Label: ParticipationType Referred By + + Referred By + Verwezen door + + + + Label: ParticipationType Referred to + + Referred to + Verwezen naar + + + + Label: ParticipationType tracker + + tracker + kopie-ontvanger + + + + Label: ParticipationType location + + location + lokatie + + + + Label: ParticipationType destination + + destination + bestemming + + + + Label: ParticipationType entry location + + entry location + invoerlokatie + + + + Label: ParticipationType origin + + origin + oorsprong + + + + Label: ParticipationType remote + + remote + extern + + + + Label: ParticipationType via + + via + + + + Label: ParticipationType performer + + performer + uitvoerende + + + + Label: ParticipationType distributor + + distributor + distributeur + + + + Label: ParticipationType primary performer + + primary performer + eerste uitvoerende + + + + Label: ParticipationType secondary performer + + secondary performer + tweede uitvoerende + + + + Label: ParticipationType responsible party + + responsible party + verantwoordelijke partij + + + + Label: ParticipationType verifier + + verifier + toezichthouder + + + + Label: ParticipationType authenticator + + authenticator + onderetkenaar + + + + Label: ParticipationType legal authenticator + + legal authenticator + wettelijke ondertekenaar + + + + Label: RoleClass child + + child + kind + + + + Label: RoleClass credentialed entity + + credentialed entity + bevoegde entiteit + + + + Label: RoleClass nurse practitioner + + nurse practitioner + + + + Label: RoleClass nurse + + nurse + verpleegkundige + + + + Label: RoleClass physician assistant + + physician assistant + arts-assistent + + + + Label: RoleClass physician + + physician + arts + + + + Label: RoleClass role + + role + rol + + + + Label: RoleClass affiliate + + affiliate + geaffilieerde + + + + Label: RoleClass agent + + agent + + + + Label: RoleClass assigned entity + + assigned entity + benoemde entiteit + + + + Label: RoleClass commissioning party + + commissioning party + + + + Label: RoleClass signing authority or officer + + signing authority or officer + ondertekenende autoriteit of functionaris + + + + Label: RoleClass contact + + contact + + + + Label: RoleClass emergency contact + + emergency contact + noodcontact + + + + Label: RoleClass next of kin + + next of kin + familie + + + + Label: RoleClass guardian + + guardian + voogd + + + + Label: RoleClass citizen + + citizen + burger + + + + Label: RoleClass covered party + + covered party + verzekerde + + + + Label: RoleClass claimant + + claimant + + + + Label: RoleClass named insured + + named insured + benoemde verzekerde + + + + Label: RoleClass dependent + + dependent + afhankelijke + + + + Label: RoleClass individual + + individual + individu + + + + Label: RoleClass subscriber + + subscriber + abonnmenthouder + + + + Label: RoleClass program eligible + + program eligible + + + + Label: RoleClass clinical research investigator + + clinical research investigator + klinisch onderzoeker + + + + Label: RoleClass clinical research sponsor + + clinical research sponsor + klinisch onderzoek sponsor + + + + Label: RoleClass employee + + employee + werknemer + + + + Label: RoleClass military person + + military person + militair + + + + Label: RoleClass Investigation Subject + + Investigation Subject + Onderzoek subject + + + + Label: RoleClass Case Subject + + Case Subject + Case subject + + + + Label: RoleClass research subject + + research subject + + + + Label: RoleClass licensed entity + + licensed entity + gelicenseerde entiteit + + + + Label: RoleClass notary public + + notary public + + + + Label: RoleClass healthcare provider + + healthcare provider + zorgaanbieder + + + + Label: RoleClass patient + + patient + patiënt + + + + Label: RoleClass payee + + payee + begunstigde + + + + Label: RoleClass invoice payor + + invoice payor + rekening betaler + + + + Label: RoleClass policy holder + + policy holder + polishouder + + + + Label: RoleClass qualified entity + + qualified entity + gekwalificeerde entiteit + + + + Label: RoleClass coverage sponsor + + coverage sponsor + verzerkering sponsor + + + + Label: RoleClass student + + student + + + + Label: RoleClass underwriter + + underwriter + + + + Label: RoleClass caregiver + + caregiver + zorgverlener + + + + Label: RoleClass personal relationship + + personal relationship + persoonlijke relatie + + + + Label: RoleClass access + + access + toegang + + + + Label: RoleClass Administerable Material + + Administerable Material + Toedienbaar materiaal + + + + Label: RoleClass birthplace + + birthplace + geboorteplaats + + + + Label: RoleClass place of death + + place of death + plaats overlijden + + + + Label: RoleClass distributed material + + distributed material + gedistribueerd materiaal + + + + Label: RoleClass retailed material + + retailed material + verkocht materiaal + + + + Label: RoleClass exposed entity + + exposed entity + blootgestelde entiteit + + + + Label: RoleClass held entity + + held entity + + + + Label: RoleClass health chart + + health chart + + + + Label: RoleClass identified entity + + identified entity + geïdentificeerde entiteit + + + + Label: RoleClass manufactured product + + manufactured product + geproduceerd product + + + + Label: RoleClass therapeutic agent + + therapeutic agent + therapeutisch agent + + + + Label: RoleClass maintained entity + + maintained entity + beheerde entiteit + + + + Label: RoleClass owned entity + + owned entity + bezitte entiteit + + + + Label: RoleClass regulated product + + regulated product + gereguleerd product + + + + Label: RoleClass service delivery location + + service delivery location + zorgverleningslokatie + + + + Label: RoleClass dedicated service delivery location + + dedicated service delivery location + lokatie bedoeld voor zorgverlening + + + + Label: RoleClass incidental service delivery location + + incidental service delivery location + toevallige zorgverleningslokatie + + + + Label: RoleClass territory of authority + + territory of authority + autoriteitsregio + + + + Label: RoleClass used entity + + used entity + gebruikte entiteit + + + + Label: RoleClass warranted product + + warranted product + product onder garantie + + + + Label: RoleClass equivalent entity + + equivalent entity + equivalente entiteit + + + + Label: RoleClass same + + same + dezelfde + + + + Label: RoleClass subsumed by + + subsumed by + opgevolgd door + + + + Label: RoleClass has generalization + + has generalization + heeft generalisatie + + + + Label: RoleClass has generic + + has generic + heeft generiekere + + + + Label: RoleClass instance + + instance + instantie + + + + Label: RoleClass subsumer + + subsumer + opvolger van + + + + Label: RoleClass content + + content + inhoud + + + + Label: RoleClass exposure agent carrier + + exposure agent carrier + + + + Label: RoleClass exposure vector + + exposure vector + + + + Label: RoleClass fomite + + fomite + + + + Label: RoleClass ingredient + + ingredient + ingrediënt + + + + Label: RoleClass active ingredient + + active ingredient + actief ingrediënt + + + + Label: RoleClass active ingredient - basis of strength + + active ingredient - basis of strength + actief ingrediënt - op basis van sterkte + + + + Label: RoleClass active ingredient - moiety is basis of strength + + active ingredient - moiety is basis of strength + actief ingrediënt - moiety is basis of strength + + + + Label: RoleClass active ingredient - reference substance is basis of strength + + active ingredient - reference substance is basis of strength + actief ingrediënt - reference substance is basis of strength + + + + Label: RoleClass additive + + additive + additief + + + + Label: RoleClass base + + base + basis + + + + Label: RoleClass inactive ingredient + + inactive ingredient + inactief ingrediënt + + + + Label: RoleClass color additive + + color additive + kleuradditief + + + + Label: RoleClass flavor additive + + flavor additive + smaakadditief + + + + Label: RoleClass preservative + + preservative + conserveringsmiddel + + + + Label: RoleClass stabilizer + + stabilizer + stabilisator + + + + Label: RoleClass located entity + + located entity + gelokaliseerde entiteit + + + + Label: RoleClass stored entity + + stored entity + opgeslagen entiteit + + + + Label: RoleClass member + + member + lid + + + + Label: RoleClass part + + part + deel + + + + Label: RoleClass active moiety + + active moiety + + + + Label: RoleClass specimen + + specimen + monster + + + + Label: RoleClass aliquot + + aliquot + + + + Label: RoleClass isolate + + isolate + isolaat + + + + Label: RoleCode Family Member + + Family Member + Familielid + + + + Label: RoleCode Child + + Child + Kind + + + + Label: RoleCode adopted child + + adopted child + geadopteerd kind + + + + Label: RoleCode adopted daughter + + adopted daughter + geadopteerde dochter + + + + Label: RoleCode adopted son + + adopted son + geadopteerde zoon + + + + Label: RoleCode foster child + + foster child + pleegkind + + + + Label: RoleCode foster daughter + + foster daughter + pleegdochter + + + + Label: RoleCode foster son + + foster son + pleegzoon + + + + Label: RoleCode child in-law + + child in-law + aangetrouwd kind + + + + Label: RoleCode daughter in-law + + daughter in-law + schoondochter + + + + Label: RoleCode son in-law + + son in-law + schoonzoon + + + + Label: RoleCode Daughter + + Daughter + Dochter + + + + Label: RoleCode natural daughterDaughter + + natural daughter + natuurlijke dochter + + + + Label: RoleCode stepdaughter + + stepdaughter + stiefdochter + + + + Label: RoleCode natural child + + natural child + natuurlijk kind + + + + Label: RoleCode natural sonSon + + natural son + naturlijke zoon + + + + Label: RoleCode son + + son + zoon + + + + Label: RoleCode stepson + + stepson + stiefzoon + + + + Label: RoleCode step child + + step child + stiefkind + + + + Label: RoleCode extended family member + + extended family member + ver familielid + + + + Label: RoleCode aunt + + aunt + tante + + + + Label: RoleCode MaternalAunt + + Maternal Aunt + Tante via moeder + + + + Label: RoleCode PaternalAunt + + Paternal Aunt + Tante via vader + + + + Label: RoleCode cousin + + cousin + neef/nicht + + + + Label: RoleCode MaternalCousin + + Maternal Cousin + Neef/nicht via moeder + + + + Label: RoleCode PaternalCousin + + Paternal Cousin + Neef/nicht via vader + + + + Label: RoleCode great grandparent + + great grandparent + overgrootouder + + + + Label: RoleCode great grandfather + + great grandfather + overgrootvader + + + + Label: RoleCode great grandmother + + great grandmother + overgrootmoeder + + + + Label: RoleCode MaternalGreatgrandfather + + Maternal Greatgrandfather + overgrootvader via moeder + + + + Label: RoleCode MaternalGreatgrandmother + + Maternal Greatgrandmother + overgrootmoeder via moeder + + + + Label: RoleCode MaternalGreatgrandparent + + Maternal Greatgrandparent + overgrootouder via moeder + + + + Label: RoleCode PaternalGreatgrandfather + + Paternal Greatgrandfather + overgrootvader via vader + + + + Label: RoleCode PaternalGreatgrandmother + + Paternal Greatgrandmother + overgrootmoeder via vader + + + + Label: RoleCode PaternalGreatgrandparent + + Paternal Greatgrandparent + overgrootouder via vader + + + + Label: RoleCode grandchild + + grandchild + kleinkind + + + + Label: RoleCode granddaughter + + granddaughter + kleindochter + + + + Label: RoleCode grandson + + grandson + kleinzoon + + + + Label: RoleCode Grandparent + + Grandparent + grootouder + + + + Label: RoleCode Grandfather + + Grandfather + grootvader + + + + Label: RoleCode Grandmother + + Grandmother + grootmoeder + + + + Label: RoleCode MaternalGrandfather + + MaternalGrandfather + grootvader via moeder + + + + Label: RoleCode MaternalGrandmother + + MaternalGrandmother + grootmoeder via moeder + + + + Label: RoleCode MaternalGrandparent + + Maternal Grandparent + grootouder via moeder + + + + Label: RoleCode PaternalGrandfather + + Paternal Grandfather + grootvader via vader + + + + Label: RoleCode PaternalGrandmother + + Paternal Grandmother + grootmoeder via vader + + + + Label: RoleCode PaternalGrandparent + + Paternal Grandparent + grootouder via vader + + + + Label: RoleCode niece/nephew + + niece/nephew + nicht/neef + + + + Label: RoleCode nephew + + nephew + neef + + + + Label: RoleCode niece + + niece + nicht + + + + Label: RoleCode uncle + + uncle + oom + + + + Label: RoleCode MaternalUncle + + Maternal Uncle + oom via moeder + + + + Label: RoleCode PaternalUncle + + Paternal Uncle + oom via vader + + + + Label: RoleCode Parent + + Parent + ouder + + + + Label: RoleCode Father + + Father + vader + + + + Label: RoleCode Mother + + Mother + moeder + + + + Label: RoleCode natural parent + + natural parent + natuurlijke ouder + + + + Label: RoleCode natural father + + natural father + natuurlijke vader + + + + Label: RoleCode natural father of fetus + + natural father of fetus + natuurlijke vader van foetus + + + + Label: RoleCode natural mother + + natural mother + natuurlijke moeder + + + + Label: RoleCode parent in-law + + parent in-law + schoonouder + + + + Label: RoleCode father-in-law + + father-in-law + schoonvader + + + + Label: RoleCode mother-in-law + + mother-in-law + schoonmoeder + + + + Label: RoleCode step parent + + step parent + stiefouder + + + + Label: RoleCode stepfather + + stepfather + stiefvader + + + + Label: RoleCode stepmother + + stepmother + stiefmoeder + + + + Label: RoleCode Sibling + + Sibling + broer/zus + + + + Label: RoleCode Brother + + Brother + broer + + + + Label: RoleCode half-sibling + + half-sibling + halfbroer/zus + + + + Label: RoleCode half-brother + + half-brother + halfbroer + + + + Label: RoleCode half-sister + + half-sister + halfzus + + + + Label: RoleCode natural sibling + + natural sibling + natuurlijke broer/zus + + + + Label: RoleCode natural brother + + natural brother + natuurlijke broer + + + + Label: RoleCode natural sister + + natural sister + natuurlijke zus + + + + Label: RoleCode sibling in-law + + sibling in-law + schoonbroer/zus + + + + Label: RoleCode brother-in-law + + brother-in-law + zwager + + + + Label: RoleCode sister-in-law + + sister-in-law + schoonzus + + + + Label: RoleCode Sister + + Sister + zus + + + + Label: RoleCode step sibling + + step sibling + stiefbroer/zus + + + + Label: RoleCode stepbrother + + stepbrother + stiefbroer + + + + Label: RoleCode stepsister + + stepsister + stiefzus + + + + Label: RoleCode significant other + + significant other + significante derde + + + + Label: RoleCode domestic partner + + domestic partner + huisgenoot + + + + Label: RoleCode spouse + + spouse + echtgenoot + + + + Label: RoleCode husband + + husband + echtgenoot + + + + Label: RoleCode wife + + wife + echtgenote + + + + Label: RoleCode unrelated friend + + unrelated friend + niet-gerelateerde vriend + + + + Label: RoleCode neighbor + + neighbor + buur + + + + Label: RoleCode Roommate + + Roommate + kamergenoot + + + + Label: RoleCode Next of Kin + + Next of Kin + familielid + + + + Label: RoleCode Emergency contact + + Emergency contact + Contact in nood + + + + Label: RoleCode General + + General + Algemeen + + + + Label: OID HL7 v2 Table 443 Provider Role code system + + consulting provider + adviserende zorgverlener + + + + Label: OID HL7 v2 Table 443 Provider Role code system + + primary care provider + eerstelijns zorgverlener + + + + Label: OID HL7 v2 Table 443 Provider Role code system + + referring provider + verwijzende zorgverlener + + + + Label: OID HL7 v2 Table 443 Provider Role code system + + medical home provider + verplegende/verzorgende zorgverlener + + + + Label: ParticipationType Author + + Author + Autor + Auteur + Autore + Auteur + + + + Label: ParticipationType Entered by + + Data Enterer + Erfasser + Saisie par + Registrati da + Ingevoerd door + + + + Label: In Fulfillment Of + + In fulfillment of + Conform + + + + Label: Informant - An informant (or source of information) is a person that provides relevant information + + Informant + Informiert + Informé + Informati + + + + Label: ParticipationType authenticator + + Authenticator + Unterzeichnet + Signataires + Ondertekenaar + + + + Label: ParticipationType Legal Authenticator + + Legal Authenticator + Rechtsgültig unterzeichnet + Légal signataires + Efficace legge firmato + Juridische ondertekenaar + + + + Label: ParticipationType Information Recipient + + Information Recipient + Ontvanger + + + + Label: ServiceEventPerformer Performer + + Performer + Uitvoerende + + + + Label: ServiceEventPerformer Primary Performer + + Primary Performer + Eerste uitvoerende + + + + Label: ParticipationType Record Target + + Patient + Paziente + Patiënt + + + + Label: ParticipationType Responsible party + + Responsible party + Verantwoordelijke + + + + Label: ServiceEventPerformer Supporting Performer + + Supporting Performer + Ondersteunend uitvoerende + + + + Label: ParticipationType Tracker + + Secondary Information Recipient + Kopie-ontvanger + + + + Label: Alphabetic transcription of name (Japanese: romaji) + + Alphabetic + alphabetisch + + + + Label: Ideographic representation of name (e.g., Japanese kanji, Chinese characters) + + Ideographic + ideographisch + + + + Label: Syllabic transcription of name (e.g., Japanese kana, Korean hangul) + + Syllabic + syllabisch + + + + Label: A name assigned to a person. Reasons some organizations assign alternate names may include not knowing the person's name, or to maintain anonymity. Some, but not necessarily all, of the name types that people call "alias" may fit into this category. + + assigned + toegekend + + + + Label: As recorded on a license, record, certificate, etc. (only if different from legal name) + + License + licentie + + + + Label: e.g. Chief Red Cloud + + Indigenous/Tribal + inheems/tribaal + + + + Label: Known as/conventional/the one you use + + Legal + Bekend als + + + + Label: The formal name as registered in an official (government) registry, but which name might not be commonly used. Particularly used in countries with a law system based on Napoleonic law. + + official registry + officieel + + + + Label: A self asserted name that the person is using or has used. + + pseudonym + pseudoniem + + + + Label: Includes writer's pseudonym, stage name, etc + + Artist/Stage + artiest/stage + + + + Label: e.g. Sister Mary Francis, Brother John + + Religious + religieus + + + + Label: A name intended for use in searching or matching. + + search + zoek + + + + Label: A name spelled phonetically. + + phonetic + fonetisch + + + + Label: A name spelled according to the SoundEx algorithm. + + Soundex + soundex + + + + Label: Home (e.g. address, or telecom type) + + Home + p + p + C + Privé + + + + Label: Vacation Home (e.g. address, or telecom type) + + Vacation Home + p + p + C + Vakantieadres + + + + Label: Home Primary (e.g. address, or telecom type) + + Home Primary + p + p + C + Privé (hoofd) + + + + Label: Workplace (e.g. address, telecom type) + + Workplace + g + g + U + Werk + + + + Label: Workplace Public (e.g. address, telecom type) + + Public + g + g + U + Werk algemeen + + + + Label: Emergency Contact (e.g. address, or telecom type) + + Emergency + Noodgevallen + + + + Label: Mobile Contact (e.g. telecom type) + + Mobile + Mobiel + + + + Label: Pager (e.g. telecom type) + + Pager + + + + Label: Postal (e.g. address type) + + Postal + Post + + + + Label: Temporary (e.g. address type) + + Temporary + Tijdelijk + + + + Label: Confidential (e.g. address type) + + Confidential + Geheim + + + + Label: Physical (e.g. address type) + + Physical + Bezoek + + + + Label: Direct (e.g. address type) + + Direct + + + + Label: BAD (e.g. address type) + + Bad address + Verkeerd adres + + + + + + Label: LOINC DOC code 11534-5 + + Temperature charts + Temperatuuroverzicht + + + + Label: LOINC DOC code 11536-0 + + Notes (Nursing) + Verslag (verpleging) + + + + Label: LOINC DOC code 11538-6 + + Study.total (CT) + Onderzoek.volledig (CT) + + + + Label: LOINC DOC code 11539-4 + + Study.total (CT) + Onderzoek.volledig (CT) + + + + Label: LOINC DOC code 11540-2 + + Study.total (CT) + Onderzoek.volledig (CT) + + + + Label: LOINC DOC code 11541-0 + + Study report (MRI) + Onderzoeksverslag (MRI) + + + + Label: LOINC DOC code 11542-8 + + Subsequent visit evaluation note ({Provider}) + Vervolgbezoek evaluatieaantekeningen ({Instelling}) + + + + Label: LOINC DOC code 11543-6 + + Nursery records + Verpleegkundig dossier + + + + Label: LOINC DOC code 11485-0 + + Anesthesia records + Anesthesiedossier + + + + Label: LOINC DOC code 11486-8 + + Chemotherapy records + Chemotherapiedossier + + + + Label: LOINC DOC code 11488-4 + + Consultation note ({Provider}) + Consultverslag ({Instelling}) + + + + Label: LOINC DOC code 11490-0 + + Discharge summarization note (Physician) + Samenvattende ontslagbrief ({Arts}) + + + + Label: LOINC DOC code 11492-6 + + History and physical note ({Provider}) + Geschiedenis en lichamelijk onderzoeksverslag ({Instelling}) + + + + Label: LOINC DOC code 11494-2 + + Initial assessment note (Physician) + Verslag eerste anamnese ({Arts}) + + + + Label: LOINC DOC code 11495-9 + + Initial assessment note (Physical therapy) + Verslag eerste anamnese (Lichamelijke oefening) + + + + Label: LOINC DOC code 11496-7 + + Initial assessment note (Podiatry) + Verslag eerste anamnese (Podologie) + + + + Label: LOINC DOC code 11497-5 + + Initial assessment note (Psychology) + Verslag eerste anamnese (Psychologie) + + + + Label: LOINC DOC code 11498-3 + + Initial assessment note (Social service) + Verslag eerste anamnese (Sociale dienst) + + + + Label: LOINC DOC code 11499-1 + + Initial assessment note (Speech therapy) + Verslag eerste anamnese (Spraaktherapie) + + + + Label: LOINC DOC code 11500-6 + + Initial assessment note (Occupational therapy) + Verslag eerste anamnese (Bezigheidstherapie) + + + + Label: LOINC DOC code 11502-2 + + Laboratory report.total + Laboratoriumrapport.volledig + + + + Label: LOINC DOC code 11503-0 + + Medical records + Medisch dossier + + + + Label: LOINC DOC code 11504-8 + + Surgical operation note ({Provider}) + Verslag chirurgische operatie ({Instelling}) + + + + Label: LOINC DOC code 11505-5 + + Procedure note (Physician) + Verslag procedure ({Arts}) + + + + Label: LOINC DOC code 11506-3 + + Subsequent evaluation note ({Provider}) + Verslag vervolgonderzoek ({Instelling}) + + + + Label: LOINC DOC code 11507-1 + + Subsequent evaluation note (Occupational therapy) + Verslag vervolgonderzoek (Bezigheidstherapie) + + + + Label: LOINC DOC code 11508-9 + + Subsequent evaluation note (Physical therapy) + Verslag vervolgonderzoek (Lichamelijke oefening) + + + + Label: LOINC DOC code 11509-7 + + Subsequent evaluation note (Podiatry) + Verslag vervolgonderzoek (Podologie) + + + + Label: LOINC DOC code 11510-5 + + Subsequent evaluation note (Psychology) + Verslag vervolgonderzoek (Psychologie) + + + + Label: LOINC DOC code 11512-1 + + Subsequent evaluation note (Speech therapy) + Verslag vervolgonderzoek (Spraaktherapie) + + + + Label: LOINC DOC code 11514-7 + + Records.total (Chiropractic) + Dossier.volledig (Chiropractie) + + + + Label: LOINC DOC code 11515-4 + + Records.total (Physical therapy) + Dossier.volledig (Lichamelijke oefening) + + + + Label: LOINC DOC code 11516-2 + + Records.total (Physician) + Dossier.volledig ({Arts}) + + + + Label: LOINC DOC code 11517-0 + + Records.total (Podiatry) + Dossier.volledig (Podologie) + + + + Label: LOINC DOC code 11518-8 + + Records.total (Psychology) + Dossier.volledig (Psychologie) + + + + Label: LOINC DOC code 11519-6 + + Records.total (Social service) + Dossier.volledig (Sociale dienst) + + + + Label: LOINC DOC code 11520-4 + + Records.total (Speech therapy) + Dossier.volledig (Spraaktherapie) + + + + Label: LOINC DOC code 11521-2 + + Records.total (Occupational therapy) + Dossier.volledig (Bezigheidstherapie) + + + + Label: LOINC DOC code 11522-0 + + Study report (Cardiac echo) + Onderzoeksverslag (Cardiac echo) + + + + Label: LOINC DOC code 11523-8 + + Study report (EEG) + Onderzoeksverslag (EEG) + + + + Label: LOINC DOC code 11524-6 + + Study report (EKG) + Onderzoeksverslag (EKG) + + + + Label: LOINC DOC code 11525-3 + + Study report (OB US) + Onderzoeksverslag (OB US) + + + + Label: LOINC DOC code 11526-1 + + Study report (Pathology) + Onderzoeksverslag (Pathologie) + + + + Label: LOINC DOC code 11527-9 + + Study report (Psychiatry) + Onderzoeksverslag (Psychiatrie) + + + + Label: LOINC DOC code 11528-7 + + Study.total (Radiology.XXX) + Onderzoek.volledig (Radiology.XXX) + + + + Label: LOINC DOC code 11529-5 + + Study report (Surgical pathology) + Onderzoeksverslag (Surgical pathology) + + + + Label: LOINC DOC code 15507-7 + + Subsequent evaluation note ({Provider}) + Verslag vervolgonderzoek ({Instelling}) + + + + Label: LOINC DOC code 15508-5 + + Labor and delivery records + Dossier zwangerschap en bevalling + + + + Label: LOINC DOC code 17787-3 + + Study report (Radnuc) + Onderzoeksverslag (Radnuc) + + + + Label: LOINC DOC code 18765-8 + + Subsequent visit evaluation note (Podiatry) + Verslag vervolgonderzoek (Podologie) + + + + Label: LOINC DOC code 18766-6 + + Subsequent visit evaluation note (Psychology) + Verslag vervolgonderzoek (Psychologie) + + + + Label: LOINC DOC code 18733-6 + + Subsequent evaluation note (Attending physician) + Verslag vervolgonderzoek (Behandelend arts) + + + + Label: LOINC DOC code 18734-4 + + Initial evaluation note (Occupational therapy) + Verslag eerste onderzoek (Bezigheidstherapie) + + + + Label: LOINC DOC code 18735-1 + + Initial evaluation note (Physical therapy) + Verslag eerste onderzoek (Lichamelijke oefening) + + + + Label: LOINC DOC code 18736-9 + + Initial evaluation note (Physician) + Verslag eerste onderzoek ({Arts}) + + + + Label: LOINC DOC code 18737-7 + + Initial evaluation note (Podiatry) + Verslag eerste onderzoek (Podologie) + + + + Label: LOINC DOC code 18738-5 + + Initial evaluation note (Psychology) + Verslag eerste onderzoek (Psychologie) + + + + Label: LOINC DOC code 18739-3 + + Initial evaluation note (Social service) + Verslag eerste onderzoek (Sociale dienst) + + + + Label: LOINC DOC code 18740-1 + + Initial evaluation note (Speech therapy) + Verslag eerste onderzoek (Spraaktherapie) + + + + Label: LOINC DOC code 18741-9 + + Subsequent visit evaluation note (Attending physician) + Verslag vervolgonderzoek (Behandelend arts) + + + + Label: LOINC DOC code 18742-7 + + Study report (Arthroscopy) + Onderzoeksverslag (Arthroscopy) + + + + Label: LOINC DOC code 18743-5 + + Autopsy report ({Provider}) + Autopsy report ({Instelling}) + + + + Label: LOINC DOC code 18744-3 + + Study report (Bronchoscopy) + Onderzoeksverslag (Bronchoscopy) + + + + Label: LOINC DOC code 18745-0 + + Study report (Cardiac catheterization) + Onderzoeksverslag (Cardiac catheterization) + + + + Label: LOINC DOC code 18746-8 + + Study report (Colonoscopy) + Onderzoeksverslag (Colonoscopy) + + + + Label: LOINC DOC code 18747-6 + + Study (CT) + Onderzoek (CT) + + + + Label: LOINC DOC code 18748-4 + + Study report (Diagnostic imaging) + Onderzoeksverslag (Diagnostic imaging) + + + + Label: LOINC DOC code 18749-2 + + Study report (Electromyogram) + Onderzoeksverslag (Electromyogram) + + + + Label: LOINC DOC code 18750-0 + + Study report (Electrophysiology) + Onderzoeksverslag (Electrophysiology) + + + + Label: LOINC DOC code 18751-8 + + Study report (Endoscopy) + Onderzoeksverslag (Endoscopy) + + + + Label: LOINC DOC code 18752-6 + + Study report (Exercise stress test) + Onderzoeksverslag (Exercise stress test) + + + + Label: LOINC DOC code 18753-4 + + Study report (Flexible sigmoidoscopy) + Onderzoeksverslag (Flexible sigmoidoscopy) + + + + Label: LOINC DOC code 18754-2 + + Study report (Holter monitor) + Onderzoeksverslag (Holter monitor) + + + + Label: LOINC DOC code 18755-9 + + Study report (MRI) + Onderzoeksverslag (MRI) + + + + Label: LOINC DOC code 18756-7 + + Study report (MRI) + Onderzoeksverslag (MRI) + + + + Label: LOINC DOC code 18757-5 + + Study report (Radnuc) + Onderzoeksverslag (Radnuc) + + + + Label: LOINC DOC code 18758-3 + + Study (PET scan) + Onderzoek (PET scan) + + + + Label: LOINC DOC code 18759-1 + + Study report (Spirometry) + Onderzoeksverslag (Spirometry) + + + + Label: LOINC DOC code 18760-9 + + Study (US) + Onderzoek (US) + + + + Label: LOINC DOC code 18761-7 + + Transfer summarization note ({Provider}) + Samenvattend verslag overplaatsing ({Instelling}) + + + + Label: LOINC DOC code 18762-5 + + Subsequent evaluation note (Chiropractor) + Verslag vervolgonderzoek (Chiropractor) + + + + Label: LOINC DOC code 18763-3 + + Initial evaluation note (Consulting physician) + Verslag eerste onderzoek (Behandelend arts) + + + + Label: LOINC DOC code 18764-1 + + Subsequent evaluation note (Nurse practitioner) + Verslag vervolgonderzoek (Nurse practitioner) + + + + Label: LOINC DOC code 18836-7 + + Procedure (*) + Ingreep (*) + + + + Label: LOINC DOC code 18841-7 + + Hospital consultations + Ziekenhuisbezoeken + + + + Label: LOINC DOC code 18842-5 + + Discharge summarization note ({Provider}) + Samenvattende ontslagbrief ({Instelling}) + + + + Label: LOINC DOC code 24611-6 + + Confirmatory consultation note ({Provider}) + Consultverslag ter bevestiging ({Instelling}) + + + + Label: LOINC DOC code 28032-1 + + Report.total (Cardiac echo) + Verslag.volledig (Hart echo) + + + + Label: LOINC DOC code 28570-0 + + Procedure note ({Provider}) + Procedure note ({Instelling}) + + + + Label: LOINC DOC code 28571-8 + + Visit note (Speech therapy) + Bezoekverslag (Spraaktherapie) + + + + Label: LOINC DOC code 28572-6 + + Initial evaluation note (Dentistry) + Verslag eerste onderzoek (Tandheelkunde) + + + + Label: LOINC DOC code 28573-4 + + Surgical operation note (Physician) + Verslag chirurgische operatie ({Arts}) + + + + Label: LOINC DOC code 28574-2 + + Discharge note ({Provider}) + Ontslagbrief ({Instelling}) + + + + Label: LOINC DOC code 28575-9 + + Progress note (Nurse practitioner) + Voortgangsrapport (Nurse practitioner) + + + + Label: LOINC DOC code 28577-5 + + Procedure note (Dentistry) + Procedure note (Tandheelkunde) + + + + Label: LOINC DOC code 28578-3 + + Visit note (Occupational therapy) + Bezoekverslag (Bezigheidstherapie) + + + + Label: LOINC DOC code 28579-1 + + Visit note (Physical therapy) + Bezoekverslag (Lichamelijke oefening) + + + + Label: LOINC DOC code 28580-9 + + Progress note (Chiropractor) + Voortgangsrapport (Chiropractor) + + + + Label: LOINC DOC code 28581-7 + + Initial evaluation note (Chiropractor) + Verslag eerste onderzoek (Chiropractor) + + + + Label: LOINC DOC code 28583-3 + + Surgical operation note (Dentistry) + Verslag chirurgische operatie (Tandheelkunde) + + + + Label: LOINC DOC code 28651-8 + + Transfer summarization note (Nursing) + Samenvattend verslag overplaatsing (Verpleging) + + + + Label: LOINC DOC code 28653-4 + + Visit note (Social service) + Bezoekverslag (Sociale dienst) + + + + Label: LOINC DOC code 28568-4 + + Visit note (Physician) + Bezoekverslag ({Arts}) + + + + Label: LOINC DOC code 28569-2 + + Subsequent evaluation note (Consulting physician) + Verslag vervolgonderzoek (Behandelend arts) + + + + Label: LOINC DOC code 28615-3 + + Audiology study + Audiologisch onderzoek + + + + Label: LOINC DOC code 28616-1 + + Transfer summarization note (Physician) + Samenvattend overplaatsingsverslag ({Arts}) + + + + Label: LOINC DOC code 28617-9 + + Subsequent evaluation note (Dentistry) + Verslag vervolgonderzoek (Tandheelkunde) + + + + Label: LOINC DOC code 28618-7 + + Visit note (Dentistry) + Bezoekverslag (Tandheelkunde) + + + + Label: LOINC DOC code 28621-1 + + Initial evaluation note (Nurse practitioner) + Verslag eerste onderzoek (Nurse practitioner) + + + + Label: LOINC DOC code 28622-9 + + Discharge assessment note (Nursing) + Discharge assessment note (Verpleging) + + + + Label: LOINC DOC code 28623-7 + + Subsequent evaluation note (Nursing) + Verslag vervolgonderzoek (Verpleging) + + + + Label: LOINC DOC code 28624-5 + + Surgical operation note (Podiatry) + Verslag chirurgische operatie (Podologie) + + + + Label: LOINC DOC code 28625-2 + + Procedure note (Podiatry) + Procedure note (Podologie) + + + + Label: LOINC DOC code 28626-0 + + History and physical note (Physician) + Verslag voorschiedenis en lichaam ({Arts}) + + + + Label: LOINC DOC code 28627-8 + + Subsequent evaluation note (Psychiatry) + Verslag vervolgonderzoek (Psychiatrie) + + + + Label: LOINC DOC code 28628-6 + + Visit note (Psychiatry) + Bezoekverslag (Psychiatrie) + + + + Label: LOINC DOC code 28633-6 + + Study report (Polysomnography) + Onderzoeksverslag (Polysomnography) + + + + Label: LOINC DOC code 28635-1 + + Initial evaluation note (Psychiatry) + Verslag eerste onderzoek (Psychiatrie) + + + + Label: LOINC DOC code 28636-9 + + Initial evaluation note ({Provider}) + Verslag eerste onderzoek ({Instelling}) + + + + Label: LOINC DOC code 28654-2 + + Initial evaluation note (Attending physician) + Verslag eerste onderzoek (Behandelend arts) + + + + Label: LOINC DOC code 28655-9 + + Discharge summarization note (Attending physician) + Samenvattende ontslagbrief (Behandelend arts) + + + + Label: LOINC DOC code 28656-7 + + Subsequent evaluation note (Social service) + Verslag vervolgonderzoek (Sociale dienst) + + + + Label: LOINC DOC code 29749-9 + + Dialysis records + Dialysedossier + + + + Label: LOINC DOC code 29750-7 + + Neonatal intensive care records + Neonataal intensieve zorg-dossier + + + + Label: LOINC DOC code 29751-5 + + Critical care records + IC-dossier + + + + Label: LOINC DOC code 29752-3 + + Perioperative records + Peri-operatief dossier + + + + Label: LOINC DOC code 29753-1 + + Initial evaluation note (Nursing) + Verslag eerste onderzoek (Verpleging) + + + + Label: LOINC DOC code 29754-9 + + Study report (Nystagmogram) + Onderzoeksverslag (Nystagmogram) + + + + Label: LOINC DOC code 29755-6 + + Study report (Nerve conduction) + Onderzoeksverslag (Zenuwconductie) + + + + Label: LOINC DOC code 29756-4 + + Study report (Peritoneoscopy) + Onderzoeksverslag (Peritoneoscopie) + + + + Label: LOINC DOC code 29757-2 + + Study report (Colposcopy) + Onderzoeksverslag (Colposcopie) + + + + Label: LOINC DOC code 29761-4 + + Discharge summarization note (Dentistry) + Samenvattende ontslagbrief (Tandheelkunde) + + + + Label: LOINC DOC code 34134-7 + + Supervisory note (Attending physician) + Supervisory note (Behandelend arts) + + + + Label: LOINC DOC code 34135-4 + + Supervisory note (Attending physician.cardiology) + Verslag van toezicht (Behandelend arts.cardiologie) + + + + Label: LOINC DOC code 34136-2 + + Supervisory note (Attending physician.gastroenterology) + Verslag van toezicht (Behandelend arts.gastro-enterologie) + + + + Label: LOINC DOC code 34137-0 + + Surgical operation note ({Provider}) + Verslag chirurgische operatie ({Instelling}) + + + + Label: LOINC DOC code 34138-8 + + Targeted history and physical note ({Provider}) + Targeted history and physical note ({Instelling}) + + + + Label: LOINC DOC code 34125-5 + + Subsequent evaluation note (Case manager) + Verslag vervolgonderzoek (Case manager) + + + + Label: LOINC DOC code 34126-3 + + Subsequent evaluation note ({Provider}) + Verslag vervolgonderzoek ({Instelling}) + + + + Label: LOINC DOC code 34127-1 + + Subsequent evaluation note (Dental hygienist) + Verslag vervolgonderzoek (Dental hygienist) + + + + Label: LOINC DOC code 34128-9 + + Subsequent evaluation note (Dentistry) + Verslag vervolgonderzoek (Tandheelkunde) + + + + Label: LOINC DOC code 34129-7 + + Subsequent evaluation note ({Provider}) + Verslag vervolgonderzoek ({Instelling}) + + + + Label: LOINC DOC code 34130-5 + + Subsequent evaluation note ({Provider}) + Verslag vervolgonderzoek ({Instelling}) + + + + Label: LOINC DOC code 34131-3 + + Subsequent evaluation note ({Provider}) + Verslag vervolgonderzoek ({Instelling}) + + + + Label: LOINC DOC code 34132-1 + + Subsequent evaluation note (Pharmacy) + Verslag vervolgonderzoek (Apotheek) + + + + Label: LOINC DOC code 34133-9 + + Summarization of episode note ({Provider}) + Summarization of episode note ({Instelling}) + + + + Label: LOINC DOC code 34798-9 + + Consultation note (Neurosurgery) + Consultverslag (Neurosurgery) + + + + Label: LOINC DOC code 34799-7 + + Evaluation and management note (Neurosurgery) + Evaluatie en voortgangsverslag (Neurosurgery) + + + + Label: LOINC DOC code 34800-3 + + Consultation note (Nutrition+Dietetics) + Consultverslag (Nutrition+Dietetics) + + + + Label: LOINC DOC code 34801-1 + + Evaluation and management note (Nutrition+Dietetics) + Evaluatie en voortgangsverslag (Nutrition+Dietetics) + + + + Label: LOINC DOC code 34802-9 + + Evaluation and management note (Occupational health) + Evaluatie en voortgangsverslag (Occupational health) + + + + Label: LOINC DOC code 34803-7 + + Consultation note (Occupational health) + Consultverslag (Occupational health) + + + + Label: LOINC DOC code 34804-5 + + Evaluation and management note (Occupational therapy) + Evaluatie en voortgangsverslag (Bezigheidstherapie) + + + + Label: LOINC DOC code 34805-2 + + Consultation note (Oncology) + Consultverslag (Oncology) + + + + Label: LOINC DOC code 33716-2 + + Study report (Cytology.non-gyn) + Onderzoeksverslag (Cytology.non-gyn) + + + + Label: LOINC DOC code 33717-0 + + Study report (Cytology) + Onderzoeksverslag (Cytology) + + + + Label: LOINC DOC code 33718-8 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 33719-6 + + Study report (Flow cytometry) + Onderzoeksverslag (Flow cytometry) + + + + Label: LOINC DOC code 33720-4 + + Blood bank consult + Bloedbank bezoek + + + + Label: LOINC DOC code 33721-2 + + Bone marrow biopsy report + Verslag beenmergbioptie + + + + Label: LOINC DOC code 34094-3 + + Admission history and physical note (Cardiology) + Admission history and physical note (Cardiologie) + + + + Label: LOINC DOC code 34095-0 + + Comprehensive history and physical note ({Provider}) + Comprehensive history and physical note ({Instelling}) + + + + Label: LOINC DOC code 34096-8 + + Comprehensive history and physical note + Uitgebreid verslag voorgeschiedenis en lichaam + + + + Label: LOINC DOC code 34097-6 + + Conference evaluation note ({Provider}) + Vergadering evaluatieverslag ({Instelling}) + + + + Label: LOINC DOC code 34098-4 + + Conference evaluation note ({Provider}) + Vergadering evaluatieverslag ({Instelling}) + + + + Label: LOINC DOC code 34099-2 + + Consultation note (Cardiology) + Consultverslag (Cardiologie) + + + + Label: LOINC DOC code 34100-8 + + Consultation note ({Provider}) + Consultverslag ({Instelling}) + + + + Label: LOINC DOC code 34101-6 + + Consultation note (General medicine) + Consultverslag (Algemene geneeskunde) + + + + Label: LOINC DOC code 34102-4 + + Consultation note (Psychiatry) + Consultverslag (Psychiatrie) + + + + Label: LOINC DOC code 34103-2 + + Consultation note (Pulmonary) + Consultverslag (Pulmonary) + + + + Label: LOINC DOC code 34104-0 + + Consultation note ({Provider}) + Consultverslag ({Instelling}) + + + + Label: LOINC DOC code 34105-7 + + Discharge summarization note ({Provider}) + Samenvattende ontslagbrief ({Instelling}) + + + + Label: LOINC DOC code 34106-5 + + Discharge summarization note (Physician) + Samenvattende ontslagbrief ({Arts}) + + + + Label: LOINC DOC code 34107-3 + + Education procedure note ({Provider}) + Education procedure note ({Instelling}) + + + + Label: LOINC DOC code 34108-1 + + Evaluation and management note ({Provider}) + Evaluatie en voortgangsverslag ({Instelling}) + + + + Label: LOINC DOC code 34109-9 + + Evaluation and management note ({Provider}) + Evaluatie en voortgangsverslag ({Instelling}) + + + + Label: LOINC DOC code 34110-7 + + Evaluation and management note (Diabetology) + Evaluatie en voortgangsverslag (Diabetologie) + + + + Label: LOINC DOC code 34111-5 + + Evaluation and management note ({Provider}) + Evaluatie en voortgangsverslag ({Instelling}) + + + + Label: LOINC DOC code 34112-3 + + Evaluation and management note ({Provider}) + Evaluatie en voortgangsverslag ({Instelling}) + + + + Label: LOINC DOC code 34113-1 + + Evaluation and management note ({Provider}) + Evaluatie en voortgangsverslag ({Instelling}) + + + + Label: LOINC DOC code 34114-9 + + Group counseling note ({Provider}) + Verslag groepstherapie ({Instelling}) + + + + Label: LOINC DOC code 34115-6 + + History and physical note (Medical student) + Verslag voorschiedenis en lichaam (Medisch student) + + + + Label: LOINC DOC code 34116-4 + + History and physical note (Physician) + Verslag voorschiedenis en lichaam ({Arts}) + + + + Label: LOINC DOC code 34117-2 + + History and physical note ({Provider}) + Verslag voorschiedenis en lichaam ({Instelling}) + + + + Label: LOINC DOC code 34118-0 + + Initial evaluation note ({Provider}) + Verslag eerste onderzoek ({Instelling}) + + + + Label: LOINC DOC code 34119-8 + + Initial evaluation note ({Provider}) + Verslag eerste onderzoek ({Instelling}) + + + + Label: LOINC DOC code 34120-6 + + Initial evaluation note ({Provider}) + Verslag eerste onderzoek ({Instelling}) + + + + Label: LOINC DOC code 34121-4 + + Interventional procedure note + Verslag interventieprocedure + + + + Label: LOINC DOC code 34122-2 + + Pathology procedure note (Pathology) + Verslag pathologische procedure (Pathologie) + + + + Label: LOINC DOC code 34123-0 + + Pre-operative evaluation and management note (Anesthesia) + Preoperatief onderzoek en voortgangsverslag (Anesthesie) + + + + Label: LOINC DOC code 34124-8 + + Subsequent evaluation note (Cardiology) + Verslag vervolgonderzoek (Cardiologie) + + + + Label: LOINC DOC code 34139-6 + + Telephone encounter note (Nursing) + Telephone encounter note (Verpleging) + + + + Label: LOINC DOC code 34140-4 + + Transfer of care referral note ({Provider}) + Transfer of care referral note ({Instelling}) + + + + Label: LOINC DOC code 34876-3 + + Pre-operative evaluation and management note (Surgery) + Preoperatief onderzoek en voortgangsverslag (Chirurgie) + + + + Label: LOINC DOC code 34877-1 + + Surgical operation note (Urology) + Verslag chirurgische operatie (Urologie) + + + + Label: LOINC DOC code 34878-9 + + Evaluation and management note (Emergency medicine) + Evaluatie en voortgangsverslag (Emergency medicine) + + + + Label: LOINC DOC code 34879-7 + + Consultation note (Endocrinology) + Consultverslag (Endocrinologie) + + + + Label: LOINC DOC code 34880-5 + + Post-operative evaluation and management note (Nurse.surgery) + Postoperatief onderzoek en voortgangsverslag (Operatieverpleegkundige) + + + + Label: LOINC DOC code 34881-3 + + Pre-operative evaluation and management note (Nurse.surgery) + Preoperatief onderzoek en voortgangsverslag (Operatieverpleegkundige) + + + + Label: LOINC DOC code 34861-5 + + Evaluation and management note (Diabetology) + Evaluatie en voortgangsverslag (Diabetologie) + + + + Label: LOINC DOC code 34862-3 + + Admission evaluation note (Attending physician.general medicine) + Voortgangsverslag opname (Behandelend arts.algemene geneeskunde) + + + + Label: LOINC DOC code 34863-1 + + Post-operative evaluation and management note (General surgery) + Postoperatief onderzoek en voortgangsverslag (Algemene chirurgie) + + + + Label: LOINC DOC code 34864-9 + + Counseling note (Mental health) + Counseling note (Geestelijke gezondheidszorg) + + + + Label: LOINC DOC code 34865-6 + + Counseling note (Psychiatry) + Counseling note (Psychiatrie) + + + + Label: LOINC DOC code 34866-4 + + Counseling note (Psychology) + Counseling note (Psychologie) + + + + Label: LOINC DOC code 34867-2 + + Post-operative evaluation and management note (Ophthalmology) + Postoperatief onderzoek en voortgangsverslag (Ophthalmologie) + + + + Label: LOINC DOC code 34868-0 + + Surgical operation note (Orthopedics) + Verslag chirurgische operatie (Orthopedie) + + + + Label: LOINC DOC code 34869-8 + + Counseling note (Pharmacy) + Verslag advies (Apotheek) + + + + Label: LOINC DOC code 34870-6 + + Surgical operation note (Plastic surgery) + Verslag chirurgische operatie (Plastic surgery) + + + + Label: LOINC DOC code 34871-4 + + Surgical operation note (Podiatry) + Verslag chirurgische operatie (Podologie) + + + + Label: LOINC DOC code 34872-2 + + Counseling note (Social work) + Counseling note (Sociaal werk) + + + + Label: LOINC DOC code 34873-0 + + Admission evaluation note (Surgery) + Admission evaluation note (Chirurgie) + + + + Label: LOINC DOC code 34874-8 + + Surgical operation note (Surgery) + Verslag chirurgische operatie (Chirurgie) + + + + Label: LOINC DOC code 34875-5 + + Post-operative evaluation and management note (Surgery) + Postoperatief onderzoek en voortgangsverslag (Chirurgie) + + + + Label: LOINC DOC code 34744-3 + + Admission evaluation note (Nursing) + Admission evaluation note (Verpleging) + + + + Label: LOINC DOC code 34745-0 + + Discharge summarization note (Nursing) + Samenvattende ontslagbrief (Verpleging) + + + + Label: LOINC DOC code 34746-8 + + Evaluation and management note (Nursing) + Evaluatie en voortgangsverslag (Verpleging) + + + + Label: LOINC DOC code 34747-6 + + Pre-operative evaluation and management note (Nursing) + Preoperatief onderzoek en voortgangsverslag (Verpleging) + + + + Label: LOINC DOC code 34748-4 + + Telephone encounter note ({Provider}) + Telephone encounter note ({Instelling}) + + + + Label: LOINC DOC code 34749-2 + + Consultation note (Anesthesia) + Consultverslag (Anasthesie) + + + + Label: LOINC DOC code 34750-0 + + Evaluation and management note (Anesthesia) + Evaluatie en voortgangsverslag (Anesthesie) + + + + Label: LOINC DOC code 34751-8 + + Pre-operative evaluation and management note (Anesthesia) + Preoperatief onderzoek en voortgangsverslag (Anesthesie) + + + + Label: LOINC DOC code 34752-6 + + Evaluation and management note (Cardiology) + Evaluatie en voortgangsverslag (Cardiologie) + + + + Label: LOINC DOC code 34753-4 + + Evaluation and management note (Cardiology) + Evaluatie en voortgangsverslag (Cardiologie) + + + + Label: LOINC DOC code 34754-2 + + Evaluation and management note (Critical care) + Evaluatie en voortgangsverslag (Spoedeisende hulp) + + + + Label: LOINC DOC code 34755-9 + + Transfer summarization note (Critical care) + Samenvattend verslag overplaatsing (Spoedeisende hulp) + + + + Label: LOINC DOC code 34756-7 + + Consultation note (Dentistry) + Consultverslag (Tandheelkunde) + + + + Label: LOINC DOC code 34757-5 + + Evaluation and management note (Dentistry) + Evaluatie en voortgangsverslag (Tandheelkunde) + + + + Label: LOINC DOC code 34758-3 + + Consultation note (Dermatology) + Consultverslag (Dermatologie) + + + + Label: LOINC DOC code 34759-1 + + Evaluation and management note (Dermatology) + Evaluatie en voortgangsverslag (Dermatologie) + + + + Label: LOINC DOC code 34760-9 + + Consultation note (Diabetology) + Consultverslag (Diabetologie) + + + + Label: LOINC DOC code 34761-7 + + Consultation note (Gastroenterology) + Consultverslag (Gastro-enterologie) + + + + Label: LOINC DOC code 34762-5 + + Evaluation and management note (Gastroenterology) + Evaluatie en voortgangsverslag (Gastro-enterologie) + + + + Label: LOINC DOC code 34763-3 + + Admission history and physical note (General medicine) + Admission history and physical note (Algemene geneeskunde) + + + + Label: LOINC DOC code 34764-1 + + Consultation note (General medicine) + Consultverslag (Algemene geneeskunde) + + + + Label: LOINC DOC code 34765-8 + + Evaluation and management note (General medicine) + Evaluatie en voortgangsverslag (Algemene geneeskunde) + + + + Label: LOINC DOC code 34766-6 + + Evaluation and management note (General medicine) + Evaluatie en voortgangsverslag (Algemene geneeskunde) + + + + Label: LOINC DOC code 34767-4 + + Evaluation and management note (Medical student.general medicine) + Evaluatie en voortgangsverslag (Medisch student.algemene geneeskunde) + + + + Label: LOINC DOC code 34768-2 + + Evaluation and management note (Nurse.general medicine) + Evaluatie en voortgangsverslag (Verpleegkundige.algemene geneeskunde) + + + + Label: LOINC DOC code 34769-0 + + Evaluation and management note (Attending physician.general medicine) + Evaluatie en voortgangsverslag (Behandelend arts.algemene geneeskunde) + + + + Label: LOINC DOC code 34770-8 + + Transfer summarization note (General medicine) + Samenvattend verslag overplaatsing (Algemene geneeskunde) + + + + Label: LOINC DOC code 34771-6 + + Consultation note (General surgery) + Consultverslag (Algemene chirurgie) + + + + Label: LOINC DOC code 34772-4 + + Evaluation and management note (General surgery) + Evaluatie en voortgangsverslag (Algemene chirurgie) + + + + Label: LOINC DOC code 34773-2 + + Evaluation and management note (Attending physician.general surgery) + Evaluatie en voortgangsverslag (Attending physician.general surgery) + + + + Label: LOINC DOC code 34774-0 + + History and physical note (General surgery) + Verslag voorschiedenis en lichaam (Algemene chirurgie) + + + + Label: LOINC DOC code 34775-7 + + Pre-operative evaluation and management note (General surgery) + Preoperatief onderzoek en voortgangsverslag (Algemene chirurgie) + + + + Label: LOINC DOC code 34776-5 + + Consultation note (Gerontology) + Consultverslag (Gerontologie) + + + + Label: LOINC DOC code 34777-3 + + Consultation note (Gynecology) + Consultverslag (Gynecology) + + + + Label: LOINC DOC code 34778-1 + + Evaluation and management note (Gynecology) + Evaluatie en voortgangsverslag (Gynecology) + + + + Label: LOINC DOC code 34779-9 + + Consultation note (Hematology+Oncology) + Consultverslag (Hematology+Oncology) + + + + Label: LOINC DOC code 34780-7 + + Evaluation and management note (Hematology+Oncology) + Evaluatie en voortgangsverslag (Hematology+Oncology) + + + + Label: LOINC DOC code 34781-5 + + Consultation note (Infectious disease) + Consultverslag (Infectious disease) + + + + Label: LOINC DOC code 34782-3 + + Evaluation and management note (Infectious disease) + Evaluatie en voortgangsverslag (Infectious disease) + + + + Label: LOINC DOC code 34783-1 + + Consultation note (Kinesiotherapy) + Consultverslag (Kinesiotherapy) + + + + Label: LOINC DOC code 34784-9 + + Evaluation and management note (Kinesiotherapy) + Evaluatie en voortgangsverslag (Kinesiotherapy) + + + + Label: LOINC DOC code 34785-6 + + Consultation note (Mental health) + Consultverslag (Geestelijke gezondheidszorg) + + + + Label: LOINC DOC code 34786-4 + + Evaluation and management note (Mental health) + Evaluatie en voortgangsverslag (Geestelijke gezondheidszorg) + + + + Label: LOINC DOC code 34787-2 + + Group counseling note (Mental health) + Group counseling note (Geestelijke gezondheidszorg) + + + + Label: LOINC DOC code 34788-0 + + Consultation note (Psychiatry) + Consultverslag (Psychiatrie) + + + + Label: LOINC DOC code 34789-8 + + Evaluation and management note (Psychiatry) + Evaluatie en voortgangsverslag (Psychiatrie) + + + + Label: LOINC DOC code 34790-6 + + Group counseling note (Psychiatry) + Group counseling note (Psychiatrie) + + + + Label: LOINC DOC code 34791-4 + + Consultation note (Psychology) + Consultverslag (Psychologie) + + + + Label: LOINC DOC code 34792-2 + + Evaluation and management note (Psychology) + Evaluatie en voortgangsverslag (Psychologie) + + + + Label: LOINC DOC code 34793-0 + + Group counseling note (Psychology) + Group counseling note (Psychologie) + + + + Label: LOINC DOC code 34794-8 + + Evaluation and management note (Multidisciplinary) + Evaluatie en voortgangsverslag (Multidisciplinary) + + + + Label: LOINC DOC code 34795-5 + + Consultation note (Nephrology) + Consultverslag (Nephrology) + + + + Label: LOINC DOC code 34796-3 + + Evaluation and management note (Nephrology) + Evaluatie en voortgangsverslag (Nephrology) + + + + Label: LOINC DOC code 34797-1 + + Consultation note (Neurology) + Consultverslag (Neurologie) + + + + Label: LOINC DOC code 34806-0 + + Evaluation and management note (Oncology) + Evaluatie en voortgangsverslag (Oncology) + + + + Label: LOINC DOC code 34807-8 + + Consultation note (Ophthalmology) + Consultverslag (Oogheelkunde) + + + + Label: LOINC DOC code 34808-6 + + Evaluation and management note (Ophthalmology) + Evaluatie en voortgangsverslag (Oogheelkunde) + + + + Label: LOINC DOC code 34809-4 + + Pre-operative evaluation and management note (Ophthalmology) + Preoperatief onderzoek en voortgangsverslag (Oogheelkunde) + + + + Label: LOINC DOC code 34810-2 + + Consultation note (Optometry) + Consultverslag (Optometrie) + + + + Label: LOINC DOC code 34811-0 + + Evaluation and management note (Optometry) + Evaluatie en voortgangsverslag (Optometrie) + + + + Label: LOINC DOC code 34812-8 + + Consultation note (Oromaxillofacial surgery) + Consultverslag (Oromaxillofaciale chirurgie) + + + + Label: LOINC DOC code 34813-6 + + Evaluation and management note (Oromaxillofacial surgery) + Evaluatie en voortgangsverslag (Oromaxillofaciale chirurgie) + + + + Label: LOINC DOC code 34814-4 + + Consultation note (Orthopedics) + Consultverslag (Orthopedie) + + + + Label: LOINC DOC code 34815-1 + + Evaluation and management note (Orthopedics) + Evaluatie en voortgangsverslag (Orthopedie) + + + + Label: LOINC DOC code 34816-9 + + Consultation note (Otorhinolaryngology) + Consultverslag (Otorhinolaryngologie) + + + + Label: LOINC DOC code 34817-7 + + Evaluation and management note (Otorhinolaryngology) + Evaluatie en voortgangsverslag (Otorhinolaryngologie) + + + + Label: LOINC DOC code 34818-5 + + Surgical operation note (Otorhinolaryngology) + Verslag chirurgische operatie (Otorhinolaryngologie) + + + + Label: LOINC DOC code 34819-3 + + Evaluation and management note (Pathology) + Evaluatie en voortgangsverslag (Pathologie) + + + + Label: LOINC DOC code 34820-1 + + Consultation note (Pharmacy) + Consultverslag (Apotheek) + + + + Label: LOINC DOC code 34821-9 + + Evaluation and management note (Pharmacy) + Evaluatie en voortgangsverslag (Apotheek) + + + + Label: LOINC DOC code 34822-7 + + Consultation note (Physical medicine and rehabilitation) + Consultverslag (Physical medicine and rehabilitation) + + + + Label: LOINC DOC code 34823-5 + + Evaluation and management note (Physical medicine and rehabilitation) + Evaluatie en voortgangsverslag (Physical medicine and rehabilitation) + + + + Label: LOINC DOC code 34824-3 + + Consultation note (Physical therapy) + Consultverslag (Lichamelijke oefening) + + + + Label: LOINC DOC code 34825-0 + + Evaluation and management note (Physical therapy) + Evaluatie en voortgangsverslag (Lichamelijke oefening) + + + + Label: LOINC DOC code 34826-8 + + Consultation note (Plastic surgery) + Consultverslag (Plastic surgery) + + + + Label: LOINC DOC code 34827-6 + + Evaluation and management note (Plastic surgery) + Evaluatie en voortgangsverslag (Plastic surgery) + + + + Label: LOINC DOC code 34828-4 + + Consultation note (Podiatry) + Consultverslag (Podologie) + + + + Label: LOINC DOC code 34829-2 + + Evaluation and management note (Podiatry) + Evaluatie en voortgangsverslag (Podologie) + + + + Label: LOINC DOC code 34830-0 + + Evaluation and management note (Pulmonary) + Evaluatie en voortgangsverslag (Pulmonary) + + + + Label: LOINC DOC code 34831-8 + + Consultation note (Radiation oncology) + Consultverslag (Radiation oncology) + + + + Label: LOINC DOC code 34832-6 + + Evaluation and management note (Radiation oncology) + Evaluatie en voortgangsverslag (Radiation oncology) + + + + Label: LOINC DOC code 34833-4 + + Consultation note (Recreational therapy) + Consultverslag (Recreational therapy) + + + + Label: LOINC DOC code 34834-2 + + Evaluation and management note (Recreational therapy) + Evaluatie en voortgangsverslag (Recreational therapy) + + + + Label: LOINC DOC code 34835-9 + + Consultation note (Rehabilitation) + Consultverslag (Rehabilitation) + + + + Label: LOINC DOC code 34836-7 + + Evaluation and management note (Rehabilitation) + Evaluatie en voortgangsverslag (Rehabilitation) + + + + Label: LOINC DOC code 34837-5 + + Consultation note (Respiratory therapy) + Consultverslag (Respiratory therapy) + + + + Label: LOINC DOC code 34838-3 + + Evaluation and management note (Respiratory therapy) + Evaluatie en voortgangsverslag (Respiratory therapy) + + + + Label: LOINC DOC code 34839-1 + + Consultation note (Rheumatology) + Consultverslag (Rheumatology) + + + + Label: LOINC DOC code 34840-9 + + Evaluation and management note (Rheumatology) + Evaluatie en voortgangsverslag (Rheumatology) + + + + Label: LOINC DOC code 34841-7 + + Consultation note (Social work) + Consultverslag (Sociaal werk) + + + + Label: LOINC DOC code 34842-5 + + Evaluation and management note (Social work) + Evaluatie en voortgangsverslag (Sociaal werk) + + + + Label: LOINC DOC code 34843-3 + + Group counseling note (Social work) + Group counseling note (Sociaal werk) + + + + Label: LOINC DOC code 34844-1 + + Telephone encounter note (Social work) + Telephone encounter note (Sociaal werk) + + + + Label: LOINC DOC code 34845-8 + + Consultation note (Speech therapy+Audiology) + Consultverslag (Spraaktherapie+Audiologie) + + + + Label: LOINC DOC code 34846-6 + + Evaluation and management note (Speech therapy+Audiology) + Evaluatie en voortgangsverslag (Spraaktherapie+Audiologie) + + + + Label: LOINC DOC code 34847-4 + + Consultation note (Surgery) + Consultverslag (Chirurgie) + + + + Label: LOINC DOC code 34848-2 + + Evaluation and management note (Surgery) + Evaluatie en voortgangsverslag (Chirurgie) + + + + Label: LOINC DOC code 34849-0 + + Consultation note (Thoracic surgery) + Consultverslag (Thorax chirurgie) + + + + Label: LOINC DOC code 34850-8 + + Evaluation and management note (Thoracic surgery) + Evaluatie en voortgangsverslag (Thorax chirurgie) + + + + Label: LOINC DOC code 34851-6 + + Consultation note (Urology) + Consultverslag (Urologie) + + + + Label: LOINC DOC code 34852-4 + + Evaluation and management note (Urology) + Evaluatie en voortgangsverslag (Urologie) + + + + Label: LOINC DOC code 34853-2 + + Consultation note (Vascular surgery) + Consultverslag (Vaatchirurgie) + + + + Label: LOINC DOC code 34854-0 + + Evaluation and management note (Vascular surgery) + Evaluatie en voortgangsverslag (Vaatchirurgie) + + + + Label: LOINC DOC code 34855-7 + + Consultation note (Occupational therapy) + Consultverslag (Bezigheidstherapie) + + + + Label: LOINC DOC code 34856-5 + + Evaluation and management note (Anticoagulation) + Evaluatie en voortgangsverslag (Anticoagulatie) + + + + Label: LOINC DOC code 34857-3 + + Evaluation and management note (Substance abuse) + Evaluatie en voortgangsverslag (Misbruik van substanties) + + + + Label: LOINC DOC code 34858-1 + + Evaluation and management note (Pain management) + Evaluatie en voortgangsverslag (Pijnbestrijding) + + + + Label: LOINC DOC code 34859-9 + + Evaluation and management note (Hyperlipidemia) + Evaluatie en voortgangsverslag (Hyperlipidemia) + + + + Label: LOINC DOC code 34860-7 + + Evaluation and management note (Hypertension) + Evaluatie en voortgangsverslag (Hypertensie) + + + + Label: LOINC DOC code 34895-3 + + Education note ({Provider}) + Opleidingsverslag ({Instelling}) + + + + Label: LOINC DOC code 34896-1 + + Interventional procedure note (Cardiology) + Interventional procedure note (Cardiologie) + + + + Label: LOINC DOC code 34897-9 + + Education note (Diabetology) + Opleidingsverslag (Diabetologie) + + + + Label: LOINC DOC code 34898-7 + + Evaluation and management note (Endocrinology) + Evaluatie en voortgangsverslag (Endocrinologie) + + + + Label: LOINC DOC code 34899-5 + + Interventional procedure note (Gastroenterology) + Interventional procedure note (Gastro-enterologie) + + + + Label: LOINC DOC code 34900-1 + + Subsequent evaluation note (General medicine) + Verslag vervolgonderzoek (Algemene geneeskunde) + + + + Label: LOINC DOC code 34901-9 + + Subsequent evaluation note (General medicine) + Verslag vervolgonderzoek (Algemene geneeskunde) + + + + Label: LOINC DOC code 34902-7 + + Education note (Gerontology) + Opleidingsverslag (Gerontologie) + + + + Label: LOINC DOC code 34903-5 + + Note (Mental health) + Verslag (Geestelijke gezondheidszorg) + + + + Label: LOINC DOC code 34904-3 + + Subsequent evaluation note (Mental health) + Verslag vervolgonderzoek (Geestelijke gezondheidszorg) + + + + Label: LOINC DOC code 34905-0 + + Evaluation and management note (Neurology) + Evaluatie en voortgangsverslag (Neurologie) + + + + Label: LOINC DOC code 34906-8 + + Note (Pastoral care) + Verslag (Pastoral care) + + + + Label: LOINC DOC code 38269-7 + + Study report (XR.DEXA) + Onderzoeksverslag (XR.DEXA) + + + + Label: LOINC DOC code 38932-0 + + VA C&P exam.acromegaly ({Provider}) + VA C&P exam.acromegaly ({Instelling}) + + + + Label: LOINC DOC code 38933-8 + + VA C&P exam.aid and attendance &or housebound ({Provider}) + VA C&P exam.aid and attendance &or housebound ({Instelling}) + + + + Label: LOINC DOC code 38934-6 + + VA C&P exam.arrhythmias ({Provider}) + VA C&P exam.arrhythmias ({Instelling}) + + + + Label: LOINC DOC code 38935-3 + + VA C&P exam.miscellaneous arteries &or veins ({Provider}) + VA C&P exam.miscellaneous arteries &or veins ({Instelling}) + + + + Label: LOINC DOC code 38936-1 + + VA C&P exam.audio ({Provider}) + VA C&P exam.audio ({Instelling}) + + + + Label: LOINC DOC code 38937-9 + + VA C&P exam.bones fractures &or bone disease ({Provider}) + VA C&P exam.bones fractures &or bone disease ({Instelling}) + + + + Label: LOINC DOC code 38938-7 + + VA C&P exam.brain &or spinal cord ({Provider}) + VA C&P exam.brain &or spinal cord ({Instelling}) + + + + Label: LOINC DOC code 38939-5 + + VA C&P exam.chronic fatigue syndrome ({Provider}) + VA C&P exam.chronic fatigue syndrome ({Instelling}) + + + + Label: LOINC DOC code 38940-3 + + VA C&P exam.cold injury protocol ({Provider}) + VA C&P exam.cold injury protocol ({Instelling}) + + + + Label: LOINC DOC code 38941-1 + + VA C&P exam.cranial nerves ({Provider}) + VA C&P exam.cranial nerves ({Instelling}) + + + + Label: LOINC DOC code 38942-9 + + VA C&P exam.Cushings syndrome ({Provider}) + VA C&P exam.Cushings syndrome ({Instelling}) + + + + Label: LOINC DOC code 38985-8 + + VA C&P exam.social &or industrial survey ({Provider}) + VA C&P exam.social &or industrial survey ({Instelling}) + + + + Label: LOINC DOC code 38986-6 + + VA C&P exam.spine ({Provider}) + VA C&P exam.spine ({Instelling}) + + + + Label: LOINC DOC code 38987-4 + + VA C&P exam.stomach &or duodenum &or peritoneal adhesions ({Provider}) + VA C&P exam.stomach &or duodenum &or peritoneal adhesions ({Instelling}) + + + + Label: LOINC DOC code 38988-2 + + VA C&P exam.thyroid &or parathyroid diseases ({Provider}) + VA C&P exam.thyroid &or parathyroid diseases ({Instelling}) + + + + Label: LOINC DOC code 38943-7 + + VA C&P exam.dental &or oral ({Provider}) + VA C&P exam.dental &or oral ({Instelling}) + + + + Label: LOINC DOC code 38944-5 + + VA C&P exam.diabetes mellitus ({Provider}) + VA C&P exam.diabetes mellitus ({Instelling}) + + + + Label: LOINC DOC code 38945-2 + + VA C&P exam.miscellaneous digestive conditions ({Provider}) + VA C&P exam.miscellaneous digestive conditions ({Instelling}) + + + + Label: LOINC DOC code 38946-0 + + VA C&P exam.ear disease ({Provider}) + VA C&P exam.ear disease ({Instelling}) + + + + Label: LOINC DOC code 38947-8 + + VA C&P exam.mental health eating disorders ({Provider}) + VA C&P exam.mental health eating disorders ({Instelling}) + + + + Label: LOINC DOC code 38948-6 + + VA C&P exam.miscellaneous endocrine diseases ({Provider}) + VA C&P exam.miscellaneous endocrine diseases ({Instelling}) + + + + Label: LOINC DOC code 38949-4 + + VA C&P exam.epilepsy &or narcolepsy ({Provider}) + VA C&P exam.epilepsy &or narcolepsy ({Instelling}) + + + + Label: LOINC DOC code 38950-2 + + VA C&P exam.esophagus &or hiatal hernia ({Provider}) + VA C&P exam.esophagus &or hiatal hernia ({Instelling}) + + + + Label: LOINC DOC code 38951-0 + + VA C&P exam.eye ({Provider}) + VA C&P exam.eye ({Instelling}) + + + + Label: LOINC DOC code 38952-8 + + VA C&P exam.feet ({Provider}) + VA C&P exam.feet ({Instelling}) + + + + Label: LOINC DOC code 38953-6 + + VA C&P exam.fibromyalgia ({Provider}) + VA C&P exam.fibromyalgia ({Instelling}) + + + + Label: LOINC DOC code 38954-4 + + VA C&P exam.general medical ({Provider}) + VA C&P exam.general medical ({Instelling}) + + + + Label: LOINC DOC code 38955-1 + + VA C&P exam.genitourinary ({Provider}) + VA C&P exam.genitourinary ({Instelling}) + + + + Label: LOINC DOC code 38956-9 + + VA C&P exam.disability in gulf war veterans ({Provider}) + VA C&P exam.disability in gulf war veterans ({Instelling}) + + + + Label: LOINC DOC code 38957-7 + + VA C&P exam.gynecological conditions &or disorders of the breast ({Provider}) + VA C&P exam.gynecological conditions &or disorders of the breast ({Instelling}) + + + + Label: LOINC DOC code 38958-5 + + VA C&P exam.hand &or thumb &or fingers ({Provider}) + VA C&P exam.hand &or thumb &or fingers ({Instelling}) + + + + Label: LOINC DOC code 38959-3 + + VA C&P exam.heart ({Provider}) + VA C&P exam.heart ({Instelling}) + + + + Label: LOINC DOC code 38960-1 + + VA C&P exam.hemic disorders ({Provider}) + VA C&P exam.hemic disorders ({Instelling}) + + + + Label: LOINC DOC code 38961-9 + + VA C&P exam.HIV-related illness ({Provider}) + VA C&P exam.HIV-related illness ({Instelling}) + + + + Label: LOINC DOC code 38962-7 + + VA C&P exam.hypertension ({Provider}) + VA C&P exam.hypertension ({Instelling}) + + + + Label: LOINC DOC code 38963-5 + + VA C&P exam.infectious &or immune &or nutritional disabilities ({Provider}) + VA C&P exam.infectious &or immune &or nutritional disabilities ({Instelling}) + + + + Label: LOINC DOC code 38964-3 + + VA C&P exam.initial evaluation post-traumatic stress disorder ({Provider}) + VA C&P exam.initial evaluation post-traumatic stress disorder ({Instelling}) + + + + Label: LOINC DOC code 38965-0 + + VA C&P exam.large &or small intestines ({Provider}) + VA C&P exam.large &or small intestines ({Instelling}) + + + + Label: LOINC DOC code 38966-8 + + VA C&P exam.extremity joints ({Provider}) + VA C&P exam.extremity joints ({Instelling}) + + + + Label: LOINC DOC code 38967-6 + + VA C&P exam.liver &or gall bladder &or pancreas ({Provider}) + VA C&P exam.liver &or gall bladder &or pancreas ({Instelling}) + + + + Label: LOINC DOC code 38968-4 + + VA C&P exam.lymphatic disorders ({Provider}) + VA C&P exam.lymphatic disorders ({Instelling}) + + + + Label: LOINC DOC code 38969-2 + + VA C&P exam.general mental disorders ({Provider}) + VA C&P exam.general mental disorders ({Instelling}) + + + + Label: LOINC DOC code 38970-0 + + VA C&P exam.mouth &or lips &or tongue ({Provider}) + VA C&P exam.mouth &or lips &or tongue ({Instelling}) + + + + Label: LOINC DOC code 38971-8 + + VA C&P exam.muscles ({Provider}) + VA C&P exam.muscles ({Instelling}) + + + + Label: LOINC DOC code 38972-6 + + VA C&P exam.miscellaneous neurological disorders ({Provider}) + VA C&P exam.miscellaneous neurological disorders ({Instelling}) + + + + Label: LOINC DOC code 38973-4 + + VA C&P exam.nose &or sinus &or larynx &or pharynx ({Provider}) + VA C&P exam.nose &or sinus &or larynx &or pharynx ({Instelling}) + + + + Label: LOINC DOC code 38974-2 + + VA C&P exam.peripheral nerves ({Provider}) + VA C&P exam.peripheral nerves ({Instelling}) + + + + Label: LOINC DOC code 38975-9 + + VA C&P exam.prisoner of war protocol ({Provider}) + VA C&P exam.prisoner of war protocol ({Instelling}) + + + + Label: LOINC DOC code 38976-7 + + VA C&P exam.pulmonary tuberculosis &or mycobacterial diseases ({Provider}) + VA C&P exam.pulmonary tuberculosis &or mycobacterial diseases ({Instelling}) + + + + Label: LOINC DOC code 38977-5 + + VA C&P exam.rectum &or anus ({Provider}) + VA C&P exam.rectum &or anus ({Instelling}) + + + + Label: LOINC DOC code 38978-3 + + VA C&P exam.residuals of amputations ({Provider}) + VA C&P exam.residuals of amputations ({Instelling}) + + + + Label: LOINC DOC code 38979-1 + + VA C&P exam.obstructive &or restrictive &or interstitial respiratory diseases ({Provider}) + VA C&P exam.obstructive &or restrictive &or interstitial respiratory diseases ({Instelling}) + + + + Label: LOINC DOC code 38980-9 + + VA C&P exam.miscellaneous respiratory diseases ({Provider}) + VA C&P exam.miscellaneous respiratory diseases ({Instelling}) + + + + Label: LOINC DOC code 38981-7 + + VA C&P exam.review evaluation post-traumatic stress disorder ({Provider}) + VA C&P exam.review evaluation post-traumatic stress disorder ({Instelling}) + + + + Label: LOINC DOC code 38982-5 + + VA C&P exam.scars ({Provider}) + VA C&P exam.scars ({Instelling}) + + + + Label: LOINC DOC code 38983-3 + + VA C&P exam.sense of smell &or taste ({Provider}) + VA C&P exam.sense of smell &or taste ({Instelling}) + + + + Label: LOINC DOC code 38984-1 + + VA C&P exam.skin diseases other than scars ({Provider}) + VA C&P exam.skin diseases other than scars ({Instelling}) + + + + Label: LOINC DOC code 46208-5 + + Nursing notes + Verpleegkundig verslag + + + + Label: LOINC DOC code 46209-3 + + Provider orders + + + + Label: LOINC DOC code 46210-1 + + Note (Case manager) + Verslag (Case manager) + + + + Label: LOINC DOC code 46213-5 + + Tilt table study + + + + Label: LOINC DOC code 46214-3 + + Intracardiac ablation study + + + + Label: LOINC DOC code 46215-0 + + Note (Wound care management) + Verslag (Wound care management) + + + + Label: LOINC DOC code 46242-4 + + Vital signs measurements + + + + Label: LOINC DOC code 46264-8 + + History of medical device use ({Provider}) + History of medical device use ({Instelling}) + + + + Label: LOINC DOC code 47039-3 + + Admission history and physical note ({Provider}) + Admission history and physical note ({Instelling}) + + + + Label: LOINC DOC code 47040-1 + + Confirmatory consultation note ({Provider}) + Confirmatory consultation note ({Instelling}) + + + + Label: LOINC DOC code 47041-9 + + Confirmatory consultation note ({Provider}) + Confirmatory consultation note ({Instelling}) + + + + Label: LOINC DOC code 47042-7 + + Counseling note ({Provider}) + Counseling note ({Instelling}) + + + + Label: LOINC DOC code 47043-5 + + Group counseling note ({Provider}) + Group counseling note ({Instelling}) + + + + Label: LOINC DOC code 47044-3 + + Initial evaluation note ({Provider}) + Verslag eerste onderzoek ({Instelling}) + + + + Label: LOINC DOC code 47045-0 + + Study report ({Provider}) + Onderzoeksverslag ({Instelling}) + + + + Label: LOINC DOC code 47046-8 + + Summary of death ({Provider}) + Summary of death ({Instelling}) + + + + Label: LOINC DOC code 47047-6 + + Supervisory note ({Provider}) + Supervisory note ({Instelling}) + + + + Label: LOINC DOC code 47048-4 + + Diagnostic interventional study report (Interventional radiology) + + + + Label: LOINC DOC code 47049-2 + + Communication ({Non-patient}) + + + + Label: LOINC DOC code 47245-6 + + HIV Rx Form + HIV Rx formulier + + + + Label: LOINC DOC code 47420-5 + + Functional status assessment ({Provider}) + Functional status assessment ({Instelling}) + + + + Label: LOINC DOC code 47519-4 + + History of Procedures ({Provider}) + History of Procedures ({Instelling}) + + + + Label: LOINC DOC code 47520-2 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47521-0 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47522-8 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47523-6 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47524-4 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47525-1 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47526-9 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47527-7 + + Cytology report (Cyto stain.thin prep) + Cytologieverslag (Cyto stain.thin prep) + + + + Label: LOINC DOC code 47528-5 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 47529-3 + + Cytology report (XXX stain) + Cytologieverslag (XXX stain) + + + + Label: LOINC DOC code 47530-1 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 48768-6 + + Payment sources + + + + Label: LOINC DOC code 48764-5 + + Summary purpose + Samenvatting doel + + + + Label: LOINC DOC code 48765-2 + + Allergies, adverse reactions, alerts + Allergieën, allergische reacties, waarschuwingen + + + + Label: LOINC DOC code 48807-2 + + Bone marrow aspiration report + + + + Label: LOINC DOC code 50007-4 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 51969-4 + + Genetic analysis summary report (Molgen) + + + + Label: LOINC DOC code 52030-4 + + Explanation of benefits attachment + + + + Label: LOINC DOC code 52031-2 + + Explanation of benefits to subscriber attachment + + + + Label: LOINC DOC code 52032-0 + + Appeal denial letter attachment + + + + Label: LOINC DOC code 52033-8 + + General correspondence attachment + + + + Label: LOINC DOC code 52034-6 + + Payer letter attachment + + + + Label: LOINC DOC code 52035-3 + + Home health claims attachment + + + + Label: LOINC DOC code 52036-1 + + Home health prior authorization attachment + + + + Label: LOINC DOC code 52037-9 + + Member ID card copy attachment + + + + Label: LOINC DOC code 52038-7 + + Subscriber Information including retroactive and presumptive eligibility attachment + + + + Label: LOINC DOC code 52039-5 + + Skilled Nursing Facility record attachment + + + + Label: LOINC DOC code 52040-3 + + Dental X-rays and other images (not DICOM) attachment + + + + Label: LOINC DOC code 52041-1 + + Blood glucose monitors attachment + + + + Label: LOINC DOC code 50971-1 + + Cytology report (Cyto stain) + Cytologieverslag (Cyto stain) + + + + Label: LOINC DOC code 51897-7 + + Healthcare Associated Infection report ({Provider}) + Healthcare Associated Infection report ({Instelling}) + + + + Label: LOINC DOC code 51898-5 + + Risk factors ({Provider}) + Risk factors ({Instelling}) + + + + Label: LOINC DOC code 51899-3 + + Details ({Provider}) + Details ({Instelling}) + + + + Label: LOINC DOC code 51900-9 + + Summary ({Provider}) + Samenvatting ({Instelling}) + + + + Label: LOINC DOC code 51845-6 + + Consultation note ({Provider}) + Consultverslag ({Instelling}) + + + + Label: LOINC DOC code 51846-4 + + Consultation note ({Provider}) + Consultverslag ({Instelling}) + + + + Label: LOINC DOC code 51847-2 + + Assessment+Plan note ({Provider}) + Assessment+Plan note ({Instelling}) + + + + Label: LOINC DOC code 51848-0 + + Assessment note ({Provider}) + Assessment note ({Instelling}) + + + + Label: LOINC DOC code 51849-8 + + Admission history and physical note ({Provider}) + Admission history and physical note ({Instelling}) + + + + Label: LOINC DOC code 51850-6 + + Physical findings (Observed) + + + + Label: LOINC DOC code 51851-4 + + Administrative note ({Provider}) + Administratief verslag ({Instelling}) + + + + Label: LOINC DOC code 51852-2 + + Letter ({Provider}) + Brief ({Instelling}) + + + + Label: LOINC DOC code 51853-0 + + Consultation note ({Provider}) + Consultverslag ({Instelling}) + + + + Label: LOINC DOC code 51854-8 + + Consultation note ({Provider}) + Consultverslag ({Instelling}) + + + + Label: LOINC DOC code 51855-5 + + Note (Patient) + Verslag (Patiënt) + + + + Label: LOINC DOC code 51965-2 + + Pharmacogenetic analysis report (Molgen) + + + + Label: LOINC DOC code 52027-0 + + Abortion consent attachment + + + + Label: LOINC DOC code 52028-8 + + Hysterectomy consent attachment + + + + Label: LOINC DOC code 52029-6 + + Sterilization consent attachment + + + + Label: LOINC DOC code 52042-9 + + Continuous positive airway pressure attachment + + + + Label: LOINC DOC code 52043-7 + + Enteral nutrition attachment + + + + Label: LOINC DOC code 52044-5 + + External infusion pump attachment + + + + Label: LOINC DOC code 52045-2 + + Gait trainers attachment + + + + Label: LOINC DOC code 52046-0 + + Hospital beds attachment + + + + Label: LOINC DOC code 52047-8 + + Immunosuppressive drugs attachment + + + + Label: LOINC DOC code 52048-6 + + Lymphedema pumps attachment + + + + Label: LOINC DOC code 52049-4 + + Manual wheelchair attachment + + + + Label: LOINC DOC code 52050-2 + + Motorized wheelchair attachment + + + + Label: LOINC DOC code 52051-0 + + Orthotics + prosthetics attachment + + + + Label: LOINC DOC code 52052-8 + + Osteogenesis stimulators attachment + + + + Label: LOINC DOC code 52053-6 + + Oxygen attachment + + + + Label: LOINC DOC code 52054-4 + + Parenteral attachment + + + + Label: LOINC DOC code 52055-1 + + Power operated vehicles attachment + + + + Label: LOINC DOC code 52056-9 + + Repair of durable medical equipment attachment + + + + Label: LOINC DOC code 52057-7 + + Seat lift mechanism attachment + + + + Label: LOINC DOC code 52058-5 + + Seating systems attachment + + + + Label: LOINC DOC code 52059-3 + + Speech generating device attachment + + + + Label: LOINC DOC code 52060-1 + + Standers + standing frames attachment + + + + Label: LOINC DOC code 52061-9 + + Support surfaces attachment + + + + Label: LOINC DOC code 52062-7 + + Transcutaneous electrical neural stimulation attachment + + + + Label: LOINC DOC code 52063-5 + + Prescription for durable medical equipment attachment + + + + Label: LOINC DOC code 52064-3 + + First report of injury attachment + + + + Label: LOINC DOC code 52065-0 + + Automobile liability attachment + + + + Label: LOINC DOC code 52066-8 + + Notice of Discharge Medicare Appeal Rights Form attachment + + + + Label: LOINC DOC code 52067-6 + + Past filing limit justification attachment + + + + Label: LOINC DOC code 52068-4 + + Property and casualty state mandated forms attachment + + + + Label: LOINC DOC code 52069-2 + + Tax ID number - IRS form W9 attachment + + + + Label: LOINC DOC code 52070-0 + + Workers compensation attachment + + + + Label: LOINC DOC code 52071-8 + + Employee assistance program attachment + + + + Label: LOINC DOC code 52072-6 + + Non-emergency transportation attachment + + + + Label: LOINC DOC code 52073-4 + + Vision attachment + + + + Label: LOINC DOC code 52075-9 + + Purchase invoice attachment + + + + Label: LOINC DOC code 53242-4 + + Charge ticket or encounter form attachment + + + + Label: LOINC DOC code 53243-2 + + Advanced beneficiary notice attachment + + + + Label: LOINC DOC code 53244-0 + + Notice of privacy practices receipt attachment + + + + Label: LOINC DOC code 53245-7 + + Driver license image attachment + Bijlage afbeelding rijbewijs + + + + Label: LOINC DOC code 53246-5 + + Non-medical services attachment + + + + Label: LOINC DOC code 53247-3 + + Eligibility acknowledgement attachment + + + + Label: LOINC DOC code 53576-5 + + Personal health monitoring report ({Provider}) + Personal health monitoring report ({Instelling}) + + + + Label: LOINC DOC code 54094-8 + + Triage note + Triageverslag + + + + Label: LOINC DOC code 54095-5 + + Chemotherapy effectiveness panel + Chemotherapie effectiviteitspanel + + + + Label: LOINC DOC code 54096-3 + + Identity testing (Molgen) + Identiteitstesten (Molgen) + + + + Label: LOINC DOC code 55107-7 + + Addendum + + + + Label: LOINC DOC code 55108-5 + + Clinical presentation + Klinische presentatie + + + + Label: LOINC DOC code 55109-3 + + Complications + Complicaties + + + + Label: LOINC DOC code 55110-1 + + Conclusions + Conclusies + + + + Label: LOINC DOC code 55111-9 + + Current imaging procedure descriptions + + + + Label: LOINC DOC code 55112-7 + + Document summary + Documentsamenvatting + + + + Label: LOINC DOC code 55113-5 + + Key images (Radiology) + Sleutelbeelden (Radiologie) + + + + Label: LOINC DOC code 55114-3 + + Prior imaging procedure descriptions + + + + Label: LOINC DOC code 55115-0 + + Requested imaging studies information + + + + Label: LOINC DOC code 55182-0 + + Quality Reporting Document Architecture incidence report + + + + Label: LOINC DOC code 55183-8 + + Quality Reporting Document Architecture patient list report + + + + Label: LOINC DOC code 55184-6 + + Quality Reporting Document Architecture calculated summary report + + + + Label: LOINC DOC code 55185-3 + + Measure set + Metingenset + + + + Label: LOINC DOC code 55186-1 + + Measure + Metingen + + + + Label: LOINC DOC code 55187-9 + + Reporting parameters + + + + Label: LOINC DOC code 55188-7 + + Patient data + Patiëntgegevens + + + + Label: LOINC DOC code 55228-1 + + Study report (Cytogenetics) + Onderzoeksverslag (Cytogenetics) + + + + Label: LOINC DOC code 55229-9 + + Study report (Immune stain) + Onderzoeksverslag (Immune stain) + + + + Label: LOINC DOC code 55230-7 + + Study report (Immunophenotyping) + Onderzoeksverslag (Immunophenotyping) + + + + Label: LOINC DOC code 55750-4 + + Patient safety report + Verslag patiëntveiligheid + + + + Label: LOINC DOC code 55751-2 + + Public health case report + Volksgezondheid incidentverslag + + + + Label: LOINC DOC code 57056-4 + + Labor and delivery admission history and physical ({Provider}) + Voorgeschiedenis en lichamelijke conditie bij opname zwangerschap en geboorte ({Instelling}) + + + + Label: LOINC DOC code 57057-2 + + Labor and delivery summary ({Provider}) + Samenvatting zwangerschap en geboorte ({Instelling}) + + + + Label: LOINC DOC code 57058-0 + + Maternal Discharge Summary ({Provider}) + Samenvattende ontslagbrief na zwangerschap ({Instelling}) + + + + Label: LOINC DOC code 56444-3 + + Healthcare communication + Zorginstellingsbrief + + + + Label: LOINC DOC code 56445-0 + + Medication summary + Medicijnkaart + + + + Label: LOINC DOC code 56446-8 + + Appointment summary + Afsprakenkaart + + + + Label: LOINC DOC code 56447-6 + + Treatment plan + Behandelplan + + + + Label: LOINC DOC code 57016-8 + + Privacy policy acknowledgment + Onderschrijving privacybeleid (Patiënt) + + + + Label: LOINC DOC code 57017-6 + + Privacy policy + Privacybeleid ({Instelling}) + + + + Label: LOINC DOC code 57024-2 + + Health Quality Measure document + Document voor meting van zorgkwaliteit + + + + Label: LOINC DOC code 57053-1 + + Note (Nursing) + Verslag (Verpleging) + + + + Label: LOINC DOC code 57054-9 + + Triage and nursing note ({Provider}) + Verslag triage en verpleging ({Instelling}) + + + + Label: LOINC DOC code 57055-6 + + Antepartum summary ({Provider}) + Antepartum samenvatting ({Instelling}) + + + + Label: LOINC DOC code 57129-9 + + Full newborn screening summary report for display or printing + Volledig verslag screening nieuwgeborene voor weergave en afdrukken + + + + Label: LOINC DOC code 57133-1 + + Referral note + Verwijsbrief + + + + Label: LOINC DOC code 57134-9 + + Referral note (Dentistry) + Verwijsbrief (Tandheelkunde) + + + + Label: LOINC DOC code 57135-6 + + Referral note (Dermatology) + Verwijsbrief (Dermatologie) + + + + Label: LOINC DOC code 57136-4 + + Referral note (Diabetology) + Verwijsbrief (Diabeteszorg) + + + + Label: LOINC DOC code 57137-2 + + Referral note (Endocrinology) + Verwijsbrief (Endocrinologie) + + + + Label: LOINC DOC code 57138-0 + + Referral note (Gastroenterology) + Verwijsbrief (Gastro-enterologie) + + + + Label: LOINC DOC code 57139-8 + + Referral note (General medicine) + Verwijsbrief (Algemene geneeskunde) + + + + Label: LOINC DOC code 57140-6 + + Referral note (General surgery) + Verwijsbrief (Algemene chirurgie) + + + + Label: LOINC DOC code 57141-4 + + Referral note (Infectious disease) + Verwijsbrief (Infectieziekten) + + + + Label: LOINC DOC code 57142-2 + + Referral note (Kinesiotherapy) + Verwijsbrief (Kinesiotherapie) + + + + Label: LOINC DOC code 57143-0 + + Referral note (Mental health) + Verwijsbrief (Geestelijke gezondheidszorg) + + + + Label: LOINC DOC code 57144-8 + + Referral note (Nephrology) + Verwijsbrief (Nephrologie) + + + + Label: LOINC DOC code 57145-5 + + Referral note (Neurology) + Verwijsbrief (Neurologie) + + + + Label: LOINC DOC code 57146-3 + + Referral note (Neurosurgery) + Verwijsbrief (Neurochirurgie) + + + + Label: LOINC DOC code 57147-1 + + Referral note (Occupational health) + Verwijsbrief (Bezigheidszorg) + + + + Label: LOINC DOC code 57148-9 + + Referral note (Occupational therapy) + Verwijsbrief (Bezigheidstherapie) + + + + Label: LOINC DOC code 57149-7 + + Referral note (Oncology) + Verwijsbrief (Oncologie) + + + + Label: LOINC DOC code 57150-5 + + Referral note (Ophthalmology) + Verwijsbrief (Oogheelkunde) + + + + Label: LOINC DOC code 57151-3 + + Referral note (Optometry) + Verwijsbrief (Optometrie) + + + + Label: LOINC DOC code 57152-1 + + Referral note (Pharmacy) + Verwijsbrief (Apotheek) + + + + Label: LOINC DOC code 57153-9 + + Referral note (Physical medicine and rehabilitation) + Verwijsbrief (Lichaamsgeneeskunde en revalidatie) + + + + Label: LOINC DOC code 57154-7 + + Referral note (Physical therapy) + Verwijsbrief (Lichamelijke oefening) + + + + Label: LOINC DOC code 57155-4 + + Referral note (Plastic surgery) + Verwijsbrief (Plastische chirurgie) + + + + Label: LOINC DOC code 57156-2 + + Referral note (Podiatry) + Verwijsbrief (Podologie) + + + + Label: LOINC DOC code 57157-0 + + Referral note (Psychiatry) + Verwijsbrief (Psychiatrie) + + + + Label: LOINC DOC code 57158-8 + + Referral note (Psychology) + Verwijsbrief (Psychologie) + + + + Label: LOINC DOC code 57159-6 + + Referral note (Radiation oncology) + Verwijsbrief (Radiologische oncologie) + + + + Label: LOINC DOC code 57160-4 + + Referral note (Recreational therapy) + Verwijsbrief (Recreationele therapie) + + + + Label: LOINC DOC code 57161-2 + + Referral note (Rehabilitation) + Verwijsbrief (Revalidatie) + + + + Label: LOINC DOC code 57162-0 + + Referral note (Respiratory therapy) + Verwijsbrief (Ademhalingstherapie) + + + + Label: LOINC DOC code 57163-8 + + Referral note (Rheumatology) + Verwijsbrief (Reumatologie) + + + + Label: LOINC DOC code 57164-6 + + Referral note (Social Work) + Verwijsbrief (Sociaal werk) + + + + Label: LOINC DOC code 57165-3 + + Referral note (Speech therapy) + Verwijsbrief (Spraaktherapie) + + + + Label: LOINC DOC code 57166-1 + + Referral note (Surgery) + Verwijsbrief (Chirurgie) + + + + Label: LOINC DOC code 57167-9 + + Referral note (Thoracic surgery) + Verwijsbrief (Thorax chirurgie) + + + + Label: LOINC DOC code 57168-7 + + Referral note (Urology) + Verwijsbrief (Urologie) + + + + Label: LOINC DOC code 57169-5 + + Referral note (Vascular surgery) + Verwijsbrief (Vasculaire chirurgie) + + + + Label: LOINC DOC code 57170-3 + + Referral note (Cardiovascular disease) + Verwijsbrief (Cardiovasculaire geneeskunde) + + + + Label: LOINC DOC code 57171-1 + + Referral note (Geriatric medicine) + Verwijsbrief (Geriatrie) + + + + Label: LOINC DOC code 57172-9 + + Referral note (Hematology and Oncology) + Verwijsbrief (Hematologie en oncologie) + + + + Label: LOINC DOC code 57173-7 + + Referral note (Nutrition and Dietetics) + Verwijsbrief (Voeding en diëtetiek) + + + + Label: LOINC DOC code 57174-5 + + Referral note (Oral surgery) + Verwijsbrief (Mondchirurgie) + + + + Label: LOINC DOC code 57175-2 + + Referral note (Orthopedic surgery) + Verwijsbrief (Orthopedische chirurgie) + + + + Label: LOINC DOC code 57176-0 + + Referral note (Otolaryngology) + Verwijsbrief (KNO) + + + + Label: LOINC DOC code 57177-8 + + Referral note (Pulmonary disease) + Verwijsbrief (Vaatziekten) + + + + Label: LOINC DOC code 57178-6 + + Referral note (Critical care medicine) + Verwijsbrief (Acute zorg) + + + + Label: LOINC DOC code 57179-4 + + Referral note (Obstetrics and Gynecology) + Verwijsbrief (Obstetrie en gynaecologie) + + + + Label: LOINC DOC code 57829-4 + + Prescription for medical equipment or product + Indicatie voor medische hulpmiddelen of producten + + + + Label: LOINC DOC code 57830-2 + + Admission request + Opnameverzoek + + + + Label: LOINC DOC code 57831-0 + + Prescription for rehabilitation + Indicatie voor revalidatie + + + + Label: LOINC DOC code 57832-8 + + Prescription for diagnostic or specialist care + Indicatie voor diagnostische of specialistische zorg + + + + Label: LOINC DOC code 57833-6 + + Prescription for medication + Medicatievoorschrift + + + + Label: LOINC DOC code 57834-4 + + Patient transportation request + Patiënt transportverzoek + + + + Label: LOINC DOC code 58477-1 + + Study report (Pulmonary function) + Onderzoeksverslag (Vaatfunctie) + + + + Label: LOINC DOC code 59258-4 + + Discharge summarization note ({Provider}) + Samenvattende ontslagbrief ({Instelling}) + + + + Label: LOINC DOC code 59259-2 + + Discharge summarization note (Psychiatry) + Samenvattende ontslagbrief (Psychiatrie) + + + + Label: LOINC DOC code 59268-3 + + Neonatal care report + Verslag neonatale zorg + + + + Label: LOINC DOC code 59281-6 + + Transthoracic cardiac echo study report (US) + Verslag trans-thorax echo-onderzoekt hart (US) + + + + Label: LOINC DOC code 59282-4 + + Stress cardiac echo study report (US) + Verslag echo-onderzoek hartbelasting (US) + + + + Label: LOINC DOC code 59283-2 + + Well child visit note ({Provider}) + Well child visit note ({Instelling}) + + + + Label: LOINC DOC code 59284-0 + + Consent (Patient) + Toestemming (Patiënt) + + + + Label: LOINC DOC code 60280-5 + + Discharge instructions ({Provider}) + Ontslagaanwijzigingen ({Spoedeisende hulp}) + + + + Label: LOINC DOC code 60281-3 + + Discharge Instructions ({Provider}) + Ontslagaanwijzigingen ({Ziekenhuis}) + + + + Label: LOINC DOC code 60568-3 + + Synoptic report + Beknopt verslag report + + + + Label: LOINC DOC code 60569-1 + + Report addendum.synoptic + Toevoeging verslag.beknopt + + + + Label: LOINC DOC code 60570-9 + + Consultation note (Pathology) + Consultverslag (Pathologie) + + + + Label: LOINC DOC code 60571-7 + + Consultation note.synoptic (Pathology) + Consultverslag.beknopt (Pathologie) + + + + Label: LOINC DOC code 60590-7 + + Medication dispensed.brief + Verstrekte medicatie.kort + + + + Label: LOINC DOC code 60591-5 + + Patient summary + Patiënt samenvatting + + + + Label: LOINC DOC code 60592-3 + + Patient summary.unexpected contact + Patiënt samenvatting.onverwacht contact + + + + Label: LOINC DOC code 60593-1 + + Medication dispensed.extended + Verstrekte medicatie.uitgebreid + + + + Label: LOINC DOC code 61143-4 + + Summary (Nursing) + Samenvatting (Verpleging) + + + + Label: LOINC DOC code 61145-9 + + Patient plan of care + Patiënt zorgplan + + + + Label: LOINC DOC code 61356-2 + + Medication pharmaceutical advice.extended + Medicatie farmaceutisch advies.uitgebreid + + + + Label: LOINC DOC code 61357-0 + + Medication pharmaceutical advice.brief + Medicatie farmaceutisch advies.kort + + + + Label: LOINC DOC code 61358-8 + + Surgerical operation consent (Patient) + Toestemming chirugische operatie (Patiënt) + + + + Label: LOINC DOC code 61359-6 + + Anesthesia consent (Patient) + Toestemming anasthesie (Patiënt) + + + + Label: LOINC DOC code 62385-0 + + Recommendation + Aanbeveling + + + + + + Label: LOINC DOC code 10160-0 + + History of medication use + Geschiedenis medicijngebruik + + + + Label: LOINC DOC code 10162-6 + + History of pregnancies + Geschiedenis zwangerschappen + + + + Label: LOINC DOC code 10164-2 + + History of present illness + Geschiedenis van huidige ziekte + + + + Label: LOINC DOC code 10167-5 + + History of surgical procedures + Geschiedenis van chirurgische ingrepen + + + + Label: LOINC DOC code 10830-8 + + Surgical operation note complications + Chirurgisch operatieverslag complicaties + + + + Label: LOINC DOC code 10154-3 + + Chief complaint + Belangrijkste klacht + + + + Label: LOINC DOC code 10155-0 + + History of allergies + Geschiedenis van allergieën + + + + Label: LOINC DOC code 10157-6 + + History of family member diseases + Geschiedenis van ziekte binnen de familie + + + + Label: LOINC DOC code 10183-2 + + Hospital discharge medications + Ziekenhuis ontslagmedicatie + + + + Label: LOINC DOC code 10184-0 + + Hospital discharge physical findings + Ziekenhuis ontslag lichamelijke bevindingen + + + + Label: LOINC DOC code 10187-3 + + Review of systems + Review van systemen + + + + Label: LOINC DOC code 10210-3 + + Physical findings + Lichamelijke bevindingen + + + + Label: LOINC DOC code 10213-7 + + Surgical operation note anesthesia + Chirurgisch operatieverslag anesthesie + + + + Label: LOINC DOC code 10215-2 + + Surgical operation note findings + Chirurgisch operatieverslag bevindingen + + + + Label: LOINC DOC code 10216-0 + + Surgical operation note fluids + Chirurgisch operatieverslag vloeistoffen + + + + Label: LOINC DOC code 10217-8 + + Surgical operation note indications + Chirurgisch operatieverslag indicaties + + + + Label: LOINC DOC code 10218-6 + + Surgical operation note postoperative Dx + Chirurgisch operatieverslag postoperatieve diagnose + + + + Label: LOINC DOC code 10219-4 + + Surgical operation note preoperative Dx + Chirurgisch operatieverslag preoperatieve diagnose + + + + Label: LOINC DOC code 10221-0 + + Surgical operation note specimens taken + Chirurgisch operatieverslag genomen monsters + + + + Label: LOINC DOC code 10223-6 + + Surgical operation note surgical procedure + Chirurgisch operatieverslag chirurgische ingreep + + + + Label: LOINC DOC code 11535-2 + + Hospital discharge Dx + Ziekenhuis onslagdiagnose + + + + Label: LOINC DOC code 11537-8 + + Surgical drains + Chirurgische drains + + + + Label: LOINC DOC code 11283-9 + + Acuity assessment + Vaststelling acute karakter + + + + Label: LOINC DOC code 11302-7 + + ED disposition + ED dispositie + + + + Label: LOINC DOC code 11329-0 + + History general + Voorgeschiedenis + + + + Label: LOINC DOC code 11332-4 + + History of cognitive function + Cognitieve functiegeschiedenis + + + + Label: LOINC DOC code 11336-5 + + History of hospitalizations + Ziekenhuisopnamegeschiedenis + + + + Label: LOINC DOC code 11346-4 + + History of outpatient visits + Poliklinische bezoekgeschiedenis + + + + Label: LOINC DOC code 11348-0 + + History of past illness + Ziektegeschiedenis + + + + Label: LOINC DOC code 11369-6 + + History of immunization + Inentingsgeschiedenis + + + + Label: LOINC DOC code 11370-4 + + Immunization status + Status inentingen + + + + Label: LOINC DOC code 11450-4 + + Problem list + Probleemlijst + + + + Label: LOINC DOC code 11459-5 + + Transport mode + Transportmodus + + + + Label: LOINC DOC code 11493-4 + + Hospital discharge studies summary + Ziekenhuis ontslag samenvatting onderzoeken + + + + Label: LOINC DOC code 18769-0 + + Microbial susceptibility tests + + + + Label: LOINC DOC code 18610-6 + + Medication.administered + Toegediende medicatie + + + + Label: LOINC DOC code 18776-5 + + Plan of treatment + Behandelplan + + + + Label: LOINC DOC code 18782-3 + + Study observation + Observatieonderzoek + + + + Label: LOINC DOC code 18783-1 + + Study recommendation + Onderzoek aanbeveling + + + + Label: LOINC DOC code 18785-6 + + Reason for study + Reden voor onderzoek + + + + Label: LOINC DOC code 18834-2 + + Comparison.study + Vergelijkend.onderzoek + + + + Label: LOINC DOC code 19005-8 + + Imaging study + Beeldvormend onderzoek study + + + + Label: LOINC DOC code 22029-3 + + Physical exam.total + Lichamelijk onderzoek.volledig + + + + Label: LOINC DOC code 29299-5 + + Reason for visit + Reden voor bezoek + + + + Label: LOINC DOC code 29545-1 + + Physical findings + Lichamelijke bevindingen + + + + Label: LOINC DOC code 29762-2 + + Social history + Sociale geschiedenis + + + + Label: LOINC DOC code 30954-2 + + Relevant diagnostic tests &or laboratory data + Relevante diagnostische tests & or laboratoriumgegevens + + + + Label: LOINC DOC code 38212-7 + + Pain assessment panel + Pijn vaststellingspanel + + + + Label: LOINC DOC code 38227-5 + + Braden scale score.total + Braden schaal score.volledig + + + + Label: LOINC DOC code 42348-3 + + Advanced directives + Advanced aanwijzingen + + + + Label: LOINC DOC code 42349-1 + + Reason for referral + Reden voor overplaatsing + + + + Label: LOINC DOC code 46239-0 + + Chief complaint+Reason for visit + Belangrijkste klacht+Reden voor bezoek + + + + Label: LOINC DOC code 46240-8 + + History of hospitalizations+History of outpatient visits + Geschiedenis van ziekenhuisopnames+Geschiedenis van poliklinische bezoeken + + + + Label: LOINC DOC code 46241-6 + + Hospital admission Dx + Ziekenhuis opnamediagnose + + + + Label: LOINC DOC code 55102-8 + + Surgical operation note disposition + Chirurgisch operatieverslag dispositie + + + + Label: LOINC DOC code 55103-6 + + Surgical operation note estimated blood loss + Chirurgisch operatieverslag geschat bloedverlies + + + + Label: LOINC DOC code 55104-4 + + Surgical operation note planned procedure + Chirurgisch operatieverslag geplande ingreep + + + + Label: LOINC DOC code 5511-1 + + CD62E + + + + Label: LOINC DOC code 57059-8 + + Pregnancy visit summary + Samenvatting zwangerschapbezoek + + + + Label: LOINC DOC code 57060-6 + + Estimated date of delivery + A terme datum + + + + Label: LOINC DOC code 57072-1 + + Intravenous fluids administered + Intraveneus toegediende vloeistoffen + + + + Label: LOINC DOC code 57073-9 + + Prenatal events + Prenatale gebeurtenissen + + + + Label: LOINC DOC code 57074-7 + + Labor and delivery process + Verloop zwangerschap en bevalling + + + + Label: LOINC DOC code 57075-4 + + Newborn delivery information + Informatie bevalling nieuwgeborene + + + + Label: LOINC DOC code 57076-2 + + Postpartum hospitalization treatment + Postpartum ziekenhuisbehandeling + + + + Label: LOINC DOC code 57077-0 + + Newborn status at maternal discharge + Status nieuwgeborene bij ontslag moeder + + + + Label: LOINC DOC code 57078-8 + + Antenatal testing and surveillance + Antenatale testen en toezicht + + + + Label: LOINC DOC code 57079-6 + + Birth plan + Geboorteplan + + + + Label: LOINC DOC code 57080-4 + + Implanted medical device + Geïmplanteerd medisch apparaat + + + + Label: LOINC DOC code 57081-2 + + Anesthesia risk review of systems + Anesthesie risicoreview van systemen + + + + Label: LOINC DOC code 56836-0 + + History of blood transfusion + Geschiedenis van bloedtransfusies + + + + Label: LOINC DOC code 56838-6 + + History of infectious disease + Geschiedenis infectieziekten + + + + Label: LOINC DOC code 57025-9 + + Data criteria + Datacriteria + + + + Label: LOINC DOC code 57026-7 + + Population criteria + Populatiecriteria + + + + Label: LOINC DOC code 57027-5 + + Measure observations + Metingen + + + + Label: LOINC DOC code 57827-8 + + Reason for co-payment exemption + Reden voor vrijstelling co-betaling + + + + Label: LOINC DOC code 5782-8 + + Crystals + Kristalvorming + + + + Label: LOINC DOC code 57828-6 + + Prescriptions + Medicatievoorschriften + + + + Label: LOINC DOC code 57826-0 + + Co-payment amount + Co-betaling bedrag + + + + Label: LOINC DOC code 59768-2 + + Procedure indications + Indicaties ingreep + + + + Label: LOINC DOC code 59769-0 + + Postprocedure diagnosis + Diagnose na ingreep + + + + Label: LOINC DOC code 59770-8 + + Procedure estimated blood loss + Bloedverlies ingreep + + + + Label: LOINC DOC code 59771-6 + + Procedure implants + Ingreep implantaten + + + + Label: LOINC DOC code 59772-4 + + Planned procedure + Geplande ingreep + + + + Label: LOINC DOC code 59773-2 + + Procedure specimens taken + Ingreep afgenomen monsters + + + + Label: LOINC DOC code 59774-0 + + Procedure anesthesia + Ingreep anesthesie + + + + Label: LOINC DOC code 59775-7 + + Procedure disposition + Ingreep dispositie + + + + Label: LOINC DOC code 59776-5 + + Procedure findings + Ingreep bevindingen + + + + Label: LOINC DOC code 61144-2 + + Diet and nutrition + Dieet en voeding + + + + Label: LOINC DOC code 61146-7 + + Goals + Doelen + + + + Label: LOINC DOC code 61147-5 + + Expected outcomes + Verwachte uitkomsten + + + + Label: LOINC DOC code 8724-7 + + Surgical operation note description + Chirurgisch operatieverslag omschrijving + + + + Label: LOINC DOC code 8716-3 + + Physical findings + Lichamelijke bevindingen + + + + Label: LOINC DOC code 8648-8 + + Hospital course + Ziekenhuis verloop + + + + Label: LOINC DOC code 8658-7 + + History of allergies + Geschiedenis allergieën + + + + Label: LOINC DOC code 8658-7 + + Fluid intake.intravascular + Vloeistof inname.intravasculair + + + + + + Label: OID ISO 3166 Alpha 2 + + ISO 3166 Alpha 2 + + + + Label: OID ISO 639-1 + + ISO 639-1 + + + + Label: OID EAN Artikelcodes + + EAN Artikelcodes + + + + Label: OID UZI-Zorgverlener + + UZI-Zorgverlener + + + + Label: OID UZI-Systemen + + UZI-Systemen + + + + Label: OID UZI-Registernummer + + UZI-Registernummer + + + + Label: OID RoleCodeNL - zorgaanbiedertype (organisaties) + + RoleCodeNL Zorgaanbiedertype + + + + Label: OID RoleCodeNL - zorgverlenertype (natuurlijke personen) + + RoleCodeNL Zorgverlenertype + + + + Label: OID RoleCodeNL-organisatiedeeltyperingen + + RoleCodeNL Organisatiedeeltype + + + + Label: OID Mate van overgevoeligheid + + Mate van overgevoeligheid + + + + Label: OID ActRegistry:x_DataDomainNL + + ActRegistryNL Gegevenssoort + + + + Label: OID Indicatie geheim + + Indicatie geheim + + + + Label: OID RoleCodeWettelijkeVertegenwoordigerNL + + RoleCodeNL WettelijkeVertegenwoordiger + + + + Label: OID Rolcode tabel Toegang Patiënt + + RolCodeNL Toegang Patiënt + + + + Label: OID Vektis AGB-Z + + Vektis AGB-Z + + + + Label: OID Burgerservicenummer BSN + + NL National PID + Burgerservicenummer + + + + Label: OID UZOVI + + NL UZOVI + UZOVI + + + + Label: OID PALGA servicetypes + + PALGA servicetypes + + + + Label: OID PALGA types obductie + + PALGA types obductie + + + + Label: OID Bestand 361 a-tabel (eenheid gebruiksadvies) + + G-Standaard Bestand 361 a-tabel (eenheid gebruiksadvies) + + + + Label: OID G-Standaard Bestand 651 (obsolete) + + G-Standaard Bestand 651 (obsolete) + + + + Label: OID G-Standaard Bestand 652 (obsolete) + + G-Standaard Bestand 652 (obsolete) + + + + Label: OID G-Standaard Bestand 725 + + G-Standaard Bestand 725 + + + + Label: OID G-Standaard Bestand 750 + + G-Standaard Bestand 750 + + + + Label: OID G-Standaard bestand 902 Thesaurus 2 + + G-Standaard bestand 902 Thesaurus 2 + + + + Label: OID G-Standaard Tabel 122 + + G-Standaard Tabel 122 + + + + Label: OID G-Standaard Tabel 40 + + G-Standaard Tabel 40 + + + + Label: OID G-Standaard GPK + + G-Standaard GPK + + + + Label: OID G-Standaard PRK + + G-Standaard PRK + + + + Label: OID G-Standaard tabel 902 thesaurus 0006 + + G-Standaard tabel 902 thesaurus 0006 + + + + Label: OID G-Standaard tabel 902 thesaurus 4 + + G-Standaard tabel 902 thesaurus 4 + + + + Label: OID Perinatologische observatiecodes + + Perinatologische observatiecodes + + + + Label: OID Perinatologische procedurecodes + + Perinatologische procedurecodes + + + + Label: OID Nederlandse postcodes + + Nederlandse postcodes + + + + Label: OID GBA Landcodes + + GBA Landcodes + + + + Label: OID LMR ontslagbestemmingen + + LMR ontslagbestemmingen + + + + Label: OID Tabel 25 + + Tabel 25 + + + + Label: OID Tabel 25 Tijdseenheden + + Tabel 25 Tijdseenheden + + + + Label: OID Gecodeerde antwoorden bij Code diagnostische bepalingen + + Gecodeerde antwoorden bij Code diagnostische bepalingen + + + + Label: OID NHG Tabel 11 Code sociale laag + + NHG Tabel 11 Code sociale laag + + + + Label: OID NHG Tabel 12 Code specialisme + + NHG Tabel 12 Code specialisme + + + + Label: OID NHG Tabel 14 Code contact + + NHG Tabel 14 Code contact + + + + Label: OID Code verrichtingen + + Code verrichtingen + + + + Label: OID NHG Tabel 20 Code opleiding + + NHG Tabel 20 Code opleiding + + + + Label: OID Code diagnostische bepalingen + + Code diagnostische bepalingen + + + + Label: OID ICPC-1-2000NL + + ICPC-1-2000NL + + + + Label: OID Journaalregeltypen + + Journaalregeltypen + + + + Label: OID Tabel 25 Eenheden gebruiksadvies + + Tabel 25 Eenheden gebruiksadvies + + + + Label: OID Tabel 25 B-codes + + NHG Tabel 25 B-codes + + + + Label: OID Tabel 25 Aanvullende teksten bij medicatiedosering (numcode) + + NHG Tabel 25 Aanvullende teksten + + + + Label: OID G-Standaard HPK + + G-Standaard HPK + + + + Label: OID G-Standaard ZI_nummer + + G-Standaard ZI_nummer + + + + Label: OID Cliq catalogus van hulpmiddelen + + Cliq catalogus van hulpmiddelen + + + + Label: OID G-Standaard thesaurus subtabel 0007 + + G-Standaard thesaurus subtabel 0007 + + + + Label: OID JGZ Regio's + + JGZ Regio's + + + + Label: OID Nederlandse Ministeriële Departementen (Ministeries) + + Nederlands Ministerie + + + + Label: OID SBV-Z Identificatiedocumenttypes + + SBV-Z Identificatiedocumenttypes + + + + Label: OID US Social Security Number + + SSN + + + + Label: OID US National Provider Identifier + + NPI + + + + Label: OID AdministrativeGender + + AdministrativeGender + + + + Label: OID ActMood + + ActMood + + + + Label: OID NullFlavor + + NullFlavor + + + + Label: OID Soort telefoonnummer + + Phone type + Soort telefoonnummer + + + + Label: OID Soort adres + + Address type + Soort adres + + + + Label: OID ActUncertainty + + ActUncertainty + + + + Label: OID ContextControl + + ContextControl + + + + Label: OID EntityCode + + EntityCode + + + + Label: OID ParticipationMode + + ParticipationMode + + + + Label: QueryResponse + + QueryResponse + + + + Label: OID RoleStatus + + RoleStatus + + + + Label: OID SubstitutionCondition + + SubstitutionCondition + + + + Label: OID EducationLevel + + EducationLevel + + + + Label: OID AcknowledgementDetail + + AcknowledgementDetail + + + + Label: OID AcknowledgementDetailCode + + AcknowledgementDetailCode + + + + Label: QueryRequestLimit + + QueryRequestLimit + + + + Label: QueryPriority + + QueryPriority + + + + Label: OID RoleCode + + RoleCode + + + + Label: OID RouteOfAdministration + + RouteOfAdministration + + + + Label: OID TimingEvent + + TimingEvent + + + + Label: OID ActStatus + + ActStatus + + + + Label: OID AcknowledgementType + + AcknowledgementType + + + + Label: OID MaritalStatus + + MaritalStatus + + + + Label: OID Confidentiality + + Confidentiality + + + + Label: OID DocumentCompletion + + DocumentCompletion + + + + Label: OID DocumentStorage + + DocumentStorage + + + + Label: OID ResponseModality + + ResponseModality + + + + Label: OID ActCode + + ActCode + + + + Label: OID ActClass + + ActClass + + + + Label: OID LanguageAbilityMode + + LanguageAbilityMode + + + + Label: OID LanguageAbilityProficiency + + LanguageAbilityProficiency + + + + Label: OID ActPriority + + ActPriority + + + + Label: OID Observation Interpretation + + Observation Interpretation + + + + Label: OID OrderableDrugForm + + OrderableDrugForm + + + + Label: OID ParticipationFunction + + ParticipationFunction + + + + Label: OID ParticipationSignature + + ParticipationSignature + + + + Label: OID LOINC + + LOINC + + + + Label: OID US National Uniform Claim Committee for Provider Types + + NUCC Provider Types + + + + Label: OID HumanLanguage + + HumanLanguage + + + + Label: OID WHO ATC + + WHO ATC + + + + Label: OID HL7 v2 Table 443 Provider Role code system + + HL7v2 Table 443 Provider Role Code + + + + Label: OID Examples + + Examples + Voorbeelden + + + + + Label: security warning text + + WARNING: Javascript injection attempt detected in source CDA document. Terminating + WAARSCHUWING: Javascript-injectiepoging gedetecteerd in bron CDA-document. Einde verwerking + + + + Label: security warning text + + WARNING: Potentially malicious content found in CDA document. + WAARSCHUWING: potentieel kwaadaardige inhoud gevonden in CDA-document. + + + + Label: security warning text + + is in the whitelist + staat op de whitelist + + + + Label: security warning text part1 + + WARNING: non-local image found + WAARSCHUWING: niet-lokale afbeelding gevonden + + + + Label: security warning text part2 + + . Removing. If you wish non-local images preserved please set the limit-external-images param to 'no'. + . Wordt niet verwerkt. Als u niet-lokale afbeelding wilt behouden, dan stelt u de parameter limit-external-images in op 'no'. + + + + Label: logicalOR (e.g. query params with multiple value elements) + + OR + OF + + + + Label: logicalAND (e.g. multiple sibling query params) + + AND + AND + + + + Label: when a document has no name + + Untitled Document + Naamloos document + + + + Label: when a document has no human readable text + + No human-readable content available + Geen voor-mensen-leesbare content beschikbaar + + + + Label: starting point for subject details + + Subject Details + Patiëntgegevens + + + + Label: starting point for author details + + Author Details + Auteurgegevens + + + + Label: starting point for encounter details + + Encounter Details + Bezoekgegevens + + + + Label: starting point for untitled section + + Untitled Section + Naamloze sectie + + + + Error message: Source document must be a bundle + + Source document must be a bundle + Brondocument moet een bundle zijn + + + + Error message: Bundle must start with a Composition resource + + Bundle must start with a Composition resource + Bundle moet beginnen met een Composition resource + + + + Error message: Warning: Bundle type does not indicate it is a document. + + Warning: Bundle type does not indicate it is a document. + Waarschuwing: Bundle type zegt niet dat dit een document is. + + + + Error message: Error: The document composition includes a reference to a resource not contained inside the document bundle: + + Error: The document composition includes a reference to a resource not contained inside the document bundle: + Fout: Er is een verwijzing in de document Composition naar een resource die ontbreekt in de Bundle: + + + + Error message: Error: A referenced resource is not contained and is not fully qualified: + + Error: A referenced resource is not contained and is not fully qualified: + Fout: Er is een verwijzing naar een resource die ontbreekt en waarvan de verwijzing niet volledig is: + + + + Error message: Warning: Headings exceed 6 levels deep. Remaining headings converted to simple paragraphs + + Warning: Headings exceed 6 levels deep. Remaining headings converted to simple paragraphs + Waarschuwing: Kopniveau's gaan dieper dan 6. De overgebleven kopniveau's worden omgezet naar normale paragrafen + + + + Error message: Source document must be a composition + + Source document must be a composition + Brondocument moet een composition zijn + + + diff --git a/src/main/resources/xslt/utilities-l10n.xsd b/src/main/resources/xslt/utilities-l10n.xsd new file mode 100644 index 0000000..38c43f5 --- /dev/null +++ b/src/main/resources/xslt/utilities-l10n.xsd @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/xslt/utilities.xsl b/src/main/resources/xslt/utilities.xsl new file mode 100644 index 0000000..4561d38 --- /dev/null +++ b/src/main/resources/xslt/utilities.xsl @@ -0,0 +1,235 @@ + + + + + Created on: May 11, 2017 + Author: ahenket + + + + + + + Vocabulary file containing language dependant strings such as labels + + + + + + + Cache language dependant strings + + + + + + + Retrieves a language dependant string from our language file such as a label based on a key. Returns string based on textLang, textLangDefault, the first two characters of the textLangDefault, e.g. 'en' in 'en-US' and finally if all else fails just the key text. + + Some text or space to prefix our string with + The key to find our text with + Some text like a colon or space to postfix our text with + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Converts Latin characters in input to lower case and returns the result + + Input string + + + + + + + + + + + Converts Latin characters in input to upper case and returns the result + + Input string + + + + + + + + + + + Converts first character in input to upper case if it is a Latin character and returns the result + + Input string + + + + + + + + + + + + + + Tokenize based on delimiters, or if no delimiter do character tokenization + + String to tokenize + Optional delimiter string + Optional prefix for every 'array' item + + + + + + + + + + + + + + + + + + + + + + + + + + Tokenize every character + + String to tokenize + Optional prefix for every 'array' item + + + + + + + + + + + + + + + + + + Tokenize based on delimiters + + String to tokenize + Required delimiter string + Optional prefix for every 'array' item + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/kotlin/uk/nhs/england/fhirvalidator/controller/ValidateControllerTest.kt b/src/test/kotlin/uk/nhs/england/fhirvalidator/controller/ValidateControllerTest.kt index f4db844..eac5965 100644 --- a/src/test/kotlin/uk/nhs/england/fhirvalidator/controller/ValidateControllerTest.kt +++ b/src/test/kotlin/uk/nhs/england/fhirvalidator/controller/ValidateControllerTest.kt @@ -3,18 +3,13 @@ package uk.nhs.england.fhirvalidator.controller import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.context.support.IValidationSupport import ca.uhn.fhir.validation.FhirValidator -import uk.nhs.england.fhirvalidator.service.CapabilityStatementApplier -import uk.nhs.england.fhirvalidator.service.MessageDefinitionApplier +import uk.nhs.england.fhirvalidator.interceptor.CapabilityStatementApplier +import uk.nhs.england.fhirvalidator.service.interactions.FHIRMessage import org.hl7.fhir.r4.model.Bundle -import org.hl7.fhir.r4.model.Patient -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.InjectMocks import org.mockito.Mock import org.mockito.junit.jupiter.MockitoExtension -import org.springframework.beans.factory.annotation.Qualifier -import uk.nhs.england.fhirvalidator.service.VerifyOAS +import uk.nhs.england.fhirvalidator.service.oas.OpenAPItoCapabilityStatementConversion @ExtendWith(MockitoExtension::class) internal class ValidateControllerTest { @@ -25,7 +20,7 @@ internal class ValidateControllerTest { lateinit var mockValidator: FhirValidator @Mock - lateinit var mockMessageDefinitionApplier: MessageDefinitionApplier + lateinit var mockFHIRMessage: FHIRMessage @Mock lateinit var mockCapabilityStatementApplier: CapabilityStatementApplier @@ -37,7 +32,7 @@ internal class ValidateControllerTest { lateinit var mockSearchParameters : Bundle @Mock - lateinit var verifyOAS: VerifyOAS + lateinit var OpenAPItoCapabilityStatementConversion: OpenAPItoCapabilityStatementConversion /* @Test