diff --git a/postman/Validated Relationship Service Sandbox.postman_collection.json b/postman/Validated Relationship Service Sandbox.postman_collection.json index 7522d040..c560b14b 100644 --- a/postman/Validated Relationship Service Sandbox.postman_collection.json +++ b/postman/Validated Relationship Service Sandbox.postman_collection.json @@ -1,11 +1,11 @@ { "info": { - "_postman_id": "4c6e58e9-dd6b-42fc-b6d7-5beac34fa4ea", - "name": "Validated Relationship Service Sandbox 18/09/25", + "_postman_id": "5c759d0a-d924-44ab-8668-3587dcaf27e1", + "name": "Validated Relationship Service Sandbox 14/10/25", "description": "This Postman collection includes example scenarios for each of the Validated Relationship Service (VRS) API endpoints, covering both valid and invalid request scenarios.\n\nThe collection is pointed towards the VRS sandbox environment, which will return a specific example response based on the request sent. All data shown in the requests or responses is test data.\n\nOur sandbox environment only covers the scenarios listed in the Postman collection and is open access. It does not allow you to test authorisation or any scenarios beyond the ones documented.\n\nFull specification is available at [https://digital.nhs.uk/developer/api-catalogue/validated-relationship-service](https://digital.nhs.uk/developer/api-catalogue/validated-relationship-service)", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "44536620", - "_collection_link": "https://www.postman.com/ellie-bound1-b2ea016f/workspace/validated-relationship-service-sandbox-18-10-2025/collection/44536620-4c6e58e9-dd6b-42fc-b6d7-5beac34fa4ea?action=share&source=collection_link&creator=44536620" + "_exporter_id": "18067099", + "_collection_link": "https://www.postman.com/lunar-crescent-672573/workspace/validated-relationship-service-14-10-2025/collection/18067099-5c759d0a-d924-44ab-8668-3587dcaf27e1?action=share&source=collection_link&creator=18067099" }, "item": [ { @@ -235,14 +235,13 @@ } ], "url": { - "raw": "{{api_base_url}}/QuestionnaireResponse?ID=156e1560-e532-4e2a-85ad-5aeff03dc43e", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"], - "query": [ - { - "key": "ID", - "value": "156e1560-e532-4e2a-85ad-5aeff03dc43e" - } + "raw": "{{api_base_url}}/QuestionnaireResponse/156e1560-e532-4e2a-85ad-5aeff03dc43e", + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse", + "156e1560-e532-4e2a-85ad-5aeff03dc43e" ] }, "description": "Example of Questionnaire Response that will be returned" @@ -257,27 +256,28 @@ "script": { "exec": [ "const expectedResponseBody = {", - " \"resourceType\": \"OperationOutcome\",", " \"issue\": [", " {", - " \"severity\": \"error\",", - " \"code\": \"required\",", + " \"code\": \"not-supported\",", " \"details\": {", " \"coding\": [", " {", - " \"system\": \"https://fhir.nhs.uk/STU3/CodeSystem/Spine-ErrorOrWarningCode-1\",", - " \"code\": \"BAD_REQUEST\",", - " \"display\": \"Bad request\"", + " \"code\": \"METHOD_NOT_ALLOWED\",", + " \"display\": \"The method is not allowed.\",", + " \"system\": \"https://fhir.nhs.uk/R4/CodeSystem/ValidatedRelationships-ErrorOrWarningCode\",", + " \"version\": \"1\"", " }", " ]", " },", - " \"diagnostics\": \"The access request ID parameter is required but was not provided.\"", + " \"diagnostics\": \"The method is not allowed for the requested resource.\",", + " \"severity\": \"error\"", " }", - " ]", + " ],", + " \"resourceType\": \"OperationOutcome\"", "};", "", - "pm.test(\"Status code is 400\", function () {", - " pm.response.to.have.status(400);", + "pm.test(\"Status code is 405\", function () {", + " pm.response.to.have.status(405);", "});", "", "pm.test(\"Should have correct response body\", () => {", @@ -305,9 +305,14 @@ } ], "url": { - "raw": "{{api_base_url}}/QuestionnaireResponse", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"] + "raw": "{{api_base_url}}/QuestionnaireResponse/", + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse", + "" + ] }, "description": "Example of an error response when reference code is missing from request" }, @@ -369,14 +374,13 @@ } ], "url": { - "raw": "{{api_base_url}}/QuestionnaireResponse?ID=INVALID", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"], - "query": [ - { - "key": "ID", - "value": "INVALID" - } + "raw": "{{api_base_url}}/QuestionnaireResponse/INVALID", + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse", + "INVALID" ] }, "description": "Example of an error response when reference code is invalid" @@ -439,14 +443,13 @@ } ], "url": { - "raw": "{{api_base_url}}/QuestionnaireResponse?ID=60d09b82-f4bb-41f9-b41e-767999b4ac9b", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"], - "query": [ - { - "key": "ID", - "value": "60d09b82-f4bb-41f9-b41e-767999b4ac9b" - } + "raw": "{{api_base_url}}/QuestionnaireResponse/60d09b82-f4bb-41f9-b41e-767999b4ac9b", + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse", + "60d09b82-f4bb-41f9-b41e-767999b4ac9b" ] }, "description": "Example of an error response when reference code is not found in database" @@ -532,8 +535,12 @@ }, "url": { "raw": "{{api_base_url}}/QuestionnaireResponse", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse" + ] }, "description": "Example of an adult to child access request with the reference code returned" }, @@ -611,8 +618,12 @@ }, "url": { "raw": "{{api_base_url}}/QuestionnaireResponse", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse" + ] }, "description": "Example of an adult to adult access request where the patient can consent with the reference code returned" }, @@ -675,8 +686,12 @@ }, "url": { "raw": "{{api_base_url}}/QuestionnaireResponse", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse" + ] } }, "response": [] @@ -753,8 +768,12 @@ }, "url": { "raw": "{{api_base_url}}/QuestionnaireResponse", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse" + ] }, "description": "Example of an adult to adult access request where the patient cannot consent with the reference code returned" }, @@ -832,8 +851,12 @@ }, "url": { "raw": "{{api_base_url}}/QuestionnaireResponse", - "host": ["{{api_base_url}}"], - "path": ["QuestionnaireResponse"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "QuestionnaireResponse" + ] }, "description": "Example of an adult to adult access request where the patient is the applicant with the reference code returned" }, @@ -846,14 +869,18 @@ "listen": "prerequest", "script": { "type": "text/javascript", - "exec": [""] + "exec": [ + "" + ] } }, { "listen": "test", "script": { "type": "text/javascript", - "exec": [""] + "exec": [ + "" + ] } } ] @@ -1011,8 +1038,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=9000000017", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1238,8 +1269,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=9000000017&_include=RelatedPerson:patient", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1304,8 +1339,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=9000000033", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1418,8 +1457,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=9000000017&patient:identifier=9000000009", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1568,8 +1611,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=9000000017&patient:identifier=9000000009&_include=RelatedPerson:patient", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1652,8 +1699,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ] }, "description": "Example of an error response when the NHS number is missing" }, @@ -1725,8 +1776,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=900000000", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1800,8 +1855,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=https://fhir.nhs.uk/Id/nhs-number|A730675929", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1876,8 +1935,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=1000000001", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -1952,8 +2015,12 @@ ], "url": { "raw": "{{api_base_url}}/RelatedPerson?identifier=9000000041", - "host": ["{{api_base_url}}"], - "path": ["RelatedPerson"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "RelatedPerson" + ], "query": [ { "key": "identifier", @@ -2366,7 +2433,9 @@ { "listen": "prerequest", "script": { - "exec": [""], + "exec": [ + "" + ], "type": "text/javascript", "packages": {} } @@ -2389,8 +2458,12 @@ }, "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000017&status=active&_include=Consent:performer&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -2611,7 +2684,9 @@ { "listen": "prerequest", "script": { - "exec": [""], + "exec": [ + "" + ], "type": "text/javascript", "packages": {} } @@ -2622,8 +2697,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000017&status=inactive", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -2999,8 +3078,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000017&status=proposed&status=active&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -3304,8 +3387,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000022", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -3769,8 +3856,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000022&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -4185,8 +4276,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000022&_include=Consent:performer", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -4773,8 +4868,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000022&_include=Consent:performer&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -5074,8 +5173,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?patient:identifier=9000000100", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "patient:identifier", @@ -5542,8 +5645,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?patient:identifier=9000000100&_include=Consent:performer&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "patient:identifier", @@ -5962,8 +6069,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?patient:identifier=9000000100&_include=Consent:performer", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "patient:identifier", @@ -6315,8 +6426,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?patient:identifier=9000000100&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "patient:identifier", @@ -6371,8 +6486,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000025", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -6504,8 +6623,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000010", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -6731,8 +6854,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000010&_include=Consent:performer&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -6872,8 +6999,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000019", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7108,8 +7239,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000019&_include=Consent:performer&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7176,8 +7311,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000017&status=test", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7244,8 +7383,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000019&_include=test", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7313,8 +7456,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000999", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7377,8 +7524,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=90000009990", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7441,8 +7592,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=https://fhir.nhs.uk/Id/nhs-number|1234567890", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7505,8 +7660,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent", - "host": ["{{api_base_url}}"], - "path": ["Consent"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ] } }, "response": [] @@ -7563,8 +7722,12 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent?performer:identifier=9000000012", - "host": ["{{api_base_url}}"], - "path": ["Consent"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ], "query": [ { "key": "performer:identifier", @@ -7630,8 +7793,12 @@ }, "url": { "raw": "{{api_base_url}}/Consent", - "host": ["{{api_base_url}}"], - "path": ["Consent"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ] } }, "response": [] @@ -7685,8 +7852,12 @@ }, "url": { "raw": "{{api_base_url}}/Consent", - "host": ["{{api_base_url}}"], - "path": ["Consent"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ] } }, "response": [] @@ -7748,8 +7919,12 @@ }, "url": { "raw": "{{api_base_url}}/Consent", - "host": ["{{api_base_url}}"], - "path": ["Consent"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ] } }, "response": [] @@ -7811,8 +7986,12 @@ }, "url": { "raw": "{{api_base_url}}/Consent", - "host": ["{{api_base_url}}"], - "path": ["Consent"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent" + ] } }, "response": [] @@ -7944,8 +8123,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/74eed847-ca25-4e76-8cf2-f2c2d7842a7a", - "host": ["{{api_base_url}}"], - "path": ["Consent", "74eed847-ca25-4e76-8cf2-f2c2d7842a7a"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "74eed847-ca25-4e76-8cf2-f2c2d7842a7a" + ] } }, "response": [] @@ -8101,8 +8285,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/74eed847-ca25-4e76-8cf2-f2c2d7842a7a?_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent", "74eed847-ca25-4e76-8cf2-f2c2d7842a7a"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "74eed847-ca25-4e76-8cf2-f2c2d7842a7a" + ], "query": [ { "key": "_include", @@ -8246,8 +8435,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/74eed847-ca25-4e76-8cf2-f2c2d7842a7a?_include=Consent:performer", - "host": ["{{api_base_url}}"], - "path": ["Consent", "74eed847-ca25-4e76-8cf2-f2c2d7842a7a"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "74eed847-ca25-4e76-8cf2-f2c2d7842a7a" + ], "query": [ { "key": "_include", @@ -8472,8 +8666,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/74eed847-ca25-4e76-8cf2-f2c2d7842a7a?_include=Consent:performer&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent", "74eed847-ca25-4e76-8cf2-f2c2d7842a7a"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "74eed847-ca25-4e76-8cf2-f2c2d7842a7a" + ], "query": [ { "key": "_include", @@ -8609,8 +8808,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/39df03a2-1b14-4d19-b1dc-d5d8cbf96948", - "host": ["{{api_base_url}}"], - "path": ["Consent", "39df03a2-1b14-4d19-b1dc-d5d8cbf96948"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "39df03a2-1b14-4d19-b1dc-d5d8cbf96948" + ] } }, "response": [] @@ -8770,8 +8974,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/39df03a2-1b14-4d19-b1dc-d5d8cbf96948?_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent", "39df03a2-1b14-4d19-b1dc-d5d8cbf96948"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "39df03a2-1b14-4d19-b1dc-d5d8cbf96948" + ], "query": [ { "key": "_include", @@ -8914,8 +9123,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/39df03a2-1b14-4d19-b1dc-d5d8cbf96948?_include=Consent:performer", - "host": ["{{api_base_url}}"], - "path": ["Consent", "39df03a2-1b14-4d19-b1dc-d5d8cbf96948"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "39df03a2-1b14-4d19-b1dc-d5d8cbf96948" + ], "query": [ { "key": "_include", @@ -9150,8 +9364,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/39df03a2-1b14-4d19-b1dc-d5d8cbf96948?_include=Consent:performer&_include=Consent:patient", - "host": ["{{api_base_url}}"], - "path": ["Consent", "39df03a2-1b14-4d19-b1dc-d5d8cbf96948"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "39df03a2-1b14-4d19-b1dc-d5d8cbf96948" + ], "query": [ { "key": "_include", @@ -9214,8 +9433,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/invalid-identifier", - "host": ["{{api_base_url}}"], - "path": ["Consent", "invalid-identifier"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "invalid-identifier" + ] } }, "response": [] @@ -9269,8 +9493,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/39df03a2-1b14-4d19-b1dc-d5d8cbf96948?_include=Consent:invalid", - "host": ["{{api_base_url}}"], - "path": ["Consent", "39df03a2-1b14-4d19-b1dc-d5d8cbf96948"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "39df03a2-1b14-4d19-b1dc-d5d8cbf96948" + ], "query": [ { "key": "_include", @@ -9329,8 +9558,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/74eed847-ca25-4e76-8cf2-f2c2d7842a7a?_unknown=true", - "host": ["{{api_base_url}}"], - "path": ["Consent", "74eed847-ca25-4e76-8cf2-f2c2d7842a7a"], + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "74eed847-ca25-4e76-8cf2-f2c2d7842a7a" + ], "query": [ { "key": "_unknown", @@ -9389,8 +9623,13 @@ "header": [], "url": { "raw": "{{api_base_url}}/Consent/a0922245-1072-40c3-8f4e-a7490c10d365", - "host": ["{{api_base_url}}"], - "path": ["Consent", "a0922245-1072-40c3-8f4e-a7490c10d365"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "a0922245-1072-40c3-8f4e-a7490c10d365" + ] } }, "response": [] @@ -9446,8 +9685,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/74eed847-ca25-4e76-8cf2-f2c2d7842a7a", - "host": ["{{api_base_url}}"], - "path": ["Consent", "74eed847-ca25-4e76-8cf2-f2c2d7842a7a"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "74eed847-ca25-4e76-8cf2-f2c2d7842a7a" + ] }, "description": "Valid patch changing status to 'active'" }, @@ -9498,8 +9742,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/6b71ac92-baa3-4b76-b0f5-a601257e2722", - "host": ["{{api_base_url}}"], - "path": ["Consent", "6b71ac92-baa3-4b76-b0f5-a601257e2722"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "6b71ac92-baa3-4b76-b0f5-a601257e2722" + ] }, "description": "Valid patch modifying the role end date" }, @@ -9550,8 +9799,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/43003db8-ffcd-4bd6-ab2f-b49b9656f9e5", - "host": ["{{api_base_url}}"], - "path": ["Consent", "43003db8-ffcd-4bd6-ab2f-b49b9656f9e5"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "43003db8-ffcd-4bd6-ab2f-b49b9656f9e5" + ] }, "description": "Valid patch modifying the role end date" }, @@ -9613,8 +9867,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/78c35330-fa2f-4934-a5dd-fff847f38de5", - "host": ["{{api_base_url}}"], - "path": ["Consent", "78c35330-fa2f-4934-a5dd-fff847f38de5"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "78c35330-fa2f-4934-a5dd-fff847f38de5" + ] }, "description": "Patch with invalid status value" }, @@ -9676,8 +9935,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/01abb0c5-b1ac-499d-9655-9cd0b8d3588f", - "host": ["{{api_base_url}}"], - "path": ["Consent", "01abb0c5-b1ac-499d-9655-9cd0b8d3588f"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "01abb0c5-b1ac-499d-9655-9cd0b8d3588f" + ] }, "description": "Patch targeting non-existent element" }, @@ -9739,8 +10003,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/0000000", - "host": ["{{api_base_url}}"], - "path": ["Consent", "0000000"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "0000000" + ] }, "description": "Patch for non-existent Consent" }, @@ -9802,8 +10071,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/849ea584-2318-471b-a24c-cee1b5ad0137", - "host": ["{{api_base_url}}"], - "path": ["Consent", "849ea584-2318-471b-a24c-cee1b5ad0137"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "849ea584-2318-471b-a24c-cee1b5ad0137" + ] }, "description": "Malformed JSON patch document" }, @@ -9865,8 +10139,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/7b7f47b8-96e5-43eb-b733-283bf1449f2c", - "host": ["{{api_base_url}}"], - "path": ["Consent", "7b7f47b8-96e5-43eb-b733-283bf1449f2c"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "7b7f47b8-96e5-43eb-b733-283bf1449f2c" + ] } }, "response": [] @@ -9927,8 +10206,13 @@ }, "url": { "raw": "{{api_base_url}}/Consent/51fb4df5-815a-45cd-8427-04d6558336b7", - "host": ["{{api_base_url}}"], - "path": ["Consent", "51fb4df5-815a-45cd-8427-04d6558336b7"] + "host": [ + "{{api_base_url}}" + ], + "path": [ + "Consent", + "51fb4df5-815a-45cd-8427-04d6558336b7" + ] } }, "response": [] @@ -9943,7 +10227,9 @@ "script": { "type": "text/javascript", "packages": {}, - "exec": [""] + "exec": [ + "" + ] } }, { @@ -9965,4 +10251,4 @@ "value": "https://sandbox.api.service.nhs.uk/validated-relationships/FHIR/R4" } ] -} +} \ No newline at end of file diff --git a/sandbox/api/app.py b/sandbox/api/app.py index 699fe8ab..6cc87571 100644 --- a/sandbox/api/app.py +++ b/sandbox/api/app.py @@ -5,11 +5,13 @@ from .get_consent import get_consent_response from .get_consent_by_id import get_consent_by_id_response -from .get_questionnaire_response import get_questionnaire_response_response +from .get_questionnaire_response_by_path_id import get_questionnaire_response_by_path_id_response from .get_related_person import get_related_person_response from .patch_consent import patch_consent_response from .post_consent import post_consent_response from .post_questionnaire_response import post_questionnaire_response_response +from .utils import generate_response_from_example +from .constants import METHOD_NOT_ALLOWED app = Flask(__name__) basicConfig(level=INFO, format="%(asctime)s - %(message)s") @@ -40,13 +42,24 @@ def get_related_persons() -> Union[dict, tuple]: @app.route(f"/{COMMON_PATH}/QuestionnaireResponse", methods=["GET"]) +@app.route(f"/{COMMON_PATH}/QuestionnaireResponse/", methods=["GET"]) def get_questionnaire_response() -> Union[dict, tuple]: """Sandbox API for GET /QuestionnaireResponse Returns: Union[dict, tuple]: Response for GET /QuestionnaireResponse """ - return get_questionnaire_response_response() + return generate_response_from_example(METHOD_NOT_ALLOWED, 405) + + +@app.route(f"/{COMMON_PATH}/QuestionnaireResponse/", methods=["GET"]) +def get_questionnaire_response_id(identifier: str) -> Union[dict, tuple]: + """Sandbox API for GET /QuestionnaireResponse + + Returns: + Union[dict, tuple]: Response for GET /QuestionnaireResponse + """ + return get_questionnaire_response_by_path_id_response(identifier) @app.route(f"/{COMMON_PATH}/QuestionnaireResponse", methods=["POST"]) diff --git a/sandbox/api/constants.py b/sandbox/api/constants.py index 0f6bdcda..5d044316 100644 --- a/sandbox/api/constants.py +++ b/sandbox/api/constants.py @@ -14,6 +14,7 @@ INVALIDATED_RESOURCE = "./api/examples/errors/invalidated-resource.yaml" MISSING_IDENTIFIER = "./api/examples/errors/missing-identifier.yaml" INVALID_IDENTIFIER = "./api/examples/errors/invalid-identifier.yaml" +METHOD_NOT_ALLOWED = "./api/examples/errors/method-not-allowed.yaml" # GET Consent examples GET_CONSENT__DIRECTORY = "./api/examples/GET_Consent/" diff --git a/sandbox/api/get_questionnaire_response.py b/sandbox/api/get_questionnaire_response_by_path_id.py similarity index 79% rename from sandbox/api/get_questionnaire_response.py rename to sandbox/api/get_questionnaire_response_by_path_id.py index 795340d4..56c06618 100644 --- a/sandbox/api/get_questionnaire_response.py +++ b/sandbox/api/get_questionnaire_response_by_path_id.py @@ -1,14 +1,12 @@ from logging import INFO, basicConfig, getLogger from typing import Union -from flask import request - from .constants import ( GET_QUESTIONNAIRE_RESPONSE__INVALID, - GET_QUESTIONNAIRE_RESPONSE__MISSING, GET_QUESTIONNAIRE_RESPONSE__NOT_FOUND, GET_QUESTIONNAIRE_RESPONSE__SUCCESS, INTERNAL_SERVER_ERROR_EXAMPLE, + METHOD_NOT_ALLOWED, ) from .utils import generate_response_from_example @@ -16,20 +14,19 @@ logger = getLogger(__name__) -def get_questionnaire_response_response() -> Union[dict, tuple]: - """Sandbox API for GET /QuestionnaireResponse +def get_questionnaire_response_by_path_id_response(access_request_id: str) -> Union[dict, tuple]: + """Sandbox API for GET /QuestionnaireResponse/{id} Returns: - Union[dict, tuple]: Response for GET /QuestionnaireResponse + Union[dict, tuple]: Response for GET /QuestionnaireResponse/{id} """ try: - access_request_id = request.args.get("ID") if access_request_id == "156e1560-e532-4e2a-85ad-5aeff03dc43e": return generate_response_from_example(GET_QUESTIONNAIRE_RESPONSE__SUCCESS, 200) elif access_request_id == "INVALID": return generate_response_from_example(GET_QUESTIONNAIRE_RESPONSE__INVALID, 400) elif access_request_id == "" or access_request_id is None: - return generate_response_from_example(GET_QUESTIONNAIRE_RESPONSE__MISSING, 400) + return generate_response_from_example(METHOD_NOT_ALLOWED, 405) elif access_request_id == "60d09b82-f4bb-41f9-b41e-767999b4ac9b": return generate_response_from_example(GET_QUESTIONNAIRE_RESPONSE__NOT_FOUND, 404) else: diff --git a/sandbox/api/tests/test_get_questionnaire_response.py b/sandbox/api/tests/test_get_questionnaire_response_by_path_id.py similarity index 50% rename from sandbox/api/tests/test_get_questionnaire_response.py rename to sandbox/api/tests/test_get_questionnaire_response_by_path_id.py index 72f9ab05..605e7abf 100644 --- a/sandbox/api/tests/test_get_questionnaire_response.py +++ b/sandbox/api/tests/test_get_questionnaire_response_by_path_id.py @@ -7,52 +7,68 @@ @pytest.mark.parametrize( - ("request_args", "response_file_name", "status_code"), + ("path", "response_file_name", "status_code"), [ ( - "ID=156e1560-e532-4e2a-85ad-5aeff03dc43e", + "/156e1560-e532-4e2a-85ad-5aeff03dc43e", "./api/examples/GET_QuestionnaireResponse/success.yaml", 200, ), ( - "ID=INVALID", + "/INVALID", "./api/examples/GET_QuestionnaireResponse/errors/invalid_access_request_id.yaml", 400, ), ( - "ID=", - "./api/examples/GET_QuestionnaireResponse/errors/missing_access_request_id.yaml", - 400, - ), - ( - "ID=60d09b82-f4bb-41f9-b41e-767999b4ac9b", + "/60d09b82-f4bb-41f9-b41e-767999b4ac9b", "./api/examples/GET_QuestionnaireResponse/errors/questionnaire_response_not_found.yaml", 404, ), ( - "ID=INVALID_CODE", + "/INVALID_CODE", "./api/examples/errors/internal-server-error.yaml", 500, ), ], ) -@patch("sandbox.api.get_questionnaire_response.generate_response_from_example") -def test_get_questionnaire_response_returns_expected_responses__mocked_utils( +@patch("sandbox.api.get_questionnaire_response_by_path_id.generate_response_from_example") +def test_get_questionnaire_response_id_returns_expected_responses__mocked_utils( mock_generate_response_from_example: MagicMock, - request_args: str, + path: str, response_file_name: str, status_code: int, client: object, ) -> None: - """Test GET Consent endpoint.""" + """Test GET /QuestionnaireResponse/{id} endpoint.""" mock_generate_response_from_example.return_value = mocked_response = Response( dumps({"data": "mocked"}), status=status_code, content_type="application/json", ) # Act - response = client.get(f"{GET_QUESTIONNAIRE_RESPONSE_API_ENDPOINT}?{request_args}") + response = client.get(f"{GET_QUESTIONNAIRE_RESPONSE_API_ENDPOINT}{path}") # Assert mock_generate_response_from_example.assert_called_once_with(response_file_name, status_code) assert response.status_code == status_code assert response.json == loads(mocked_response.get_data(as_text=True)) + + +@pytest.mark.parametrize("path", ["/", ""]) +@patch("sandbox.api.app.generate_response_from_example") +def test_get_questionnaire_response_without_path_params_return_405_errors( + mock_generate_response_from_example: MagicMock, + path: str, + client: object, +) -> None: + """Test the GET /QuestionnaireResponse endpoint with no path params.""" + mock_generate_response_from_example.return_value = mocked_response = Response( + dumps({"data": "mocked"}), + status=405, + content_type="application/json", + ) + # Act + response = client.get(f"{GET_QUESTIONNAIRE_RESPONSE_API_ENDPOINT}{path}") + # Assert + mock_generate_response_from_example.assert_called_once_with("./api/examples/errors/method-not-allowed.yaml", 405) + assert response.status_code == 405 + assert response.json == loads(mocked_response.get_data(as_text=True)) diff --git a/sandbox/api/tests/test_patch_consent.py b/sandbox/api/tests/test_patch_consent.py index c8c086e0..2db8a5c4 100644 --- a/sandbox/api/tests/test_patch_consent.py +++ b/sandbox/api/tests/test_patch_consent.py @@ -23,11 +23,27 @@ ("74eed847-ca25-4e76-8cf2-f2c2d7842a7a", PATCH_CONSENT__SUCCESS, 200), ("6b71ac92-baa3-4b76-b0f5-a601257e2722", PATCH_CONSENT__SUCCESS, 200), ("43003db8-ffcd-4bd6-ab2f-b49b9656f9e5", PATCH_CONSENT__SUCCESS, 200), - ("849ea584-2318-471b-a24c-cee1b5ad0137", PATCH_CONSENT__INVALID_PATCH_FORMAT, 400), + ( + "849ea584-2318-471b-a24c-cee1b5ad0137", + PATCH_CONSENT__INVALID_PATCH_FORMAT, + 400, + ), ("01abb0c5-b1ac-499d-9655-9cd0b8d3588f", PATCH_CONSENT__INVALID_PATH, 400), - ("78c35330-fa2f-4934-a5dd-fff847f38de5", PATCH_CONSENT__INVALID_STATUS_CODE, 422), - ("51fb4df5-815a-45cd-8427-04d6558336b7", PATCH_CONSENT__INVALID_STATUS_REASON, 422), - ("7b7f47b8-96e5-43eb-b733-283bf1449f2c", PATCH_CONSENT__INVALID_STATE_TRANSITION, 422), + ( + "78c35330-fa2f-4934-a5dd-fff847f38de5", + PATCH_CONSENT__INVALID_STATUS_CODE, + 422, + ), + ( + "51fb4df5-815a-45cd-8427-04d6558336b7", + PATCH_CONSENT__INVALID_STATUS_REASON, + 422, + ), + ( + "7b7f47b8-96e5-43eb-b733-283bf1449f2c", + PATCH_CONSENT__INVALID_STATE_TRANSITION, + 422, + ), ("xxxxxxxx", PATCH_CONSENT__RESOURCE_NOT_FOUND, 404), ("12345678", PATCH_CONSENT__RESOURCE_NOT_FOUND, 404), ], diff --git a/sandbox/api/tests/test_post_questionnaire_response.py b/sandbox/api/tests/test_post_questionnaire_response.py index 7851f8b4..decf88c0 100644 --- a/sandbox/api/tests/test_post_questionnaire_response.py +++ b/sandbox/api/tests/test_post_questionnaire_response.py @@ -59,7 +59,10 @@ def test_post_questionnaire_response( status=status_code, content_type="application/json", ) - json = {"resourceType": "QuestionnaireResponse", "source": {"identifier": {"value": nhs_num}}} + json = { + "resourceType": "QuestionnaireResponse", + "source": {"identifier": {"value": nhs_num}}, + } # Act response = client.post(QUESTIONNAIRE_RESPONSE_API_ENDPOINT, json=json) # Assert diff --git a/specification/examples/responses/errors/method-not-allowed.yaml b/specification/examples/responses/errors/method-not-allowed.yaml new file mode 100644 index 00000000..37c27618 --- /dev/null +++ b/specification/examples/responses/errors/method-not-allowed.yaml @@ -0,0 +1,15 @@ +MethodNotAllowedError: + summary: Method is not allowed + description: 405 error response bundle as HTTP method is not allowed + value: + resourceType: "OperationOutcome" + issue: + - code: "not-supported" + details: + coding: + - system: "https://fhir.nhs.uk/R4/CodeSystem/ValidatedRelationships-ErrorOrWarningCode" + version: "1" + code: "METHOD_NOT_ALLOWED" + display: "The method is not allowed." + diagnostics: "The method is not allowed for the requested resource." + severity: "error" diff --git a/specification/validated-relationships-service-api.yaml b/specification/validated-relationships-service-api.yaml index b430f911..3c4c25af 100644 --- a/specification/validated-relationships-service-api.yaml +++ b/specification/validated-relationships-service-api.yaml @@ -3,7 +3,7 @@ openapi: "3.0.0" info: title: "Validated Relationships Service API" - version: "1.13.0" + version: "1.14.0" description: | ## Overview Use this API to access the Validated Relationships Service - the national electronic database of relationships @@ -141,7 +141,7 @@ info: * only covers a limited set of scenarios * is open access, so does not allow you to test authorisation - [Run In Postman](https://app.getpostman.com/run-collection/44536620-c011ca09-3246-4d9c-870e-33ebd0629114?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D44536620-c011ca09-3246-4d9c-870e-33ebd0629114%26entityType%3Dcollection%26workspaceId%3D81756490-ef07-4f09-9861-3c601a39729e) + [Run In Postman](https://app.getpostman.com/run-collection/18067099-5c759d0a-d924-44ab-8668-3587dcaf27e1?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D18067099-5c759d0a-d924-44ab-8668-3587dcaf27e1%26entityType%3Dcollection%26workspaceId%3D1ee72d72-3355-4213-a165-a79aa2ab1de8) ### Integration testing @@ -300,6 +300,8 @@ paths: examples: internalServerError: $ref: "./examples/responses/errors/internal-server-error.yaml#/InternalServerError" + + /QuestionnaireResponse/{id}: get: summary: Get a proxy access request description: | @@ -308,7 +310,7 @@ paths: QuestionnaireResponse document that was previously submitted. ## Request Requirements - A valid access request ID must be provided as a query parameter. This access request ID is returned + A valid access request ID must be provided as a path parameter. This access request ID is returned when a QuestionnaireResponse is initially submitted via the POST endpoint. ## Access modes @@ -319,25 +321,19 @@ paths: ## Sandbox test scenarios - | Scenario | Request | Response | - | -------------------------------- | -----------------------------------------| ------------------------------------------------------------- | - | Valid access request ID | `ID=156e1560-e532-4e2a-85ad-5aeff03dc43e`| HTTP Status 200 with QuestionnaireResponse | - | Invalid access request ID | `ID=INVALID` | HTTP Status 400 with INVALID_IDENTIFIER_VALUE message | - | Missing access request ID | No ID parameter | HTTP Status 400 with BAD_REQUEST message | - | Non-existent access request ID | `ID=60d09b82-f4bb-41f9-b41e-767999b4ac9b`| HTTP Status 404 with QUESTIONNAIRE_RESPONSE_NOT_FOUND message | + | Scenario | Request | Response | + | -------------------------------- | ------------------------------------------------ | ------------------------------------------------------------- | + | Valid access request ID | ID value: `156e1560-e532-4e2a-85ad-5aeff03dc43e` | HTTP Status 200 with QuestionnaireResponse | + | Invalid access request ID | ID value: `INVALID` | HTTP Status 400 with INVALID_IDENTIFIER_VALUE message | + | Missing access request ID | No ID path parameter | HTTP Status 405 with METHOD_NOT_ALLOWED message | + | Non-existent access request ID | ID value: `60d09b82-f4bb-41f9-b41e-767999b4ac9b` | HTTP Status 404 with QUESTIONNAIRE_RESPONSE_NOT_FOUND message | operationId: get-questionnaire-response parameters: - $ref: "#/components/parameters/BearerAuthorization" - $ref: "#/components/parameters/RequestID" - $ref: "#/components/parameters/CorrelationID" - - name: ID - in: query - description: The unique access request ID of the QuestionnaireResponse to retrieve - required: true - schema: - type: string - example: "156e1560-e532-4e2a-85ad-5aeff03dc43e" + - $ref: "#/components/parameters/AccessRequestID" responses: "200": description: QuestionnaireResponse successfully retrieved. @@ -374,7 +370,7 @@ paths: invalidAccessRequestID: $ref: "./examples/responses/GET_QuestionnaireResponse/errors/invalid_access_request_id.yaml#/InvalidAccessRequestID" missingAccessRequestID: - $ref: "./examples/responses/GET_QuestionnaireResponse/errors/missing_access_request_id.yaml#/MissingAccessRequestID" + $ref: "./examples/responses/errors/method-not-allowed.yaml#/MethodNotAllowedError" questionnaireResponseNotFound: $ref: "./examples/responses/GET_QuestionnaireResponse/errors/questionnaire_response_not_found.yaml#/QuestionnaireResponseNotFound" "5XX": @@ -2788,3 +2784,14 @@ components: format: uuid 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: 74eed847-ca25-4e76-8cf2-f2c2d7842a7a + + AccessRequestID: + in: path + name: id + required: true + description: The unique access request ID of the QuestionnaireResponse to retrieve + schema: + type: string + format: uuid + 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: "156e1560-e532-4e2a-85ad-5aeff03dc43e"