{
  "version": "1.0.0",
  "exportedAt": "2026-06-09T05:24:36.272Z",
  "workflow": {
    "name": "HIMSS - RPM Ingestion (HL7 over HTTP)",
    "description": "End-to-end workflow: Ingest -> Auth -> Create Visit (ADT^A01 via HTTP) -> File Data (ORU^R01 via HTTP)."
  },
  "flow": {
    "tab": {
      "id": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
      "type": "tab",
      "label": "HIMSS - RPM Ingestion (HL7 over HTTP)",
      "disabled": false,
      "info": "End-to-end workflow: Ingest -> Auth -> Create Visit (ADT^A01 via HTTP) -> File Data (ORU^R01 via HTTP).",
      "env": []
    },
    "nodes": [
      {
        "id": "ac730675cbc3541f",
        "type": "group",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "name": "Remote Process Monitoring Data Ingestion",
        "style": {
          "label": true,
          "stroke": "#001f60",
          "fill": "#bfc7d7",
          "fill-opacity": "0.67",
          "color": "#001f60"
        },
        "nodes": [
          "5594bde31c1470b6",
          "3370460cdaddda93",
          "a1b2e920e5cb23d3",
          "30aa96c719f8d6a7",
          "d75590c46dd95ce3",
          "2724aa4e6beaf054",
          "7599d174b14dcaf4",
          "b2b61cc74fd8dd27",
          "13b2535e60984140",
          "286a5f39a0de7309",
          "d488f784a136b57c",
          "9ffcb49c9b027d9d",
          "dfb4eda3620a6d3f",
          "8fd0ac10a58d53ec",
          "b227bcda46a5182a",
          "8d46fe6a2dbefed4",
          "4ae21fcaec88348f",
          "e5b645fe21f7f657",
          "7fa85c3275196879",
          "5174d08b910dcc4d",
          "d4101a1b96b5e8e0",
          "b51be744ccbc34ee"
        ],
        "x": 54,
        "y": 39,
        "w": 1292,
        "h": 482
      },
      {
        "id": "5594bde31c1470b6",
        "type": "comment",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Step 1: Ingest + Auth",
        "info": "Accepts simplified JSON from MedTech partners and Authenticates with EHR.",
        "x": 200,
        "y": 140,
        "wires": []
      },
      {
        "id": "3370460cdaddda93",
        "type": "http in",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "POST /vital-ingest",
        "url": "/device-data-ingest",
        "method": "post",
        "upload": false,
        "skipBodyParsing": false,
        "swaggerDoc": "",
        "x": 190,
        "y": 180,
        "wires": [
          [
            "a1b2e920e5cb23d3",
            "30aa96c719f8d6a7"
          ]
        ]
      },
      {
        "id": "a1b2e920e5cb23d3",
        "type": "debug",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Log Input",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 500,
        "y": 100,
        "wires": [],
        "icon": "font-awesome/fa-outdent"
      },
      {
        "id": "30aa96c719f8d6a7",
        "type": "ec-auth-backend",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Get System Token",
        "integrationId": "",
        "integrationMetadata": {
          "ehr": "epic",
          "type": "backend",
          "scopes": "patient/*.read user/*.read"
        },
        "customScopes": "",
        "x": 450,
        "y": 180,
        "wires": [
          [
            "2724aa4e6beaf054"
          ]
        ]
      },
      {
        "id": "d75590c46dd95ce3",
        "type": "comment",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Step 2: Generate Encounter Context",
        "info": "Generate a unique Visit ID to link the ADT (Creation) and ORU (Data) messages.",
        "x": 770,
        "y": 140,
        "wires": []
      },
      {
        "id": "2724aa4e6beaf054",
        "type": "function",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Generate Visit ID",
        "func": "// Generate a unique Visit ID based on timestamp and patient\n// Format: RPM-YYYYMMDD-PATIENTID\nconst dateStr = new Date().toISOString().replace(/[-:T.]/g, \"\").substring(0, 14);\nmsg.payload.visitId = `RPM-${dateStr}-${msg.payload.patient.identifier}`;\n// Store original payload to preserve it across ADT flow\nmsg.originalPayload = RED.util.cloneMessage(msg.payload);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 710,
        "y": 180,
        "wires": [
          [
            "b2b61cc74fd8dd27"
          ]
        ]
      },
      {
        "id": "7599d174b14dcaf4",
        "type": "comment",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Step 3: Create Patient Visit",
        "info": "Generate and Send ADT^A01 to create the encounter container.",
        "x": 210,
        "y": 240,
        "wires": []
      },
      {
        "id": "b2b61cc74fd8dd27",
        "type": "ec-hl7-mapper",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Build Visit-Open Message",
        "templateType": "custom",
        "template": "{\n  \"hl7msg\": [\n    \"MSH|^~\\\\&|EHRConnect|RPM_Sys|||{{msg.payload.timestamp | date: '%Y%m%d%H%M%S'}}||ADT^A01|{{uuid}}|T|2.3\",\n    \"EVN|A01|{{msg.payload.timestamp | date: '%Y%m%d%H%M%S'}}\",\n    \"PID|||{{msg.payload.patient.identifier}}||||||||||||||||{{msg.payload.visitId}}\",\n    \"PV1||O|Virtual^^RPM||||||||||||||||{{msg.payload.visitId}}|||||||||||||||||||||||||{{msg.payload.timestamp | date: '%Y%m%d%H%M%S'}}\"\n  ]\n}",
        "outputFormat": "text",
        "inputField": "payload",
        "inputFieldType": "msg",
        "x": 190,
        "y": 300,
        "wires": [
          [
            "13b2535e60984140"
          ]
        ]
      },
      {
        "id": "13b2535e60984140",
        "type": "function",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Set Auth Headers",
        "func": "msg.head = {\n    'Authorization': 'Bearer ' + (msg.accessToken || 'mock_token'),\n    'Content-Type': 'application/hl7-v2+er7',\n    'Epic-Client-ID': 'YOUR-EPIC-CLIENT-ID-HERE' // Replace with your actual Client ID\n};\nmsg.payload = msg.payload.hl7msg.join('\\r') + '\\r';\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 410,
        "y": 300,
        "wires": [
          [
            "7fa85c3275196879"
          ]
        ]
      },
      {
        "id": "286a5f39a0de7309",
        "type": "switch",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Check Visit Was Created",
        "property": "statusCode",
        "propertyType": "msg",
        "rules": [
          {
            "t": "eq",
            "v": "200",
            "vt": "num"
          },
          {
            "t": "else"
          }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 820,
        "y": 300,
        "wires": [
          [
            "9ffcb49c9b027d9d"
          ],
          [
            "d488f784a136b57c"
          ]
        ]
      },
      {
        "id": "d488f784a136b57c",
        "type": "debug",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Visit Creation Error",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1020,
        "y": 320,
        "wires": [],
        "icon": "node-red/alert.svg"
      },
      {
        "id": "9ffcb49c9b027d9d",
        "type": "function",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Restore Context",
        "func": "// Restore the original JSON payload to proceed with ORU mapping\nmsg.payload = msg.originalPayload;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1040,
        "y": 260,
        "wires": [
          [
            "8fd0ac10a58d53ec"
          ]
        ]
      },
      {
        "id": "dfb4eda3620a6d3f",
        "type": "comment",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Step 4: File the Readings",
        "info": "Generate and Send ORU^R01 linked to the same Visit ID.",
        "x": 210,
        "y": 380,
        "wires": []
      },
      {
        "id": "8fd0ac10a58d53ec",
        "type": "ec-hl7-mapper",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Build Readings Message",
        "templateType": "custom",
        "template": "{\n  \"hl7msg\": [\n    \"MSH|^~\\\\&|EHRConnect|RPM_DEVICE|||{{timestamp | date: '%Y%m%d%H%M%S'}}||ORU^R01|{{uuid}}|T|2.3\",\n    \"PID|||{{patient.identifier}}||||||||||||||||{{visitId}}\",\n    \"PV1|||Virtual^^RPM||||||||||||||||{{visitId}}\",\n    \"OBR|1|||RPM Flowsheet Data|||{{timestamp | date: '%Y%m%d%H%M%S'}}|||RPM_DEVICE\"{% for item in observations %},\n    \"OBX|{{forloop.index}}||{{item.type}}||{{item.value}}|{{item.unit}}|||||F|||{{timestamp | date: '%Y%m%d%H%M%S'}}\"{% endfor %}\n  ]\n}",
        "outputFormat": "text",
        "inputField": "payload",
        "inputFieldType": "msg",
        "x": 190,
        "y": 420,
        "wires": [
          [
            "b227bcda46a5182a"
          ]
        ]
      },
      {
        "id": "b227bcda46a5182a",
        "type": "function",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Set Auth Headers",
        "func": "msg.headers = {\n    'Authorization': 'Bearer ' + (msg.access_token || 'mock_token'),\n    'Content-Type': 'application/hl7-v2+er7',\n    'Epic-Client-ID': 'YOUR-EPIC-CLIENT-ID-HERE' // Replace with your actual Client ID\n};\nmsg.payload = msg.payload.hl7msg.join('\\r') + '\\r';\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 410,
        "y": 420,
        "wires": [
          [
            "5174d08b910dcc4d"
          ]
        ]
      },
      {
        "id": "8d46fe6a2dbefed4",
        "type": "switch",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Check Readings Were Filed",
        "property": "statusCode",
        "propertyType": "msg",
        "rules": [
          {
            "t": "eq",
            "v": "200",
            "vt": "num"
          },
          {
            "t": "else"
          }
        ],
        "checkall": true,
        "repair": false,
        "outputs": 2,
        "x": 820,
        "y": 420,
        "wires": [
          [
            "d4101a1b96b5e8e0"
          ],
          [
            "4ae21fcaec88348f"
          ]
        ]
      },
      {
        "id": "4ae21fcaec88348f",
        "type": "debug",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Readings Filing Error",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1030,
        "y": 480,
        "wires": [],
        "icon": "node-red/alert.svg"
      },
      {
        "id": "e5b645fe21f7f657",
        "type": "inject",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Demo Request",
        "props": [
          {
            "p": "payload"
          }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "{   \"patient\": {     \"identifier\": \"YOUR-PATIENT-ID-HERE\"    },   \"timestamp\": \"2025-12-08T14:30:00Z\",   \"observations\": [     {       \"type\": \"Systolic Blood Pressure\",       \"value\": \"120\",       \"unit\": \"mmHg\"     },     {       \"type\": \"Diastolic Blood Pressure\",       \"value\": \"80\",       \"unit\": \"mmHg\"     },     {       \"type\": \"Heart Rate\",       \"value\": \"72\",       \"unit\": \"bpm\"     }   ] }",
        "payloadType": "json",
        "x": 180,
        "y": 80,
        "wires": [
          [
            "30aa96c719f8d6a7"
          ]
        ]
      },
      {
        "id": "7fa85c3275196879",
        "type": "http request",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Send Visit-Open Message",
        "method": "POST",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "https://vendorservices.epic.com/interconnect-amcurprd-oauth/api/epic/2015/EDI/HTTP/HL7v2/YOUR-ADT-INTERFACE-ID",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [
          {
            "keyType": "Authorization",
            "keyValue": "",
            "valueType": "msg",
            "valueValue": "head.Authorization"
          },
          {
            "keyType": "other",
            "keyValue": "Epic-Client-ID",
            "valueType": "other",
            "valueValue": "YOUR-EPIC-CLIENT-ID-HERE"
          },
          {
            "keyType": "Content-Type",
            "keyValue": "",
            "valueType": "other",
            "valueValue": "application/hl7-v2+er7"
          }
        ],
        "x": 610,
        "y": 300,
        "wires": [
          [
            "286a5f39a0de7309"
          ]
        ]
      },
      {
        "id": "5174d08b910dcc4d",
        "type": "http request",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Send Readings Message",
        "method": "POST",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "https://vendorservices.epic.com/interconnect-amcurprd-oauth/api/epic/2015/EDI/HTTP/HL7v2/YOUR-ORU-INTERFACE-ID",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [
          {
            "keyType": "Authorization",
            "keyValue": "",
            "valueType": "msg",
            "valueValue": "head.Authorization"
          },
          {
            "keyType": "other",
            "keyValue": "Epic-Client-ID",
            "valueType": "other",
            "valueValue": "YOUR-EPIC-CLIENT-ID-HERE"
          },
          {
            "keyType": "Content-Type",
            "keyValue": "",
            "valueType": "other",
            "valueValue": "application/hl7-v2+er7"
          }
        ],
        "x": 610,
        "y": 420,
        "wires": [
          [
            "8d46fe6a2dbefed4"
          ]
        ]
      },
      {
        "id": "d4101a1b96b5e8e0",
        "type": "function",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "Format Summary",
        "func": "const original = msg.originalPayload || {};\nconst patient = original.patient || {};\nconst observations = original.observations || [];\n\nconst patientId = patient.identifier || 'N/A';\nconst visitId = original.visitId || msg.visitId || 'N/A';\nconst timestamp = original.timestamp || new Date().toISOString();\n\nconst observationTypes = observations.length\n    ? observations.map(o => o.type || o.name || 'Unknown').join(' | ')\n    : 'No observations';\n\nconst completedAt = new Date(timestamp).toLocaleString('en-US', {\n    dateStyle: 'medium',\n    timeStyle: 'short'\n});\n\nlet processingTime = '< 1 sec';\nif (msg.startTime) {\n    const durationMs = Date.now() - new Date(msg.startTime).getTime();\n    processingTime = durationMs < 1000\n        ? `${durationMs} ms`\n        : `${(durationMs / 1000).toFixed(2)} sec`;\n}\n\nconst screenSummary = `\n==================================================\n        EPIC SANDBOX UPDATED SUCCESSFULLY\n==================================================\nRPM DATA RECEIVED -> HL7 CREATED -> EPIC UPDATED\n\nPATIENT ID\n${patientId}\n\nVISIT CREATED\n${visitId}\n\nDATA FILED\n${observations.length} vitals filed successfully\n\nVITALS\n${observationTypes}\n\nHL7 MESSAGES\nADT^A01  Visit Created\nORU^R01  RPM Vitals Filed\n\nRESULT\nPatient visit and RPM vitals are visible in Epic.\n\nCOMPLETED: ${completedAt}     SPEED: ${processingTime}\n==================================================\n`;\n\nmsg.payload = screenSummary;\n\nmsg.demoSummary = {\n    status: \"SUCCESS\",\n    workflow: \"RPM Data Received -> HL7 Created -> Epic Updated\",\n    patientId,\n    visitId,\n    vitalsFiled: observations.length,\n    observationTypes,\n    hl7Messages: [\"ADT^A01\", \"ORU^R01\"],\n    processingTime,\n    completedAt,\n    result: \"Patient visit and RPM vitals are visible in Epic.\"\n};\n\nconsole.log(screenSummary);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1030,
        "y": 420,
        "wires": [
          [
            "b51be744ccbc34ee"
          ]
        ]
      },
      {
        "id": "b51be744ccbc34ee",
        "type": "debug",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "g": "ac730675cbc3541f",
        "name": "📊 Log Success",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1220,
        "y": 420,
        "wires": []
      },
      {
        "id": "0412f1867f7bdf1d",
        "type": "http in",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "name": "Post Device Vitals",
        "url": "/post-device",
        "method": "get",
        "upload": false,
        "skipBodyParsing": false,
        "swaggerDoc": "",
        "x": 250,
        "y": 700,
        "wires": [
          [
            "cd1cbc5de0579a85"
          ]
        ]
      },
      {
        "id": "cd1cbc5de0579a85",
        "type": "ec-auth-backend",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "name": "Get System Token",
        "integrationId": "",
        "integrationMetadata": {
          "ehr": "epic",
          "type": "backend",
          "scopes": "patient/*.* user/*.* launch profile fhirUser openid system/*.write system/Observation.read system/Observation.write system/Patient.read system/ExplanationOfBenefit.read system/DocumentReference.read system/Appointment.read system/Encounter.read system/Condition.read system/MedicationRequest.read                                                                                     system/MedicationStatement.read system/AllergyIntolerance.read"
        },
        "customScopes": "",
        "outputFormat": "token_only",
        "outputField": "",
        "outputFieldType": "msg",
        "x": 480,
        "y": 700,
        "wires": [
          [
            "f7a19fecaac73111"
          ]
        ]
      },
      {
        "id": "f7a19fecaac73111",
        "type": "ec-fhir-create",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "name": "Create Encounter",
        "integrationId": "",
        "integrationMetadata": {
          "ehr": "epic",
          "type": "backend",
          "scopes": "patient/*.* user/*.* launch profile fhirUser openid system/*.write system/Observation.read system/Observation.write system/Patient.read system/ExplanationOfBenefit.read system/DocumentReference.read system/Appointment.read"
        },
        "resourceType": "Encounter",
        "resource": "",
        "outputField": "",
        "outputFieldType": "msg",
        "x": 730,
        "y": 700,
        "wires": [
          [
            "22a36f896b7f95c4"
          ]
        ]
      },
      {
        "id": "22a36f896b7f95c4",
        "type": "ec-fhir-create",
        "z": "workflow_50c3ba71-4e5e-4c92-9e79-bd4a0cb6808d",
        "name": "File Vital Reading",
        "integrationId": "",
        "integrationMetadata": {
          "ehr": "epic",
          "type": "backend",
          "scopes": "patient/*.* user/*.* launch profile fhirUser openid system/*.write system/Observation.read system/Observation.write system/Patient.read system/ExplanationOfBenefit.read system/DocumentReference.read system/Appointment.read"
        },
        "resourceType": "Observation",
        "resource": "",
        "outputField": "",
        "outputFieldType": "msg",
        "x": 1000,
        "y": 720,
        "wires": [
          []
        ]
      }
    ]
  },
  "requirements": [
    {
      "ehr": "epic",
      "type": "backend",
      "scopes": "patient/*.read user/*.read"
    },
    {
      "ehr": "epic",
      "type": "backend",
      "scopes": "patient/*.* user/*.* launch profile fhirUser openid system/*.write system/Observation.read system/Observation.write system/Patient.read system/ExplanationOfBenefit.read system/DocumentReference.read system/Appointment.read system/Encounter.read system/Condition.read system/MedicationRequest.read                                                                                     system/MedicationStatement.read system/AllergyIntolerance.read"
    },
    {
      "ehr": "epic",
      "type": "backend",
      "scopes": "patient/*.* user/*.* launch profile fhirUser openid system/*.write system/Observation.read system/Observation.write system/Patient.read system/ExplanationOfBenefit.read system/DocumentReference.read system/Appointment.read"
    }
  ]
}