diff --git a/package-lock.json b/package-lock.json index d4e451f03..77d38cf20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1960,18 +1960,6 @@ "node": ">= 0.6" } }, - "node_modules/core-js": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", - "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", - "dev": true, - "hasInstallScript": true, - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-js-compat": { "version": "3.49.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", diff --git a/postman/NhsNotify.Integration.postman_collection.json b/postman/NhsNotify.Integration.postman_collection.json index 282b3c2d0..3b885ce83 100644 --- a/postman/NhsNotify.Integration.postman_collection.json +++ b/postman/NhsNotify.Integration.postman_collection.json @@ -1,441 +1,406 @@ { - "collection" : { - "event" : [ - { - "listen" : "prerequest", - "script" : { - "exec" : [ - "var uuid = require('uuid');", - "", - "var privateKey = pm.environment.get('private_key') || '';", - "var api_key_value = pm.environment.get('api_key') || '';", - "", - "if (!privateKey) {", - " throw new Error(\"Variable private_key must be set with your private key for signed JWT authentication.\");", - "}", - "", - "if (!api_key_value) {", - " throw new Error(\"Variable api_key must be set with your integration testing application API key.\");", - "}", - "", - "var auth_url = 'https://int.api.service.nhs.uk/oauth2/token';", - "var navigator = {};", - "var window = {};", - "const interval = setTimeout(() => {}, 2147483647);", - "", - "return new Promise((resolve, reject) => { ", - " if (pm.globals.has('jsrsasign-js') && pm.globals.get('jsrsasign-js') !== \"\") {", - " return resolve();", - " }", - "", - " pm.sendRequest(", - " {", - " url: 'https://kjur.github.io/jsrsasign/jsrsasign-all-min.js',", - " method: 'GET'", - " }, function (err, res) {", - " if (err) {", - " return reject(err);", - " }", - "", - " pm.globals.set('jsrsasign-js', res.text()); ", - " return resolve();", - " }", - " );", - "}).then(() => { ", - " eval(pm.globals.get(\"jsrsasign-js\")); ", - "", - " // Set headers for JWT", - " var header = {", - " 'typ': 'JWT',", - " 'alg': 'RS512',", - " 'kid': 'local'", - " };", - "", - " // Prepare timestamp in seconds", - " var currentTimestamp = Math.floor(Date.now() / 1000)", - " var uuid = require('uuid');", - " var jti_value = uuid.v4();", - " var data = {", - " 'sub': api_key_value,", - " 'iss': api_key_value,", - " 'jti': jti_value,", - " 'aud': auth_url,", - " 'exp': currentTimestamp + 180, // expiry time is 180 seconds from time of creation", - " } ", - "", - " var sJWT = KJUR.jws.JWS.sign(header.alg, JSON.stringify(header), JSON.stringify(data), privateKey); ", - " return new Promise((resolve, reject) => { ", - " pm.sendRequest({", - " url: auth_url,", - " method: \"POST\",", - " header: {", - " \"Content-Type\": \"application/x-www-form-urlencoded\"", - " },", - " body: {", - " mode: \"urlencoded\",", - " urlencoded: [", - " {", - " key: \"grant_type\",", - " value: \"client_credentials\"", - " },", - " {", - " key: \"client_assertion_type\",", - " value: \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\",", - " },", - " {", - " key: \"client_assertion\",", - " value: sJWT", - " }", - " ]", - " }", - " }, function (err, res) { ", - " if (err) {", - " return reject(err);", - " }", - "", - " //assign the authorization header value", - " pm.environment.set('authorization_header_value', `Bearer ${res.json().access_token}`);", - "", - " //assign the message batch reference", - " pm.environment.set(\"message_batch_reference\", uuid.v4());", - "", - " //assign the message reference", - " pm.environment.set(\"message_reference\", uuid.v4());", - "", - " //generate a correlation identifier", - " pm.environment.set(\"correlation_id\", uuid.v4());", - "", - " return resolve();", - " }); ", - " });", - "}).then(() => { ", - " clearTimeout(interval);", - "}).catch((err) => { ", - " console.error(err); ", - " clearTimeout(interval); ", + "info": { + "_postman_id": "13801099-9499-4e14-92b0-f706358a7c3f", + "name": "NHS Notify - Integration", + "description": "This collection enables you to make requests against our integration test environment.\n\nThis environment requires you to be authenticated and authorised to make these requests, plus you must have completed (or be in the progress of) onboarding onto the NHS Notify Service.\n\nFor more information on the NHS Notify API please refer to [the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify).\n\n## Authentication\n\nThis collection will carry out the [signed JWT authentication flow](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication) for you automatically.\n\nYou must provide your API key and private key within the environment variables.\n\nIf you have not yet created an API client with an API key and private key, then please [refer to the documentation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication). Instructions are given here on how to create an application and how to generate a key pair for generating bearer tokens.\n\nMake sure to create your API application in the `Integration Testing` environment, and to request access to the `NHS Notify (Integration Testing)` API. Your API application will be granted access to this API automatically.\n\nOnce you have your API key and your private key, put these into the `api_key` and `private_key` variables within the `Integration` environment.\n\nRequests will now have a bearer token attached to them automatically, authenticating your requests.\n\nIf you have not yet started the onboarding process with the NHS Notify service then your requests, although authenticated, will return a `403 - Forbidden` response.\n\n**Ensure that your API key and private key are kept secret at all times!**\n\n**If you publish/share your API key or private key you must revoke them via the** [NHS onboarding portal](https://onboarding.prod.api.platform.nhs.uk/) **immediately.**\n\nLeaking these credentials will allow other people to generate tokens to call the API on your behalf.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "54991697", + "_collection_link": "https://go.postman.co/collection/54991697-13801099-9499-4e14-92b0-f706358a7c3f?source=collection_link" + }, + "item": [ + { + "name": "Send Messages", + "item": [ + { + "name": "201 - Message Batch Created", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Correlation identifier is returned\", () => {\r", + " pm.response.to.have.header(\"x-correlation-id\");\r", + " pm.response.to.be.header(\"x-correlation-id\", pm.environment.get(\"correlation_id\"));\r", + "});\r", + "\r", + "pm.test(\"Content-negotiation was successful\", () => {\r", + " pm.response.to.have.header(\"content-type\");\r", + " pm.response.to.be.header(\"content-type\", pm.environment.get(\"mime_type\"));\r", + "});\r", + "\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", "});" - ], - "id" : "ff9efab8-042e-4df9-8c1d-4c7246878785", - "type" : "text/javascript" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } } - }, - { - "listen" : "test", - "script" : { - "exec" : [ + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "{{mime_type}}", + "type": "default" + }, + { + "key": "Accept", + "value": "{{mime_type}}", + "type": "default" + }, + { + "key": "Authorization", + "value": "{{authorization_header_value}}", + "type": "default" + }, + { + "key": "X-Correlation-Id", + "value": "{{correlation_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"type\": \"MessageBatch\",\r\n \"attributes\": {\r\n \"routingPlanId\": \"{{routing_plan_id}}\",\r\n \"messageBatchReference\": \"{{message_batch_reference}}\",\r\n \"messages\": [\r\n {\r\n \"messageReference\": \"703b8008-545d-4a04-bb90-1f2946ce1575\",\r\n \"recipient\": {\r\n \"nhsNumber\": \"9990548609\",\r\n \"dateOfBirth\": \"1932-01-06\"\r\n },\r\n \"originator\": {\r\n \"odsCode\": \"X26\"\r\n },\r\n \"personalisation\": {\r\n \"custom\": \"value\"\r\n },\r\n \"answerOptions\": {\r\n \"NHSAPP\": [\r\n {\r\n \"code\": \"Yes\"\r\n },\r\n {\r\n \"code\": \"No\"\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{base_url}}/v1/message-batches", + "host": [ + "{{base_url}}" + ], + "path": [ + "v1", + "message-batches" + ] + }, + "description": "Sends a request to create a message batch.\n\nIt is possible to toggle the mime type used for sending and receiving data by changing the `mime_type` environment variable. Valid values for this can be found in [the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify#post-/v1/message-batches).\n\nA random `X-Correlation-Id` header and `messageBatchReference` body value will be generated for each request in the pre-request script." + }, + "response": [] + }, + { + "name": "201 - Send Single Message", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ "" - ], - "id" : "0fbc974b-ce93-4a5f-b0ff-2fa68ed08235", - "type" : "text/javascript" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Correlation identifier is returned\", () => {\r", + " pm.response.to.have.header(\"x-correlation-id\");\r", + " pm.response.to.be.header(\"x-correlation-id\", pm.environment.get(\"correlation_id\"));\r", + "});\r", + "\r", + "pm.test(\"Content-negotiation was successful\", () => {\r", + " pm.response.to.have.header(\"content-type\");\r", + " pm.response.to.be.header(\"content-type\", pm.environment.get(\"mime_type\"));\r", + "});\r", + "\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } } - } - ], - "info" : { - "_postman_id" : "9c132bcd-f76f-448f-a58c-ba38c5d64d4f", - "createdAt" : "2025-01-28T17:00:28.000Z", - "description" : "This collection enables you to make requests against our integration test environment.\n\nThis environment requires you to be authenticated and authorised to make these requests, plus you must have completed (or be in the progress of) onboarding onto the NHS Notify Service.\n\nFor more information on the NHS Notify API please refer to [the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify).\n\n## Authentication\n\nThis collection will carry out the [signed JWT authentication flow](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication) for you automatically.\n\nYou must provide your API key and private key within the environment variables.\n\nIf you have not yet created an API client with an API key and private key, then please [refer to the documentation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/application-restricted-restful-apis-signed-jwt-authentication). Instructions are given here on how to create an application and how to generate a key pair for generating bearer tokens.\n\nMake sure to create your API application in the `Integration Testing` environment, and to request access to the `NHS Notify (Integration Testing)` API. Your API application will be granted access to this API automatically.\n\nOnce you have your API key and your private key, put these into the `api_key` and `private_key` variables within the `Integration` environment.\n\nRequests will now have a bearer token attached to them automatically, authenticating your requests.\n\nIf you have not yet started the onboarding process with the NHS Notify service then your requests, although authenticated, will return a `403 - Forbidden` response.\n\n**Ensure that your API key and private key are kept secret at all times!**\n\n**If you publish/share your API key or private key you must revoke them via the** [NHS onboarding portal](https://onboarding.prod.api.platform.nhs.uk/) **immediately.**\n\nLeaking these credentials will allow other people to generate tokens to call the API on your behalf.", - "lastUpdatedBy" : "41628342", - "name" : "NHS Notify - Integration", - "schema" : "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "uid" : "41628342-9c132bcd-f76f-448f-a58c-ba38c5d64d4f", - "updatedAt" : "2025-01-28T17:00:29.000Z" - }, - "item" : [ - { - "description" : "These example calls show how to use the send messages endpoint. This endpoint allows you to create a `MessageBatch`.\n\nFor more information on this endpoint [refer to the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify#post-/v1/message-batches).", - "id" : "3a741c32-5b4c-4306-82fd-9e7b5efa19a3", - "item" : [ - { - "event" : [ - { - "listen" : "prerequest", - "script" : { - "exec" : [ - "" - ], - "id" : "8e1504c8-e0e3-4ee7-8a60-57764decbafb", - "packages" : {}, - "type" : "text/javascript" - } - }, - { - "listen" : "test", - "script" : { - "exec" : [ - "pm.test(\"Correlation identifier is returned\", () => {\r", - " pm.response.to.have.header(\"x-correlation-id\");\r", - " pm.response.to.be.header(\"x-correlation-id\", pm.environment.get(\"correlation_id\"));\r", - "});\r", - "\r", - "pm.test(\"Content-negotiation was successful\", () => {\r", - " pm.response.to.have.header(\"content-type\");\r", - " pm.response.to.be.header(\"content-type\", pm.environment.get(\"mime_type\"));\r", - "});\r", - "\r", - "pm.test(\"Status code is 201\", () => {\r", - " pm.response.to.have.status(201);\r", - "});" - ], - "id" : "b8b43e42-a61c-4305-8c36-da4764e98073", - "packages" : {}, - "type" : "text/javascript" - } - } - ], - "id" : "9cbeab24-3374-47e5-89be-40916eb34d4f", - "name" : "201 - Message Batch Created", - "protocolProfileBehavior" : { - "disableBodyPruning" : true - }, - "request" : { - "body" : { - "mode" : "raw", - "options" : { - "raw" : { - "language" : "json" - } - }, - "raw" : "{\r\n \"data\": {\r\n \"type\": \"MessageBatch\",\r\n \"attributes\": {\r\n \"routingPlanId\": \"{{routing_plan_id}}\",\r\n \"messageBatchReference\": \"{{message_batch_reference}}\",\r\n \"messages\": [\r\n {\r\n \"messageReference\": \"703b8008-545d-4a04-bb90-1f2946ce1575\",\r\n \"recipient\": {\r\n \"nhsNumber\": \"9990548609\",\r\n \"dateOfBirth\": \"1932-01-06\"\r\n },\r\n \"originator\": {\r\n \"odsCode\": \"X26\"\r\n },\r\n \"personalisation\": {\r\n \"custom\" : \"value\"\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n}" - }, - "description" : "Sends a request to create a message batch.\n\nIt is possible to toggle the mime type used for sending and receiving data by changing the `mime_type` environment variable. Valid values for this can be found in [the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify#post-/v1/message-batches).\n\nA random `X-Correlation-Id` header and `messageBatchReference` body value will be generated for each request in the pre-request script.", - "header" : [ - { - "key" : "Content-Type", - "type" : "default", - "value" : "{{mime_type}}" - }, - { - "key" : "Accept", - "type" : "default", - "value" : "{{mime_type}}" - }, - { - "key" : "Authorization", - "type" : "default", - "value" : "{{authorization_header_value}}" - }, - { - "key" : "X-Correlation-Id", - "type" : "text", - "value" : "{{correlation_id}}" - } - ], - "method" : "POST", - "url" : { - "host" : [ - "{{base_url}}" - ], - "path" : [ - "v1", - "message-batches" - ], - "raw" : "{{base_url}}/v1/message-batches" - } - }, - "response" : [], - "uid" : "41628342-9cbeab24-3374-47e5-89be-40916eb34d4f" - }, - { - "event" : [ - { - "listen" : "prerequest", - "script" : { - "exec" : [ - "" - ], - "id" : "ce480a3c-dee9-4812-bec3-6b8144c0dd53", - "packages" : {}, - "type" : "text/javascript" - } - }, - { - "listen" : "test", - "script" : { - "exec" : [ - "pm.test(\"Correlation identifier is returned\", () => {\r", - " pm.response.to.have.header(\"x-correlation-id\");\r", - " pm.response.to.be.header(\"x-correlation-id\", pm.environment.get(\"correlation_id\"));\r", - "});\r", - "\r", - "pm.test(\"Content-negotiation was successful\", () => {\r", - " pm.response.to.have.header(\"content-type\");\r", - " pm.response.to.be.header(\"content-type\", pm.environment.get(\"mime_type\"));\r", - "});\r", - "\r", - "pm.test(\"Status code is 201\", () => {\r", - " pm.response.to.have.status(201);\r", - "});" - ], - "id" : "ed7bc9d8-9b2c-43d7-a9f0-a6598ff51032", - "packages" : {}, - "type" : "text/javascript" - } - } - ], - "id" : "90a4ab92-8959-4579-bc1f-fcab1673bcf9", - "name" : "201 - Send Single Message", - "protocolProfileBehavior" : { - "disableBodyPruning" : true - }, - "request" : { - "body" : { - "mode" : "raw", - "options" : { - "raw" : { - "language" : "json" - } - }, - "raw" : "{\r\n \"data\": {\r\n \"type\": \"Message\",\r\n \"attributes\": {\r\n \"routingPlanId\": \"{{routing_plan_id}}\",\r\n \"messageReference\": \"{{message_reference}}\",\r\n \"recipient\": {\r\n \"nhsNumber\": \"9990548609\",\r\n \"dateOfBirth\": \"1932-01-06\"\r\n },\r\n \"originator\": {\r\n \"odsCode\": \"X26\"\r\n },\r\n \"personalisation\": {\r\n \"custom\": \"value\"\r\n }\r\n }\r\n }\r\n}" - }, - "description" : "Sends a request to send a single message.\n\nIt is possible to toggle the mime type used for sending and receiving data by changing the `mime_type` environment variable. Valid values for this can be found in [the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify#post-/v1/message-batches).\n\nA random `X-Correlation-Id` header and `messageReference` body value will be generated for each request in the pre-request script.", - "header" : [ - { - "key" : "Content-Type", - "value" : "{{mime_type}}" - }, - { - "key" : "Accept", - "value" : "{{mime_type}}" - }, - { - "key" : "Authorization", - "value" : "{{authorization_header_value}}" - }, - { - "key" : "X-Correlation-Id", - "value" : "{{correlation_id}}" - } - ], - "method" : "POST", - "url" : { - "host" : [ - "{{base_url}}" - ], - "path" : [ - "v1", - "messages" - ], - "raw" : "{{base_url}}/v1/messages" - } - }, - "response" : [], - "uid" : "41628342-90a4ab92-8959-4579-bc1f-fcab1673bcf9" - } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "{{mime_type}}" + }, + { + "key": "Accept", + "value": "{{mime_type}}" + }, + { + "key": "Authorization", + "value": "{{authorization_header_value}}" + }, + { + "key": "X-Correlation-Id", + "value": "{{correlation_id}}" + } ], - "name" : "Send Messages", - "uid" : "41628342-3a741c32-5b4c-4306-82fd-9e7b5efa19a3" - }, - { - "id" : "04acb90e-bd17-4a69-b198-ac64acc561d6", - "item" : [ - { - "id" : "784918ee-ea64-4008-a6e1-c2ae3494f1aa", - "name" : "200 - Get Message", - "protocolProfileBehavior" : { - "disableBodyPruning" : true - }, - "request" : { - "description" : "This request successfully retrieves a message status.", - "header" : [ - { - "key" : "Authorization", - "value" : "{{authorization_header_value}}" - } - ], - "method" : "GET", - "url" : { - "host" : [ - "{{base_url}}" - ], - "path" : [ - "v1", - "messages", - "2aUxQER3co3kXdvTKrhbSFHRRxR" - ], - "raw" : "{{base_url}}/v1/messages/2aUxQER3co3kXdvTKrhbSFHRRxR" - } - }, - "response" : [], - "uid" : "41628342-784918ee-ea64-4008-a6e1-c2ae3494f1aa" - } + "body": { + "mode": "raw", + "raw": "{\r\n \"data\": {\r\n \"type\": \"Message\",\r\n \"attributes\": {\r\n \"routingPlanId\": \"{{routing_plan_id}}\",\r\n \"messageReference\": \"{{message_reference}}\",\r\n \"recipient\": {\r\n \"nhsNumber\": \"9990548609\",\r\n \"dateOfBirth\": \"1932-01-06\"\r\n },\r\n \"originator\": {\r\n \"odsCode\": \"X26\"\r\n },\r\n \"personalisation\": {\r\n \"custom\": \"value\"\r\n },\r\n \"answerOptions\": {\r\n \"NHSAPP\": [\r\n {\r\n \"code\": \"Yes\"\r\n },\r\n {\r\n \"code\": \"No\"\r\n }\r\n ]\r\n }\r\n }\r\n }\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{base_url}}/v1/messages", + "host": [ + "{{base_url}}" + ], + "path": [ + "v1", + "messages" + ] + }, + "description": "Sends a request to send a single message.\n\nIt is possible to toggle the mime type used for sending and receiving data by changing the `mime_type` environment variable. Valid values for this can be found in [the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify#post-/v1/message-batches).\n\nA random `X-Correlation-Id` header and `messageReference` body value will be generated for each request in the pre-request script." + }, + "response": [] + } + ], + "description": "These example calls show how to use the send messages endpoint. This endpoint allows you to create a `MessageBatch`.\n\nFor more information on this endpoint [refer to the documentation](https://digital.nhs.uk/developer/api-catalogue/nhs-notify#post-/v1/message-batches)." + }, + { + "name": "Get Message", + "item": [ + { + "name": "200 - Get Message", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "{{authorization_header_value}}" + } ], - "name" : "Get Message", - "uid" : "41628342-04acb90e-bd17-4a69-b198-ac64acc561d6" - }, - { - "id" : "ed012ff6-abd8-49a4-a71e-eb9e160dea7e", - "item" : [ - { - "event" : [ - { - "listen" : "test", - "script" : { - "exec" : [ - "pm.test(\"Status code is 200\", () => {", - " pm.response.to.have.status(200);", - "});" - ], - "id" : "cd9304fc-d712-4e40-8e59-8564be7c4bed", - "packages" : {}, - "type" : "text/javascript" - } - } - ], - "id" : "f3881d9b-5f4a-4132-88b2-a541494373f3", - "name" : "200 - NHS App Account - Multipage", - "protocolProfileBehavior" : { - "disableBodyPruning" : true - }, - "request" : { - "description" : "The request successfully retrieves NHS numbers registered for notifications in the NHS App against an ODS code, adding the \"page\" parameter allows you to access the full paginated response", - "header" : [ - { - "key" : "Authorization", - "value" : "{{authorization_header_value}}" - } - ], - "method" : "GET", - "url" : { - "host" : [ - "{{base_url}}" - ], - "path" : [ - "channels", - "nhsapp", - "accounts" - ], - "query" : [ - { - "key" : "ods-organisation-code", - "value" : "T00001" - }, - { - "key" : "page", - "value" : "2" - } - ], - "raw" : "{{base_url}}/channels/nhsapp/accounts?ods-organisation-code=T00001&page=2" - } - }, - "response" : [], - "uid" : "41628342-f3881d9b-5f4a-4132-88b2-a541494373f3" - } + "url": { + "raw": "{{base_url}}/v1/messages/2aUxQER3co3kXdvTKrhbSFHRRxR", + "host": [ + "{{base_url}}" + ], + "path": [ + "v1", + "messages", + "2aUxQER3co3kXdvTKrhbSFHRRxR" + ] + }, + "description": "This request successfully retrieves a message status." + }, + "response": [] + } + ] + }, + { + "name": "NHS App Account", + "item": [ + { + "name": "200 - NHS App Account - Multipage", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});" + ], + "packages": {}, + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "{{authorization_header_value}}" + } ], - "name" : "NHS App Account", - "uid" : "41628342-ed012ff6-abd8-49a4-a71e-eb9e160dea7e" - } - ], - "variable" : [ - { - "key" : "base_url", - "type" : "string", - "value" : "https://int.api.service.nhs.uk/comms" - }, - { - "key" : "routing_plan_id", - "type" : "string", - "value" : "119bdd50-783c-4161-a765-792785e46851" - } + "url": { + "raw": "{{base_url}}/channels/nhsapp/accounts?ods-organisation-code=T00001&page=2", + "host": [ + "{{base_url}}" + ], + "path": [ + "channels", + "nhsapp", + "accounts" + ], + "query": [ + { + "key": "ods-organisation-code", + "value": "T00001" + }, + { + "key": "page", + "value": "2" + } + ] + }, + "description": "The request successfully retrieves NHS numbers registered for notifications in the NHS App against an ODS code, adding the \"page\" parameter allows you to access the full paginated response" + }, + "response": [] + } ] - } -} + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "var uuid = require('uuid');", + "", + "var privateKey = pm.environment.get('private_key') || '';", + "var api_key_value = pm.environment.get('api_key') || '';", + "", + "if (!privateKey) {", + " throw new Error(\"Variable private_key must be set with your private key for signed JWT authentication.\");", + "}", + "", + "if (!api_key_value) {", + " throw new Error(\"Variable api_key must be set with your integration testing application API key.\");", + "}", + "", + "var auth_url = 'https://int.api.service.nhs.uk/oauth2/token';", + "var navigator = {};", + "var window = {};", + "const interval = setTimeout(() => {}, 2147483647);", + "", + "return new Promise((resolve, reject) => { ", + " if (pm.globals.has('jsrsasign-js') && pm.globals.get('jsrsasign-js') !== \"\") {", + " return resolve();", + " }", + "", + " pm.sendRequest(", + " {", + " url: 'https://kjur.github.io/jsrsasign/jsrsasign-all-min.js',", + " method: 'GET'", + " }, function (err, res) {", + " if (err) {", + " return reject(err);", + " }", + "", + " pm.globals.set('jsrsasign-js', res.text()); ", + " return resolve();", + " }", + " );", + "}).then(() => { ", + " eval(pm.globals.get(\"jsrsasign-js\")); ", + "", + " // Set headers for JWT", + " var header = {", + " 'typ': 'JWT',", + " 'alg': 'RS512',", + " 'kid': 'local'", + " };", + "", + " // Prepare timestamp in seconds", + " var currentTimestamp = Math.floor(Date.now() / 1000)", + " var uuid = require('uuid');", + " var jti_value = uuid.v4();", + " var data = {", + " 'sub': api_key_value,", + " 'iss': api_key_value,", + " 'jti': jti_value,", + " 'aud': auth_url,", + " 'exp': currentTimestamp + 180, // expiry time is 180 seconds from time of creation", + " } ", + "", + " var sJWT = KJUR.jws.JWS.sign(header.alg, JSON.stringify(header), JSON.stringify(data), privateKey); ", + " return new Promise((resolve, reject) => { ", + " pm.sendRequest({", + " url: auth_url,", + " method: \"POST\",", + " header: {", + " \"Content-Type\": \"application/x-www-form-urlencoded\"", + " },", + " body: {", + " mode: \"urlencoded\",", + " urlencoded: [", + " {", + " key: \"grant_type\",", + " value: \"client_credentials\"", + " },", + " {", + " key: \"client_assertion_type\",", + " value: \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\",", + " },", + " {", + " key: \"client_assertion\",", + " value: sJWT", + " }", + " ]", + " }", + " }, function (err, res) { ", + " if (err) {", + " return reject(err);", + " }", + "", + " //assign the authorization header value", + " pm.environment.set('authorization_header_value', `Bearer ${res.json().access_token}`);", + "", + " //assign the message batch reference", + " pm.environment.set(\"message_batch_reference\", uuid.v4());", + "", + " //assign the message reference", + " pm.environment.set(\"message_reference\", uuid.v4());", + "", + " //generate a correlation identifier", + " pm.environment.set(\"correlation_id\", uuid.v4());", + "", + " return resolve();", + " }); ", + " });", + "}).then(() => { ", + " clearTimeout(interval);", + "}).catch((err) => { ", + " console.error(err); ", + " clearTimeout(interval); ", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "variable": [ + { + "key": "base_url", + "value": "https://int.api.service.nhs.uk/comms" + }, + { + "key": "routing_plan_id", + "value": "119bdd50-783c-4161-a765-792785e46851" + } + ] +} \ No newline at end of file diff --git a/specification/documentation/APIDescription.md b/specification/documentation/APIDescription.md index c0cea814b..039680c79 100644 --- a/specification/documentation/APIDescription.md +++ b/specification/documentation/APIDescription.md @@ -215,6 +215,20 @@ Every request includes an `idempotencyKey` field located in the meta collection If a request fails, our retry policy will continue to attempt to deliver the callback for a period of 2 hours. +## Two-way messaging + +**This feature is currently under development and is not yet ready to use.** + +The two way messaging feature lets the message recipient to receive a question and then reply choosing from a list of pre-defined responses. + +e.g. +Question: Can you still attend your appointment tomorrow? +Answer options: [Yes, No] + +In order to present the recipient with answers include the `answerOptions` field. + +This is currently only supported by the NHSAPP channel. + ## Message character limits Different character limits apply to each of the communication channels as listed below. NHS Notify will validate that any personalisation fields submitted in the send message request do not exceed these limits but it is the client's responsibility to ensure that when personalisation is combined with any templated text, the channel character limit is not exceeded. diff --git a/specification/documentation/CreateMessage.md b/specification/documentation/CreateMessage.md index be30b7d71..8b08e3e0b 100644 --- a/specification/documentation/CreateMessage.md +++ b/specification/documentation/CreateMessage.md @@ -33,6 +33,6 @@ Here is an example curl request which creates a message using one of these routi curl -X POST \ --header "Accept: */*" \ --header "Content-type: application/vnd.api+json" \ - -d '{"data": {"type": "Message","attributes": {"routingPlanId": "b838b13c-f98c-4def-93f0-515d4e4f4ee1","messageReference": "da0b1495-c7cb-468c-9d81-07dee089d728","recipient": {"nhsNumber": "9990548609"},"originator": {"odsCode":"X123"},"personalisation": {}}}}' \ + -d '{"data": {"type": "Message","attributes": {"routingPlanId": "b838b13c-f98c-4def-93f0-515d4e4f4ee1","messageReference": "da0b1495-c7cb-468c-9d81-07dee089d728","recipient": {"nhsNumber": "9990548609"},"originator": {"odsCode":"X123"},"personalisation": {},"answerOptions": {"NHSAPP":[{"code":"Yes"},{"code":"No"}]}}}}' \ https://sandbox.api.service.nhs.uk/comms/v1/messages ``` diff --git a/specification/documentation/CreateMessageBatch.md b/specification/documentation/CreateMessageBatch.md index af66080fb..6d1a27f8a 100644 --- a/specification/documentation/CreateMessageBatch.md +++ b/specification/documentation/CreateMessageBatch.md @@ -38,6 +38,6 @@ Here is an example curl request which creates a message batch using one of these curl -X POST \ --header "Accept: */*" \ --header "Content-type: application/vnd.api+json" \ - -d '{"data": {"type": "MessageBatch","attributes": {"routingPlanId": "b838b13c-f98c-4def-93f0-515d4e4f4ee1","messageBatchReference": "da0b1495-c7cb-468c-9d81-07dee089d728","messages": [{"messageReference": "703b8008-545d-4a04-bb90-1f2946ce1575","recipient": {"nhsNumber": "9990548609"},"originator": {"odsCode":"X123"},"personalisation": {}}]}}}' \ + -d '{"data": {"type": "MessageBatch","attributes": {"routingPlanId": "b838b13c-f98c-4def-93f0-515d4e4f4ee1","messageBatchReference": "da0b1495-c7cb-468c-9d81-07dee089d728","messages": [{"messageReference": "703b8008-545d-4a04-bb90-1f2946ce1575","recipient": {"nhsNumber": "9990548609"},"originator": {"odsCode":"X123"},"personalisation": {},"answerOptions": {"NHSAPP":[{"code":"Yes"},{"code":"No"}]}}]}}}' \ https://sandbox.api.service.nhs.uk/comms/v1/message-batches ``` diff --git a/specification/schemas/components/Message.yaml b/specification/schemas/components/Message.yaml index 2c070ab80..e11db589d 100644 --- a/specification/schemas/components/Message.yaml +++ b/specification/schemas/components/Message.yaml @@ -15,6 +15,28 @@ properties: personalisation: type: object description: The personalisation keys and values for this message. These are linked to the routingPlanId provided and are agreed upon during [onboarding](#overview--onboarding). + answerOptions: + type: object + optional: true + description: |- + The answer options for this message. These are channel specific. + + If you provide answer options, then they will be presented to the receipient for reply options. These will then be sent back via the two-way messaging callback mechanism. + + This feature needs to be enabled on your account and is subject to the relevant callback integration being completed. + properties: + type: + $ref: ../enums/EnumAnswerOptionsType.yaml + options: + type: array + items: + type: object + properties: + code: + description: |- + This is the code that will be sent back to you in the callback when a recipient selects this option. It is for your reference to understand which option the recipient has selected. It is also the display value shown to the recipient. + type: string + example: Yes required: - messageReference - recipient diff --git a/specification/schemas/enums/EnumAnswerOptionsType.yaml b/specification/schemas/enums/EnumAnswerOptionsType.yaml new file mode 100644 index 000000000..59bac31df --- /dev/null +++ b/specification/schemas/enums/EnumAnswerOptionsType.yaml @@ -0,0 +1,6 @@ +title: Enum_AnswerOptionsType +description: The type of answer options available for this message. +type: string +enum: + - NHSAPP +example: NHSAPP diff --git a/specification/schemas/requests/CreateMessage.yaml b/specification/schemas/requests/CreateMessage.yaml index e8b264a71..fc6f9c5b6 100644 --- a/specification/schemas/requests/CreateMessage.yaml +++ b/specification/schemas/requests/CreateMessage.yaml @@ -38,7 +38,29 @@ properties: $ref: ../components/Originator.yaml personalisation: type: object - description: 'The personalisation keys and values for this message. These are linked to the routingPlanId provided and are agreed upon during [onboarding](#overview--onboarding).' + description: "The personalisation keys and values for this message. These are linked to the routingPlanId provided and are agreed upon during [onboarding](#overview--onboarding)." + answerOptions: + type: object + optional: true + description: |- + The answer options for this message. These are channel specific. + + If you provide answer options, then they will be presented to the receipient for reply options. These will then be sent back via the two-way messaging callback mechanism. + + This feature needs to be enabled on your account and is subject to the relevant callback integration being completed. + properties: + type: + $ref: ../enums/EnumAnswerOptionsType.yaml + options: + type: array + items: + type: object + properties: + code: + description: |- + This is the code that will be sent back to you in the callback when a recipient selects this option. It is for your reference to understand which option the recipient has selected. It is also the display value shown to the recipient. + type: string + example: Yes required: - type - attributes